Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
authorLinus Torvalds <torvalds@linux-foundation.org>
Mon, 27 Aug 2018 18:59:39 +0000 (11:59 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 27 Aug 2018 18:59:39 +0000 (11:59 -0700)
Pull networking fixes from David Miller:

 1) ICE, E1000, IGB, IXGBE, and I40E bug fixes from the Intel folks.

 2) Better fix for AB-BA deadlock in packet scheduler code, from Cong
    Wang.

 3) bpf sockmap fixes (zero sized key handling, etc.) from Daniel
    Borkmann.

 4) Send zero IPID in TCP resets and SYN-RECV state ACKs, to prevent
    attackers using it as a side-channel. From Eric Dumazet.

 5) Memory leak in mediatek bluetooth driver, from Gustavo A. R. Silva.

 6) Hook up rt->dst.input of ipv6 anycast routes properly, from Hangbin
    Liu.

 7) hns and hns3 bug fixes from Huazhong Tan.

 8) Fix RIF leak in mlxsw driver, from Ido Schimmel.

 9) iova range check fix in vhost, from Jason Wang.

10) Fix hang in do_tcp_sendpages() with tls, from John Fastabend.

11) More r8152 chips need to disable RX aggregation, from Kai-Heng Feng.

12) Memory exposure in TCA_U32_SEL handling, from Kees Cook.

13) TCP BBR congestion control fixes from Kevin Yang.

14) hv_netvsc, ignore non-PCI devices, from Stephen Hemminger.

15) qed driver fixes from Tomer Tayar.

* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net: (77 commits)
  net: sched: Fix memory exposure from short TCA_U32_SEL
  qed: fix spelling mistake "comparsion" -> "comparison"
  vhost: correctly check the iova range when waking virtqueue
  qlge: Fix netdev features configuration.
  net: macb: do not disable MDIO bus at open/close time
  Revert "net: stmmac: fix build failure due to missing COMMON_CLK dependency"
  net: macb: Fix regression breaking non-MDIO fixed-link PHYs
  mlxsw: spectrum_switchdev: Do not leak RIFs when removing bridge
  i40e: fix condition of WARN_ONCE for stat strings
  i40e: Fix for Tx timeouts when interface is brought up if DCB is enabled
  ixgbe: fix driver behaviour after issuing VFLR
  ixgbe: Prevent unsupported configurations with XDP
  ixgbe: Replace GFP_ATOMIC with GFP_KERNEL
  igb: Replace mdelay() with msleep() in igb_integrated_phy_loopback()
  igb: Replace GFP_ATOMIC with GFP_KERNEL in igb_sw_init()
  igb: Use an advanced ctx descriptor for launchtime
  e1000: ensure to free old tx/rx rings in set_ringparam()
  e1000: check on netif_running() before calling e1000_up()
  ixgb: use dma_zalloc_coherent instead of allocator/memset
  ice: Trivial formatting fixes
  ...

2302 files changed:
.mailmap
Documentation/ABI/stable/sysfs-driver-mlxreg-io [new file with mode: 0644]
Documentation/ABI/testing/sysfs-fs-f2fs
Documentation/admin-guide/cgroup-v2.rst
Documentation/admin-guide/kernel-parameters.txt
Documentation/core-api/index.rst
Documentation/core-api/kernel-api.rst
Documentation/core-api/mm-api.rst [new file with mode: 0644]
Documentation/devicetree/bindings/arm/adapteva.txt [deleted file]
Documentation/devicetree/bindings/arm/amlogic.txt
Documentation/devicetree/bindings/arm/atmel-pmc.txt [deleted file]
Documentation/devicetree/bindings/arm/bcm/brcm,brcmstb.txt
Documentation/devicetree/bindings/arm/cpu-capacity.txt
Documentation/devicetree/bindings/arm/cpus.txt
Documentation/devicetree/bindings/arm/freescale/m4if.txt [new file with mode: 0644]
Documentation/devicetree/bindings/arm/freescale/tigerp.txt [new file with mode: 0644]
Documentation/devicetree/bindings/arm/fsl.txt
Documentation/devicetree/bindings/arm/idle-states.txt
Documentation/devicetree/bindings/arm/insignal-boards.txt [deleted file]
Documentation/devicetree/bindings/arm/mediatek.txt
Documentation/devicetree/bindings/arm/omap/l4.txt
Documentation/devicetree/bindings/arm/rockchip.txt
Documentation/devicetree/bindings/arm/samsung/samsung-boards.txt
Documentation/devicetree/bindings/arm/shmobile.txt
Documentation/devicetree/bindings/arm/ti/k3.txt [new file with mode: 0644]
Documentation/devicetree/bindings/arm/xilinx.txt
Documentation/devicetree/bindings/ata/ahci-platform.txt
Documentation/devicetree/bindings/ata/sata_rcar.txt
Documentation/devicetree/bindings/bus/sun50i-de2-bus.txt [new file with mode: 0644]
Documentation/devicetree/bindings/bus/ti-sysc.txt
Documentation/devicetree/bindings/clock/at91-clock.txt
Documentation/devicetree/bindings/clock/exynos5440-clock.txt [deleted file]
Documentation/devicetree/bindings/cpufreq/cpufreq-exynos5440.txt [deleted file]
Documentation/devicetree/bindings/display/marvell,pxa2xx-lcdc.txt
Documentation/devicetree/bindings/display/marvell,pxa300-gcu.txt [new file with mode: 0644]
Documentation/devicetree/bindings/eeprom/at24.txt
Documentation/devicetree/bindings/i2c/i2c-fsi.txt [new file with mode: 0644]
Documentation/devicetree/bindings/i2c/i2c-owl.txt [new file with mode: 0644]
Documentation/devicetree/bindings/i2c/i2c-rcar.txt
Documentation/devicetree/bindings/i2c/i2c-sh_mobile.txt
Documentation/devicetree/bindings/input/hid-over-i2c.txt
Documentation/devicetree/bindings/interrupt-controller/renesas,irqc.txt
Documentation/devicetree/bindings/iommu/mediatek,iommu.txt
Documentation/devicetree/bindings/iommu/renesas,ipmmu-vmsa.txt
Documentation/devicetree/bindings/leds/backlight/pwm-backlight.txt
Documentation/devicetree/bindings/memory-controllers/mediatek,smi-common.txt
Documentation/devicetree/bindings/memory-controllers/mediatek,smi-larb.txt
Documentation/devicetree/bindings/mfd/as3722.txt
Documentation/devicetree/bindings/mfd/axp20x.txt
Documentation/devicetree/bindings/mfd/madera.txt [new file with mode: 0644]
Documentation/devicetree/bindings/mfd/rohm,bd71837-pmic.txt [new file with mode: 0644]
Documentation/devicetree/bindings/mfd/tps65910.txt
Documentation/devicetree/bindings/mmc/sunxi-mmc.txt
Documentation/devicetree/bindings/net/dwmac-sun8i.txt
Documentation/devicetree/bindings/net/nfc/pn544.txt
Documentation/devicetree/bindings/pinctrl/cirrus,madera-pinctrl.txt [new file with mode: 0644]
Documentation/devicetree/bindings/power/reset/qcom,pon.txt [new file with mode: 0644]
Documentation/devicetree/bindings/power/supply/maxim,ds2760.txt [new file with mode: 0644]
Documentation/devicetree/bindings/power/supply/sbs_sbs-battery.txt
Documentation/devicetree/bindings/pwm/pwm-fsl-ftm.txt
Documentation/devicetree/bindings/pwm/pwm-mediatek.txt
Documentation/devicetree/bindings/pwm/renesas,pwm-rcar.txt
Documentation/devicetree/bindings/reserved-memory/reserved-memory.txt
Documentation/devicetree/bindings/reset/amlogic,meson-axg-audio-arb.txt [new file with mode: 0644]
Documentation/devicetree/bindings/reset/qcom,aoss-reset.txt [new file with mode: 0644]
Documentation/devicetree/bindings/reset/uniphier-reset.txt
Documentation/devicetree/bindings/rtc/isil,isl1219.txt [new file with mode: 0644]
Documentation/devicetree/bindings/rtc/rtc-ds1307.txt
Documentation/devicetree/bindings/soc/mediatek/pwrap.txt
Documentation/devicetree/bindings/sound/mrvl,pxa-ssp.txt
Documentation/devicetree/bindings/sram/sunxi-sram.txt
Documentation/devicetree/bindings/thermal/thermal.txt
Documentation/devicetree/bindings/timer/ti,davinci-timer.txt [new file with mode: 0644]
Documentation/devicetree/bindings/vendor-prefixes.txt
Documentation/devicetree/bindings/w1/w1-gpio.txt
Documentation/devicetree/bindings/w1/w1.txt [new file with mode: 0644]
Documentation/driver-api/libata.rst
Documentation/early-userspace/README
Documentation/fb/fbcon.txt
Documentation/filesystems/Locking
Documentation/filesystems/f2fs.txt
Documentation/filesystems/overlayfs.txt
Documentation/filesystems/proc.txt
Documentation/filesystems/ramfs-rootfs-initramfs.txt
Documentation/filesystems/vfs.txt
Documentation/hwmon/raspberrypi-hwmon [new file with mode: 0644]
Documentation/i2c/busses/i2c-i801
Documentation/i2c/busses/i2c-ocores
Documentation/i2c/gpio-fault-injection
Documentation/input/multi-touch-protocol.rst
Documentation/kbuild/kconfig-language.txt
Documentation/kbuild/makefiles.txt
Documentation/networking/dpaa2/dpio-driver.rst [moved from drivers/staging/fsl-mc/bus/dpio/dpio-driver.txt with 95% similarity]
Documentation/networking/dpaa2/index.rst
Documentation/process/changes.rst
Documentation/sysctl/fs.txt
Documentation/sysctl/kernel.txt
Documentation/sysctl/vm.txt
Documentation/virtual/kvm/api.txt
Documentation/virtual/kvm/devices/arm-vgic-v3.txt
Documentation/virtual/kvm/devices/arm-vgic.txt
MAINTAINERS
Makefile
arch/Kconfig
arch/alpha/kernel/osf_sys.c
arch/arc/Makefile
arch/arm/Kconfig
arch/arm/Kconfig.debug
arch/arm/Makefile
arch/arm/boot/dts/Makefile
arch/arm/boot/dts/am335x-baltos.dtsi
arch/arm/boot/dts/am335x-evm.dts
arch/arm/boot/dts/am335x-evmsk.dts
arch/arm/boot/dts/am335x-osd3358-sm-red.dts [new file with mode: 0755]
arch/arm/boot/dts/am335x-sancloud-bbe.dts [new file with mode: 0644]
arch/arm/boot/dts/am335x-sl50.dts
arch/arm/boot/dts/am33xx.dtsi
arch/arm/boot/dts/am3517-evm.dts
arch/arm/boot/dts/am3517-som.dtsi
arch/arm/boot/dts/am437x-gp-evm.dts
arch/arm/boot/dts/am571x-idk.dts
arch/arm/boot/dts/am572x-idk-common.dtsi
arch/arm/boot/dts/am57xx-idk-common.dtsi
arch/arm/boot/dts/armada-388-clearfog-base.dts
arch/arm/boot/dts/armada-388-clearfog-pro.dts
arch/arm/boot/dts/armada-388-clearfog.dts
arch/arm/boot/dts/armada-388-clearfog.dtsi
arch/arm/boot/dts/armada-388-helios4.dts [new file with mode: 0644]
arch/arm/boot/dts/armada-38x-solidrun-microsom.dtsi
arch/arm/boot/dts/aspeed-ast2500-evb.dts
arch/arm/boot/dts/aspeed-bmc-opp-romulus.dts
arch/arm/boot/dts/aspeed-g4.dtsi
arch/arm/boot/dts/aspeed-g5.dtsi
arch/arm/boot/dts/at91-dvk_som60.dts [new file with mode: 0644]
arch/arm/boot/dts/at91-dvk_su60_somc.dtsi [new file with mode: 0644]
arch/arm/boot/dts/at91-dvk_su60_somc_lcm.dtsi [new file with mode: 0644]
arch/arm/boot/dts/at91-gatwick.dts [new file with mode: 0644]
arch/arm/boot/dts/at91-som60.dtsi [new file with mode: 0644]
arch/arm/boot/dts/at91-wb45n.dts [new file with mode: 0644]
arch/arm/boot/dts/at91-wb45n.dtsi [new file with mode: 0644]
arch/arm/boot/dts/at91-wb50n.dts [new file with mode: 0644]
arch/arm/boot/dts/at91-wb50n.dtsi [new file with mode: 0644]
arch/arm/boot/dts/at91sam9261.dtsi
arch/arm/boot/dts/at91sam9263.dtsi
arch/arm/boot/dts/at91sam9rl.dtsi
arch/arm/boot/dts/at91sam9x5.dtsi
arch/arm/boot/dts/bcm-cygnus.dtsi
arch/arm/boot/dts/bcm2835-rpi-cm1-io1.dts [new file with mode: 0644]
arch/arm/boot/dts/bcm2835-rpi-cm1.dtsi [new file with mode: 0644]
arch/arm/boot/dts/bcm2837.dtsi
arch/arm/boot/dts/bcm283x.dtsi
arch/arm/boot/dts/bcm4708-asus-rt-ac56u.dts
arch/arm/boot/dts/bcm4708-asus-rt-ac68u.dts
arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts
arch/arm/boot/dts/bcm4708-linksys-ea6300-v1.dts
arch/arm/boot/dts/bcm4708-luxul-xap-1510.dts
arch/arm/boot/dts/bcm4708-luxul-xwc-1000.dts
arch/arm/boot/dts/bcm4708-netgear-r6250.dts
arch/arm/boot/dts/bcm4708-netgear-r6300-v2.dts
arch/arm/boot/dts/bcm4708-smartrg-sr400ac.dts
arch/arm/boot/dts/bcm47081-asus-rt-n18u.dts
arch/arm/boot/dts/bcm47081-buffalo-wzr-600dhp2.dts
arch/arm/boot/dts/bcm47081-buffalo-wzr-900dhp.dts
arch/arm/boot/dts/bcm47081-luxul-xap-1410.dts
arch/arm/boot/dts/bcm47081-luxul-xwr-1200.dts
arch/arm/boot/dts/bcm47081-tplink-archer-c5-v2.dts
arch/arm/boot/dts/bcm4709-asus-rt-ac87u.dts
arch/arm/boot/dts/bcm4709-buffalo-wxr-1900dhp.dts
arch/arm/boot/dts/bcm4709-linksys-ea9200.dts
arch/arm/boot/dts/bcm4709-netgear-r7000.dts
arch/arm/boot/dts/bcm4709-netgear-r8000.dts
arch/arm/boot/dts/bcm4709-tplink-archer-c9-v1.dts
arch/arm/boot/dts/bcm47094-dlink-dir-885l.dts
arch/arm/boot/dts/bcm47094-linksys-panamera.dts
arch/arm/boot/dts/bcm47094-luxul-abr-4500.dts
arch/arm/boot/dts/bcm47094-luxul-xbr-4500.dts
arch/arm/boot/dts/bcm47094-luxul-xwr-3100.dts
arch/arm/boot/dts/bcm47094-netgear-r8500.dts
arch/arm/boot/dts/bcm47094.dtsi
arch/arm/boot/dts/bcm5301x.dtsi
arch/arm/boot/dts/bcm53573.dtsi
arch/arm/boot/dts/bcm94708.dts
arch/arm/boot/dts/bcm94709.dts
arch/arm/boot/dts/bcm953012er.dts
arch/arm/boot/dts/bcm953012hr.dts
arch/arm/boot/dts/bcm953012k.dts
arch/arm/boot/dts/berlin2.dtsi
arch/arm/boot/dts/berlin2q.dtsi
arch/arm/boot/dts/da850-enbw-cmc.dts
arch/arm/boot/dts/da850-evm.dts
arch/arm/boot/dts/da850-lcdk.dts
arch/arm/boot/dts/da850-lego-ev3.dts
arch/arm/boot/dts/da850.dtsi
arch/arm/boot/dts/dra7-evm-common.dtsi
arch/arm/boot/dts/dra7-evm.dts
arch/arm/boot/dts/dra7.dtsi
arch/arm/boot/dts/dra71-evm.dts
arch/arm/boot/dts/dra72-evm-common.dtsi
arch/arm/boot/dts/dra74x.dtsi
arch/arm/boot/dts/dra76-evm.dts
arch/arm/boot/dts/dra76x.dtsi
arch/arm/boot/dts/emev2-kzm9d.dts
arch/arm/boot/dts/emev2.dtsi
arch/arm/boot/dts/exynos3250.dtsi
arch/arm/boot/dts/exynos4.dtsi
arch/arm/boot/dts/exynos4210.dtsi
arch/arm/boot/dts/exynos4412-midas.dtsi
arch/arm/boot/dts/exynos4412-tmu-sensor-conf.dtsi [deleted file]
arch/arm/boot/dts/exynos4412.dtsi
arch/arm/boot/dts/exynos5.dtsi
arch/arm/boot/dts/exynos5250.dtsi
arch/arm/boot/dts/exynos5410.dtsi
arch/arm/boot/dts/exynos5420-cpus.dtsi
arch/arm/boot/dts/exynos5420-tmu-sensor-conf.dtsi [deleted file]
arch/arm/boot/dts/exynos5420.dtsi
arch/arm/boot/dts/exynos5422-cpus.dtsi
arch/arm/boot/dts/gemini-sl93512r.dts [new file with mode: 0644]
arch/arm/boot/dts/gemini-sq201.dts
arch/arm/boot/dts/gr-peach-audiocamerashield.dtsi [new file with mode: 0644]
arch/arm/boot/dts/highbank.dts
arch/arm/boot/dts/imx31-lite.dts [new file with mode: 0644]
arch/arm/boot/dts/imx31.dtsi
arch/arm/boot/dts/imx50-evk.dts
arch/arm/boot/dts/imx50-pinfunc.h
arch/arm/boot/dts/imx50.dtsi
arch/arm/boot/dts/imx51-babbage.dts
arch/arm/boot/dts/imx51-eukrea-mbimxsd51-baseboard.dts
arch/arm/boot/dts/imx51-zii-rdu1.dts
arch/arm/boot/dts/imx51-zii-scu2-mezz.dts [new file with mode: 0644]
arch/arm/boot/dts/imx51-zii-scu3-esb.dts [new file with mode: 0644]
arch/arm/boot/dts/imx51.dtsi
arch/arm/boot/dts/imx53-kp-ddc.dts [new file with mode: 0644]
arch/arm/boot/dts/imx53-kp-hsc.dts [new file with mode: 0644]
arch/arm/boot/dts/imx53-kp.dtsi [new file with mode: 0644]
arch/arm/boot/dts/imx53-ppd.dts
arch/arm/boot/dts/imx53-qsb-common.dtsi
arch/arm/boot/dts/imx53.dtsi
arch/arm/boot/dts/imx6dl-colibri-eval-v3.dts
arch/arm/boot/dts/imx6dl-icore-mipi.dts [new file with mode: 0644]
arch/arm/boot/dts/imx6dl-mamoj.dts
arch/arm/boot/dts/imx6dl-nit6xlite.dts
arch/arm/boot/dts/imx6dl-nitrogen6x.dts
arch/arm/boot/dts/imx6dl-riotboard.dts
arch/arm/boot/dts/imx6dl.dtsi
arch/arm/boot/dts/imx6q-apalis-eval.dts
arch/arm/boot/dts/imx6q-apalis-ixora-v1.1.dts
arch/arm/boot/dts/imx6q-apalis-ixora.dts
arch/arm/boot/dts/imx6q-cm-fx6.dts
arch/arm/boot/dts/imx6q-icore-mipi.dts
arch/arm/boot/dts/imx6q-nitrogen6_max.dts
arch/arm/boot/dts/imx6q-nitrogen6_som2.dts
arch/arm/boot/dts/imx6q-nitrogen6x.dts
arch/arm/boot/dts/imx6q-var-dt6customboard.dts
arch/arm/boot/dts/imx6q.dtsi
arch/arm/boot/dts/imx6qdl-apalis.dtsi
arch/arm/boot/dts/imx6qdl-colibri.dtsi
arch/arm/boot/dts/imx6qdl-icore.dtsi
arch/arm/boot/dts/imx6qdl-nit6xlite.dtsi
arch/arm/boot/dts/imx6qdl-nitrogen6_max.dtsi
arch/arm/boot/dts/imx6qdl-nitrogen6_som2.dtsi
arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi
arch/arm/boot/dts/imx6qdl-sabreauto.dtsi
arch/arm/boot/dts/imx6qdl-sabresd.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-nitrogen6_max.dts
arch/arm/boot/dts/imx6qp-nitrogen6_som2.dts
arch/arm/boot/dts/imx6sl-evk.dts
arch/arm/boot/dts/imx6sl.dtsi
arch/arm/boot/dts/imx6sll-evk.dts [new file with mode: 0644]
arch/arm/boot/dts/imx6sll-pinfunc.h [new file with mode: 0644]
arch/arm/boot/dts/imx6sll.dtsi [new file with mode: 0644]
arch/arm/boot/dts/imx6sx-nitrogen6sx.dts
arch/arm/boot/dts/imx6sx-sdb-reva.dts
arch/arm/boot/dts/imx6sx.dtsi
arch/arm/boot/dts/imx6ul-ccimx6ulsbcexpress.dts [new file with mode: 0644]
arch/arm/boot/dts/imx6ul-ccimx6ulsom.dtsi [new file with mode: 0644]
arch/arm/boot/dts/imx6ul-pico-hobbit.dts
arch/arm/boot/dts/imx6ul.dtsi
arch/arm/boot/dts/imx6ull-colibri-wifi.dtsi
arch/arm/boot/dts/imx6ull.dtsi
arch/arm/boot/dts/imx7d-nitrogen7.dts
arch/arm/boot/dts/imx7d-sdb.dts
arch/arm/boot/dts/imx7d.dtsi
arch/arm/boot/dts/imx7s.dtsi
arch/arm/boot/dts/iwg20d-q7-common.dtsi
arch/arm/boot/dts/iwg20d-q7-dbcm-ca.dtsi
arch/arm/boot/dts/keystone-k2e-netcp.dtsi
arch/arm/boot/dts/keystone-k2g-evm.dts
arch/arm/boot/dts/keystone-k2g-ice.dts
arch/arm/boot/dts/keystone-k2g-netcp.dtsi [new file with mode: 0644]
arch/arm/boot/dts/keystone-k2g.dtsi
arch/arm/boot/dts/keystone-k2hk-netcp.dtsi
arch/arm/boot/dts/keystone-k2l-netcp.dtsi
arch/arm/boot/dts/logicpd-som-lv.dtsi
arch/arm/boot/dts/logicpd-torpedo-37xx-devkit.dts
arch/arm/boot/dts/ls1021a.dtsi
arch/arm/boot/dts/mt7623.dtsi
arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts
arch/arm/boot/dts/mt7623n-rfb-nand.dts [deleted file]
arch/arm/boot/dts/mt7623n-rfb.dtsi [deleted file]
arch/arm/boot/dts/omap3-cm-t3517.dts
arch/arm/boot/dts/omap3-cm-t3730.dts
arch/arm/boot/dts/omap3-evm-common.dtsi
arch/arm/boot/dts/omap3-igep0020-rev-f.dts
arch/arm/boot/dts/omap3-igep0030-rev-g.dts
arch/arm/boot/dts/omap3-zoom3.dts
arch/arm/boot/dts/omap4-droid4-xt894.dts
arch/arm/boot/dts/omap4-duovero-parlor.dts
arch/arm/boot/dts/omap4-duovero.dtsi
arch/arm/boot/dts/omap4-l4.dtsi [new file with mode: 0644]
arch/arm/boot/dts/omap4-panda-common.dtsi
arch/arm/boot/dts/omap4-panda-es.dts
arch/arm/boot/dts/omap4-sdp.dts
arch/arm/boot/dts/omap4-var-som-om44-wlan.dtsi
arch/arm/boot/dts/omap4.dtsi
arch/arm/boot/dts/omap4460.dtsi
arch/arm/boot/dts/omap5-board-common.dtsi
arch/arm/boot/dts/omap5.dtsi
arch/arm/boot/dts/pxa2xx.dtsi
arch/arm/boot/dts/pxa3xx.dtsi
arch/arm/boot/dts/qcom-ipq4019.dtsi
arch/arm/boot/dts/qcom-ipq8064.dtsi
arch/arm/boot/dts/qcom-msm8974-lge-nexus5-hammerhead.dts
arch/arm/boot/dts/r7s72100-genmai.dts
arch/arm/boot/dts/r7s72100-gr-peach.dts
arch/arm/boot/dts/r7s72100-rskrza1.dts
arch/arm/boot/dts/r7s72100.dtsi
arch/arm/boot/dts/r8a73a4-ape6evm.dts
arch/arm/boot/dts/r8a73a4.dtsi
arch/arm/boot/dts/r8a7740-armadillo800eva.dts
arch/arm/boot/dts/r8a7740.dtsi
arch/arm/boot/dts/r8a7743-iwg20d-q7-dbcm-ca.dts
arch/arm/boot/dts/r8a7743-iwg20d-q7.dts
arch/arm/boot/dts/r8a7743-iwg20m.dtsi
arch/arm/boot/dts/r8a7743-sk-rzg1m.dts
arch/arm/boot/dts/r8a7743.dtsi
arch/arm/boot/dts/r8a7745-iwg22d-sodimm-dbhd-ca.dts
arch/arm/boot/dts/r8a7745-iwg22d-sodimm.dts
arch/arm/boot/dts/r8a7745-iwg22m.dtsi
arch/arm/boot/dts/r8a7745-sk-rzg1e.dts
arch/arm/boot/dts/r8a7745.dtsi
arch/arm/boot/dts/r8a77470.dtsi
arch/arm/boot/dts/r8a7778-bockw.dts
arch/arm/boot/dts/r8a7778.dtsi
arch/arm/boot/dts/r8a7779-marzen.dts
arch/arm/boot/dts/r8a7779.dtsi
arch/arm/boot/dts/r8a7790-lager.dts
arch/arm/boot/dts/r8a7790.dtsi
arch/arm/boot/dts/r8a7791-koelsch.dts
arch/arm/boot/dts/r8a7791-porter.dts
arch/arm/boot/dts/r8a7791.dtsi
arch/arm/boot/dts/r8a7792-blanche.dts
arch/arm/boot/dts/r8a7792-wheat.dts
arch/arm/boot/dts/r8a7792.dtsi
arch/arm/boot/dts/r8a7793-gose.dts
arch/arm/boot/dts/r8a7793.dtsi
arch/arm/boot/dts/r8a7794-alt.dts
arch/arm/boot/dts/r8a7794-silk.dts
arch/arm/boot/dts/r8a7794.dtsi
arch/arm/boot/dts/r8a77xx-aa104xd12-panel.dtsi
arch/arm/boot/dts/r8a77xx-aa121td01-panel.dtsi
arch/arm/boot/dts/r9a06g032-rzn1d400-db.dts [new file with mode: 0644]
arch/arm/boot/dts/r9a06g032.dtsi [new file with mode: 0644]
arch/arm/boot/dts/rk3036-evb.dts
arch/arm/boot/dts/rk3036-kylin.dts
arch/arm/boot/dts/rk3036.dtsi
arch/arm/boot/dts/rk3066a-bqcurie2.dts
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/rk3228-evb.dts
arch/arm/boot/dts/rk3229-evb.dts
arch/arm/boot/dts/rk3229.dtsi
arch/arm/boot/dts/rk322x.dtsi
arch/arm/boot/dts/rk3288-evb-act8846.dts
arch/arm/boot/dts/rk3288-evb-rk808.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-popmetal.dts
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.dts
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-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/rk3xxx.dtsi
arch/arm/boot/dts/rv1108-evb.dts
arch/arm/boot/dts/rv1108.dtsi
arch/arm/boot/dts/s5pv210-aries.dtsi [new file with mode: 0644]
arch/arm/boot/dts/s5pv210-fascinate4g.dts [new file with mode: 0644]
arch/arm/boot/dts/s5pv210-galaxys.dts [new file with mode: 0644]
arch/arm/boot/dts/s5pv210-pinctrl.dtsi
arch/arm/boot/dts/sama5d2-pinfunc.h
arch/arm/boot/dts/sama5d3.dtsi
arch/arm/boot/dts/sama5d4.dtsi
arch/arm/boot/dts/sh73a0-kzm9g.dts
arch/arm/boot/dts/sh73a0.dtsi
arch/arm/boot/dts/socfpga_arria10.dtsi
arch/arm/boot/dts/ste-nomadik-stn8815.dtsi
arch/arm/boot/dts/stm32f429.dtsi
arch/arm/boot/dts/stm32f746.dtsi
arch/arm/boot/dts/stm32mp157-pinctrl.dtsi
arch/arm/boot/dts/stm32mp157c-ed1.dts
arch/arm/boot/dts/stm32mp157c-ev1.dts
arch/arm/boot/dts/stm32mp157c.dtsi
arch/arm/boot/dts/sun4i-a10-inet97fv2.dts
arch/arm/boot/dts/sun4i-a10.dtsi
arch/arm/boot/dts/sun5i.dtsi
arch/arm/boot/dts/sun6i-a31.dtsi
arch/arm/boot/dts/sun7i-a20.dtsi
arch/arm/boot/dts/sun8i-a23-a33.dtsi
arch/arm/boot/dts/sun8i-a33.dtsi
arch/arm/boot/dts/sun8i-a83t-allwinner-h8homlet-v2.dts
arch/arm/boot/dts/sun8i-a83t-bananapi-m3.dts
arch/arm/boot/dts/sun8i-a83t-cubietruck-plus.dts
arch/arm/boot/dts/sun8i-a83t.dtsi
arch/arm/boot/dts/sun8i-h2-plus-bananapi-m2-zero.dts
arch/arm/boot/dts/sun8i-h3-beelink-x2.dts
arch/arm/boot/dts/sun8i-h3.dtsi
arch/arm/boot/dts/sun8i-r40-bananapi-m2-ultra.dts
arch/arm/boot/dts/sun8i-r40.dtsi
arch/arm/boot/dts/sunxi-h3-h5.dtsi
arch/arm/boot/dts/sunxi-libretech-all-h3-cc.dtsi
arch/arm/boot/dts/tegra114-dalmore.dts
arch/arm/boot/dts/tegra114-roth.dts
arch/arm/boot/dts/tegra114-tn7.dts
arch/arm/boot/dts/tegra114.dtsi
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/tegra124.dtsi
arch/arm/boot/dts/tegra20-colibri-iris.dts [moved from arch/arm/boot/dts/tegra20-iris-512.dts with 95% similarity]
arch/arm/boot/dts/tegra20-colibri.dtsi [moved from arch/arm/boot/dts/tegra20-colibri-512.dtsi with 96% similarity]
arch/arm/boot/dts/tegra20-harmony.dts
arch/arm/boot/dts/tegra20-paz00.dts
arch/arm/boot/dts/tegra20-seaboard.dts
arch/arm/boot/dts/tegra20-tamonten.dtsi
arch/arm/boot/dts/tegra20-trimslice.dts
arch/arm/boot/dts/tegra20-ventana.dts
arch/arm/boot/dts/tegra20.dtsi
arch/arm/boot/dts/tegra30-apalis.dtsi
arch/arm/boot/dts/tegra30-beaver.dts
arch/arm/boot/dts/tegra30-cardhu.dtsi
arch/arm/boot/dts/tegra30-colibri.dtsi
arch/arm/boot/dts/tegra30.dtsi
arch/arm/boot/dts/uniphier-pxs2.dtsi
arch/arm/boot/dts/vf610-zii-cfu1.dts [new file with mode: 0644]
arch/arm/boot/dts/vf610-zii-ssmb-spu3.dts [new file with mode: 0644]
arch/arm/boot/dts/zynq-cc108.dts
arch/arm/boot/dts/zynq-microzed.dts
arch/arm/boot/dts/zynq-parallella.dts
arch/arm/boot/dts/zynq-zc702.dts
arch/arm/boot/dts/zynq-zc706.dts
arch/arm/boot/dts/zynq-zc770-xm010.dts
arch/arm/boot/dts/zynq-zc770-xm011.dts
arch/arm/boot/dts/zynq-zc770-xm012.dts
arch/arm/boot/dts/zynq-zc770-xm013.dts
arch/arm/boot/dts/zynq-zed.dts
arch/arm/boot/dts/zynq-zturn.dts [new file with mode: 0644]
arch/arm/boot/dts/zynq-zybo-z7.dts
arch/arm/boot/dts/zynq-zybo.dts
arch/arm/configs/aspeed_g4_defconfig
arch/arm/configs/aspeed_g5_defconfig
arch/arm/configs/bcm2835_defconfig
arch/arm/configs/davinci_all_defconfig
arch/arm/configs/exynos_defconfig
arch/arm/configs/imx_v6_v7_defconfig
arch/arm/configs/keystone_defconfig
arch/arm/configs/multi_v5_defconfig
arch/arm/configs/multi_v7_defconfig
arch/arm/configs/mvebu_v7_defconfig
arch/arm/configs/mxs_defconfig
arch/arm/configs/pxa_defconfig
arch/arm/configs/qcom_defconfig
arch/arm/configs/s5pv210_defconfig
arch/arm/configs/shmobile_defconfig
arch/arm/crypto/sha256_glue.c
arch/arm/crypto/sha256_neon_glue.c
arch/arm/firmware/trusted_foundations.c
arch/arm/include/asm/kvm_emulate.h
arch/arm/include/asm/kvm_host.h
arch/arm/include/asm/kvm_mmu.h
arch/arm/include/debug/renesas-scif.S
arch/arm/include/uapi/asm/kvm.h
arch/arm/kernel/asm-offsets.c
arch/arm/kernel/process.c
arch/arm/kvm/coproc.c
arch/arm/kvm/guest.c
arch/arm/mach-at91/pm.c
arch/arm/mach-at91/pm.h
arch/arm/mach-at91/pm_suspend.S
arch/arm/mach-davinci/Kconfig
arch/arm/mach-davinci/Makefile
arch/arm/mach-davinci/aemif.c [deleted file]
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-dm355-leopard.c
arch/arm/mach-davinci/board-dm365-evm.c
arch/arm/mach-davinci/board-dm644x-evm.c
arch/arm/mach-davinci/board-dm646x-evm.c
arch/arm/mach-davinci/board-mityomapl138.c
arch/arm/mach-davinci/board-neuros-osd2.c
arch/arm/mach-davinci/board-omapl138-hawk.c
arch/arm/mach-davinci/board-sffsdr.c
arch/arm/mach-davinci/clock.c [deleted file]
arch/arm/mach-davinci/clock.h
arch/arm/mach-davinci/common.c
arch/arm/mach-davinci/da830.c
arch/arm/mach-davinci/da850.c
arch/arm/mach-davinci/da8xx-dt.c
arch/arm/mach-davinci/davinci.h
arch/arm/mach-davinci/devices-da8xx.c
arch/arm/mach-davinci/devices.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-davinci/include/mach/clock.h
arch/arm/mach-davinci/include/mach/common.h
arch/arm/mach-davinci/include/mach/da8xx.h
arch/arm/mach-davinci/pm_domain.c
arch/arm/mach-davinci/psc.c [deleted file]
arch/arm/mach-davinci/psc.h
arch/arm/mach-davinci/time.c
arch/arm/mach-davinci/usb-da8xx.c
arch/arm/mach-exynos/exynos.c
arch/arm/mach-exynos/suspend.c
arch/arm/mach-hisi/hotplug.c
arch/arm/mach-imx/Kconfig
arch/arm/mach-imx/Makefile
arch/arm/mach-imx/common.h
arch/arm/mach-imx/cpu-imx5.c
arch/arm/mach-imx/cpu.c
arch/arm/mach-imx/cpuidle-imx6sl.c
arch/arm/mach-imx/cpuidle-imx6sx.c
arch/arm/mach-imx/gpc.c
arch/arm/mach-imx/imx31-dt.c
arch/arm/mach-imx/mach-imx51.c
arch/arm/mach-imx/mach-imx53.c
arch/arm/mach-imx/mach-imx6sl.c
arch/arm/mach-imx/mach-imx7d-cm4.c [new file with mode: 0644]
arch/arm/mach-imx/pm-imx6.c
arch/arm/mach-mvebu/platsmp.c
arch/arm/mach-mvebu/pmsu.c
arch/arm/mach-omap1/ams-delta-fiq-handler.S
arch/arm/mach-omap1/ams-delta-fiq.c
arch/arm/mach-omap1/ams-delta-fiq.h [new file with mode: 0644]
arch/arm/mach-omap1/board-ams-delta.c
arch/arm/mach-omap1/board-h2.c
arch/arm/mach-omap1/board-h3.c
arch/arm/mach-omap1/board-htcherald.c
arch/arm/mach-omap1/board-osk.c
arch/arm/mach-omap2/omap_hwmod_reset.c
arch/arm/mach-omap2/pm-asm-offsets.c
arch/arm/mach-omap2/pm-debug.c
arch/arm/mach-omap2/pm33xx-core.c
arch/arm/mach-omap2/sleep33xx.S
arch/arm/mach-omap2/sleep43xx.S
arch/arm/mach-pxa/devices.c
arch/arm/mach-pxa/hx4700.c
arch/arm/mach-pxa/mioa701.c
arch/arm/mach-pxa/zylonite.c
arch/arm/mach-rockchip/Kconfig
arch/arm/mach-s3c24xx/include/mach/s3c2412.h
arch/arm/mach-shmobile/Kconfig
arch/arm/mach-shmobile/Makefile
arch/arm/mach-shmobile/common.h
arch/arm/mach-shmobile/headsmp-apmu.S
arch/arm/mach-shmobile/platsmp-apmu.c
arch/arm/mach-shmobile/platsmp-apmu.h [deleted file]
arch/arm/mach-shmobile/platsmp.c
arch/arm/mach-shmobile/pm-r8a7779.c [deleted file]
arch/arm/mach-shmobile/pm-rcar-gen2.c
arch/arm/mach-shmobile/r8a7779.h
arch/arm/mach-shmobile/r8a7790.h [deleted file]
arch/arm/mach-shmobile/r8a7791.h [deleted file]
arch/arm/mach-shmobile/regulator-quirk-rcar-gen2.c
arch/arm/mach-shmobile/setup-emev2.c
arch/arm/mach-shmobile/setup-r7s72100.c
arch/arm/mach-shmobile/setup-r8a73a4.c
arch/arm/mach-shmobile/setup-r8a7740.c
arch/arm/mach-shmobile/setup-r8a7778.c
arch/arm/mach-shmobile/setup-r8a7779.c
arch/arm/mach-shmobile/setup-r8a7790.c [deleted file]
arch/arm/mach-shmobile/setup-r8a7791.c [deleted file]
arch/arm/mach-shmobile/setup-rcar-gen2.c
arch/arm/mach-shmobile/setup-sh73a0.c
arch/arm/mach-shmobile/smp-emev2.c
arch/arm/mach-shmobile/smp-r8a7779.c
arch/arm/mach-shmobile/smp-r8a7790.c [deleted file]
arch/arm/mach-shmobile/smp-r8a7791.c [deleted file]
arch/arm/mach-shmobile/timer.c
arch/arm/mach-uniphier/Kconfig
arch/arm/mach-uniphier/Makefile [deleted file]
arch/arm/probes/uprobes/core.c
arch/arm64/Kconfig
arch/arm64/Kconfig.platforms
arch/arm64/Makefile
arch/arm64/boot/dts/Makefile
arch/arm64/boot/dts/allwinner/Makefile
arch/arm64/boot/dts/allwinner/sun50i-a64-amarula-relic.dts [new file with mode: 0644]
arch/arm64/boot/dts/allwinner/sun50i-a64-bananapi-m64.dts
arch/arm64/boot/dts/allwinner/sun50i-a64-nanopi-a64.dts
arch/arm64/boot/dts/allwinner/sun50i-a64-olinuxino.dts
arch/arm64/boot/dts/allwinner/sun50i-a64-orangepi-win.dts
arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts
arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts [new file with mode: 0644]
arch/arm64/boot/dts/allwinner/sun50i-a64-sopine-baseboard.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-orangepi-pc2.dts
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-axg-s400.dts
arch/arm64/boot/dts/amlogic/meson-axg.dtsi
arch/arm64/boot/dts/amlogic/meson-gx-p23x-q20x.dtsi
arch/arm64/boot/dts/amlogic/meson-gxbb-nanopi-k2.dts
arch/arm64/boot/dts/amlogic/meson-gxl-s805x-p241.dts [new file with mode: 0644]
arch/arm64/boot/dts/amlogic/meson-gxl-s905d-p230.dts
arch/arm64/boot/dts/amlogic/meson-gxl-s905d-p231.dts
arch/arm64/boot/dts/amlogic/meson-gxl-s905w-p281.dts [new file with mode: 0644]
arch/arm64/boot/dts/amlogic/meson-gxl-s905w-tx3-mini.dts [new file with mode: 0644]
arch/arm64/boot/dts/amlogic/meson-gxm-khadas-vim2.dts
arch/arm64/boot/dts/amlogic/meson-gxm-q200.dts
arch/arm64/boot/dts/amlogic/meson-gxm-q201.dts
arch/arm64/boot/dts/arm/juno-r1.dts
arch/arm64/boot/dts/arm/juno-r2.dts
arch/arm64/boot/dts/arm/juno.dts
arch/arm64/boot/dts/broadcom/stingray/Makefile
arch/arm64/boot/dts/broadcom/stingray/bcm958742-base.dtsi
arch/arm64/boot/dts/broadcom/stingray/bcm958802a802x.dts [new file with mode: 0644]
arch/arm64/boot/dts/broadcom/stingray/stingray-board-base.dtsi [new file with mode: 0644]
arch/arm64/boot/dts/broadcom/stingray/stingray-clock.dtsi
arch/arm64/boot/dts/broadcom/stingray/stingray-pcie.dtsi [new file with mode: 0644]
arch/arm64/boot/dts/broadcom/stingray/stingray.dtsi
arch/arm64/boot/dts/exynos/exynos5433-tmu-g3d-sensor-conf.dtsi [deleted file]
arch/arm64/boot/dts/exynos/exynos5433-tmu-sensor-conf.dtsi [deleted file]
arch/arm64/boot/dts/exynos/exynos5433.dtsi
arch/arm64/boot/dts/exynos/exynos7-tmu-sensor-conf.dtsi [deleted file]
arch/arm64/boot/dts/exynos/exynos7.dtsi
arch/arm64/boot/dts/freescale/fsl-ls1012a-frdm.dts
arch/arm64/boot/dts/freescale/fsl-ls1012a-qds.dts
arch/arm64/boot/dts/freescale/fsl-ls1012a-rdb.dts
arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi
arch/arm64/boot/dts/freescale/fsl-ls1043-post.dtsi
arch/arm64/boot/dts/freescale/fsl-ls1043a-qds.dts
arch/arm64/boot/dts/freescale/fsl-ls1043a-rdb.dts
arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
arch/arm64/boot/dts/freescale/fsl-ls1046-post.dtsi
arch/arm64/boot/dts/freescale/fsl-ls1046a-qds.dts
arch/arm64/boot/dts/freescale/fsl-ls1046a-rdb.dts
arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi
arch/arm64/boot/dts/freescale/fsl-ls1088a-qds.dts
arch/arm64/boot/dts/freescale/fsl-ls1088a-rdb.dts
arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi
arch/arm64/boot/dts/freescale/fsl-ls2080a-qds.dts
arch/arm64/boot/dts/freescale/fsl-ls2080a-rdb.dts
arch/arm64/boot/dts/freescale/fsl-ls2080a-simu.dts
arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi
arch/arm64/boot/dts/freescale/fsl-ls2088a-qds.dts
arch/arm64/boot/dts/freescale/fsl-ls2088a-rdb.dts
arch/arm64/boot/dts/freescale/fsl-ls2088a.dtsi
arch/arm64/boot/dts/freescale/fsl-ls208xa-qds.dtsi
arch/arm64/boot/dts/freescale/fsl-ls208xa-rdb.dtsi
arch/arm64/boot/dts/freescale/fsl-ls208xa.dtsi
arch/arm64/boot/dts/freescale/qoriq-bman-portals.dtsi
arch/arm64/boot/dts/freescale/qoriq-fman3-0-10g-0.dtsi
arch/arm64/boot/dts/freescale/qoriq-fman3-0-10g-1.dtsi
arch/arm64/boot/dts/freescale/qoriq-fman3-0-1g-0.dtsi
arch/arm64/boot/dts/freescale/qoriq-fman3-0-1g-1.dtsi
arch/arm64/boot/dts/freescale/qoriq-fman3-0-1g-2.dtsi
arch/arm64/boot/dts/freescale/qoriq-fman3-0-1g-3.dtsi
arch/arm64/boot/dts/freescale/qoriq-fman3-0-1g-4.dtsi
arch/arm64/boot/dts/freescale/qoriq-fman3-0-1g-5.dtsi
arch/arm64/boot/dts/freescale/qoriq-fman3-0.dtsi
arch/arm64/boot/dts/freescale/qoriq-qman-portals.dtsi
arch/arm64/boot/dts/hisilicon/hi3660-hikey960.dts
arch/arm64/boot/dts/hisilicon/hi3660.dtsi
arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts
arch/arm64/boot/dts/hisilicon/hi6220.dtsi
arch/arm64/boot/dts/marvell/armada-37xx.dtsi
arch/arm64/boot/dts/marvell/armada-8040-mcbin.dts
arch/arm64/boot/dts/marvell/armada-cp110.dtsi
arch/arm64/boot/dts/mediatek/Makefile
arch/arm64/boot/dts/mediatek/mt2712e.dtsi
arch/arm64/boot/dts/mediatek/mt6797-x20-dev.dts [new file with mode: 0644]
arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts
arch/arm64/boot/dts/mediatek/mt7622.dtsi
arch/arm64/boot/dts/mediatek/mt8173.dtsi
arch/arm64/boot/dts/nvidia/tegra194-p2888.dtsi
arch/arm64/boot/dts/nvidia/tegra194.dtsi
arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi
arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi
arch/arm64/boot/dts/qcom/msm8916.dtsi
arch/arm64/boot/dts/qcom/msm8996.dtsi
arch/arm64/boot/dts/qcom/pm8005.dtsi [new file with mode: 0644]
arch/arm64/boot/dts/qcom/pm8998.dtsi [new file with mode: 0644]
arch/arm64/boot/dts/qcom/sdm845-mtp.dts
arch/arm64/boot/dts/qcom/sdm845.dtsi
arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb-kf.dts
arch/arm64/boot/dts/renesas/r8a7795-es1-h3ulcb.dts
arch/arm64/boot/dts/renesas/r8a7795-es1-salvator-x.dts
arch/arm64/boot/dts/renesas/r8a7795-es1.dtsi
arch/arm64/boot/dts/renesas/r8a7795-h3ulcb-kf.dts
arch/arm64/boot/dts/renesas/r8a7795-h3ulcb.dts
arch/arm64/boot/dts/renesas/r8a7795-salvator-x.dts
arch/arm64/boot/dts/renesas/r8a7795-salvator-xs.dts
arch/arm64/boot/dts/renesas/r8a7795.dtsi
arch/arm64/boot/dts/renesas/r8a7796-m3ulcb-kf.dts
arch/arm64/boot/dts/renesas/r8a7796-m3ulcb.dts
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/r8a77970-eagle.dts
arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts
arch/arm64/boot/dts/renesas/r8a77970.dtsi
arch/arm64/boot/dts/renesas/r8a77980-condor.dts
arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts
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/r8a77995.dtsi
arch/arm64/boot/dts/renesas/salvator-common.dtsi
arch/arm64/boot/dts/renesas/salvator-x.dtsi
arch/arm64/boot/dts/renesas/salvator-xs.dtsi
arch/arm64/boot/dts/renesas/ulcb-kf.dtsi
arch/arm64/boot/dts/renesas/ulcb.dtsi
arch/arm64/boot/dts/rockchip/Makefile
arch/arm64/boot/dts/rockchip/rk3328-evb.dts
arch/arm64/boot/dts/rockchip/rk3328-rock64.dts
arch/arm64/boot/dts/rockchip/rk3328.dtsi
arch/arm64/boot/dts/rockchip/rk3368-evb-act8846.dts
arch/arm64/boot/dts/rockchip/rk3368-evb.dtsi
arch/arm64/boot/dts/rockchip/rk3368-geekbox.dts
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 [new file with mode: 0644]
arch/arm64/boot/dts/rockchip/rk3399-firefly.dts
arch/arm64/boot/dts/rockchip/rk3399-gru-bob.dts [new file with mode: 0644]
arch/arm64/boot/dts/rockchip/rk3399-gru-chromebook.dtsi [new file with mode: 0644]
arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts
arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi
arch/arm64/boot/dts/rockchip/rk3399-op1-opp.dtsi
arch/arm64/boot/dts/rockchip/rk3399-opp.dtsi
arch/arm64/boot/dts/rockchip/rk3399-puma-haikou.dts
arch/arm64/boot/dts/rockchip/rk3399-puma.dtsi
arch/arm64/boot/dts/rockchip/rk3399-sapphire-excavator.dts
arch/arm64/boot/dts/rockchip/rk3399-sapphire.dtsi
arch/arm64/boot/dts/rockchip/rk3399.dtsi
arch/arm64/boot/dts/socionext/uniphier-ld11-global.dts
arch/arm64/boot/dts/socionext/uniphier-ld20-global.dts
arch/arm64/boot/dts/socionext/uniphier-ld20.dtsi
arch/arm64/boot/dts/sprd/sc2731.dtsi
arch/arm64/boot/dts/sprd/sc9860.dtsi
arch/arm64/boot/dts/sprd/whale2.dtsi
arch/arm64/boot/dts/ti/Makefile [new file with mode: 0644]
arch/arm64/boot/dts/ti/k3-am65-main.dtsi [new file with mode: 0644]
arch/arm64/boot/dts/ti/k3-am65.dtsi [new file with mode: 0644]
arch/arm64/boot/dts/ti/k3-am654-base-board.dts [new file with mode: 0644]
arch/arm64/boot/dts/ti/k3-am654.dtsi [new file with mode: 0644]
arch/arm64/boot/dts/xilinx/Makefile
arch/arm64/boot/dts/xilinx/avnet-ultra96-rev1.dts [new file with mode: 0644]
arch/arm64/boot/dts/xilinx/zynqmp-ep108-clk.dtsi [deleted file]
arch/arm64/boot/dts/xilinx/zynqmp-ep108.dts [deleted file]
arch/arm64/boot/dts/xilinx/zynqmp-zcu100-revC.dts
arch/arm64/boot/dts/xilinx/zynqmp-zcu102-revA.dts
arch/arm64/boot/dts/xilinx/zynqmp-zcu106-revA.dts
arch/arm64/boot/dts/xilinx/zynqmp-zcu111-revA.dts
arch/arm64/boot/dts/xilinx/zynqmp.dtsi
arch/arm64/configs/defconfig
arch/arm64/include/asm/cpucaps.h
arch/arm64/include/asm/kvm_arm.h
arch/arm64/include/asm/kvm_emulate.h
arch/arm64/include/asm/kvm_host.h
arch/arm64/include/asm/kvm_mmu.h
arch/arm64/include/asm/memory.h
arch/arm64/include/asm/pgtable-prot.h
arch/arm64/include/asm/sysreg.h
arch/arm64/include/asm/tlb.h
arch/arm64/include/uapi/asm/kvm.h
arch/arm64/kernel/cpufeature.c
arch/arm64/kvm/guest.c
arch/arm64/kvm/hyp-init.S
arch/arm64/kvm/hyp/sysreg-sr.c
arch/arm64/kvm/inject_fault.c
arch/arm64/kvm/reset.c
arch/arm64/kvm/sys_regs.c
arch/c6x/Makefile
arch/h8300/Kconfig
arch/h8300/Makefile
arch/h8300/boot/dts/h8300h_sim.dts
arch/h8300/include/asm/bitops.h
arch/h8300/include/asm/ptrace.h
arch/h8300/kernel/kgdb.c
arch/h8300/kernel/setup.c
arch/h8300/kernel/sim-console.c
arch/hexagon/Makefile
arch/ia64/Kconfig
arch/ia64/hp/common/sba_iommu.c
arch/ia64/include/asm/io.h
arch/ia64/kernel/asm-offsets.c
arch/ia64/kernel/fsys.S
arch/ia64/kernel/setup.c
arch/ia64/mm/contig.c
arch/ia64/mm/discontig.c
arch/m68k/Makefile
arch/m68k/coldfire/clk.c
arch/m68k/include/asm/dma.h
arch/microblaze/Kconfig
arch/microblaze/Makefile
arch/microblaze/include/asm/Kbuild
arch/microblaze/include/asm/dma-mapping.h [deleted file]
arch/microblaze/include/asm/pgtable.h
arch/microblaze/kernel/dma.c
arch/microblaze/kernel/head.S
arch/microblaze/mm/consistent.c
arch/microblaze/pci/pci-common.c
arch/microblaze/pci/xilinx_pci.c
arch/mips/Kconfig
arch/mips/Makefile
arch/mips/boot/compressed/Makefile
arch/mips/include/asm/asm-prototypes.h
arch/mips/include/asm/atomic.h
arch/mips/include/asm/compiler.h
arch/mips/include/asm/mmu_context.h
arch/mips/include/asm/tlbex.h
arch/mips/kernel/traps.c
arch/mips/kernel/uprobes.c
arch/mips/lasat/image/Makefile
arch/mips/lib/multi3.c
arch/mips/mm/tlb-funcs.S
arch/mips/mm/tlbex.c
arch/nds32/Makefile
arch/openrisc/Kconfig
arch/openrisc/include/asm/Kbuild
arch/openrisc/include/asm/dma-mapping.h [deleted file]
arch/openrisc/kernel/dma.c
arch/parisc/include/asm/elf.h
arch/parisc/include/asm/linkage.h
arch/parisc/include/asm/processor.h
arch/parisc/include/asm/traps.h
arch/parisc/include/asm/unwind.h
arch/parisc/kernel/entry.S
arch/parisc/kernel/processor.c
arch/parisc/kernel/stacktrace.c
arch/parisc/kernel/sys_parisc.c
arch/parisc/kernel/syscall.S
arch/parisc/kernel/traps.c
arch/parisc/kernel/unwind.c
arch/powerpc/Kconfig
arch/powerpc/Makefile
arch/powerpc/include/asm/book3s/64/pgtable.h
arch/powerpc/include/asm/nohash/pgtable.h
arch/powerpc/include/asm/opal.h
arch/powerpc/include/asm/topology.h
arch/powerpc/kernel/fadump.c
arch/powerpc/kernel/idle_power4.S
arch/powerpc/kernel/smp.c
arch/powerpc/kernel/traps.c
arch/powerpc/kvm/book3s_hv.c
arch/powerpc/kvm/book3s_pr.c
arch/powerpc/kvm/book3s_xive.c
arch/powerpc/mm/mmu_context_book3s64.c
arch/powerpc/mm/mmu_context_iommu.c
arch/powerpc/mm/numa.c
arch/powerpc/mm/pgtable-radix.c
arch/powerpc/mm/slb.c
arch/powerpc/platforms/powermac/low_i2c.c
arch/powerpc/platforms/powernv/opal.c
arch/powerpc/platforms/powernv/pci-ioda.c
arch/powerpc/platforms/powernv/vas-window.c
arch/powerpc/sysdev/xive/common.c
arch/riscv/Makefile
arch/riscv/include/asm/Kbuild
arch/riscv/include/asm/compat.h [deleted file]
arch/riscv/include/asm/unistd.h
arch/riscv/include/asm/vdso.h
arch/riscv/include/uapi/asm/syscalls.h
arch/riscv/kernel/sys_riscv.c
arch/s390/Kconfig
arch/s390/Makefile
arch/s390/include/asm/ap.h
arch/s390/include/asm/ftrace.h
arch/s390/include/uapi/asm/zcrypt.h
arch/s390/kernel/asm-offsets.c
arch/s390/kernel/crash_dump.c
arch/s390/kernel/ebcdic.c
arch/s390/kernel/ftrace.c
arch/s390/kernel/mcount.S
arch/s390/kernel/perf_cpum_sf.c
arch/s390/pci/pci.c
arch/s390/pci/pci_debug.c
arch/sh/Makefile
arch/sparc/Kconfig
arch/sparc/Makefile
arch/sparc/include/asm/dma-mapping.h
arch/sparc/kernel/ioport.c
arch/sparc/kernel/sys_sparc_32.c
arch/sparc/kernel/sys_sparc_64.c
arch/sparc/mm/init_32.c
arch/um/Makefile
arch/x86/Kconfig
arch/x86/Makefile
arch/x86/Makefile.um
arch/x86/boot/compressed/Makefile
arch/x86/boot/compressed/kaslr.c
arch/x86/entry/vdso/Makefile
arch/x86/hyperv/mmu.c
arch/x86/include/asm/Kbuild
arch/x86/include/asm/export.h [deleted file]
arch/x86/include/asm/irq_remapping.h
arch/x86/include/asm/mce.h
arch/x86/include/asm/paravirt.h
arch/x86/include/asm/paravirt_types.h
arch/x86/include/asm/processor.h
arch/x86/include/asm/set_memory.h
arch/x86/include/asm/tlbflush.h
arch/x86/include/asm/vmx.h
arch/x86/include/asm/xen/hypercall.h
arch/x86/kernel/acpi/cstate.c
arch/x86/kernel/cpu/bugs.c
arch/x86/kernel/cpu/mcheck/mce-internal.h
arch/x86/kernel/cpu/mcheck/mce.c
arch/x86/kernel/kvm.c
arch/x86/kernel/paravirt.c
arch/x86/kernel/pci-dma.c
arch/x86/kernel/process_64.c
arch/x86/kvm/svm.c
arch/x86/kvm/vmx.c
arch/x86/kvm/x86.c
arch/x86/mm/cpu_entry_area.c
arch/x86/mm/init.c
arch/x86/mm/mmap.c
arch/x86/mm/pat.c
arch/x86/mm/pgtable.c
arch/x86/mm/tlb.c
arch/x86/xen/enlighten_pv.c
arch/x86/xen/mmu_pv.c
arch/x86/xen/setup.c
arch/x86/xen/xen-ops.h
arch/xtensa/Kconfig
arch/xtensa/Makefile
arch/xtensa/boot/boot-elf/Makefile
arch/xtensa/boot/boot-elf/bootstrap.S
arch/xtensa/configs/nommu_kc705_defconfig
arch/xtensa/include/asm/Kbuild
arch/xtensa/include/asm/cacheasm.h
arch/xtensa/include/asm/dma-mapping.h [deleted file]
arch/xtensa/include/asm/initialize_mmu.h
arch/xtensa/include/asm/irq.h
arch/xtensa/include/asm/kmem_layout.h
arch/xtensa/include/asm/page.h
arch/xtensa/include/asm/pgtable.h
arch/xtensa/include/asm/platform.h
arch/xtensa/include/asm/processor.h
arch/xtensa/include/asm/vectors.h
arch/xtensa/kernel/head.S
arch/xtensa/kernel/irq.c
arch/xtensa/kernel/pci-dma.c
arch/xtensa/kernel/setup.c
arch/xtensa/kernel/vmlinux.lds.S
arch/xtensa/platforms/iss/include/platform/hardware.h [deleted file]
arch/xtensa/platforms/xt2000/include/platform/hardware.h
arch/xtensa/platforms/xtfpga/include/platform/hardware.h
arch/xtensa/variants/test_kc705_be/include/variant/core.h [new file with mode: 0644]
arch/xtensa/variants/test_kc705_be/include/variant/tie-asm.h [new file with mode: 0644]
arch/xtensa/variants/test_kc705_be/include/variant/tie.h [new file with mode: 0644]
block/bfq-cgroup.c
block/bfq-iosched.c
block/bfq-wf2q.c
block/blk-core.c
block/blk-mq-sched.c
block/blk-mq-sched.h
block/blk-mq-tag.c
block/blk-mq.c
block/blk-sysfs.c
block/blk-wbt.c
block/blk.h
block/elevator.c
certs/system_certificates.S
drivers/acpi/Kconfig
drivers/acpi/acpica/aclocal.h
drivers/acpi/acpica/acnamesp.h
drivers/acpi/acpica/acutils.h
drivers/acpi/acpica/dbinput.c
drivers/acpi/acpica/dbmethod.c
drivers/acpi/acpica/dbxface.c
drivers/acpi/acpica/dsfield.c
drivers/acpi/acpica/hwregs.c
drivers/acpi/acpica/hwsleep.c
drivers/acpi/acpica/nsaccess.c
drivers/acpi/acpica/psloop.c
drivers/acpi/acpica/tbdata.c
drivers/acpi/acpica/utdelete.c
drivers/acpi/acpica/utstrsuppt.c
drivers/acpi/acpica/utstrtoul64.c
drivers/acpi/nfit/core.c
drivers/acpi/nfit/nfit.h
drivers/acpi/pmic/intel_pmic_crc.c
drivers/acpi/processor_core.c
drivers/ata/ahci.c
drivers/ata/ahci.h
drivers/ata/ahci_brcm.c
drivers/ata/ahci_ceva.c
drivers/ata/ahci_da850.c
drivers/ata/ahci_dm816.c
drivers/ata/ahci_imx.c
drivers/ata/ahci_mtk.c
drivers/ata/ahci_mvebu.c
drivers/ata/ahci_platform.c
drivers/ata/ahci_qoriq.c
drivers/ata/ahci_seattle.c
drivers/ata/ahci_st.c
drivers/ata/ahci_sunxi.c
drivers/ata/ahci_tegra.c
drivers/ata/ahci_xgene.c
drivers/ata/libahci.c
drivers/ata/libahci_platform.c
drivers/ata/libata-core.c
drivers/ata/libata-scsi.c
drivers/ata/libata-sff.c
drivers/ata/pata_cmd640.c
drivers/ata/pata_icside.c
drivers/ata/pata_imx.c
drivers/ata/pata_legacy.c
drivers/ata/pata_palmld.c
drivers/ata/pata_pcmcia.c
drivers/ata/pata_platform.c
drivers/ata/pata_via.c
drivers/ata/sata_rcar.c
drivers/block/DAC960.c
drivers/block/mtip32xx/mtip32xx.c
drivers/block/pktcdvd.c
drivers/block/rbd.c
drivers/block/rsxx/core.c
drivers/block/zram/zram_drv.c
drivers/bus/Kconfig
drivers/bus/Makefile
drivers/bus/sun50i-de2.c [new file with mode: 0644]
drivers/bus/ti-sysc.c
drivers/char/rtc.c
drivers/clk/davinci/psc-da830.c
drivers/clk/davinci/psc-da850.c
drivers/clk/davinci/psc-dm365.c
drivers/clk/davinci/psc-dm644x.c
drivers/clk/davinci/psc-dm646x.c
drivers/clk/samsung/Makefile
drivers/clk/samsung/clk-exynos5440.c [deleted file]
drivers/clk/ti/clk-7xx.c
drivers/cpufreq/Kconfig.arm
drivers/cpufreq/Makefile
drivers/cpufreq/cpufreq_governor.c
drivers/cpufreq/exynos5440-cpufreq.c [deleted file]
drivers/cpuidle/governors/menu.c
drivers/crypto/caam/sg_sw_qm2.h
drivers/crypto/caam/sg_sw_sec4.h
drivers/crypto/vmx/ghashp8-ppc.pl
drivers/dax/device.c
drivers/dax/pmem.c
drivers/dax/super.c
drivers/dma/dmaengine.c
drivers/edac/edac_mc.c
drivers/firmware/arm_scmi/perf.c
drivers/firmware/efi/efi-bgrt.c
drivers/firmware/efi/libstub/Makefile
drivers/firmware/psci_checker.c
drivers/firmware/raspberrypi.c
drivers/gpio/Kconfig
drivers/gpio/Makefile
drivers/gpio/gpio-madera.c [new file with mode: 0644]
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c
drivers/gpu/drm/amd/amdgpu/amdgpu_sched.c
drivers/gpu/drm/amd/amdgpu/vega20_reg_init.c
drivers/gpu/drm/amd/amdgpu/vi.c
drivers/gpu/drm/amd/display/Kconfig
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
drivers/gpu/drm/amd/display/dc/Makefile
drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c
drivers/gpu/drm/amd/display/dc/calcs/Makefile
drivers/gpu/drm/amd/display/dc/core/dc.c
drivers/gpu/drm/amd/display/dc/core/dc_debug.c
drivers/gpu/drm/amd/display/dc/core/dc_link.c
drivers/gpu/drm/amd/display/dc/core/dc_resource.c
drivers/gpu/drm/amd/display/dc/dc.h
drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c
drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h
drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c
drivers/gpu/drm/amd/display/dc/dce/dce_clocks.h
drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c
drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c
drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
drivers/gpu/drm/amd/display/dc/gpio/Makefile
drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c
drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c
drivers/gpu/drm/amd/display/dc/i2caux/Makefile
drivers/gpu/drm/amd/display/dc/i2caux/i2caux.c
drivers/gpu/drm/amd/display/dc/inc/core_types.h
drivers/gpu/drm/amd/display/dc/irq/Makefile
drivers/gpu/drm/amd/display/dc/irq/irq_service.c
drivers/gpu/drm/amd/display/dc/os_types.h
drivers/gpu/drm/amd/powerplay/hwmgr/hardwaremanager.c
drivers/gpu/drm/drm_edid.c
drivers/gpu/drm/gma500/framebuffer.c
drivers/gpu/drm/gma500/gem.c
drivers/gpu/drm/gma500/psb_drv.h
drivers/gpu/drm/i915/Kconfig
drivers/gpu/drm/i915/i915_gem_userptr.c
drivers/gpu/drm/i915/i915_utils.h
drivers/gpu/drm/i915/intel_display.h
drivers/gpu/drm/i915/intel_drv.h
drivers/gpu/drm/i915/intel_hdmi.c
drivers/gpu/drm/panel/panel-simple.c
drivers/gpu/drm/radeon/radeon_mn.c
drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c
drivers/hid/Kconfig
drivers/hid/Makefile
drivers/hid/hid-core.c
drivers/hid/hid-cougar.c [new file with mode: 0644]
drivers/hid/hid-elan.c
drivers/hid/hid-ids.h
drivers/hid/hid-input.c
drivers/hid/hid-microsoft.c
drivers/hid/hid-multitouch.c
drivers/hid/hid-ntrig.c
drivers/hid/hid-redragon.c
drivers/hid/hid-sony.c
drivers/hid/hid-wiimote-core.c
drivers/hid/hid-wiimote-modules.c
drivers/hid/hid-wiimote.h
drivers/hid/i2c-hid/i2c-hid.c
drivers/hid/intel-ish-hid/ipc/ipc.c
drivers/hid/intel-ish-hid/ipc/pci-ish.c
drivers/hid/intel-ish-hid/ishtp/hbm.c
drivers/hid/usbhid/hid-core.c
drivers/hid/wacom_sys.c
drivers/hid/wacom_wac.c
drivers/hwmon/Kconfig
drivers/hwmon/Makefile
drivers/hwmon/raspberrypi-hwmon.c [new file with mode: 0644]
drivers/hwtracing/intel_th/msu.c
drivers/i2c/Makefile
drivers/i2c/busses/Kconfig
drivers/i2c/busses/Makefile
drivers/i2c/busses/i2c-amd8111.c
drivers/i2c/busses/i2c-aspeed.c
drivers/i2c/busses/i2c-brcmstb.c
drivers/i2c/busses/i2c-davinci.c
drivers/i2c/busses/i2c-designware-baytrail.c
drivers/i2c/busses/i2c-designware-common.c
drivers/i2c/busses/i2c-designware-core.h
drivers/i2c/busses/i2c-designware-master.c
drivers/i2c/busses/i2c-designware-pcidrv.c
drivers/i2c/busses/i2c-designware-platdrv.c
drivers/i2c/busses/i2c-designware-slave.c
drivers/i2c/busses/i2c-emev2.c
drivers/i2c/busses/i2c-exynos5.c
drivers/i2c/busses/i2c-fsi.c [new file with mode: 0644]
drivers/i2c/busses/i2c-gpio.c
drivers/i2c/busses/i2c-highlander.c
drivers/i2c/busses/i2c-i801.c
drivers/i2c/busses/i2c-imx.c
drivers/i2c/busses/i2c-mxs.c
drivers/i2c/busses/i2c-ocores.c
drivers/i2c/busses/i2c-owl.c [new file with mode: 0644]
drivers/i2c/busses/i2c-pasemi.c
drivers/i2c/busses/i2c-pmcmsp.c
drivers/i2c/busses/i2c-qcom-geni.c [new file with mode: 0644]
drivers/i2c/busses/i2c-rcar.c
drivers/i2c/busses/i2c-riic.c
drivers/i2c/busses/i2c-s3c2410.c
drivers/i2c/busses/i2c-sh_mobile.c
drivers/i2c/busses/i2c-sprd.c
drivers/i2c/busses/i2c-stu300.c
drivers/i2c/busses/i2c-tegra.c
drivers/i2c/busses/i2c-xlr.c
drivers/i2c/i2c-core-acpi.c
drivers/i2c/i2c-core-base.c
drivers/i2c/i2c-core-slave.c
drivers/i2c/i2c-mux.c
drivers/i2c/muxes/i2c-mux-mlxcpld.c
drivers/i2c/muxes/i2c-mux-pca9541.c
drivers/i2c/muxes/i2c-mux-pca954x.c
drivers/ide/hpt366.c
drivers/ide/ide-floppy.c
drivers/ide/ide-io.c
drivers/ide/ide-probe.c
drivers/ide/ide-tape.c
drivers/ide/ide-taskfile.c
drivers/ide/sis5513.c
drivers/iio/dac/ltc2632.c
drivers/iio/temperature/mlx90614.c
drivers/infiniband/Kconfig
drivers/infiniband/core/umem_odp.c
drivers/infiniband/hw/hfi1/affinity.c
drivers/infiniband/hw/hfi1/mmu_rb.c
drivers/infiniband/hw/mlx5/odp.c
drivers/input/keyboard/Kconfig
drivers/input/serio/ams_delta_serio.c
drivers/input/touchscreen/rohm_bu21023.c
drivers/iommu/Kconfig
drivers/iommu/Makefile
drivers/iommu/amd_iommu.c
drivers/iommu/amd_iommu_debugfs.c [new file with mode: 0644]
drivers/iommu/amd_iommu_init.c
drivers/iommu/amd_iommu_proto.h
drivers/iommu/amd_iommu_types.h
drivers/iommu/arm-smmu-v3.c
drivers/iommu/arm-smmu.c
drivers/iommu/dmar.c
drivers/iommu/exynos-iommu.c
drivers/iommu/intel-iommu.c
drivers/iommu/intel-pasid.c [new file with mode: 0644]
drivers/iommu/intel-pasid.h [new file with mode: 0644]
drivers/iommu/intel-svm.c
drivers/iommu/io-pgtable-arm-v7s.c
drivers/iommu/io-pgtable-arm.c
drivers/iommu/iommu-debugfs.c [new file with mode: 0644]
drivers/iommu/iommu.c
drivers/iommu/ipmmu-vmsa.c
drivers/iommu/msm_iommu.c
drivers/iommu/mtk_iommu.c
drivers/iommu/mtk_iommu_v1.c
drivers/iommu/omap-iommu.c
drivers/iommu/qcom_iommu.c
drivers/iommu/rockchip-iommu.c
drivers/iommu/tegra-gart.c
drivers/iommu/tegra-smmu.c
drivers/irqchip/irq-bcm7038-l1.c
drivers/irqchip/irq-gic-v3.c
drivers/irqchip/irq-renesas-h8s.c
drivers/irqchip/irq-s3c24xx.c
drivers/irqchip/irq-stm32-exti.c
drivers/irqchip/irq-tango.c
drivers/irqchip/irq-xtensa-mx.c
drivers/irqchip/irq-xtensa-pic.c
drivers/macintosh/therm_windtunnel.c
drivers/md/bcache/Kconfig
drivers/md/bcache/alloc.c
drivers/md/bcache/bcache.h
drivers/md/bcache/bset.c
drivers/md/bcache/bset.h
drivers/md/bcache/btree.c
drivers/md/bcache/btree.h
drivers/md/bcache/closure.c
drivers/md/bcache/closure.h
drivers/md/bcache/debug.c
drivers/md/bcache/debug.h
drivers/md/bcache/extents.c
drivers/md/bcache/extents.h
drivers/md/bcache/io.c
drivers/md/bcache/journal.c
drivers/md/bcache/journal.h
drivers/md/bcache/movinggc.c
drivers/md/bcache/request.c
drivers/md/bcache/request.h
drivers/md/bcache/stats.c
drivers/md/bcache/stats.h
drivers/md/bcache/super.c
drivers/md/bcache/sysfs.c
drivers/md/bcache/sysfs.h
drivers/md/bcache/util.c
drivers/md/bcache/util.h
drivers/md/bcache/writeback.c
drivers/md/bcache/writeback.h
drivers/md/dm-writecache.c
drivers/media/cec/cec-notifier.c
drivers/media/dvb-frontends/af9013.c
drivers/media/dvb-frontends/drxk_hard.c
drivers/media/dvb-frontends/rtl2830.c
drivers/media/dvb-frontends/tda1004x.c
drivers/media/media-device.c
drivers/media/platform/Kconfig
drivers/media/platform/Makefile
drivers/media/platform/cros-ec-cec/Makefile [new file with mode: 0644]
drivers/media/platform/cros-ec-cec/cros-ec-cec.c [new file with mode: 0644]
drivers/media/tuners/tda18271-common.c
drivers/memory/tegra/mc.c
drivers/memory/ti-emif-pm.c
drivers/mfd/88pm860x-i2c.c
drivers/mfd/Kconfig
drivers/mfd/Makefile
drivers/mfd/arizona-core.c
drivers/mfd/as3722.c
drivers/mfd/axp20x-i2c.c
drivers/mfd/axp20x.c
drivers/mfd/cros_ec_dev.c
drivers/mfd/cs47l35-tables.c [new file with mode: 0644]
drivers/mfd/cs47l85-tables.c [new file with mode: 0644]
drivers/mfd/cs47l90-tables.c [new file with mode: 0644]
drivers/mfd/da9063-core.c
drivers/mfd/da9063-i2c.c
drivers/mfd/da9063-irq.c
drivers/mfd/dln2.c
drivers/mfd/hi655x-pmic.c
drivers/mfd/intel-lpss-pci.c
drivers/mfd/kempld-core.c
drivers/mfd/madera-core.c [new file with mode: 0644]
drivers/mfd/madera-i2c.c [new file with mode: 0644]
drivers/mfd/madera-spi.c [new file with mode: 0644]
drivers/mfd/madera.h [new file with mode: 0644]
drivers/mfd/rave-sp.c
drivers/mfd/rohm-bd718x7.c [new file with mode: 0644]
drivers/mfd/sec-core.c
drivers/mfd/sm501.c
drivers/mfd/ti_am335x_tscadc.c
drivers/mfd/wm8994-core.c
drivers/misc/cb710/core.c
drivers/misc/eeprom/at24.c
drivers/misc/mic/scif/scif_dma.c
drivers/misc/sgi-gru/grutlbpurge.c
drivers/mtd/ubi/cdev.c
drivers/mtd/ubi/kapi.c
drivers/mtd/ubi/ubi-media.h
drivers/mtd/ubi/ubi.h
drivers/mtd/ubi/vmt.c
drivers/mtd/ubi/vtbl.c
drivers/net/ethernet/smsc/smc911x.c
drivers/net/ethernet/smsc/smc91x.c
drivers/net/ethernet/smsc/smc91x.h
drivers/net/tun.c
drivers/nvdimm/bus.c
drivers/nvdimm/dimm.c
drivers/nvdimm/dimm_devs.c
drivers/nvdimm/namespace_devs.c
drivers/nvdimm/nd-core.h
drivers/nvdimm/nd.h
drivers/nvdimm/pmem.c
drivers/nvdimm/pmem.h
drivers/nvdimm/region_devs.c
drivers/pci/pci-acpi.c
drivers/pci/quirks.c
drivers/pinctrl/Kconfig
drivers/pinctrl/Makefile
drivers/pinctrl/cirrus/Kconfig [new file with mode: 0644]
drivers/pinctrl/cirrus/Makefile [new file with mode: 0644]
drivers/pinctrl/cirrus/pinctrl-cs47l35.c [new file with mode: 0644]
drivers/pinctrl/cirrus/pinctrl-cs47l85.c [new file with mode: 0644]
drivers/pinctrl/cirrus/pinctrl-cs47l90.c [new file with mode: 0644]
drivers/pinctrl/cirrus/pinctrl-madera-core.c [new file with mode: 0644]
drivers/pinctrl/cirrus/pinctrl-madera.h [new file with mode: 0644]
drivers/platform/chrome/Kconfig
drivers/platform/chrome/Makefile
drivers/platform/chrome/chromeos_tbmc.c
drivers/platform/chrome/cros_ec_i2c.c [moved from drivers/mfd/cros_ec_i2c.c with 100% similarity]
drivers/platform/chrome/cros_ec_proto.c
drivers/platform/chrome/cros_ec_spi.c [moved from drivers/mfd/cros_ec_spi.c with 100% similarity]
drivers/platform/mellanox/Kconfig
drivers/platform/mellanox/Makefile
drivers/platform/mellanox/mlxreg-hotplug.c
drivers/platform/mellanox/mlxreg-io.c [new file with mode: 0644]
drivers/platform/x86/Kconfig
drivers/platform/x86/Makefile
drivers/platform/x86/acer-wmi.c
drivers/platform/x86/asus-nb-wmi.c
drivers/platform/x86/asus-wireless.c
drivers/platform/x86/asus-wmi.c
drivers/platform/x86/dell-smbios-base.c
drivers/platform/x86/dell-smbios-smm.c
drivers/platform/x86/dell-smbios-wmi.c
drivers/platform/x86/ideapad-laptop.c
drivers/platform/x86/intel-hid.c
drivers/platform/x86/intel-vbtn.c
drivers/platform/x86/intel_ips.c
drivers/platform/x86/intel_pmc_core.c
drivers/platform/x86/intel_pmc_core.h
drivers/platform/x86/intel_punit_ipc.c
drivers/platform/x86/mlx-platform.c
drivers/platform/x86/thinkpad_acpi.c
drivers/platform/x86/toshiba_acpi.c
drivers/platform/x86/touchscreen_dmi.c [moved from drivers/platform/x86/silead_dmi.c with 70% similarity]
drivers/platform/x86/wmi.c
drivers/power/reset/Kconfig
drivers/power/reset/Makefile
drivers/power/reset/gemini-poweroff.c
drivers/power/reset/ltc2952-poweroff.c
drivers/power/reset/qcom-pon.c [new file with mode: 0644]
drivers/power/reset/vexpress-poweroff.c
drivers/power/reset/zx-reboot.c
drivers/power/supply/Kconfig
drivers/power/supply/Makefile
drivers/power/supply/ab8500_fg.c
drivers/power/supply/adp5061.c [new file with mode: 0644]
drivers/power/supply/axp20x_usb_power.c
drivers/power/supply/axp288_charger.c
drivers/power/supply/bq27xxx_battery.c
drivers/power/supply/cros_usbpd-charger.c [new file with mode: 0644]
drivers/power/supply/ds2760_battery.c
drivers/power/supply/generic-adc-battery.c
drivers/power/supply/lego_ev3_battery.c
drivers/power/supply/max1721x_battery.c
drivers/power/supply/max77693_charger.c
drivers/power/supply/power_supply_core.c
drivers/power/supply/sbs-battery.c
drivers/power/supply/tps65217_charger.c
drivers/power/supply/wm8350_power.c
drivers/pwm/Kconfig
drivers/pwm/pwm-berlin.c
drivers/pwm/pwm-cros-ec.c
drivers/pwm/pwm-fsl-ftm.c
drivers/pwm/pwm-imx.c
drivers/pwm/pwm-mediatek.c
drivers/pwm/pwm-meson.c
drivers/pwm/pwm-mxs.c
drivers/pwm/pwm-omap-dmtimer.c
drivers/pwm/pwm-stm32-lp.c
drivers/pwm/pwm-tiehrpwm.c
drivers/rapidio/devices/rio_mport_cdev.c
drivers/regulator/da9063-regulator.c
drivers/reset/Kconfig
drivers/reset/Makefile
drivers/reset/reset-imx7.c
drivers/reset/reset-meson-audio-arb.c [new file with mode: 0644]
drivers/reset/reset-qcom-aoss.c [new file with mode: 0644]
drivers/reset/reset-simple.c
drivers/reset/reset-uniphier-usb3.c [new file with mode: 0644]
drivers/reset/reset-uniphier.c
drivers/rtc/Kconfig
drivers/rtc/class.c
drivers/rtc/interface.c
drivers/rtc/rtc-armada38x.c
drivers/rtc/rtc-bq4802.c
drivers/rtc/rtc-core.h
drivers/rtc/rtc-dev.c
drivers/rtc/rtc-ds1307.c
drivers/rtc/rtc-ds1685.c
drivers/rtc/rtc-isl1208.c
drivers/rtc/rtc-m48t59.c
drivers/rtc/rtc-max77686.c
drivers/rtc/rtc-max8997.c
drivers/rtc/rtc-max8998.c
drivers/rtc/rtc-omap.c
drivers/rtc/rtc-pcf2127.c
drivers/rtc/rtc-pcf85063.c
drivers/rtc/rtc-s5m.c
drivers/rtc/rtc-sa1100.c
drivers/rtc/rtc-sh.c
drivers/rtc/rtc-snvs.c
drivers/rtc/rtc-stmp3xxx.c
drivers/rtc/rtc-sysfs.c
drivers/rtc/rtc-test.c
drivers/s390/block/dcssblk.c
drivers/s390/crypto/ap_bus.c
drivers/s390/crypto/ap_bus.h
drivers/s390/crypto/ap_card.c
drivers/s390/crypto/ap_queue.c
drivers/s390/crypto/pkey_api.c
drivers/s390/crypto/zcrypt_api.c
drivers/s390/crypto/zcrypt_api.h
drivers/s390/crypto/zcrypt_card.c
drivers/s390/crypto/zcrypt_cca_key.h
drivers/s390/crypto/zcrypt_cex2a.c
drivers/s390/crypto/zcrypt_cex2a.h
drivers/s390/crypto/zcrypt_cex4.c
drivers/s390/crypto/zcrypt_error.h
drivers/s390/crypto/zcrypt_msgtype50.c
drivers/s390/crypto/zcrypt_msgtype50.h
drivers/s390/crypto/zcrypt_msgtype6.c
drivers/s390/crypto/zcrypt_msgtype6.h
drivers/s390/crypto/zcrypt_pcixcc.c
drivers/s390/crypto/zcrypt_pcixcc.h
drivers/s390/crypto/zcrypt_queue.c
drivers/scsi/osd/osd_uld.c
drivers/scsi/sd.c
drivers/soc/bcm/brcmstb/pm/pm-arm.c
drivers/soc/fsl/Kconfig
drivers/soc/fsl/Makefile
drivers/soc/fsl/dpio/Makefile [moved from drivers/staging/fsl-mc/bus/dpio/Makefile with 100% similarity]
drivers/soc/fsl/dpio/dpio-cmd.h [moved from drivers/staging/fsl-mc/bus/dpio/dpio-cmd.h with 100% similarity]
drivers/soc/fsl/dpio/dpio-driver.c [moved from drivers/staging/fsl-mc/bus/dpio/dpio-driver.c with 99% similarity]
drivers/soc/fsl/dpio/dpio-service.c [moved from drivers/staging/fsl-mc/bus/dpio/dpio-service.c with 99% similarity]
drivers/soc/fsl/dpio/dpio.c [moved from drivers/staging/fsl-mc/bus/dpio/dpio.c with 100% similarity]
drivers/soc/fsl/dpio/dpio.h [moved from drivers/staging/fsl-mc/bus/dpio/dpio.h with 100% similarity]
drivers/soc/fsl/dpio/qbman-portal.c [moved from drivers/staging/fsl-mc/bus/dpio/qbman-portal.c with 99% similarity]
drivers/soc/fsl/dpio/qbman-portal.h [moved from drivers/staging/fsl-mc/bus/dpio/qbman-portal.h with 99% similarity]
drivers/soc/fsl/qbman/Kconfig
drivers/soc/fsl/qe/Kconfig
drivers/soc/fsl/qe/gpio.c
drivers/soc/imx/gpc.c
drivers/soc/mediatek/mtk-pmic-wrap.c
drivers/soc/renesas/Makefile
drivers/soc/renesas/r9a06g032-smp.c [new file with mode: 0644]
drivers/soc/renesas/rcar-sysc.c
drivers/soc/sunxi/sunxi_sram.c
drivers/soc/ti/Kconfig
drivers/soc/ti/pm33xx.c
drivers/soc/ti/wkup_m3_ipc.c
drivers/staging/Kconfig
drivers/staging/Makefile
drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.c
drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.h
drivers/staging/fsl-mc/Kconfig [deleted file]
drivers/staging/fsl-mc/Makefile [deleted file]
drivers/staging/fsl-mc/bus/Kconfig [deleted file]
drivers/staging/fsl-mc/bus/Makefile [deleted file]
drivers/target/iscsi/iscsi_target.c
drivers/target/iscsi/iscsi_target.h
drivers/target/iscsi/iscsi_target_login.c
drivers/tee/optee/Kconfig
drivers/tee/optee/core.c
drivers/tee/optee/rpc.c
drivers/thermal/Kconfig
drivers/thermal/intel_powerclamp.c
drivers/thermal/intel_soc_dts_thermal.c
drivers/tty/hvc/hvc_opal.c
drivers/tty/sysrq.c
drivers/tty/tty_io.c
drivers/usb/host/ehci-exynos.c
drivers/usb/host/ohci-exynos.c
drivers/vhost/Kconfig
drivers/vhost/scsi.c
drivers/video/backlight/adp8860_bl.c
drivers/video/backlight/pwm_bl.c
drivers/video/console/Kconfig
drivers/video/console/dummycon.c
drivers/video/console/vgacon.c
drivers/video/fbdev/amifb.c
drivers/video/fbdev/core/fbcon.c
drivers/video/fbdev/core/fbmem.c
drivers/video/fbdev/core/modedb.c
drivers/video/fbdev/efifb.c
drivers/video/fbdev/fsl-diu-fb.c
drivers/video/fbdev/goldfishfb.c
drivers/video/fbdev/i740fb.c
drivers/video/fbdev/metronomefb.c
drivers/video/fbdev/omap/omapfb_main.c
drivers/video/fbdev/omap2/omapfb/Makefile
drivers/video/fbdev/omap2/omapfb/displays/encoder-tpd12s015.c
drivers/video/fbdev/omap2/omapfb/dss/dispc.c
drivers/video/fbdev/omap2/omapfb/omapfb-main.c
drivers/video/fbdev/pm2fb.c
drivers/video/fbdev/pxa3xx-gcu.c
drivers/video/fbdev/pxafb.c
drivers/video/fbdev/pxafb.h
drivers/video/fbdev/simplefb.c
drivers/video/fbdev/tdfxfb.c
drivers/video/fbdev/tridentfb.c
drivers/video/fbdev/udlfb.c
drivers/video/fbdev/via/lcd.c
drivers/video/fbdev/via/viafbdev.c
drivers/virtio/virtio_balloon.c
drivers/virtio/virtio_mmio.c
drivers/virtio/virtio_pci_legacy.c
drivers/w1/slaves/Kconfig
drivers/w1/slaves/Makefile
drivers/w1/slaves/w1_ds2760.c [deleted file]
drivers/w1/slaves/w1_ds2760.h [deleted file]
drivers/w1/w1.c
drivers/watchdog/kempld_wdt.c
drivers/xen/gntdev.c
drivers/xen/mcelog.c
drivers/xen/xen-acpi-processor.c
fs/adfs/inode.c
fs/afs/internal.h
fs/afs/write.c
fs/autofs/autofs_i.h
fs/autofs/expire.c
fs/autofs/inode.c
fs/autofs/root.c
fs/btrfs/ctree.h
fs/btrfs/ioctl.c
fs/ceph/acl.c
fs/ceph/addr.c
fs/ceph/cache.c
fs/ceph/caps.c
fs/ceph/dir.c
fs/ceph/file.c
fs/ceph/inode.c
fs/ceph/mds_client.c
fs/ceph/mds_client.h
fs/ceph/quota.c
fs/ceph/snap.c
fs/ceph/super.c
fs/ceph/super.h
fs/ceph/xattr.c
fs/cifs/cifsfs.h
fs/cifs/sess.c
fs/cifs/smb2misc.c
fs/cifs/smb2ops.c
fs/cifs/smb2pdu.c
fs/cifs/smb2pdu.h
fs/dax.c
fs/devpts/inode.c
fs/eventpoll.c
fs/exec.c
fs/f2fs/checkpoint.c
fs/f2fs/data.c
fs/f2fs/debug.c
fs/f2fs/dir.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/node.h
fs/f2fs/recovery.c
fs/f2fs/segment.c
fs/f2fs/segment.h
fs/f2fs/super.c
fs/f2fs/sysfs.c
fs/f2fs/xattr.c
fs/fat/cache.c
fs/fat/dir.c
fs/fat/fat.h
fs/fat/fatent.c
fs/fat/file.c
fs/fat/inode.c
fs/fat/misc.c
fs/fat/namei_msdos.c
fs/fat/namei_vfat.c
fs/fcntl.c
fs/file_table.c
fs/fuse/dev.c
fs/fuse/dir.c
fs/fuse/file.c
fs/fuse/fuse_i.h
fs/fuse/inode.c
fs/hfs/brec.c
fs/hfsplus/Kconfig
fs/hfsplus/Makefile
fs/hfsplus/acl.h [deleted file]
fs/hfsplus/brec.c
fs/hfsplus/dir.c
fs/hfsplus/extents.c
fs/hfsplus/hfsplus_fs.h
fs/hfsplus/inode.c
fs/hfsplus/posix_acl.c [deleted file]
fs/hfsplus/super.c
fs/hfsplus/unicode.c
fs/hfsplus/xattr.c
fs/hfsplus/xattr.h
fs/hfsplus/xattr_security.c
fs/hpfs/namei.c
fs/hugetlbfs/inode.c
fs/inode.c
fs/internal.h
fs/ioctl.c
fs/iomap.c
fs/lockd/clntlock.c
fs/lockd/clntproc.c
fs/lockd/svclock.c
fs/lockd/svcsubs.c
fs/locks.c
fs/namei.c
fs/namespace.c
fs/nfs/blocklayout/blocklayout.c
fs/nfs/blocklayout/dev.c
fs/nfs/callback.h
fs/nfs/callback_proc.c
fs/nfs/callback_xdr.c
fs/nfs/client.c
fs/nfs/dir.c
fs/nfs/direct.c
fs/nfs/file.c
fs/nfs/flexfilelayout/flexfilelayout.c
fs/nfs/nfs3acl.c
fs/nfs/nfs42proc.c
fs/nfs/nfs42xdr.c
fs/nfs/nfs4_fs.h
fs/nfs/nfs4client.c
fs/nfs/nfs4file.c
fs/nfs/nfs4idmap.c
fs/nfs/nfs4proc.c
fs/nfs/nfs4state.c
fs/nfs/nfs4xdr.c
fs/nfs/pagelist.c
fs/nfs/pnfs.c
fs/nfs/pnfs.h
fs/nfs/pnfs_nfs.c
fs/nfs/super.c
fs/nfs/write.c
fs/nfsd/netns.h
fs/nfsd/nfs3proc.c
fs/nfsd/nfs4callback.c
fs/nfsd/nfs4layouts.c
fs/nfsd/nfs4proc.c
fs/nfsd/nfs4state.c
fs/nfsd/nfs4xdr.c
fs/nfsd/nfsctl.c
fs/nfsd/nfsd.h
fs/nfsd/nfsfh.c
fs/nfsd/nfsproc.c
fs/nfsd/state.h
fs/nilfs2/file.c
fs/nilfs2/super.c
fs/notify/dnotify/dnotify.c
fs/notify/fanotify/fanotify.c
fs/ocfs2/file.c
fs/open.c
fs/overlayfs/Kconfig
fs/overlayfs/Makefile
fs/overlayfs/copy_up.c
fs/overlayfs/dir.c
fs/overlayfs/export.c
fs/overlayfs/file.c [new file with mode: 0644]
fs/overlayfs/inode.c
fs/overlayfs/namei.c
fs/overlayfs/overlayfs.h
fs/overlayfs/ovl_entry.h
fs/overlayfs/readdir.c
fs/overlayfs/super.c
fs/overlayfs/util.c
fs/proc/Kconfig
fs/proc/base.c
fs/proc/generic.c
fs/proc/inode.c
fs/proc/internal.h
fs/proc/kcore.c
fs/proc/meminfo.c
fs/proc/stat.c
fs/proc/task_mmu.c
fs/proc/task_nommu.c
fs/proc/uptime.c
fs/proc/vmcore.c
fs/read_write.c
fs/reiserfs/item_ops.c
fs/reiserfs/journal.c
fs/reiserfs/procfs.c
fs/reiserfs/reiserfs.h
fs/reiserfs/xattr.c
fs/super.c
fs/sysv/inode.c
fs/tracefs/inode.c
fs/ubifs/Kconfig
fs/ubifs/Makefile
fs/ubifs/budget.c
fs/ubifs/commit.c
fs/ubifs/crypto.c
fs/ubifs/debug.c
fs/ubifs/debug.h
fs/ubifs/dir.c
fs/ubifs/file.c
fs/ubifs/find.c
fs/ubifs/gc.c
fs/ubifs/io.c
fs/ubifs/journal.c
fs/ubifs/key.h
fs/ubifs/log.c
fs/ubifs/lprops.c
fs/ubifs/lpt.c
fs/ubifs/lpt_commit.c
fs/ubifs/master.c
fs/ubifs/misc.c
fs/ubifs/misc.h
fs/ubifs/orphan.c
fs/ubifs/recovery.c
fs/ubifs/replay.c
fs/ubifs/sb.c
fs/ubifs/scan.c
fs/ubifs/shrinker.c
fs/ubifs/super.c
fs/ubifs/tnc.c
fs/ubifs/tnc_commit.c
fs/ubifs/tnc_misc.c
fs/ubifs/ubifs.h
fs/ubifs/xattr.c
fs/userfaultfd.c
fs/xattr.c
fs/xfs/scrub/repair.c
fs/xfs/xfs_file.c
fs/xfs/xfs_mount.c
include/acpi/acconfig.h
include/acpi/acexcep.h
include/acpi/acpixf.h
include/asm-generic/bug.h
include/asm-generic/export.h
include/asm-generic/tlb.h
include/asm-generic/vmlinux.lds.h
include/dt-bindings/bus/ti-sysc.h
include/dt-bindings/clock/dra7.h
include/dt-bindings/clock/exynos5440.h [deleted file]
include/dt-bindings/memory/mt2712-larb-port.h [new file with mode: 0644]
include/dt-bindings/reset/amlogic,meson-axg-audio-arb.h [new file with mode: 0644]
include/dt-bindings/reset/qcom,sdm845-aoss.h [new file with mode: 0644]
include/kvm/arm_vgic.h
include/linux/ahci_platform.h
include/linux/backing-dev-defs.h
include/linux/backing-dev.h
include/linux/backlight.h
include/linux/bitops.h
include/linux/ceph/auth.h
include/linux/ceph/ceph_features.h
include/linux/ceph/decode.h
include/linux/ceph/messenger.h
include/linux/ceph/msgr.h
include/linux/ceph/osd_client.h
include/linux/ceph/pagelist.h
include/linux/clk/at91_pmc.h
include/linux/compiler-clang.h
include/linux/compiler-gcc.h
include/linux/compiler-intel.h
include/linux/compiler.h
include/linux/compiler_types.h
include/linux/console.h
include/linux/cpuhotplug.h
include/linux/crash_core.h
include/linux/crc64.h [new file with mode: 0644]
include/linux/dax.h
include/linux/dcache.h
include/linux/dmar.h
include/linux/export.h
include/linux/f2fs_fs.h
include/linux/fb.h
include/linux/fs.h
include/linux/fsnotify.h
include/linux/ftrace.h
include/linux/gfp.h
include/linux/hid.h
include/linux/huge_mm.h
include/linux/hugetlb.h
include/linux/i2c.h
include/linux/idr.h
include/linux/init.h
include/linux/init_task.h
include/linux/intel-iommu.h
include/linux/iommu.h
include/linux/ipc_namespace.h
include/linux/irqchip/arm-gic-v3.h
include/linux/irqchip/arm-gic.h
include/linux/irqflags.h
include/linux/kcore.h
include/linux/kernel.h
include/linux/kvm_host.h
include/linux/libata.h
include/linux/lockd/lockd.h
include/linux/lockdep.h
include/linux/memcontrol.h
include/linux/memory_hotplug.h
include/linux/mfd/as3722.h
include/linux/mfd/cros_ec.h
include/linux/mfd/cros_ec_commands.h
include/linux/mfd/da9063/core.h
include/linux/mfd/madera/core.h [new file with mode: 0644]
include/linux/mfd/madera/pdata.h [new file with mode: 0644]
include/linux/mfd/madera/registers.h [new file with mode: 0644]
include/linux/mfd/rave-sp.h
include/linux/mfd/rohm-bd718x7.h [new file with mode: 0644]
include/linux/mfd/syscon/imx6q-iomuxc-gpr.h
include/linux/mfd/wm8994/pdata.h
include/linux/mm.h
include/linux/mmu_notifier.h
include/linux/mmzone.h
include/linux/net_dim.h
include/linux/nfs4.h
include/linux/nfs_fs.h
include/linux/nfs_fs_sb.h
include/linux/nfs_xdr.h
include/linux/nodemask.h
include/linux/oom.h
include/linux/page-flags.h
include/linux/pci.h
include/linux/percpu.h
include/linux/pid.h
include/linux/platform_data/ams-delta-fiq.h [moved from arch/arm/mach-omap1/include/mach/ams-delta-fiq.h with 68% similarity]
include/linux/platform_data/i2c-hid.h
include/linux/platform_data/i2c-ocores.h
include/linux/platform_data/mtd-davinci-aemif.h
include/linux/platform_data/pm33xx.h
include/linux/platform_data/sh_ipmmu.h [deleted file]
include/linux/platform_data/ti-sysc.h
include/linux/power_supply.h
include/linux/preempt.h
include/linux/proc_fs.h
include/linux/ptrace.h
include/linux/ring_buffer.h
include/linux/rtc.h
include/linux/sched.h
include/linux/sched/signal.h
include/linux/sched/sysctl.h
include/linux/sched/user.h
include/linux/set_memory.h
include/linux/shrinker.h
include/linux/signal.h
include/linux/soc/renesas/rcar-sysc.h
include/linux/srcu.h
include/linux/sunrpc/auth.h
include/linux/sunrpc/clnt.h
include/linux/sunrpc/metrics.h
include/linux/sunrpc/svc.h
include/linux/sunrpc/svcauth.h
include/linux/swap.h
include/linux/swapops.h
include/linux/time32.h
include/linux/tracepoint.h
include/linux/uprobes.h
include/linux/userfaultfd_k.h
include/linux/w1.h
include/linux/wkup_m3_ipc.h
include/media/cec-notifier.h
include/net/scm.h
include/rdma/ib_cache.h
include/rdma/ib_umem_odp.h
include/soc/bcm2835/raspberrypi-firmware.h
include/soc/fsl/dpaa2-fd.h [moved from drivers/staging/fsl-mc/include/dpaa2-fd.h with 97% similarity]
include/soc/fsl/dpaa2-global.h [moved from drivers/staging/fsl-mc/include/dpaa2-global.h with 100% similarity]
include/soc/fsl/dpaa2-io.h [moved from drivers/staging/fsl-mc/include/dpaa2-io.h with 100% similarity]
include/trace/events/cgroup.h
include/trace/events/preemptirq.h
include/uapi/linux/auto_fs.h
include/uapi/linux/bcache.h
include/uapi/linux/input.h
include/uapi/linux/kvm.h
include/uapi/mtd/ubi-user.h
include/video/udlfb.h
init/Kconfig
init/do_mounts.c
init/do_mounts_initrd.c
init/do_mounts_md.c
init/do_mounts_rd.c
init/init_task.c
init/initramfs.c
init/main.c
ipc/msg.c
ipc/namespace.c
ipc/sem.c
ipc/shm.c
ipc/util.c
ipc/util.h
kernel/cgroup/cgroup-internal.h
kernel/cgroup/cgroup-v1.c
kernel/cgroup/cgroup.c
kernel/crash_core.c
kernel/events/callchain.c
kernel/events/core.c
kernel/events/uprobes.c
kernel/exit.c
kernel/fork.c
kernel/futex.c
kernel/hung_task.c
kernel/kallsyms.c
kernel/livepatch/core.c
kernel/livepatch/transition.c
kernel/locking/lockdep.c
kernel/memremap.c
kernel/module.c
kernel/pid.c
kernel/power/Kconfig
kernel/printk/printk.c
kernel/sched/core.c
kernel/sched/idle.c
kernel/sched/wait.c
kernel/signal.c
kernel/sys.c
kernel/sysctl.c
kernel/time/itimer.c
kernel/time/posix-cpu-timers.c
kernel/time/posix-timers.c
kernel/trace/Kconfig
kernel/trace/Makefile
kernel/trace/blktrace.c
kernel/trace/bpf_trace.c
kernel/trace/ftrace.c
kernel/trace/preemptirq_delay_test.c [new file with mode: 0644]
kernel/trace/ring_buffer.c
kernel/trace/ring_buffer_benchmark.c
kernel/trace/trace.c
kernel/trace/trace.h
kernel/trace/trace_benchmark.h
kernel/trace/trace_clock.c
kernel/trace/trace_entries.h
kernel/trace/trace_event_perf.c
kernel/trace/trace_events.c
kernel/trace/trace_events_filter.c
kernel/trace/trace_events_filter_test.h
kernel/trace/trace_events_hist.c
kernel/trace/trace_events_trigger.c
kernel/trace/trace_hwlat.c
kernel/trace/trace_irqsoff.c
kernel/trace/trace_kprobe.c
kernel/trace/trace_kprobe_selftest.c [new file with mode: 0644]
kernel/trace/trace_kprobe_selftest.h [new file with mode: 0644]
kernel/trace/trace_output.c
kernel/trace/trace_output.h
kernel/trace/trace_preemptirq.c [new file with mode: 0644]
kernel/trace/trace_printk.c
kernel/trace/trace_probe.c
kernel/trace/trace_probe.h
kernel/trace/trace_seq.c
kernel/trace/trace_stat.h
kernel/trace/trace_uprobe.c
kernel/trace/tracing_map.c
kernel/trace/tracing_map.h
kernel/tracepoint.c
kernel/user.c
kernel/user_namespace.c
kernel/utsname_sysctl.c
kernel/workqueue.c
lib/.gitignore
lib/Kconfig
lib/Kconfig.debug
lib/Makefile
lib/bitmap.c
lib/crc64.c [new file with mode: 0644]
lib/fonts/font_7x14.c
lib/fonts/font_8x16.c
lib/fonts/font_8x8.c
lib/fonts/font_pearl_8x8.c
lib/gen_crc64table.c [new file with mode: 0644]
lib/idr.c
lib/radix-tree.c
lib/rhashtable.c
lib/test_debug_virtual.c
lib/test_hexdump.c
lib/test_ida.c [new file with mode: 0644]
mm/Kconfig.debug
mm/backing-dev.c
mm/gup.c
mm/hmm.c
mm/huge_memory.c
mm/hugetlb.c
mm/internal.h
mm/khugepaged.c
mm/ksm.c
mm/madvise.c
mm/memcontrol.c
mm/memory-failure.c
mm/memory.c
mm/memory_hotplug.c
mm/mempolicy.c
mm/mempool.c
mm/migrate.c
mm/mm_init.c
mm/mmap.c
mm/mmu_notifier.c
mm/oom_kill.c
mm/page_alloc.c
mm/percpu.c
mm/shmem.c
mm/swap_slots.c
mm/swapfile.c
mm/util.c
mm/vmscan.c
net/ceph/Kconfig
net/ceph/Makefile
net/ceph/auth.c
net/ceph/auth_none.c
net/ceph/auth_none.h
net/ceph/auth_x.c
net/ceph/auth_x.h
net/ceph/auth_x_protocol.h
net/ceph/ceph_common.c
net/ceph/cls_lock_client.c
net/ceph/crush/mapper.c
net/ceph/messenger.c
net/ceph/mon_client.c
net/ceph/osd_client.c
net/ceph/pagevec.c
net/core/net_namespace.c
net/netfilter/ipvs/Kconfig
net/netfilter/ipvs/ip_vs_mh.c
net/smc/smc_ib.c
net/sunrpc/auth.c
net/sunrpc/auth_gss/auth_gss.c
net/sunrpc/auth_gss/gss_generic_token.c
net/sunrpc/auth_gss/gss_krb5_crypto.c
net/sunrpc/auth_gss/gss_krb5_keys.c
net/sunrpc/auth_gss/gss_krb5_seal.c
net/sunrpc/auth_gss/gss_krb5_unseal.c
net/sunrpc/auth_gss/gss_krb5_wrap.c
net/sunrpc/auth_gss/gss_rpc_upcall.c
net/sunrpc/auth_gss/svcauth_gss.c
net/sunrpc/auth_null.c
net/sunrpc/auth_unix.c
net/sunrpc/backchannel_rqst.c
net/sunrpc/clnt.c
net/sunrpc/rpcb_clnt.c
net/sunrpc/stats.c
net/sunrpc/sunrpc.h
net/sunrpc/svc.c
net/sunrpc/xprt.c
net/sunrpc/xprtrdma/svc_rdma.c
net/sunrpc/xprtrdma/svc_rdma_recvfrom.c
net/sunrpc/xprtrdma/svc_rdma_rw.c
net/sunrpc/xprtrdma/svc_rdma_sendto.c
net/sunrpc/xprtrdma/svc_rdma_transport.c
net/sunrpc/xprtrdma/verbs.c
net/sunrpc/xprtsock.c
scripts/Kbuild.include
scripts/Makefile.build
scripts/Makefile.lib
scripts/Makefile.modpost
scripts/checkpatch.pl
scripts/clang-version.sh
scripts/coccinelle/api/alloc/zalloc-simple.cocci
scripts/dtc/Makefile
scripts/gcc-plugins/Kconfig
scripts/get_maintainer.pl
scripts/kconfig/Makefile
scripts/kconfig/conf.c
scripts/kconfig/symbol.c
scripts/kconfig/tests/err_recursive_dep/Kconfig [moved from scripts/kconfig/tests/warn_recursive_dep/Kconfig with 93% similarity]
scripts/kconfig/tests/err_recursive_dep/__init__.py [new file with mode: 0644]
scripts/kconfig/tests/err_recursive_dep/expected_stderr [new file with mode: 0644]
scripts/kconfig/tests/warn_recursive_dep/__init__.py [deleted file]
scripts/kconfig/tests/warn_recursive_dep/expected_stderr [deleted file]
scripts/link-vmlinux.sh
scripts/mod/modpost.c
scripts/spelling.txt
security/apparmor/apparmorfs.c
security/apparmor/domain.c
security/apparmor/file.c
security/apparmor/include/perms.h
security/apparmor/lib.c
security/apparmor/policy_ns.c
security/apparmor/policy_unpack.c
security/commoncap.c
security/security.c
sound/ac97/bus.c
sound/ac97/snd_ac97_compat.c
sound/core/seq/seq_virmidi.c
sound/pci/hda/patch_realtek.c
sound/soc/intel/common/sst-dsp-priv.h
tools/arch/x86/include/asm/cpufeatures.h
tools/arch/x86/lib/memcpy_64.S
tools/include/linux/bitmap.h
tools/lib/lockdep/Makefile
tools/lib/traceevent/Makefile
tools/lib/traceevent/event-parse.c
tools/lib/traceevent/event-parse.h
tools/lib/traceevent/event-plugin.c
tools/lib/traceevent/event-utils.h
tools/lib/traceevent/kbuffer-parse.c
tools/lib/traceevent/parse-filter.c
tools/lib/traceevent/parse-utils.c
tools/lib/traceevent/plugin_cfg80211.c
tools/lib/traceevent/plugin_function.c
tools/lib/traceevent/plugin_hrtimer.c
tools/lib/traceevent/plugin_jbd2.c
tools/lib/traceevent/plugin_kmem.c
tools/lib/traceevent/plugin_kvm.c
tools/lib/traceevent/plugin_mac80211.c
tools/lib/traceevent/plugin_sched_switch.c
tools/lib/traceevent/plugin_scsi.c
tools/lib/traceevent/plugin_xen.c
tools/lib/traceevent/trace-seq.c
tools/perf/Documentation/perf-annotate.txt
tools/perf/Documentation/perf-report.txt
tools/perf/Makefile
tools/perf/arch/arm64/util/arm-spe.c
tools/perf/arch/powerpc/util/sym-handling.c
tools/perf/arch/s390/util/auxtrace.c
tools/perf/arch/x86/Makefile
tools/perf/builtin-annotate.c
tools/perf/builtin-kmem.c
tools/perf/builtin-report.c
tools/perf/builtin-script.c
tools/perf/builtin-trace.c
tools/perf/check-headers.sh
tools/perf/examples/bpf/augmented_syscalls.c [new file with mode: 0644]
tools/perf/examples/bpf/hello.c [new file with mode: 0644]
tools/perf/examples/bpf/sys_enter_openat.c [new file with mode: 0644]
tools/perf/include/bpf/bpf.h
tools/perf/include/bpf/stdio.h [new file with mode: 0644]
tools/perf/pmu-events/arch/arm64/ampere/emag/core-imp-def.json [new file with mode: 0644]
tools/perf/pmu-events/arch/arm64/mapfile.csv
tools/perf/tests/bitmap.c
tools/perf/tests/code-reading.c
tools/perf/tests/kmod-path.c
tools/perf/tests/mem2node.c
tools/perf/ui/browsers/annotate.c
tools/perf/util/Build
tools/perf/util/annotate.c
tools/perf/util/annotate.h
tools/perf/util/auxtrace.c
tools/perf/util/auxtrace.h
tools/perf/util/bpf-loader.c
tools/perf/util/bpf-loader.h
tools/perf/util/compress.h
tools/perf/util/data-convert-bt.c
tools/perf/util/dso.c
tools/perf/util/dso.h
tools/perf/util/event.c
tools/perf/util/evlist.c
tools/perf/util/evsel.c
tools/perf/util/evsel.h
tools/perf/util/header.c
tools/perf/util/llvm-utils.c
tools/perf/util/llvm-utils.h
tools/perf/util/lzma.c
tools/perf/util/machine.c
tools/perf/util/machine.h
tools/perf/util/map.c
tools/perf/util/map.h
tools/perf/util/mmap.c
tools/perf/util/mmap.h
tools/perf/util/namespaces.c
tools/perf/util/parse-events.c
tools/perf/util/python.c
tools/perf/util/s390-cpumsf-kernel.h [new file with mode: 0644]
tools/perf/util/s390-cpumsf.c [new file with mode: 0644]
tools/perf/util/s390-cpumsf.h [new file with mode: 0644]
tools/perf/util/scripting-engines/trace-event-perl.c
tools/perf/util/scripting-engines/trace-event-python.c
tools/perf/util/setup.py
tools/perf/util/sort.c
tools/perf/util/sort.h
tools/perf/util/trace-event-parse.c
tools/perf/util/trace-event-read.c
tools/perf/util/trace-event-scripting.c
tools/perf/util/trace-event.c
tools/perf/util/trace-event.h
tools/perf/util/zlib.c
tools/power/cpupower/po/de.po
tools/power/cpupower/po/fr.po
tools/testing/nvdimm/pmem-dax.c
tools/testing/nvdimm/test/nfit.c
tools/testing/radix-tree/Makefile
tools/testing/radix-tree/idr-test.c
tools/testing/radix-tree/linux/xarray.h [new file with mode: 0644]
tools/testing/radix-tree/main.c
tools/testing/radix-tree/test.h
tools/testing/selftests/android/ion/ionapp_export.c
tools/testing/selftests/cgroup/.gitignore [new file with mode: 0644]
tools/testing/selftests/cgroup/Makefile
tools/testing/selftests/cgroup/cgroup_util.c
tools/testing/selftests/cgroup/cgroup_util.h
tools/testing/selftests/cgroup/test_core.c [new file with mode: 0644]
tools/testing/selftests/ftrace/config
tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args_string.tc
tools/testing/selftests/ftrace/test.d/kprobe/probepoint.tc
tools/testing/selftests/ftrace/test.d/preemptirq/irqsoff_tracer.tc [new file with mode: 0644]
tools/testing/selftests/kvm/Makefile
tools/testing/selftests/kvm/cr4_cpuid_sync_test.c
tools/testing/selftests/kvm/dirty_log_test.c [new file with mode: 0644]
tools/testing/selftests/kvm/include/kvm_util.h
tools/testing/selftests/kvm/include/test_util.h
tools/testing/selftests/kvm/lib/kvm_util.c
tools/testing/selftests/kvm/lib/x86.c
tools/testing/selftests/kvm/set_sregs_test.c
tools/testing/selftests/kvm/state_test.c
tools/testing/selftests/kvm/sync_regs_test.c
tools/testing/selftests/kvm/vmx_tsc_adjust_test.c
tools/testing/selftests/mount/config
tools/testing/selftests/proc/.gitignore
tools/testing/selftests/proc/Makefile
tools/testing/selftests/proc/proc.h
tools/testing/selftests/proc/self.c [new file with mode: 0644]
tools/testing/selftests/proc/thread-self.c [new file with mode: 0644]
tools/testing/selftests/vDSO/Makefile
tools/testing/selftests/vDSO/vdso_test.c
tools/testing/selftests/vm/.gitignore
tools/testing/selftests/vm/Makefile
tools/testing/selftests/vm/map_populate.c [new file with mode: 0644]
tools/testing/selftests/vm/run_vmtests
usr/Makefile
usr/gen_initramfs_list.sh [moved from scripts/gen_initramfs_list.sh with 99% similarity]
usr/initramfs_data.S
virt/kvm/arm/arch_timer.c
virt/kvm/arm/arm.c
virt/kvm/arm/mmu.c
virt/kvm/arm/vgic/vgic-debug.c
virt/kvm/arm/vgic/vgic-init.c
virt/kvm/arm/vgic/vgic-its.c
virt/kvm/arm/vgic/vgic-mmio-v2.c
virt/kvm/arm/vgic/vgic-mmio-v3.c
virt/kvm/arm/vgic/vgic-mmio.c
virt/kvm/arm/vgic/vgic-mmio.h
virt/kvm/arm/vgic/vgic-v2.c
virt/kvm/arm/vgic/vgic-v3.c
virt/kvm/arm/vgic/vgic.c
virt/kvm/arm/vgic/vgic.h
virt/kvm/kvm_main.c

index 2a6f685..285e096 100644 (file)
--- a/.mailmap
+++ b/.mailmap
@@ -159,6 +159,7 @@ Ralf Wildenhues <Ralf.Wildenhues@gmx.de>
 Randy Dunlap <rdunlap@infradead.org> <rdunlap@xenotime.net>
 Rémi Denis-Courmont <rdenis@simphalempin.com>
 Ricardo Ribalda Delgado <ricardo.ribalda@gmail.com>
+Ross Zwisler <zwisler@kernel.org> <ross.zwisler@linux.intel.com>
 Rudolf Marek <R.Marek@sh.cvut.cz>
 Rui Saraiva <rmps@joel.ist.utl.pt>
 Sachin P Sant <ssant@in.ibm.com>
diff --git a/Documentation/ABI/stable/sysfs-driver-mlxreg-io b/Documentation/ABI/stable/sysfs-driver-mlxreg-io
new file mode 100644 (file)
index 0000000..d9d117d
--- /dev/null
@@ -0,0 +1,78 @@
+What:          /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/
+                                                       asic_health
+
+Date:          June 2018
+KernelVersion: 4.19
+Contact:       Vadim Pasternak <vadimpmellanox.com>
+Description:   This file shows ASIC health status. The possible values are:
+               0 - health failed, 2 - health OK, 3 - ASIC in booting state.
+
+               The files are read only.
+
+What:          /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/
+                                                       cpld1_version
+                                                       cpld2_version
+
+Date:          June 2018
+KernelVersion: 4.19
+Contact:       Vadim Pasternak <vadimpmellanox.com>
+Description:   These files show with which CPLD versions have been burned
+               on carrier and switch boards.
+
+               The files are read only.
+
+What:          /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/select_iio
+Date:          June 2018
+KernelVersion: 4.19
+Contact:       Vadim Pasternak <vadimpmellanox.com>
+Description:   This file allows iio devices selection.
+
+               Attribute select_iio can be written with 0 or with 1. It
+               selects which one of iio devices can be accessed.
+
+               The file is read/write.
+
+What:          /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/psu1_on
+               /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/psu2_on
+               /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/pwr_cycle
+               /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/pwr_down
+Date:          June 2018
+KernelVersion: 4.19
+Contact:       Vadim Pasternak <vadimpmellanox.com>
+Description:   These files allow asserting system power cycling, switching
+               power supply units on and off and system's main power domain
+               shutdown.
+               Expected behavior:
+               When pwr_cycle is written 1: auxiliary power domain will go
+               down and after short period (about 1 second) up.
+               When  psu1_on or psu2_on is written 1, related unit will be
+               disconnected from the power source, when written 0 - connected.
+               If both are written 1 - power supplies main power domain will
+               go down.
+               When pwr_down is written 1, system's main power domain will go
+               down.
+
+               The files are write only.
+
+What:          /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/
+                                                       reset_aux_pwr_or_ref
+                                                       reset_asic_thermal
+                                                       reset_hotswap_or_halt
+                                                       reset_hotswap_or_wd
+                                                       reset_fw_reset
+                                                       reset_long_pb
+                                                       reset_main_pwr_fail
+                                                       reset_short_pb
+                                                       reset_sw_reset
+Date:          June 2018
+KernelVersion: 4.19
+Contact:       Vadim Pasternak <vadimpmellanox.com>
+Description:   These files show the system reset cause, as following: power
+               auxiliary outage or power refresh, ASIC thermal shutdown, halt,
+               hotswap, watchdog, firmware reset, long press power button,
+               short press power button, software reset. Value 1 in file means
+               this is reset cause, 0 - otherwise. Only one of the above
+               causes could be 1 at the same time, representing only last
+               reset cause.
+
+               The files are read only.
index 9b01233..94a24ae 100644 (file)
@@ -51,6 +51,14 @@ Description:
                 Controls the dirty page count condition for the in-place-update
                 policies.
 
+What:          /sys/fs/f2fs/<disk>/min_seq_blocks
+Date:          August 2018
+Contact:       "Jaegeuk Kim" <jaegeuk@kernel.org>
+Description:
+                Controls the dirty page count condition for batched sequential
+                writes in ->writepages.
+
+
 What:          /sys/fs/f2fs/<disk>/min_hot_blocks
 Date:          March 2017
 Contact:       "Jaegeuk Kim" <jaegeuk@kernel.org>
index 1746131..184193b 100644 (file)
@@ -1072,6 +1072,24 @@ PAGE_SIZE multiple when read back.
        high limit is used and monitored properly, this limit's
        utility is limited to providing the final safety net.
 
+  memory.oom.group
+       A read-write single value file which exists on non-root
+       cgroups.  The default value is "0".
+
+       Determines whether the cgroup should be treated as
+       an indivisible workload by the OOM killer. If set,
+       all tasks belonging to the cgroup or to its descendants
+       (if the memory cgroup is not a leaf cgroup) are killed
+       together or not at all. This can be used to avoid
+       partial kills to guarantee workload integrity.
+
+       Tasks with the OOM protection (oom_score_adj set to -1000)
+       are treated as an exception and are never killed.
+
+       If the OOM killer is invoked in a cgroup, it's not going
+       to kill any tasks outside of this cgroup, regardless
+       memory.oom.group values of ancestor cgroups.
+
   memory.events
        A read-only flat-keyed file which exists on non-root cgroups.
        The following entries are defined.  Unless specified
index bffb0ca..9871e64 100644 (file)
                merge
                nomerge
                soft
-               pt              [x86, IA-64]
+               pt              [x86]
+               nopt            [x86]
                nobypass        [PPC/POWERNV]
                        Disable IOMMU bypass, using IOMMU for PCI devices.
 
                        on: enable the feature
 
        page_poison=    [KNL] Boot-time parameter changing the state of
-                       poisoning on the buddy allocator.
-                       off: turn off poisoning
+                       poisoning on the buddy allocator, available with
+                       CONFIG_PAGE_POISONING=y.
+                       off: turn off poisoning (default)
                        on: turn on poisoning
 
        panic=          [KNL] Kernel behaviour on panic: delay <timeout>
index b5379fb..26b735c 100644 (file)
@@ -27,6 +27,7 @@ Core utilities
    errseq
    printk-formats
    circular-buffers
+   mm-api
    gfp_mask-from-fs-io
    timekeeping
    boot-time-mm
index 76fe2d0..3431337 100644 (file)
@@ -39,6 +39,10 @@ String Manipulation
 .. kernel-doc:: lib/string.c
    :export:
 
+.. kernel-doc:: mm/util.c
+   :functions: kstrdup kstrdup_const kstrndup kmemdup kmemdup_nul memdup_user
+               vmemdup_user strndup_user memdup_user_nul
+
 Basic Kernel Library Functions
 ==============================
 
@@ -155,60 +159,6 @@ UUID/GUID
 .. kernel-doc:: lib/uuid.c
    :export:
 
-Memory Management in Linux
-==========================
-
-The Slab Cache
---------------
-
-.. kernel-doc:: include/linux/slab.h
-   :internal:
-
-.. kernel-doc:: mm/slab.c
-   :export:
-
-.. kernel-doc:: mm/util.c
-   :export:
-
-User Space Memory Access
-------------------------
-
-.. kernel-doc:: arch/x86/include/asm/uaccess.h
-   :internal:
-
-.. kernel-doc:: arch/x86/lib/usercopy_32.c
-   :export:
-
-More Memory Management Functions
---------------------------------
-
-.. kernel-doc:: mm/readahead.c
-   :export:
-
-.. kernel-doc:: mm/filemap.c
-   :export:
-
-.. kernel-doc:: mm/memory.c
-   :export:
-
-.. kernel-doc:: mm/vmalloc.c
-   :export:
-
-.. kernel-doc:: mm/page_alloc.c
-   :internal:
-
-.. kernel-doc:: mm/mempool.c
-   :export:
-
-.. kernel-doc:: mm/dmapool.c
-   :export:
-
-.. kernel-doc:: mm/page-writeback.c
-   :export:
-
-.. kernel-doc:: mm/truncate.c
-   :export:
-
 Kernel IPC facilities
 =====================
 
@@ -437,4 +387,3 @@ Read-Copy Update (RCU)
 .. kernel-doc:: include/linux/rcu_sync.h
 
 .. kernel-doc:: kernel/rcu/sync.c
-
diff --git a/Documentation/core-api/mm-api.rst b/Documentation/core-api/mm-api.rst
new file mode 100644 (file)
index 0000000..46ae353
--- /dev/null
@@ -0,0 +1,78 @@
+======================
+Memory Management APIs
+======================
+
+User Space Memory Access
+========================
+
+.. kernel-doc:: arch/x86/include/asm/uaccess.h
+   :internal:
+
+.. kernel-doc:: arch/x86/lib/usercopy_32.c
+   :export:
+
+.. kernel-doc:: mm/util.c
+   :functions: get_user_pages_fast
+
+Memory Allocation Controls
+==========================
+
+Functions which need to allocate memory often use GFP flags to express
+how that memory should be allocated. The GFP acronym stands for "get
+free pages", the underlying memory allocation function. Not every GFP
+flag is allowed to every function which may allocate memory. Most
+users will want to use a plain ``GFP_KERNEL``.
+
+.. kernel-doc:: include/linux/gfp.h
+   :doc: Page mobility and placement hints
+
+.. kernel-doc:: include/linux/gfp.h
+   :doc: Watermark modifiers
+
+.. kernel-doc:: include/linux/gfp.h
+   :doc: Reclaim modifiers
+
+.. kernel-doc:: include/linux/gfp.h
+   :doc: Common combinations
+
+The Slab Cache
+==============
+
+.. kernel-doc:: include/linux/slab.h
+   :internal:
+
+.. kernel-doc:: mm/slab.c
+   :export:
+
+.. kernel-doc:: mm/util.c
+   :functions: kfree_const kvmalloc_node kvfree
+
+More Memory Management Functions
+================================
+
+.. kernel-doc:: mm/readahead.c
+   :export:
+
+.. kernel-doc:: mm/filemap.c
+   :export:
+
+.. kernel-doc:: mm/memory.c
+   :export:
+
+.. kernel-doc:: mm/vmalloc.c
+   :export:
+
+.. kernel-doc:: mm/page_alloc.c
+   :internal:
+
+.. kernel-doc:: mm/mempool.c
+   :export:
+
+.. kernel-doc:: mm/dmapool.c
+   :export:
+
+.. kernel-doc:: mm/page-writeback.c
+   :export:
+
+.. kernel-doc:: mm/truncate.c
+   :export:
diff --git a/Documentation/devicetree/bindings/arm/adapteva.txt b/Documentation/devicetree/bindings/arm/adapteva.txt
deleted file mode 100644 (file)
index 1d8af9e..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-Adapteva Platforms Device Tree Bindings
----------------------------------------
-
-Parallella board
-
-Required root node properties:
-    - compatible = "adapteva,parallella";
index 6988056..b5c2b5c 100644 (file)
@@ -41,6 +41,14 @@ Boards with the Amlogic Meson GXL S905D SoC shall have the following properties:
   Required root node property:
     compatible: "amlogic,s905d", "amlogic,meson-gxl";
 
+Boards with the Amlogic Meson GXL S805X SoC shall have the following properties:
+  Required root node property:
+    compatible: "amlogic,s805x", "amlogic,meson-gxl";
+
+Boards with the Amlogic Meson GXL S905W SoC shall have the following properties:
+  Required root node property:
+    compatible: "amlogic,s905w", "amlogic,meson-gxl";
+
 Boards with the Amlogic Meson GXM S912 SoC shall have the following properties:
   Required root node property:
     compatible: "amlogic,s912", "amlogic,meson-gxm";
@@ -79,6 +87,11 @@ Board compatible values (alphabetically, grouped by SoC):
   - "amlogic,p230" (Meson gxl s905d)
   - "amlogic,p231" (Meson gxl s905d)
 
+  - "amlogic,p241" (Meson gxl s805x)
+
+  - "amlogic,p281" (Meson gxl s905w)
+  - "oranth,tx3-mini" (Meson gxl s905w)
+
   - "amlogic,q200" (Meson gxm s912)
   - "amlogic,q201" (Meson gxm s912)
   - "khadas,vim2" (Meson gxm s912)
diff --git a/Documentation/devicetree/bindings/arm/atmel-pmc.txt b/Documentation/devicetree/bindings/arm/atmel-pmc.txt
deleted file mode 100644 (file)
index 795cc78..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-* Power Management Controller (PMC)
-
-Required properties:
-- compatible: Should be "atmel,<chip>-pmc".
-       <chip> can be: at91rm9200, at91sam9260, at91sam9g45, at91sam9n12,
-       at91sam9x5, sama5d3
-
-- reg: Should contain PMC registers location and length
-
-Examples:
-       pmc: pmc@fffffc00 {
-               compatible = "atmel,at91rm9200-pmc";
-               reg = <0xfffffc00 0x100>;
-       };
index c052caa..104cc9b 100644 (file)
@@ -189,7 +189,11 @@ Power-Down (SRPD), among other things.
 
 Required properties:
 - compatible     : should contain one of these
+       "brcm,brcmstb-memc-ddr-rev-b.2.1"
        "brcm,brcmstb-memc-ddr-rev-b.2.2"
+       "brcm,brcmstb-memc-ddr-rev-b.2.3"
+       "brcm,brcmstb-memc-ddr-rev-b.3.0"
+       "brcm,brcmstb-memc-ddr-rev-b.3.1"
        "brcm,brcmstb-memc-ddr"
 - reg            : the MEMC DDR register range
 
index 7809fbe..9b5685a 100644 (file)
@@ -94,7 +94,7 @@ cpus {
        };
 
        idle-states {
-               entry-method = "arm,psci";
+               entry-method = "psci";
 
                CPU_SLEEP_0: cpu-sleep-0 {
                        compatible = "arm,idle-state";
index 29e1dc5..96dfccc 100644 (file)
@@ -183,6 +183,7 @@ described below.
                            "marvell,sheeva-v5"
                            "nvidia,tegra132-denver"
                            "nvidia,tegra186-denver"
+                           "nvidia,tegra194-carmel"
                            "qcom,krait"
                            "qcom,kryo"
                            "qcom,kryo385"
@@ -219,6 +220,7 @@ described below.
                            "qcom,kpss-acc-v1"
                            "qcom,kpss-acc-v2"
                            "renesas,apmu"
+                           "renesas,r9a06g032-smp"
                            "rockchip,rk3036-smp"
                            "rockchip,rk3066-smp"
                            "ste,dbx500-smp"
diff --git a/Documentation/devicetree/bindings/arm/freescale/m4if.txt b/Documentation/devicetree/bindings/arm/freescale/m4if.txt
new file mode 100644 (file)
index 0000000..93bd7b8
--- /dev/null
@@ -0,0 +1,12 @@
+* Freescale Multi Master Multi Memory Interface (M4IF) module
+
+Required properties:
+- compatible : Should be "fsl,imx51-m4if"
+- reg : Address and length of the register set for the device
+
+Example:
+
+m4if: m4if@83fd8000 {
+       compatible = "fsl,imx51-m4if";
+       reg = <0x83fd8000 0x1000>;
+};
diff --git a/Documentation/devicetree/bindings/arm/freescale/tigerp.txt b/Documentation/devicetree/bindings/arm/freescale/tigerp.txt
new file mode 100644 (file)
index 0000000..19e2aad
--- /dev/null
@@ -0,0 +1,12 @@
+* Freescale Tigerp platform module
+
+Required properties:
+- compatible : Should be "fsl,imx51-tigerp"
+- reg : Address and length of the register set for the device
+
+Example:
+
+tigerp: tigerp@83fa0000 {
+       compatible = "fsl,imx51-tigerp";
+       reg = <0x83fa0000 0x28>;
+};
index cdb9dd7..8a1baa2 100644 (file)
@@ -53,6 +53,10 @@ i.MX6 Quad SABRE Automotive Board
 Required root node properties:
     - compatible = "fsl,imx6q-sabreauto", "fsl,imx6q";
 
+i.MX6SLL EVK board
+Required root node properties:
+    - compatible = "fsl,imx6sll-evk", "fsl,imx6sll";
+
 Generic i.MX boards
 -------------------
 
index 7a59133..2c73847 100644 (file)
@@ -237,8 +237,8 @@ processor idle states, defined as device tree nodes, are listed.
                Value type: <stringlist>
                Usage and definition depend on ARM architecture version.
                        # On ARM v8 64-bit this property is required and must
-                         be one of:
-                          - "psci" (see bindings in [2])
+                         be:
+                          - "psci"
                        # On ARM 32-bit systems this property is optional
 
 The nodes describing the idle states (state) can only be defined within the
diff --git a/Documentation/devicetree/bindings/arm/insignal-boards.txt b/Documentation/devicetree/bindings/arm/insignal-boards.txt
deleted file mode 100644 (file)
index 524c3dc..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-* Insignal's Exynos4210 based Origen evaluation board
-
-Origen low-cost evaluation board is based on Samsung's Exynos4210 SoC.
-
-Required root node properties:
-    - compatible = should be one or more of the following.
-        (a) "samsung,smdkv310" - for Samsung's SMDKV310 eval board.
-        (b) "samsung,exynos4210"  - for boards based on Exynos4210 SoC.
index 48fac4e..8f260e5 100644 (file)
@@ -51,6 +51,9 @@ Supported boards:
 - Evaluation board for MT6797(Helio X20):
     Required root node properties:
       - compatible = "mediatek,mt6797-evb", "mediatek,mt6797";
+- Mediatek X20 Development Board:
+    Required root node properties:
+      - compatible = "archermind,mt6797-x20-dev", "mediatek,mt6797";
 - Reference board variant 1 for MT7622:
     Required root node properties:
       - compatible = "mediatek,mt7622-rfb1", "mediatek,mt7622";
@@ -63,9 +66,6 @@ Supported boards:
 - Reference board for MT7623n with eMMC:
     Required root node properties:
       - compatible = "mediatek,mt7623n-rfb-emmc", "mediatek,mt7623";
-- Reference  board for MT7623n with NAND:
-    Required root node properties:
-      - compatible = "mediatek,mt7623n-rfb-nand", "mediatek,mt7623";
 - Bananapi BPI-R2 board:
       - compatible = "bananapi,bpi-r2", "mediatek,mt7623";
 - MTK mt8127 tablet moose EVB:
index b4f8a16..6816adc 100644 (file)
@@ -7,6 +7,7 @@ Required properties:
               Should be "ti,omap2-l4-wkup" for OMAP2 family l4 wkup bus
               Should be "ti,omap3-l4-core" for OMAP3 family l4 core bus
               Should be "ti,omap4-l4-cfg" for OMAP4 family l4 cfg bus
+              Should be "ti,omap4-l4-per" for OMAP4 family l4 per bus
               Should be "ti,omap4-l4-wkup" for OMAP4 family l4 wkup bus
               Should be "ti,omap5-l4-cfg" for OMAP5 family l4 cfg bus
               Should be "ti,omap5-l4-wkup" for OMAP5 family l4 wkup bus
@@ -15,11 +16,21 @@ Required properties:
               Should be "ti,am3-l4-wkup" for AM33xx family l4 wkup bus
               Should be "ti,am4-l4-wkup" for AM43xx family l4 wkup bus
 - ranges : contains the IO map range for the bus
+- reg : registers link agent and interconnect agent and access protection
+- reg-names : "la" for link agent, "ia0" to "ia3" for one to three
+              interconnect agent instances, "ap" for access if it exists
 
 Examples:
 
-l4: l4@48000000 {
-       compatible "ti,omap2-l4", "simple-bus";
+l4: interconnect@48000000 {
+       compatible "ti,omap4-l4-per", "simple-bus";
+       reg = <0x48000000 0x800>,
+             <0x48000800 0x800>,
+             <0x48001000 0x400>,
+             <0x48001400 0x400>,
+             <0x48001800 0x400>,
+             <0x48001c00 0x400>;
+       reg-names = "ap", "la", "ia0", "ia1", "ia2", "ia3";
        #address-cells = <1>;
        #size-cells = <1>;
        ranges = <0 0x48000000 0x100000>;
index 1c1d62d..acfd3c7 100644 (file)
@@ -1,5 +1,10 @@
 Rockchip platforms device tree bindings
 ---------------------------------------
+
+- 96boards RK3399 Ficus (ROCK960 Enterprise Edition)
+    Required root node properties:
+      - compatible = "vamrs,ficus", "rockchip,rk3399";
+
 - Amarula Vyasa RK3288 board
     Required root node properties:
       - compatible = "amarula,vyasa-rk3288", "rockchip,rk3288";
@@ -66,6 +71,15 @@ Rockchip platforms device tree bindings
     Required root node properties:
       - compatible = "geekbuying,geekbox", "rockchip,rk3368";
 
+- Google Bob (Asus Chromebook Flip C101PA):
+    Required root node properties:
+       compatible = "google,bob-rev13", "google,bob-rev12",
+                    "google,bob-rev11", "google,bob-rev10",
+                    "google,bob-rev9", "google,bob-rev8",
+                    "google,bob-rev7", "google,bob-rev6",
+                    "google,bob-rev5", "google,bob-rev4",
+                    "google,bob", "google,gru", "rockchip,rk3399";
+
 - Google Brain (dev-board):
     Required root node properties:
       - compatible = "google,veyron-brain-rev0", "google,veyron-brain",
index 6970f30..56021bf 100644 (file)
@@ -1,7 +1,10 @@
-* Samsung's Exynos SoC based boards
+* Samsung's Exynos and S5P SoC based boards
 
 Required root node properties:
     - compatible = should be one or more of the following.
+       - "samsung,aries"       - for S5PV210-based Samsung Aries board.
+       - "samsung,fascinate4g" - for S5PV210-based Samsung Galaxy S Fascinate 4G (SGH-T959P) board.
+       - "samsung,galaxys"     - for S5PV210-based Samsung Galaxy S (i9000)  board.
        - "samsung,artik5"      - for Exynos3250-based Samsung ARTIK5 module.
        - "samsung,artik5-eval" - for Exynos3250-based Samsung ARTIK5 eval board.
        - "samsung,monk"        - for Exynos3250-based Samsung Simband board.
index d8cf740..89b4a38 100644 (file)
@@ -51,7 +51,8 @@ SoCs:
     compatible = "renesas,r8a77990"
   - R-Car D3 (R8A77995)
     compatible = "renesas,r8a77995"
-
+  - RZ/N1D (R9A06G032)
+    compatible = "renesas,r9a06g032"
 
 Boards:
 
@@ -112,6 +113,8 @@ Boards:
     compatible = "renesas,porter", "renesas,r8a7791"
   - RSKRZA1 (YR0K77210C000BE)
     compatible = "renesas,rskrza1", "renesas,r7s72100"
+  - RZN1D-DB (RZ/N1D Demo Board for the RZ/N1D 400 pins package)
+    compatible = "renesas,rzn1d400-db", "renesas,r9a06g032"
   - Salvator-X (RTP0RC7795SIPB0010S)
     compatible = "renesas,salvator-x", "renesas,r8a7795"
   - Salvator-X (RTP0RC7796SIPB0011S)
diff --git a/Documentation/devicetree/bindings/arm/ti/k3.txt b/Documentation/devicetree/bindings/arm/ti/k3.txt
new file mode 100644 (file)
index 0000000..6a059ca
--- /dev/null
@@ -0,0 +1,23 @@
+Texas Instruments K3 Multicore SoC architecture device tree bindings
+--------------------------------------------------------------------
+
+Platforms based on Texas Instruments K3 Multicore SoC architecture
+shall follow the following scheme:
+
+SoCs
+----
+
+Each device tree root node must specify which exact SoC in K3 Multicore SoC
+architecture it uses, using one of the following compatible values:
+
+- AM654
+  compatible = "ti,am654";
+
+Boards
+------
+
+In addition, each device tree root node must specify which one or more
+of the following board-specific compatible values:
+
+- AM654 EVM
+  compatible = "ti,am654-evm", "ti,am654";
index b9043bc..26fe5ec 100644 (file)
@@ -8,18 +8,38 @@ Required root node properties:
 
 Additional compatible strings:
 
-- Xilinx internal board cc108
+- Adapteva Parallella board
+  "adapteva,parallella"
+
+- Avnet MicroZed board
+  "avnet,zynq-microzed"
+  "xlnx,zynq-microzed"
+
+- Avnet ZedBoard board
+  "avnet,zynq-zed"
+  "xlnx,zynq-zed"
+
+- Digilent Zybo board
+  "digilent,zynq-zybo"
+
+- Digilent Zybo Z7 board
+  "digilent,zynq-zybo-z7"
+
+- Xilinx CC108 internal board
   "xlnx,zynq-cc108"
 
-- Xilinx internal board zc770 with different FMC cards
+- Xilinx ZC702 internal board
+  "xlnx,zynq-zc702"
+
+- Xilinx ZC706 internal board
+  "xlnx,zynq-zc706"
+
+- Xilinx ZC770 internal board, with different FMC cards
   "xlnx,zynq-zc770-xm010"
   "xlnx,zynq-zc770-xm011"
   "xlnx,zynq-zc770-xm012"
   "xlnx,zynq-zc770-xm013"
 
-- Digilent Zybo Z7 board
-  "digilent,zynq-zybo-z7"
-
 ---------------------------------------------------------------
 
 Xilinx Zynq UltraScale+ MPSoC Platforms Device Tree Bindings
index c760ecb..5d5bd45 100644 (file)
@@ -17,7 +17,6 @@ Required properties:
   - "marvell,armada-380-ahci"
   - "marvell,armada-3700-ahci"
   - "snps,dwc-ahci"
-  - "snps,exynos5440-ahci"
   - "snps,spear-ahci"
   - "generic-ahci"
 - interrupts        : <interrupt mapping for SATA IRQ>
@@ -30,6 +29,7 @@ compatible:
 Optional properties:
 - dma-coherent      : Present if dma operations are coherent
 - clocks            : a list of phandle + clock specifier pairs
+- resets            : a list of phandle + reset specifier pairs
 - target-supply     : regulator for SATA target power
 - phys              : reference to the SATA PHY node
 - phy-names         : must be "sata-phy"
index e20eac7..4268e17 100644 (file)
@@ -8,6 +8,7 @@ Required properties:
                          - "renesas,sata-r8a7791" for R-Car M2-W
                          - "renesas,sata-r8a7793" for R-Car M2-N
                          - "renesas,sata-r8a7795" for R-Car H3
+                         - "renesas,sata-r8a77965" for R-Car M3-N
                          - "renesas,rcar-gen2-sata" for a generic R-Car Gen2 compatible device
                          - "renesas,rcar-gen3-sata" for a generic R-Car Gen3 compatible device
                          - "renesas,rcar-sata" is deprecated
diff --git a/Documentation/devicetree/bindings/bus/sun50i-de2-bus.txt b/Documentation/devicetree/bindings/bus/sun50i-de2-bus.txt
new file mode 100644 (file)
index 0000000..87dfb33
--- /dev/null
@@ -0,0 +1,37 @@
+Device tree bindings for Allwinner A64 DE2 bus
+
+The Allwinner A64 DE2 is on a special bus, which needs a SRAM region (SRAM C)
+to be claimed for enabling the access.
+
+Required properties:
+
+ - compatible:         Should contain "allwinner,sun50i-a64-de2"
+ - reg:                        A resource specifier for the register space
+ - #address-cells:     Must be set to 1
+ - #size-cells:                Must be set to 1
+ - ranges:             Must be set up to map the address space inside the
+                       DE2, for the sub-blocks of DE2.
+ - allwinner,sram:     the SRAM that needs to be claimed
+
+Example:
+
+       de2@1000000 {
+               compatible = "allwinner,sun50i-a64-de2";
+               reg = <0x1000000 0x400000>;
+               allwinner,sram = <&de2_sram 1>;
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges = <0 0x1000000 0x400000>;
+
+               display_clocks: clock@0 {
+                       compatible = "allwinner,sun50i-a64-de2-clk";
+                       reg = <0x0 0x100000>;
+                       clocks = <&ccu CLK_DE>,
+                                <&ccu CLK_BUS_DE>;
+                       clock-names = "mod",
+                                     "bus";
+                       resets = <&ccu RST_BUS_DE>;
+                       #clock-cells = <1>;
+                       #reset-cells = <1>;
+               };
+       };
index d8ed5b7..91dc233 100644 (file)
@@ -36,6 +36,7 @@ Required standard properties:
                "ti,sysc-omap-aes"
                "ti,sysc-mcasp"
                "ti,sysc-usb-host-fs"
+               "ti,sysc-dra7-mcan"
 
 - reg          shall have register areas implemented for the interconnect
                target module in question such as revision, sysc and syss
index 09968ee..8f8f950 100644 (file)
@@ -17,14 +17,13 @@ Required properties:
        "atmel,at91sam9x5-clk-slow-rc-osc":
                at91 internal slow RC oscillator
 
-       "atmel,at91rm9200-pmc" or
-       "atmel,at91sam9g45-pmc" or
-       "atmel,at91sam9n12-pmc" or
-       "atmel,at91sam9x5-pmc" or
-       "atmel,sama5d3-pmc":
+       "atmel,<chip>-pmc":
                at91 PMC (Power Management Controller)
                All at91 specific clocks (clocks defined below) must be child
                node of the PMC node.
+               <chip> can be: at91rm9200, at91sam9260, at91sam9261,
+               at91sam9263, at91sam9g45, at91sam9n12, at91sam9rl, at91sam9x5,
+               sama5d2, sama5d3 or sama5d4.
 
        "atmel,at91sam9x5-clk-slow" (under sckc node)
        or
diff --git a/Documentation/devicetree/bindings/clock/exynos5440-clock.txt b/Documentation/devicetree/bindings/clock/exynos5440-clock.txt
deleted file mode 100644 (file)
index c7d227c..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-* Samsung Exynos5440 Clock Controller
-
-The Exynos5440 clock controller generates and supplies clock to various
-controllers within the Exynos5440 SoC.
-
-Required Properties:
-
-- compatible: should be "samsung,exynos5440-clock".
-
-- reg: physical base address of the controller and length of memory mapped
-  region.
-
-- #clock-cells: should be 1.
-
-Each clock is assigned an identifier and client nodes can use this identifier
-to specify the clock which they consume.
-
-All available clocks are defined as preprocessor macros in
-dt-bindings/clock/exynos5440.h header and can be used in device
-tree sources.
-
-Example: An example of a clock controller node is listed below.
-
-       clock: clock-controller@10010000 {
-               compatible = "samsung,exynos5440-clock";
-               reg = <0x160000 0x10000>;
-               #clock-cells = <1>;
-       };
diff --git a/Documentation/devicetree/bindings/cpufreq/cpufreq-exynos5440.txt b/Documentation/devicetree/bindings/cpufreq/cpufreq-exynos5440.txt
deleted file mode 100644 (file)
index caff1a5..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-
-Exynos5440 cpufreq driver
--------------------
-
-Exynos5440 SoC cpufreq driver for CPU frequency scaling.
-
-Required properties:
-- interrupts: Interrupt to know the completion of cpu frequency change.
-- operating-points: Table of frequencies and voltage CPU could be transitioned into,
-       in the decreasing order. Frequency should be in KHz units and voltage
-       should be in microvolts.
-
-Optional properties:
-- clock-latency: Clock monitor latency in microsecond.
-
-All the required listed above must be defined under node cpufreq.
-
-Example:
---------
-       cpufreq@160000 {
-               compatible = "samsung,exynos5440-cpufreq";
-               reg = <0x160000 0x1000>;
-               interrupts = <0 57 0>;
-               operating-points = <
-                               1000000 975000
-                               800000  925000>;
-               clock-latency = <100000>;
-       };
index f79641b..45ffd6c 100644 (file)
@@ -10,6 +10,9 @@ Required properties:
  - interrupts : framebuffer controller interrupt.
  - clocks: phandle to input clocks
 
+Optional properties:
+ - lcd-supply: A phandle to a power regulator that controls the LCD voltage.
+
 Required nodes:
  - port: connection to the LCD panel (see video-interfaces.txt)
         This node must have its properties bus-width and remote-endpoint set.
diff --git a/Documentation/devicetree/bindings/display/marvell,pxa300-gcu.txt b/Documentation/devicetree/bindings/display/marvell,pxa300-gcu.txt
new file mode 100644 (file)
index 0000000..9cfae5c
--- /dev/null
@@ -0,0 +1,17 @@
+PXA3xx GCU Controller
+---------------------
+
+Required properties:
+ - compatible : "marvell,pxa300-gcu"
+ - reg : should contain the register range (address and length).
+ - interrupts : Controller interrupt.
+ - clocks: phandle to the PXA specific input clock.
+
+Example for PXA300:
+
+       display-controller@54000000 {
+               compatible = "marvell,pxa300-gcu";
+               reg = <0x54000000 0x1000>;
+               interrupts = <39>;
+               clocks = <&clks CLK_PXA300_GCU>;
+       };
index 61d833a..aededdb 100644 (file)
@@ -72,6 +72,8 @@ Optional properties:
 
   - wp-gpios: GPIO to which the write-protect pin of the chip is connected.
 
+  - address-width: number of address bits (one of 8, 16).
+
 Example:
 
 eeprom@52 {
diff --git a/Documentation/devicetree/bindings/i2c/i2c-fsi.txt b/Documentation/devicetree/bindings/i2c/i2c-fsi.txt
new file mode 100644 (file)
index 0000000..b1be2ce
--- /dev/null
@@ -0,0 +1,40 @@
+Device-tree bindings for FSI-attached I2C master and busses
+-----------------------------------------------------------
+
+Required properties:
+ - compatible = "ibm,i2c-fsi";
+ - reg = < address size >;             : The FSI CFAM address and address
+                                         space size.
+ - #address-cells = <1>;               : Number of address cells in child
+                                         nodes.
+ - #size-cells = <0>;                  : Number of size cells in child nodes.
+ - child nodes                         : Nodes to describe busses off the I2C
+                                         master.
+
+Child node required properties:
+ - reg = < port number >               : The port number on the I2C master.
+
+Child node optional properties:
+ - child nodes                         : Nodes to describe devices on the I2C
+                                         bus.
+
+Examples:
+
+    i2c@1800 {
+        compatible = "ibm,i2c-fsi";
+        reg = < 0x1800 0x400 >;
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        i2c-bus@0 {
+            reg = <0>;
+        };
+
+        i2c-bus@1 {
+            reg = <1>;
+
+            eeprom@50 {
+                compatible = "vendor,dev-name";
+            };
+        };
+    };
diff --git a/Documentation/devicetree/bindings/i2c/i2c-owl.txt b/Documentation/devicetree/bindings/i2c/i2c-owl.txt
new file mode 100644 (file)
index 0000000..b743fe4
--- /dev/null
@@ -0,0 +1,27 @@
+Actions Semiconductor Owl I2C controller
+
+Required properties:
+
+- compatible        : Should be "actions,s900-i2c".
+- reg               : Offset and length of the register set for the device.
+- #address-cells    : Should be 1.
+- #size-cells       : Should be 0.
+- interrupts        : A single interrupt specifier.
+- clocks            : Phandle of the clock feeding the I2C controller.
+
+Optional properties:
+
+- clock-frequency   : Desired I2C bus clock frequency in Hz. As only Normal and
+                      Fast modes are supported, possible values are 100000 and
+                      400000.
+Examples:
+
+        i2c0: i2c@e0170000 {
+                compatible = "actions,s900-i2c";
+                reg = <0 0xe0170000 0 0x1000>;
+                #address-cells = <1>;
+                #size-cells = <0>;
+                interrupts = <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>;
+                clocks = <&clock CLK_I2C0>;
+                clock-frequency = <100000>;
+        };
index 7ce8fae..39cd21d 100644 (file)
@@ -4,6 +4,7 @@ Required properties:
 - compatible:
        "renesas,i2c-r8a7743" if the device is a part of a R8A7743 SoC.
        "renesas,i2c-r8a7745" if the device is a part of a R8A7745 SoC.
+       "renesas,i2c-r8a774a1" if the device is a part of a R8A774A1 SoC.
        "renesas,i2c-r8a7778" if the device is a part of a R8A7778 SoC.
        "renesas,i2c-r8a7779" if the device is a part of a R8A7779 SoC.
        "renesas,i2c-r8a7790" if the device is a part of a R8A7790 SoC.
@@ -16,11 +17,13 @@ Required properties:
        "renesas,i2c-r8a77965" if the device is a part of a R8A77965 SoC.
        "renesas,i2c-r8a77970" if the device is a part of a R8A77970 SoC.
        "renesas,i2c-r8a77980" if the device is a part of a R8A77980 SoC.
+       "renesas,i2c-r8a77990" if the device is a part of a R8A77990 SoC.
        "renesas,i2c-r8a77995" if the device is a part of a R8A77995 SoC.
        "renesas,rcar-gen1-i2c" for a generic R-Car Gen1 compatible device.
        "renesas,rcar-gen2-i2c" for a generic R-Car Gen2 or RZ/G1 compatible
                                device.
-       "renesas,rcar-gen3-i2c" for a generic R-Car Gen3 compatible device.
+       "renesas,rcar-gen3-i2c" for a generic R-Car Gen3 or RZ/G2 compatible
+                               device.
        "renesas,i2c-rcar" (deprecated)
 
        When compatible with the generic version, nodes must list the
index fc7e178..872673a 100644 (file)
@@ -6,6 +6,7 @@ Required properties:
                        - "renesas,iic-r8a7740" (R-Mobile A1)
                        - "renesas,iic-r8a7743" (RZ/G1M)
                        - "renesas,iic-r8a7745" (RZ/G1E)
+                       - "renesas,iic-r8a774a1" (RZ/G2M)
                        - "renesas,iic-r8a7790" (R-Car H2)
                        - "renesas,iic-r8a7791" (R-Car M2-W)
                        - "renesas,iic-r8a7792" (R-Car V2H)
@@ -17,7 +18,8 @@ Required properties:
                        - "renesas,iic-sh73a0" (SH-Mobile AG5)
                        - "renesas,rcar-gen2-iic" (generic R-Car Gen2 or RZ/G1
                                                        compatible device)
-                       - "renesas,rcar-gen3-iic" (generic R-Car Gen3 compatible device)
+                       - "renesas,rcar-gen3-iic" (generic R-Car Gen3 or RZ/G2
+                                                       compatible device)
                        - "renesas,rmobile-iic" (generic device)
 
                        When compatible with a generic R-Car version, nodes
index f1cb9f8..c76bafa 100644 (file)
@@ -25,7 +25,8 @@ device-specific compatible properties, which should be used in addition to the
 
 - compatible:
   * "wacom,w9013" (Wacom W9013 digitizer). Supports:
-    - vdd-supply
+    - vdd-supply (3.3V)
+    - vddl-supply (1.8V)
     - post-power-on-delay-ms
 
 - vdd-supply: phandle of the regulator that provides the supply voltage.
index 697ca2f..a046ed3 100644 (file)
@@ -13,6 +13,7 @@ Required properties:
     - "renesas,irqc-r8a7792" (R-Car V2H)
     - "renesas,irqc-r8a7793" (R-Car M2-N)
     - "renesas,irqc-r8a7794" (R-Car E2)
+    - "renesas,intc-ex-r8a774a1" (RZ/G2M)
     - "renesas,intc-ex-r8a7795" (R-Car H3)
     - "renesas,intc-ex-r8a7796" (R-Car M3-W)
     - "renesas,intc-ex-r8a77965" (R-Car M3-N)
index 53c20ca..df5db73 100644 (file)
@@ -40,6 +40,7 @@ video decode local arbiter, all these ports are according to the video HW.
 Required properties:
 - compatible : must be one of the following string:
        "mediatek,mt2701-m4u" for mt2701 which uses generation one m4u HW.
+       "mediatek,mt2712-m4u" for mt2712 which uses generation two m4u HW.
        "mediatek,mt8173-m4u" for mt8173 which uses generation two m4u HW.
 - reg : m4u register base and size.
 - interrupts : the interrupt of m4u.
@@ -50,8 +51,9 @@ Required properties:
        according to the local arbiter index, like larb0, larb1, larb2...
 - iommu-cells : must be 1. This is the mtk_m4u_id according to the HW.
        Specifies the mtk_m4u_id as defined in
-       dt-binding/memory/mt2701-larb-port.h for mt2701 and
-       dt-binding/memory/mt8173-larb-port.h for mt8173
+       dt-binding/memory/mt2701-larb-port.h for mt2701,
+       dt-binding/memory/mt2712-larb-port.h for mt2712, and
+       dt-binding/memory/mt8173-larb-port.h for mt8173.
 
 Example:
        iommu: iommu@10205000 {
index ffadb7c..c6e2d85 100644 (file)
@@ -19,7 +19,10 @@ Required Properties:
     - "renesas,ipmmu-r8a7794" for the R8A7794 (R-Car E2) IPMMU.
     - "renesas,ipmmu-r8a7795" for the R8A7795 (R-Car H3) IPMMU.
     - "renesas,ipmmu-r8a7796" for the R8A7796 (R-Car M3-W) IPMMU.
+    - "renesas,ipmmu-r8a77965" for the R8A77965 (R-Car M3-N) IPMMU.
     - "renesas,ipmmu-r8a77970" for the R8A77970 (R-Car V3M) IPMMU.
+    - "renesas,ipmmu-r8a77980" for the R8A77980 (R-Car V3H) IPMMU.
+    - "renesas,ipmmu-r8a77990" for the R8A77990 (R-Car E3) IPMMU.
     - "renesas,ipmmu-r8a77995" for the R8A77995 (R-Car D3) IPMMU.
     - "renesas,ipmmu-vmsa" for generic R-Car Gen2 or RZ/G1 VMSA-compatible
                           IPMMU.
index 3108109..64fa2fb 100644 (file)
@@ -3,13 +3,6 @@ pwm-backlight bindings
 Required properties:
   - compatible: "pwm-backlight"
   - pwms: OF device-tree PWM specification (see PWM binding[0])
-  - brightness-levels: Array of distinct brightness levels. Typically these
-      are in the range from 0 to 255, but any range starting at 0 will do.
-      The actual brightness level (PWM duty cycle) will be interpolated
-      from these values. 0 means a 0% duty cycle (darkest/off), while the
-      last value in the array represents a 100% duty cycle (brightest).
-  - default-brightness-level: the default brightness level (index into the
-      array defined by the "brightness-levels" property)
   - power-supply: regulator for supply voltage
 
 Optional properties:
@@ -21,6 +14,19 @@ Optional properties:
                           and enabling the backlight using GPIO.
   - pwm-off-delay-ms: Delay in ms between disabling the backlight using GPIO
                       and setting PWM value to 0.
+  - brightness-levels: Array of distinct brightness levels. Typically these
+                       are in the range from 0 to 255, but any range starting at
+                       0 will do. The actual brightness level (PWM duty cycle)
+                       will be interpolated from these values. 0 means a 0% duty
+                       cycle (darkest/off), while the last value in the array
+                       represents a 100% duty cycle (brightest).
+  - default-brightness-level: The default brightness level (index into the
+                              array defined by the "brightness-levels" property).
+  - num-interpolated-steps: Number of interpolated steps between each value
+                            of brightness-levels table. This way a high
+                            resolution pwm duty cycle can be used without
+                            having to list out every possible value in the
+                            brightness-level array.
 
 [0]: Documentation/devicetree/bindings/pwm/pwm.txt
 [1]: Documentation/devicetree/bindings/gpio/gpio.txt
@@ -39,3 +45,17 @@ Example:
                post-pwm-on-delay-ms = <10>;
                pwm-off-delay-ms = <10>;
        };
+
+Example using num-interpolation-steps:
+
+       backlight {
+               compatible = "pwm-backlight";
+               pwms = <&pwm 0 5000000>;
+
+               brightness-levels = <0 2048 4096 8192 16384 65535>;
+               num-interpolated-steps = <2048>;
+               default-brightness-level = <4096>;
+
+               power-supply = <&vdd_bl_reg>;
+               enable-gpios = <&gpio 58 0>;
+       };
index aa614b2..615abdd 100644 (file)
@@ -2,8 +2,9 @@ SMI (Smart Multimedia Interface) Common
 
 The hardware block diagram please check bindings/iommu/mediatek,iommu.txt
 
-Mediatek SMI have two generations of HW architecture, mt8173 uses the second
-generation of SMI HW while mt2701 uses the first generation HW of SMI.
+Mediatek SMI have two generations of HW architecture, mt2712 and mt8173 use
+the second generation of SMI HW while mt2701 uses the first generation HW of
+SMI.
 
 There's slight differences between the two SMI, for generation 2, the
 register which control the iommu port is at each larb's register base. But
@@ -15,6 +16,7 @@ not needed for SMI generation 2.
 Required properties:
 - compatible : must be one of :
        "mediatek,mt2701-smi-common"
+       "mediatek,mt2712-smi-common"
        "mediatek,mt8173-smi-common"
 - reg : the register and size of the SMI block.
 - power-domains : a phandle to the power domain of this local arbiter.
index ddf46b8..083155c 100644 (file)
@@ -4,8 +4,9 @@ The hardware block diagram please check bindings/iommu/mediatek,iommu.txt
 
 Required properties:
 - compatible : must be one of :
-               "mediatek,mt8173-smi-larb"
                "mediatek,mt2701-smi-larb"
+               "mediatek,mt2712-smi-larb"
+               "mediatek,mt8173-smi-larb"
 - reg : the register and size of this local arbiter.
 - mediatek,smi : a phandle to the smi_common node.
 - power-domains : a phandle to the power domain of this local arbiter.
@@ -15,7 +16,7 @@ Required properties:
            the register.
   - "smi" : It's the clock for transfer data and command.
 
-Required property for mt2701:
+Required property for mt2701 and mt2712:
 - mediatek,larb-id :the hardware id of this larb.
 
 Example:
index 5297b22..2a66574 100644 (file)
@@ -20,6 +20,8 @@ Optional properties:
 - ams,enable-internal-i2c-pullup: Boolean property, to enable internal pullup on
        i2c scl/sda pins. Missing this will disable internal pullup on i2c
        scl/sda lines.
+- ams,enable-ac-ok-power-on: Boolean property, to enable exit out of power off
+       mode with AC_OK pin (pin enabled in power off mode).
 
 Optional submodule and their properties:
 =======================================
index 62091f6..188f037 100644 (file)
@@ -44,8 +44,11 @@ Optional properties:
                          board is driving OTG VBus or not.
                          (axp221 / axp223 / axp803/ axp813 only)
 
-- x-powers,master-mode: Boolean (axp806 only). Set this when the PMIC is
-                       wired for master mode. The default is slave mode.
+- x-powers,self-working-mode and
+  x-powers,master-mode: Boolean (axp806 only). Set either of these when the
+                       PMIC is wired for self-working mode or master mode.
+                       If neither is set then slave mode is assumed.
+                       This corresponds to how the MODESET pin is wired.
 
 - <input>-supply: a phandle to the regulator supply node. May be omitted if
                  inputs are unregulated, such as using the IPSOUT output
diff --git a/Documentation/devicetree/bindings/mfd/madera.txt b/Documentation/devicetree/bindings/mfd/madera.txt
new file mode 100644 (file)
index 0000000..db32660
--- /dev/null
@@ -0,0 +1,102 @@
+Cirrus Logic Madera class audio codecs Multi-Functional Device
+
+These devices are audio SoCs with extensive digital capabilities and a range
+of analogue I/O.
+
+See also the child driver bindings in:
+bindings/pinctrl/cirrus,madera-pinctrl.txt
+bindings/regulator/arizona-regulator.txt
+bindings/sound/madera.txt
+
+Required properties:
+
+  - compatible : One of the following chip-specific strings:
+        "cirrus,cs47l35"
+        "cirrus,cs47l85"
+        "cirrus,cs47l90"
+        "cirrus,cs47l91"
+        "cirrus,wm1840"
+
+  - reg : I2C slave address when connected using I2C, chip select number when
+    using SPI.
+
+  - DCVDD-supply : Power supply for the device as defined in
+    bindings/regulator/regulator.txt
+    Mandatory on CS47L35, CS47L90, CS47L91
+    Optional on CS47L85, WM1840
+
+  - AVDD-supply, DBVDD1-supply, DBVDD2-supply, CPVDD1-supply, CPVDD2-supply :
+    Power supplies for the device
+
+  - DBVDD3-supply, DBVDD4-supply : Power supplies for the device
+    (CS47L85, CS47L90, CS47L91, WM1840)
+
+  - SPKVDDL-supply, SPKVDDR-supply : Power supplies for the device
+    (CS47L85, WM1840)
+
+  - SPKVDD-supply : Power supply for the device
+    (CS47L35)
+
+  - interrupt-controller : Indicates that this device is an interrupt controller
+
+  - #interrupt-cells: the number of cells to describe an IRQ, must be 2.
+    The first cell is the IRQ number.
+    The second cell is the flags, encoded as the trigger masks from
+    bindings/interrupt-controller/interrupts.txt
+
+  - gpio-controller : Indicates this device is a GPIO controller.
+
+  - #gpio-cells : Must be 2. The first cell is the pin number. The second cell
+    is reserved for future use and must be zero
+
+  - interrupt-parent : The parent interrupt controller.
+
+  - interrupts : The interrupt line the /IRQ signal for the device is
+    connected to.
+
+Optional properties:
+
+  - MICVDD-supply : Power supply, only need to be specified if
+    powered externally
+
+  - reset-gpios : One entry specifying the GPIO controlling /RESET.
+    As defined in bindings/gpio.txt.
+    Although optional, it is strongly recommended to use a hardware reset
+
+  - MICBIASx : Initial data for the MICBIAS regulators, as covered in
+    Documentation/devicetree/bindings/regulator/regulator.txt.
+    One for each MICBIAS generator (MICBIAS1, MICBIAS2, ...)
+    (all codecs)
+
+    One for each output pin (MICBIAS1A, MIBCIAS1B, MICBIAS2A, ...)
+    (all except CS47L85, WM1840)
+
+    The following following additional property is supported for the generator
+    nodes:
+      - cirrus,ext-cap : Set to 1 if the MICBIAS has external decoupling
+        capacitors attached.
+
+Optional child nodes:
+    micvdd : Node containing initialization data for the micvdd regulator
+    See bindings/regulator/arizona-regulator.txt
+
+    ldo1 : Node containing initialization data for the LDO1 regulator
+    See bindings/regulator/arizona-regulator.txt
+    (cs47l85, wm1840)
+
+Example:
+
+cs47l85@0 {
+       compatible = "cirrus,cs47l85";
+       reg = <0>;
+
+       reset-gpios = <&gpio 0>;
+
+       interrupt-controller;
+       #interrupt-cells = <2>;
+       interrupts = <&host_irq1>;
+       interrupt-parent = <&gic>;
+
+       gpio-controller;
+       #gpio-cells = <2>;
+};
diff --git a/Documentation/devicetree/bindings/mfd/rohm,bd71837-pmic.txt b/Documentation/devicetree/bindings/mfd/rohm,bd71837-pmic.txt
new file mode 100644 (file)
index 0000000..3ca56fd
--- /dev/null
@@ -0,0 +1,62 @@
+* ROHM BD71837 Power Management Integrated Circuit bindings
+
+BD71837MWV is a programmable Power Management IC for powering single-core,
+dual-core, and quad-core SoCs such as NXP-i.MX 8M. It is optimized for
+low BOM cost and compact solution footprint. It integrates 8 Buck
+egulators and 7 LDOs to provide all the power rails required by the SoC and
+the commonly used peripherals.
+
+Datasheet for PMIC is available at:
+https://www.rohm.com/datasheet/BD71837MWV/bd71837mwv-e
+
+Required properties:
+ - compatible          : Should be "rohm,bd71837".
+ - reg                 : I2C slave address.
+ - interrupt-parent    : Phandle to the parent interrupt controller.
+ - interrupts          : The interrupt line the device is connected to.
+ - clocks              : The parent clock connected to PMIC. If this is missing
+                         32768 KHz clock is assumed.
+ - #clock-cells                : Should be 0.
+ - regulators:         : List of child nodes that specify the regulators.
+                         Please see ../regulator/rohm,bd71837-regulator.txt
+
+Optional properties:
+- clock-output-names   : Should contain name for output clock.
+
+Example:
+
+       /* external oscillator node */
+       osc: oscillator {
+               compatible = "fixed-clock";
+               #clock-cells = <1>;
+               clock-frequency  = <32768>;
+               clock-output-names = "osc";
+       };
+
+       pmic: pmic@4b {
+               compatible = "rohm,bd71837";
+               reg = <0x4b>;
+               interrupt-parent = <&gpio1>;
+               interrupts = <29 GPIO_ACTIVE_LOW>;
+               interrupt-names = "irq";
+               #clock-cells = <0>;
+               clocks = <&osc 0>;
+               clock-output-names = "bd71837-32k-out";
+
+               regulators {
+                       buck1: BUCK1 {
+                               regulator-name = "buck1";
+                               regulator-min-microvolt = <700000>;
+                               regulator-max-microvolt = <1300000>;
+                               regulator-boot-on;
+                               regulator-ramp-delay = <1250>;
+                       };
+               };
+       };
+
+       /* Clock consumer node */
+       rtc@0 {
+               compatible = "company,my-rtc";
+               clock-names = "my-clock";
+               clocks = <&pmic>;
+       };
index 8af1202..4f62143 100644 (file)
@@ -22,7 +22,7 @@ Required properties:
   The valid regulator-compatible values are:
   tps65910: vrtc, vio, vdd1, vdd2, vdd3, vdig1, vdig2, vpll, vdac, vaux1,
             vaux2, vaux33, vmmc, vbb
-  tps65911: vrtc, vio, vdd1, vdd3, vddctrl, ldo1, ldo2, ldo3, ldo4, ldo5,
+  tps65911: vrtc, vio, vdd1, vdd2, vddctrl, ldo1, ldo2, ldo3, ldo4, ldo5,
             ldo6, ldo7, ldo8
 
 - xxx-supply: Input voltage supply regulator.
index 132e000..e9cb3ec 100644 (file)
@@ -16,6 +16,8 @@ Required properties:
    * "allwinner,sun9i-a80-mmc"
    * "allwinner,sun50i-a64-emmc"
    * "allwinner,sun50i-a64-mmc"
+   * "allwinner,sun50i-h6-emmc", "allwinner.sun50i-a64-emmc"
+   * "allwinner,sun50i-h6-mmc", "allwinner.sun50i-a64-mmc"
  - reg : mmc controller base registers
  - clocks : a list with 4 phandle + clock specifier pairs
  - clock-names : must contain "ahb", "mmc", "output" and "sample"
index cfe7243..5bb3a18 100644 (file)
@@ -19,8 +19,6 @@ Required properties:
 - reset-names: must be "stmmaceth"
 - phy-mode: See ethernet.txt
 - phy-handle: See ethernet.txt
-- #address-cells: shall be 1
-- #size-cells: shall be 0
 - syscon: A phandle to the device containing the EMAC or GMAC clock register
 
 Optional properties:
@@ -86,8 +84,6 @@ emac: ethernet@1c0b000 {
        reset-names = "stmmaceth";
        clocks = <&ccu CLK_BUS_EMAC>;
        clock-names = "stmmaceth";
-       #address-cells = <1>;
-       #size-cells = <0>;
 
        phy-handle = <&int_mii_phy>;
        phy-mode = "mii";
@@ -137,8 +133,6 @@ emac: ethernet@1c0b000 {
        reset-names = "stmmaceth";
        clocks = <&ccu CLK_BUS_EMAC>;
        clock-names = "stmmaceth";
-       #address-cells = <1>;
-       #size-cells = <0>;
 
        phy-handle = <&ext_rgmii_phy>;
        phy-mode = "rgmii";
@@ -191,8 +185,6 @@ emac: ethernet@1c0b000 {
        reset-names = "stmmaceth";
        clocks = <&ccu CLK_BUS_EMAC>;
        clock-names = "stmmaceth";
-       #address-cells = <1>;
-       #size-cells = <0>;
 
        phy-handle = <&ext_rgmii_phy>;
        phy-mode = "rgmii";
index 5b93740..92f399e 100644 (file)
@@ -2,7 +2,7 @@
 
 Required properties:
 - compatible: Should be "nxp,pn544-i2c".
-- clock-frequency: I²C work frequency.
+- clock-frequency: I²C work frequency.
 - reg: address on the bus
 - interrupts: GPIO interrupt to which the chip is connected
 - enable-gpios: Output GPIO pin used for enabling/disabling the PN544
diff --git a/Documentation/devicetree/bindings/pinctrl/cirrus,madera-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/cirrus,madera-pinctrl.txt
new file mode 100644 (file)
index 0000000..b0e36cf
--- /dev/null
@@ -0,0 +1,99 @@
+Cirrus Logic Madera class audio codecs pinctrl driver
+
+The Cirrus Logic Madera codecs provide a number of GPIO functions for
+interfacing to external hardware and to provide logic outputs to other devices.
+Certain groups of GPIO pins also have an alternate function, normally as an
+audio interface.
+
+The set of available GPIOs, functions and alternate function groups differs
+between codecs so refer to the datasheet for the codec for further information
+on what is supported on that device.
+
+The properties for this driver exist within the parent MFD driver node.
+
+See also
+  the core bindings for the parent MFD driver:
+    Documentation/devicetree/bindings/mfd/madera.txt
+
+  the generic pinmix bindings:
+    Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
+
+Required properties of parent mfd node:
+  - pinctrl-names : must be "default"
+  - pinctrl-0 : a phandle to the node containing the subnodes containing default
+      configurations
+
+Required subnodes:
+  One subnode is required to contain the default settings. It contains an
+  arbitrary number of configuration subnodes, one for each group or pin
+  configuration you want to apply as a default.
+
+Required properties of configuration subnodes:
+  - groups : name of one pin group to configure. One of:
+       aif1, aif2, aif3, aif4, mif1, mif2, mif3, pdmspk1, pdmspk2,
+       dmic4, dmic5, dmic6,
+       gpio1, gpio2, ..., gpio40
+    The gpioN groups select the single pin of this name for configuration
+
+Optional properties of configuration subnodes:
+  Any configuration option not explicitly listed in the dts will be left at
+  chip default setting.
+
+  - function : name of function to assign to this group. One of:
+       aif1, aif2, aif3, aif4, mif1, mif2, mif3, pdmspk1, pdmspk2,
+       dmic3, dmic4, dmic5, dmic6,
+       io, dsp-gpio, irq1, irq2,
+       fll1-clk, fll1-lock, fll2-clk, fll2-lock, fll3-clk, fll3-lock,
+       fllao-clk, fllao-lock,
+       opclk, opclk-async, pwm1, pwm2, spdif,
+       asrc1-in1-lock, asrc1-in2-lock, asrc2-in1-lock, asrc2-in2-lock,
+       spkl-short-circuit, spkr-short-circuit, spk-shutdown,
+       spk-overheat-shutdown, spk-overheat-warn,
+       timer1-sts, timer2-sts, timer3-sts, timer4-sts, timer5-sts, timer6-sts,
+       timer7-sts, timer8-sts,
+       log1-fifo-ne, log2-fifo-ne, log3-fifo-ne, log4-fifo-ne, log5-fifo-ne,
+       log6-fifo-ne, log7-fifo-ne, log8-fifo-ne,
+
+  - bias-disable : disable pull-up and pull-down
+  - bias-bus-hold : enable buskeeper
+  - bias-pull-up : output is pulled-up
+  - bias-pull-down : output is pulled-down
+  - drive-push-pull : CMOS output
+  - drive-open-drain : open-drain output
+  - drive-strength : drive strength in mA. Valid values are 4 or 8
+  - input-schmitt-enable : enable schmitt-trigger mode
+  - input-schmitt-disable : disable schmitt-trigger mode
+  - input-debounce : A value of 0 disables debounce, a value !=0 enables
+       debounce
+  - output-low : set the pin to output mode with low level
+  - output-high : set the pin to output mode with high level
+
+Example:
+
+cs47l85@0 {
+       compatible = "cirrus,cs47l85";
+
+       pinctrl-names = "default";
+       pinctrl-0 = <&cs47l85_defaults>;
+
+       cs47l85_defaults: cs47l85-gpio-defaults {
+               aif1 {
+                       groups = "aif1";
+                       function = "aif1";
+                       bias-bus-hold;
+               };
+
+               aif2 {
+                       groups = "aif2";
+                       function = "aif2";
+                       bias-bus-hold;
+               };
+
+               opclk {
+                       groups = "gpio1";
+                       function = "opclk";
+                       bias-pull-up;
+                       drive-strength = <8>;
+               };
+       };
+};
diff --git a/Documentation/devicetree/bindings/power/reset/qcom,pon.txt b/Documentation/devicetree/bindings/power/reset/qcom,pon.txt
new file mode 100644 (file)
index 0000000..651491b
--- /dev/null
@@ -0,0 +1,45 @@
+Qualcomm PON Device
+
+The Power On device for Qualcomm PM8xxx is MFD supporting pwrkey
+and resin along with the Android reboot-mode.
+
+This DT node has pwrkey and resin as sub nodes.
+
+Required Properties:
+-compatible: "qcom,pm8916-pon"
+-reg: Specifies the physical address of the pon register
+
+Optional subnode:
+-pwrkey: Specifies the subnode pwrkey and should follow the
+ qcom,pm8941-pwrkey.txt description.
+-resin: Specifies the subnode resin and should follow the
+ qcom,pm8xxx-pwrkey.txt description.
+
+The rest of the properties should follow the generic reboot-mode description
+found in reboot-mode.txt
+
+Example:
+
+       pon@800 {
+               compatible = "qcom,pm8916-pon";
+
+               reg = <0x800>;
+               mode-bootloader = <0x2>;
+               mode-recovery = <0x1>;
+
+               pwrkey {
+                       compatible = "qcom,pm8941-pwrkey";
+                       interrupts = <0x0 0x8 0 IRQ_TYPE_EDGE_BOTH>;
+                       debounce = <15625>;
+                       bias-pull-up;
+                       linux,code = <KEY_POWER>;
+               };
+
+               resin {
+                       compatible = "qcom,pm8941-resin";
+                       interrupts = <0x0 0x8 1 IRQ_TYPE_EDGE_BOTH>;
+                       debounce = <15625>;
+                       bias-pull-up;
+                       linux,code = <KEY_VOLUMEDOWN>;
+               };
+       };
diff --git a/Documentation/devicetree/bindings/power/supply/maxim,ds2760.txt b/Documentation/devicetree/bindings/power/supply/maxim,ds2760.txt
new file mode 100644 (file)
index 0000000..55967a0
--- /dev/null
@@ -0,0 +1,26 @@
+Devicetree bindings for Maxim DS2760
+====================================
+
+The ds2760 is a w1 slave device and must hence have its sub-node in DT
+under a w1 bus master node.
+
+The device exposes a power supply, so the details described in
+Documentation/devicetree/bindings/power/supply/power_supply.txt apply.
+
+Required properties:
+- compatible: must be "maxim,ds2760"
+
+Optional properties:
+- power-supplies:      Refers to one or more power supplies connected to
+                       this battery.
+- maxim,pmod-enabled:  This boolean property enables the DS2760 to enter
+                       sleep mode when the DQ line goes low for greater
+                       than 2 seconds and leave sleep Mode when the DQ
+                       line goes high.
+- maxim,cache-time-ms: Time im milliseconds to cache the data for. When
+                       this time expires, the values are read again from
+                       the hardware. Defaults to 1000.
+- rated-capacity-microamp-hours:
+                       The rated capacity of the battery, in mAh.
+                       If not specified, the value stored in the
+                       non-volatile chip memory is used.
index c40e892..4e78e51 100644 (file)
@@ -2,7 +2,11 @@ SBS sbs-battery
 ~~~~~~~~~~
 
 Required properties :
- - compatible : "sbs,sbs-battery"
+ - compatible: "<vendor>,<part-number>", "sbs,sbs-battery" as fallback. The
+     part number compatible string might be used in order to take care of
+     vendor specific registers.
+     Known <vendor>,<part-number>:
+       ti,bq20z75
 
 Optional properties :
  - sbs,i2c-retry-count : The number of times to retry i2c transactions on i2c
@@ -14,9 +18,9 @@ Optional properties :
 
 Example:
 
-       bq20z75@b {
-               compatible = "sbs,sbs-battery";
-               reg = < 0xb >;
+       battery@b {
+               compatible = "ti,bq20z75", "sbs,sbs-battery";
+               reg = <0xb>;
                sbs,i2c-retry-count = <2>;
                sbs,poll-retry-count = <10>;
                sbs,battery-detect-gpios = <&gpio-controller 122 1>;
index 3899d6a..576ad00 100644 (file)
@@ -16,7 +16,10 @@ modes in device tree.
 
 
 Required properties:
-- compatible: Should be "fsl,vf610-ftm-pwm".
+- compatible : should be "fsl,<soc>-ftm-pwm" and one of the following
+   compatible strings:
+  - "fsl,vf610-ftm-pwm" for PWM compatible with the one integrated on VF610
+  - "fsl,imx8qm-ftm-pwm" for PWM compatible with the one integrated on i.MX8QM
 - reg: Physical base address and length of the controller's registers
 - #pwm-cells: Should be 3. See pwm.txt in this directory for a description of
   the cells format.
index ef8bd3c..991728c 100644 (file)
@@ -5,11 +5,13 @@ Required properties:
    - "mediatek,mt2712-pwm": found on mt2712 SoC.
    - "mediatek,mt7622-pwm": found on mt7622 SoC.
    - "mediatek,mt7623-pwm": found on mt7623 SoC.
+   - "mediatek,mt7628-pwm": found on mt7628 SoC.
  - reg: physical base address and length of the controller's registers.
  - #pwm-cells: must be 2. See pwm.txt in this directory for a description of
    the cell format.
  - clocks: phandle and clock specifier of the PWM reference clock.
- - clock-names: must contain the following:
+ - clock-names: must contain the following, except for MT7628 which
+                has no clocks
    - "top": the top clock generator
    - "main": clock used by the PWM core
    - "pwm1-8": the eight per PWM clocks for mt2712
index 35a3b97..e1ef6af 100644 (file)
@@ -12,6 +12,7 @@ Required Properties:
  - "renesas,pwm-r8a7795": for R-Car H3
  - "renesas,pwm-r8a7796": for R-Car M3-W
  - "renesas,pwm-r8a77965": for R-Car M3-N
+ - "renesas,pwm-r8a77990": for R-Car E3
  - "renesas,pwm-r8a77995": for R-Car D3
 - reg: base address and length of the registers block for the PWM.
 - #pwm-cells: should be 2. See pwm.txt in this directory for a description of
index 16291f2..bac4afa 100644 (file)
@@ -49,7 +49,7 @@ compatible (optional) - standard definition
     - may contain the following strings:
         - shared-dma-pool: This indicates a region of memory meant to be
           used as a shared pool of DMA buffers for a set of devices. It can
-          be used by an operating system to instanciate the necessary pool
+          be used by an operating system to instantiate the necessary pool
           management subsystem if necessary.
         - vendor specific string in the form <vendor>,[<device>-]<usage>
 no-map (optional) - empty property
diff --git a/Documentation/devicetree/bindings/reset/amlogic,meson-axg-audio-arb.txt b/Documentation/devicetree/bindings/reset/amlogic,meson-axg-audio-arb.txt
new file mode 100644 (file)
index 0000000..26e542e
--- /dev/null
@@ -0,0 +1,21 @@
+* Amlogic audio memory arbiter controller
+
+The Amlogic Audio ARB is a simple device which enables or
+disables the access of Audio FIFOs to DDR on AXG based SoC.
+
+Required properties:
+- compatible: 'amlogic,meson-axg-audio-arb'
+- reg: physical base address of the controller and length of memory
+       mapped region.
+- clocks: phandle to the fifo peripheral clock provided by the audio
+         clock controller.
+- #reset-cells: must be 1.
+
+Example on the A113 SoC:
+
+arb: reset-controller@280 {
+       compatible = "amlogic,meson-axg-audio-arb";
+       reg = <0x0 0x280 0x0 0x4>;
+       #reset-cells = <1>;
+       clocks = <&clkc_audio AUD_CLKID_DDR_ARB>;
+};
diff --git a/Documentation/devicetree/bindings/reset/qcom,aoss-reset.txt b/Documentation/devicetree/bindings/reset/qcom,aoss-reset.txt
new file mode 100644 (file)
index 0000000..510c748
--- /dev/null
@@ -0,0 +1,52 @@
+Qualcomm AOSS Reset Controller
+======================================
+
+This binding describes a reset-controller found on AOSS-CC (always on subsystem)
+for Qualcomm SDM845 SoCs.
+
+Required properties:
+- compatible:
+       Usage: required
+       Value type: <string>
+       Definition: must be:
+                   "qcom,sdm845-aoss-cc"
+
+- reg:
+       Usage: required
+       Value type: <prop-encoded-array>
+       Definition: must specify the base address and size of the register
+                   space.
+
+- #reset-cells:
+       Usage: required
+       Value type: <uint>
+       Definition: must be 1; cell entry represents the reset index.
+
+Example:
+
+aoss_reset: reset-controller@c2a0000 {
+       compatible = "qcom,sdm845-aoss-cc";
+       reg = <0xc2a0000 0x31000>;
+       #reset-cells = <1>;
+};
+
+Specifying reset lines connected to IP modules
+==============================================
+
+Device nodes that need access to reset lines should
+specify them as a reset phandle in their corresponding node as
+specified in reset.txt.
+
+For list of all valid reset indicies see
+<dt-bindings/reset/qcom,sdm845-aoss.h>
+
+Example:
+
+modem-pil@4080000 {
+       ...
+
+       resets = <&aoss_reset AOSS_CC_MSS_RESTART>;
+       reset-names = "mss_restart";
+
+       ...
+};
index 93efed6..101743d 100644 (file)
@@ -118,3 +118,59 @@ Example:
 
                other nodes ...
        };
+
+
+USB3 core reset
+---------------
+
+USB3 core reset belongs to USB3 glue layer. Before using the core reset,
+it is necessary to control the clocks and resets to enable this layer.
+These clocks and resets should be described in each property.
+
+Required properties:
+- compatible: Should be
+    "socionext,uniphier-pro4-usb3-reset" - for Pro4 SoC
+    "socionext,uniphier-pxs2-usb3-reset" - for PXs2 SoC
+    "socionext,uniphier-ld20-usb3-reset" - for LD20 SoC
+    "socionext,uniphier-pxs3-usb3-reset" - for PXs3 SoC
+- #reset-cells: Should be 1.
+- reg: Specifies offset and length of the register set for the device.
+- clocks: A list of phandles to the clock gate for USB3 glue layer.
+       According to the clock-names, appropriate clocks are required.
+- clock-names: Should contain
+    "gio", "link" - for Pro4 SoC
+    "link"        - for others
+- resets: A list of phandles to the reset control for USB3 glue layer.
+       According to the reset-names, appropriate resets are required.
+- reset-names: Should contain
+    "gio", "link" - for Pro4 SoC
+    "link"        - for others
+
+Example:
+
+       usb-glue@65b00000 {
+               compatible = "socionext,uniphier-ld20-dwc3-glue",
+                            "simple-mfd";
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges = <0 0x65b00000 0x400>;
+
+               usb_rst: reset@0 {
+                       compatible = "socionext,uniphier-ld20-usb3-reset";
+                       reg = <0x0 0x4>;
+                       #reset-cells = <1>;
+                       clock-names = "link";
+                       clocks = <&sys_clk 14>;
+                       reset-names = "link";
+                       resets = <&sys_rst 14>;
+               };
+
+               regulator {
+                       ...
+               };
+
+               phy {
+                       ...
+               };
+               ...
+       };
diff --git a/Documentation/devicetree/bindings/rtc/isil,isl1219.txt b/Documentation/devicetree/bindings/rtc/isil,isl1219.txt
new file mode 100644 (file)
index 0000000..c3efd48
--- /dev/null
@@ -0,0 +1,29 @@
+Intersil ISL1219 I2C RTC/Alarm chip with event in
+
+ISL1219 has additional pins EVIN and #EVDET for tamper detection.
+
+Required properties supported by the device:
+
+ - "compatible": must be "isil,isl1219"
+ - "reg": I2C bus address of the device
+
+Optional properties:
+
+ - "interrupt-names": list which may contains "irq" and "evdet"
+ - "interrupts": list of interrupts for "irq" and "evdet"
+ - "isil,ev-evienb": if present EV.EVIENB bit is set to the specified
+                     value for proper operation.
+
+
+Example isl1219 node with #IRQ pin connected to SoC gpio1 pin12
+ and #EVDET pin connected to SoC gpio2 pin 24:
+
+       isl1219: rtc@68 {
+               compatible = "isil,isl1219";
+               reg = <0x68>;
+               interrupt-names = "irq", "evdet";
+               interrupts-extended = <&gpio1 12 IRQ_TYPE_EDGE_FALLING>,
+                       <&gpio2 24 IRQ_TYPE_EDGE_FALLING>;
+               isil,ev-evienb = <1>;
+       };
+
index 226cc93..eebfbe0 100644 (file)
@@ -13,6 +13,7 @@ Required properties:
        "maxim,ds3231",
        "st,m41t0",
        "st,m41t00",
+       "st,m41t11",
        "microchip,mcp7940x",
        "microchip,mcp7941x",
        "pericom,pt7c4338",
index bf80e3f..f9987c3 100644 (file)
@@ -19,6 +19,7 @@ IP Pairing
 Required properties in pwrap device node.
 - compatible:
        "mediatek,mt2701-pwrap" for MT2701/7623 SoCs
+       "mediatek,mt6797-pwrap" for MT6797 SoCs
        "mediatek,mt7622-pwrap" for MT7622 SoCs
        "mediatek,mt8135-pwrap" for MT8135 SoCs
        "mediatek,mt8173-pwrap" for MT8173 SoCs
index 93b982e..feef39b 100644 (file)
@@ -17,20 +17,18 @@ Example:
 
        /* upstream device */
 
-       ssp0: ssp@41000000 {
+       ssp1: ssp@41000000 {
                compatible = "mrvl,pxa3xx-ssp";
                reg = <0x41000000 0x40>;
                interrupts = <24>;
                clock-names = "pxa27x-ssp.0";
-               dmas = <&dma 13
-                       &dma 14>;
-               dma-names = "rx", "tx";
        };
 
        /* DAI as user */
 
        ssp_dai0: ssp_dai@0 {
                compatible = "mrvl,pxa-ssp-dai";
-               port = <&ssp0>;
+               port = <&ssp1>;
+               #sound-dai-cells = <0>;
        };
 
index d087f04..c51ade8 100644 (file)
@@ -10,8 +10,14 @@ Controller Node
 
 Required properties:
 - compatible : should be:
-    - "allwinner,sun4i-a10-sram-controller"
-    - "allwinner,sun50i-a64-sram-controller"
+    - "allwinner,sun4i-a10-sram-controller" (deprecated)
+    - "allwinner,sun4i-a10-system-control"
+    - "allwinner,sun5i-a13-system-control"
+    - "allwinner,sun7i-a20-system-control", "allwinner,sun4i-a10-system-control"
+    - "allwinner,sun8i-a23-system-control"
+    - "allwinner,sun8i-h3-system-control"
+    - "allwinner,sun50i-a64-sram-controller" (deprecated)
+    - "allwinner,sun50i-a64-system-control"
 - reg : sram controller register offset + length
 
 SRAM nodes
@@ -26,8 +32,25 @@ once again the representation described in the mmio-sram binding.
 
 The valid sections compatible for A10 are:
     - allwinner,sun4i-a10-sram-a3-a4
+    - allwinner,sun4i-a10-sram-c1
     - allwinner,sun4i-a10-sram-d
 
+The valid sections compatible for A13 are:
+    - allwinner,sun5i-a13-sram-a3-a4, allwinner,sun4i-a10-sram-a3-a4
+    - allwinner,sun5i-a13-sram-c1, allwinner,sun4i-a10-sram-c1
+    - allwinner,sun5i-a13-sram-d, allwinner,sun4i-a10-sram-d
+
+The valid sections compatible for A20 are:
+    - allwinner,sun7i-a20-sram-a3-a4, allwinner,sun4i-a10-sram-a3-a4
+    - allwinner,sun7i-a20-sram-c1, allwinner,sun4i-a10-sram-c1
+    - allwinner,sun7i-a20-sram-d, allwinner,sun4i-a10-sram-d
+
+The valid sections compatible for A23/A33 are:
+    - allwinner,sun8i-a23-sram-c1, allwinner,sun4i-a10-sram-c1
+
+The valid sections compatible for H3 are:
+    - allwinner,sun8i-h3-sram-c1, allwinner,sun4i-a10-sram-c1
+
 The valid sections compatible for A64 are:
     - allwinner,sun50i-a64-sram-c
 
@@ -47,8 +70,8 @@ This valid values for this argument are:
 
 Example
 -------
-sram-controller@1c00000 {
-       compatible = "allwinner,sun4i-a10-sram-controller";
+system-control@1c00000 {
+       compatible = "allwinner,sun4i-a10-system-control";
        reg = <0x01c00000 0x30>;
        #address-cells = <1>;
        #size-cells = <1>;
index cc553f0..eb7ee91 100644 (file)
@@ -97,8 +97,8 @@ get assigned to trip points of the zone. The cooling devices are expected
 to be loaded in the target system.
 
 Required properties:
-- cooling-device:      A phandle of a cooling device with its specifier,
-  Type: phandle +      referring to which cooling device is used in this
+- cooling-device:      A list of phandles of cooling devices with their specifiers,
+  Type: phandle +      referring to which cooling devices are used in this
     cooling specifier  binding. In the cooling specifier, the first cell
                        is the minimum cooling state and the second cell
                        is the maximum cooling state used in this map.
@@ -276,12 +276,7 @@ thermal-zones {
                        };
                        map1 {
                                trip = <&cpu_alert1>;
-                               cooling-device = <&fan0 5 THERMAL_NO_LIMIT>;
-                       };
-                       map2 {
-                               trip = <&cpu_alert1>;
-                               cooling-device =
-                                   <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+                               cooling-device = <&fan0 5 THERMAL_NO_LIMIT>, <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
                        };
                };
        };
diff --git a/Documentation/devicetree/bindings/timer/ti,davinci-timer.txt b/Documentation/devicetree/bindings/timer/ti,davinci-timer.txt
new file mode 100644 (file)
index 0000000..29bf91c
--- /dev/null
@@ -0,0 +1,37 @@
+* Device tree bindings for Texas Instruments DaVinci timer
+
+This document provides bindings for the 64-bit timer in the DaVinci
+architecture devices. The timer can be configured as a general-purpose 64-bit
+timer, dual general-purpose 32-bit timers. When configured as dual 32-bit
+timers, each half can operate in conjunction (chain mode) or independently
+(unchained mode) of each other.
+
+The timer is a free running up-counter and can generate interrupts when the
+counter reaches preset counter values.
+
+Also see ../watchdog/davinci-wdt.txt for timers that are configurable as
+watchdog timers.
+
+Required properties:
+
+- compatible : should be "ti,da830-timer".
+- reg : specifies base physical address and count of the registers.
+- interrupts : interrupts generated by the timer.
+- interrupt-names: should be "tint12", "tint34", "cmpint0", "cmpint1",
+                  "cmpint2", "cmpint3", "cmpint4", "cmpint5", "cmpint6",
+                  "cmpint7" ("cmpintX" may be omitted if not present in the
+                  hardware).
+- clocks : the clock feeding the timer clock.
+
+Example:
+
+       clocksource: timer@20000 {
+               compatible = "ti,da830-timer";
+               reg = <0x20000 0x1000>;
+               interrupts = <21>, <22>, <74>, <75>, <76>, <77>, <78>, <79>,
+                            <80>, <81>;
+               interrupt-names = "tint12", "tint34", "cmpint0", "cmpint1",
+                                 "cmpint2", "cmpint3", "cmpint4", "cmpint5",
+                                 "cmpint6", "cmpint7";
+               clocks = <&pll0_auxclk>;
+       };
index 2f36205..2c3fc51 100644 (file)
@@ -142,6 +142,7 @@ 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.
 gmt    Global Mixed-mode Technology, Inc.
@@ -200,6 +201,7 @@ 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
@@ -279,6 +281,7 @@ 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.
@@ -322,6 +325,7 @@ rohm        ROHM Semiconductor Co., Ltd
 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
@@ -401,6 +405,7 @@ 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
index 3709190..3d6554e 100644 (file)
@@ -13,10 +13,15 @@ Optional properties:
  - linux,open-drain: if specified, the data pin is considered in
                     open-drain mode.
 
+Also refer to the generic w1.txt document.
+
 Examples:
 
        onewire {
                compatible = "w1-gpio";
-               gpios = <&gpio 126 0>, <&gpio 105 0>;
-       };
+               gpios = <&gpio 0 GPIO_ACTIVE_HIGH>;
 
+               battery {
+                       // ...
+               };
+       };
diff --git a/Documentation/devicetree/bindings/w1/w1.txt b/Documentation/devicetree/bindings/w1/w1.txt
new file mode 100644 (file)
index 0000000..05f26b2
--- /dev/null
@@ -0,0 +1,25 @@
+Generic devicetree bindings for onewire (w1) busses
+===================================================
+
+Onewire busses are described through nodes of their master bus controller.
+Slave devices are listed as sub-nodes of such master devices. For now, only
+one slave is allowed per bus master.
+
+
+Example:
+
+       charger: charger {
+               compatible = "gpio-charger";
+               charger-type = "mains";
+               gpios = <&gpio 1 GPIO_ACTIVE_LOW>;
+       };
+
+       onewire {
+               compatible = "w1-gpio";
+               gpios = <&gpio 100 0>, <&gpio 101 0>;
+
+               battery {
+                       compatible = "maxim,ds2760";
+                       power-supplies = <&charger>;
+               };
+       };
index 4adc056..70e180e 100644 (file)
@@ -118,8 +118,7 @@ PIO data read/write
 All bmdma-style drivers must implement this hook. This is the low-level
 operation that actually copies the data bytes during a PIO data
 transfer. Typically the driver will choose one of
-:c:func:`ata_sff_data_xfer_noirq`, :c:func:`ata_sff_data_xfer`, or
-:c:func:`ata_sff_data_xfer32`.
+:c:func:`ata_sff_data_xfer`, or :c:func:`ata_sff_data_xfer32`.
 
 ATA command execute
 ~~~~~~~~~~~~~~~~~~~
index 2c00b07..1e10579 100644 (file)
@@ -66,17 +66,17 @@ early userspace image can be built by an unprivileged user.
 
 As a technical note, when directories and files are specified, the
 entire CONFIG_INITRAMFS_SOURCE is passed to
-scripts/gen_initramfs_list.sh.  This means that CONFIG_INITRAMFS_SOURCE
+usr/gen_initramfs_list.sh.  This means that CONFIG_INITRAMFS_SOURCE
 can really be interpreted as any legal argument to
 gen_initramfs_list.sh.  If a directory is specified as an argument then
 the contents are scanned, uid/gid translation is performed, and
 usr/gen_init_cpio file directives are output.  If a directory is
-specified as an argument to scripts/gen_initramfs_list.sh then the
+specified as an argument to usr/gen_initramfs_list.sh then the
 contents of the file are simply copied to the output.  All of the output
 directives from directory scanning and file contents copying are
 processed by usr/gen_init_cpio.
 
-See also 'scripts/gen_initramfs_list.sh -h'.
+See also 'usr/gen_initramfs_list.sh -h'.
 
 Where's this all leading?
 =========================
index d4d642e..62af305 100644 (file)
@@ -18,9 +18,10 @@ made available by the underlying graphics card are also possible.
 A. Configuration
 
        The framebuffer console can be enabled by using your favorite kernel
-configuration tool.  It is under Device Drivers->Graphics Support->Support for
-framebuffer devices->Framebuffer Console Support. Select 'y' to compile
-support statically, or 'm' for module support.  The module will be fbcon.
+configuration tool.  It is under Device Drivers->Graphics Support->Frame
+buffer Devices->Console display driver support->Framebuffer Console Support.
+Select 'y' to compile support statically or 'm' for module support.  The
+module will be fbcon.
 
        In order for fbcon to activate, at least one framebuffer driver is
 required, so choose from any of the numerous drivers available. For x86
@@ -29,10 +30,10 @@ always be available. However, using a chipset-specific driver will give you
 more speed and features, such as the ability to change the video mode
 dynamically.
 
-       To display the penguin logo, choose any logo available in Logo
-Configuration->Boot up logo.
+       To display the penguin logo, choose any logo available in Graphics
+support->Bootup logo.
 
-       Also, you will need to select at least one compiled-in fonts, but if
+       Also, you will need to select at least one compiled-in font, but if
 you don't do anything, the kernel configuration tool will select one for you,
 usually an 8x16 font.
 
@@ -135,16 +136,16 @@ C. Boot options
 
        The angle can be changed anytime afterwards by 'echoing' the same
        numbers to any one of the 2 attributes found in
-        /sys/class/graphics/fbcon
+       /sys/class/graphics/fbcon:
 
                rotate     - rotate the display of the active console
                rotate_all - rotate the display of all consoles
 
-       Console rotation will only become available if Console Rotation
-       Support is compiled in your kernel.
+       Console rotation will only become available if Framebuffer Console
+       Rotation support is compiled in your kernel.
 
        NOTE: This is purely console rotation.  Any other applications that
-       use the framebuffer will remain at their 'normal'orientation.
+       use the framebuffer will remain at their 'normal' orientation.
        Actually, the underlying fb driver is totally ignorant of console
        rotation.
 
@@ -164,7 +165,7 @@ C. Boot options
 
 C. Attaching, Detaching and Unloading
 
-Before going on how to attach, detach and unload the framebuffer console, an
+Before going on to how to attach, detach and unload the framebuffer console, an
 illustration of the dependencies may help.
 
 The console layer, as with most subsystems, needs a driver that interfaces with
@@ -182,7 +183,7 @@ because fbcon is an intermediate layer between the console and the drivers:
 
 console ---> fbcon ---> fbdev drivers ---> hardware
 
-The fbdev drivers cannot be unloaded if it's bound to fbcon, and fbcon cannot
+The fbdev drivers cannot be unloaded if bound to fbcon, and fbcon cannot
 be unloaded if it's bound to the console layer.
 
 So to unload the fbdev drivers, one must first unbind fbcon from the console,
@@ -232,7 +233,7 @@ restored properly. The following is one of the several methods that you can do:
        echo 0 > /sys/class/vtconsole/vtcon1/bind
 
 6. That's it, you're back to VGA mode. And if you compiled fbcon as a module,
-   you can unload it by 'rmmod fbcon'
+   you can unload it by 'rmmod fbcon'.
 
 7. To reattach fbcon:
 
@@ -290,7 +291,7 @@ Samples:
 ========
 
 Here are 2 sample bash scripts that you can use to bind or unbind the
-framebuffer console driver if you are in an X86 box:
+framebuffer console driver if you are on an X86 box:
 
 ---------------------------------------------------------------------------
 #!/bin/bash
index 9e6f19e..efea228 100644 (file)
@@ -21,8 +21,7 @@ prototypes:
        char *(*d_dname)((struct dentry *dentry, char *buffer, int buflen);
        struct vfsmount *(*d_automount)(struct path *path);
        int (*d_manage)(const struct path *, bool);
-       struct dentry *(*d_real)(struct dentry *, const struct inode *,
-                                unsigned int, unsigned int);
+       struct dentry *(*d_real)(struct dentry *, const struct inode *);
 
 locking rules:
                rename_lock     ->d_lock        may block       rcu-walk
index 69f8de9..e5edd29 100644 (file)
@@ -157,6 +157,24 @@ data_flush             Enable data flushing before checkpoint in order to
                        persist data of regular and symlink.
 fault_injection=%d     Enable fault injection in all supported types with
                        specified injection rate.
+fault_type=%d          Support configuring fault injection type, should be
+                       enabled with fault_injection option, fault type value
+                       is shown below, it supports single or combined type.
+                       Type_Name               Type_Value
+                       FAULT_KMALLOC           0x000000001
+                       FAULT_KVMALLOC          0x000000002
+                       FAULT_PAGE_ALLOC                0x000000004
+                       FAULT_PAGE_GET          0x000000008
+                       FAULT_ALLOC_BIO         0x000000010
+                       FAULT_ALLOC_NID         0x000000020
+                       FAULT_ORPHAN            0x000000040
+                       FAULT_BLOCK             0x000000080
+                       FAULT_DIR_DEPTH         0x000000100
+                       FAULT_EVICT_INODE       0x000000200
+                       FAULT_TRUNCATE          0x000000400
+                       FAULT_IO                        0x000000800
+                       FAULT_CHECKPOINT                0x000001000
+                       FAULT_DISCARD           0x000002000
 mode=%s                Control block allocation mode which supports "adaptive"
                        and "lfs". In "lfs" mode, there should be no random
                        writes towards main area.
index 72615a2..51c136c 100644 (file)
@@ -10,10 +10,6 @@ union-filesystems).  An overlay-filesystem tries to present a
 filesystem which is the result over overlaying one filesystem on top
 of the other.
 
-The result will inevitably fail to look exactly like a normal
-filesystem for various technical reasons.  The expectation is that
-many use cases will be able to ignore these differences.
-
 
 Overlay objects
 ---------------
@@ -266,6 +262,30 @@ rightmost one and going left.  In the above example lower1 will be the
 top, lower2 the middle and lower3 the bottom layer.
 
 
+Metadata only copy up
+--------------------
+
+When metadata only copy up feature is enabled, overlayfs will only copy
+up metadata (as opposed to whole file), when a metadata specific operation
+like chown/chmod is performed. Full file will be copied up later when
+file is opened for WRITE operation.
+
+In other words, this is delayed data copy up operation and data is copied
+up when there is a need to actually modify data.
+
+There are multiple ways to enable/disable this feature. A config option
+CONFIG_OVERLAY_FS_METACOPY can be set/unset to enable/disable this feature
+by default. Or one can enable/disable it at module load time with module
+parameter metacopy=on/off. Lastly, there is also a per mount option
+metacopy=on/off to enable/disable this feature per mount.
+
+Do not use metacopy=on with untrusted upper/lower directories. Otherwise
+it is possible that an attacker can create a handcrafted file with
+appropriate REDIRECT and METACOPY xattrs, and gain access to file on lower
+pointed by REDIRECT. This should not be possible on local system as setting
+"trusted." xattrs will require CAP_SYS_ADMIN. But it should be possible
+for untrusted layers like from a pen drive.
+
 Sharing and copying layers
 --------------------------
 
@@ -284,7 +304,7 @@ though it will not result in a crash or deadlock.
 Mounting an overlay using an upper layer path, where the upper layer path
 was previously used by another mounted overlay in combination with a
 different lower layer path, is allowed, unless the "inodes index" feature
-is enabled.
+or "metadata only copy up" feature is enabled.
 
 With the "inodes index" feature, on the first time mount, an NFS file
 handle of the lower layer root directory, along with the UUID of the lower
@@ -297,6 +317,10 @@ lower root origin, mount will fail with ESTALE.  An overlayfs mount with
 does not support NFS export, lower filesystem does not have a valid UUID or
 if the upper filesystem does not support extended attributes.
 
+For "metadata only copy up" feature there is no verification mechanism at
+mount time. So if same upper is mounted with different set of lower, mount
+probably will succeed but expect the unexpected later on. So don't do it.
+
 It is quite a common practice to copy overlay layers to a different
 directory tree on the same or different underlying filesystem, and even
 to a different machine.  With the "inodes index" feature, trying to mount
@@ -306,27 +330,40 @@ the copied layers will fail the verification of the lower root file handle.
 Non-standard behavior
 ---------------------
 
-The copy_up operation essentially creates a new, identical file and
-moves it over to the old name.  Any open files referring to this inode
-will access the old data.
+Overlayfs can now act as a POSIX compliant filesystem with the following
+features turned on:
+
+1) "redirect_dir"
+
+Enabled with the mount option or module option: "redirect_dir=on" or with
+the kernel config option CONFIG_OVERLAY_FS_REDIRECT_DIR=y.
+
+If this feature is disabled, then rename(2) on a lower or merged directory
+will fail with EXDEV ("Invalid cross-device link").
+
+2) "inode index"
+
+Enabled with the mount option or module option "index=on" or with the
+kernel config option CONFIG_OVERLAY_FS_INDEX=y.
 
-The new file may be on a different filesystem, so both st_dev and st_ino
-of the real file may change.  The values of st_dev and st_ino returned by
-stat(2) on an overlay object are often not the same as the real file
-stat(2) values to prevent the values from changing on copy_up.
+If this feature is disabled and a file with multiple hard links is copied
+up, then this will "break" the link.  Changes will not be propagated to
+other names referring to the same inode.
 
-Unless "xino" feature is enabled, when overlay layers are not all on the
-same underlying filesystem, the value of st_dev may be different for two
-non-directory objects in the same overlay filesystem and the value of
-st_ino for directory objects may be non persistent and could change even
-while the overlay filesystem is still mounted.
+3) "xino"
 
-Unless "inode index" feature is enabled, if a file with multiple hard
-links is copied up, then this will "break" the link.  Changes will not be
-propagated to other names referring to the same inode.
+Enabled with the mount option "xino=auto" or "xino=on", with the module
+option "xino_auto=on" or with the kernel config option
+CONFIG_OVERLAY_FS_XINO_AUTO=y.  Also implicitly enabled by using the same
+underlying filesystem for all layers making up the overlay.
 
-Unless "redirect_dir" feature is enabled, rename(2) on a lower or merged
-directory will fail with EXDEV.
+If this feature is disabled or the underlying filesystem doesn't have
+enough free bits in the inode number, then overlayfs will not be able to
+guarantee that the values of st_ino and st_dev returned by stat(2) and the
+value of d_ino returned by readdir(3) will act like on a normal filesystem.
+E.g. the value of st_dev may be different for two objects in the same
+overlay filesystem and the value of st_ino for directory objects may not be
+persistent and could change even while the overlay filesystem is mounted.
 
 
 Changes to underlying filesystems
index 1605acb..22b4b00 100644 (file)
@@ -870,6 +870,7 @@ Committed_AS:   100056 kB
 VmallocTotal:   112216 kB
 VmallocUsed:       428 kB
 VmallocChunk:   111088 kB
+Percpu:          62080 kB
 HardwareCorrupted:   0 kB
 AnonHugePages:   49152 kB
 ShmemHugePages:      0 kB
@@ -962,6 +963,8 @@ Committed_AS: The amount of memory presently allocated on the system.
 VmallocTotal: total size of vmalloc memory area
  VmallocUsed: amount of vmalloc area which is used
 VmallocChunk: largest contiguous block of vmalloc area which is free
+      Percpu: Memory allocated to the percpu allocator used to back percpu
+              allocations. This stat excludes the cost of metadata.
 
 ..............................................................................
 
index b176928..79637d2 100644 (file)
@@ -164,7 +164,7 @@ Documentation/early-userspace/README for more details.)
 The kernel does not depend on external cpio tools.  If you specify a
 directory instead of a configuration file, the kernel's build infrastructure
 creates a configuration file from that directory (usr/Makefile calls
-scripts/gen_initramfs_list.sh), and proceeds to package up that directory
+usr/gen_initramfs_list.sh), and proceeds to package up that directory
 using the config file (by feeding it to usr/gen_init_cpio, which is created
 from usr/gen_init_cpio.c).  The kernel's build-time cpio creation code is
 entirely self-contained, and the kernel's boot-time extractor is also
index 85907d5..4b2084d 100644 (file)
@@ -989,8 +989,7 @@ struct dentry_operations {
        char *(*d_dname)(struct dentry *, char *, int);
        struct vfsmount *(*d_automount)(struct path *);
        int (*d_manage)(const struct path *, bool);
-       struct dentry *(*d_real)(struct dentry *, const struct inode *,
-                                unsigned int, unsigned int);
+       struct dentry *(*d_real)(struct dentry *, const struct inode *);
 };
 
   d_revalidate: called when the VFS needs to revalidate a dentry. This
@@ -1124,22 +1123,15 @@ struct dentry_operations {
        dentry being transited from.
 
   d_real: overlay/union type filesystems implement this method to return one of
-       the underlying dentries hidden by the overlay.  It is used in three
+       the underlying dentries hidden by the overlay.  It is used in two
        different modes:
 
-       Called from open it may need to copy-up the file depending on the
-       supplied open flags.  This mode is selected with a non-zero flags
-       argument.  In this mode the d_real method can return an error.
-
        Called from file_dentry() it returns the real dentry matching the inode
        argument.  The real dentry may be from a lower layer already copied up,
        but still referenced from the file.  This mode is selected with a
-       non-NULL inode argument.  This will always succeed.
-
-       With NULL inode and zero flags the topmost real underlying dentry is
-       returned.  This will always succeed.
+       non-NULL inode argument.
 
-       This method is never called with both non-NULL inode and non-zero flags.
+       With NULL inode the topmost real underlying dentry is returned.
 
 Each dentry has a pointer to its parent dentry, as well as a hash list
 of child dentries. Child dentries are basically like files in a
diff --git a/Documentation/hwmon/raspberrypi-hwmon b/Documentation/hwmon/raspberrypi-hwmon
new file mode 100644 (file)
index 0000000..3c92e2c
--- /dev/null
@@ -0,0 +1,22 @@
+Kernel driver raspberrypi-hwmon
+===============================
+
+Supported boards:
+  * Raspberry Pi A+ (via GPIO on SoC)
+  * Raspberry Pi B+ (via GPIO on SoC)
+  * Raspberry Pi 2 B (via GPIO on SoC)
+  * Raspberry Pi 3 B (via GPIO on port expander)
+  * Raspberry Pi 3 B+ (via PMIC)
+
+Author: Stefan Wahren <stefan.wahren@i2se.com>
+
+Description
+-----------
+
+This driver periodically polls a mailbox property of the VC4 firmware to detect
+undervoltage conditions.
+
+Sysfs entries
+-------------
+
+in0_lcrit_alarm                Undervoltage alarm
index 65514c2..d1ee484 100644 (file)
@@ -21,24 +21,21 @@ Supported adapters:
   * Intel DH89xxCC (PCH)
   * Intel Panther Point (PCH)
   * Intel Lynx Point (PCH)
-  * Intel Lynx Point-LP (PCH)
   * Intel Avoton (SOC)
   * Intel Wellsburg (PCH)
   * Intel Coleto Creek (PCH)
   * Intel Wildcat Point (PCH)
-  * Intel Wildcat Point-LP (PCH)
   * Intel BayTrail (SOC)
   * Intel Braswell (SOC)
-  * Intel Sunrise Point-H (PCH)
-  * Intel Sunrise Point-LP (PCH)
-  * Intel Kaby Lake-H (PCH)
+  * Intel Sunrise Point (PCH)
+  * Intel Kaby Lake (PCH)
   * Intel DNV (SOC)
   * Intel Broxton (SOC)
   * Intel Lewisburg (PCH)
   * Intel Gemini Lake (SOC)
-  * Intel Cannon Lake-H (PCH)
-  * Intel Cannon Lake-LP (PCH)
+  * Intel Cannon Lake (PCH)
   * Intel Cedar Fork (PCH)
+  * Intel Ice Lake (PCH)
    Datasheets: Publicly available at the Intel website
 
 On Intel Patsburg and later chipsets, both the normal host SMBus controller
index 4e713f4..9caaf7d 100644 (file)
@@ -4,7 +4,7 @@ Supported adapters:
   * OpenCores.org I2C controller by Richard Herveille (see datasheet link)
     https://opencores.org/project/i2c/overview
 
-Author: Peter Korsgaard <jacmet@sunsite.dk>
+Author: Peter Korsgaard <peter@korsgaard.com>
 
 Description
 -----------
index e0c4f77..a4ce620 100644 (file)
@@ -34,21 +34,48 @@ I2C specification version 4, section 3.1.16) using the helpers of the Linux I2C
 core (see 'struct bus_recovery_info'). However, the bus recovery will not
 succeed because SDA is still pinned low until you manually release it again
 with "echo 1 > sda". A test with an automatic release can be done with the
-'incomplete_transfer' file.
+following class of fault injectors.
 
-"incomplete_transfer"
----------------------
+Introduction to incomplete transfers
+------------------------------------
+
+The following fault injectors create situations where SDA will be held low by a
+device. Bus recovery should be able to fix these situations. But please note:
+there are I2C client devices which detect a stuck SDA on their side and release
+it on their own after a few milliseconds. Also, there might be an external
+device deglitching and monitoring the I2C bus. It could also detect a stuck SDA
+and will init a bus recovery on its own. If you want to implement bus recovery
+in a bus master driver, make sure you checked your hardware setup for such
+devices before. And always verify with a scope or logic analyzer!
+
+"incomplete_address_phase"
+--------------------------
 
 This file is write only and you need to write the address of an existing I2C
-client device to it. Then, a transfer to this device will be started, but it
-will stop at the ACK phase after the address of the client has been
+client device to it. Then, a read transfer to this device will be started, but
+it will stop at the ACK phase after the address of the client has been
 transmitted. Because the device will ACK its presence, this results in SDA
 being pulled low by the device while SCL is high. So, similar to the "sda" file
 above, the bus master under test should detect this condition and try a bus
 recovery. This time, however, it should succeed and the device should release
-SDA after toggling SCL. Please note: there are I2C client devices which detect
-a stuck SDA on their side and release it on their own after a few milliseconds.
-Also, there are external devices deglitching and monitoring the I2C bus. They
-can also detect a stuck SDA and will init a bus recovery on their own. If you
-want to implement bus recovery in a bus master driver, make sure you checked
-your hardware setup carefully before.
+SDA after toggling SCL.
+
+"incomplete_write_byte"
+-----------------------
+
+Similar to above, this file is write only and you need to write the address of
+an existing I2C client device to it.
+
+The injector will again stop at one ACK phase, so the device will keep SDA low
+because it acknowledges data. However, there are two differences compared to
+'incomplete_address_phase':
+
+a) the message sent out will be a write message
+b) after the address byte, a 0x00 byte will be transferred. Then, stop at ACK.
+
+This is a highly delicate state, the device is set up to write any data to
+register 0x00 (if it has registers) when further clock pulses happen on SCL.
+This is why bus recovery (up to 9 clock pulses) must either check SDA or send
+additional STOP conditions to ensure the bus has been released. Otherwise
+random data will be written to a device!
+
index b51751a..6be7034 100644 (file)
@@ -310,12 +310,12 @@ ABS_MT_TOOL_Y
 ABS_MT_TOOL_TYPE
     The type of approaching tool. A lot of kernel drivers cannot distinguish
     between different tool types, such as a finger or a pen. In such cases, the
-    event should be omitted. The protocol currently supports MT_TOOL_FINGER,
-    MT_TOOL_PEN, and MT_TOOL_PALM [#f2]_. For type B devices, this event is
-    handled by input core; drivers should instead use
-    input_mt_report_slot_state(). A contact's ABS_MT_TOOL_TYPE may change over
-    time while still touching the device, because the firmware may not be able
-    to determine which tool is being used when it first appears.
+    event should be omitted. The protocol currently mainly supports
+    MT_TOOL_FINGER, MT_TOOL_PEN, and MT_TOOL_PALM [#f2]_.
+    For type B devices, this event is handled by input core; drivers should
+    instead use input_mt_report_slot_state(). A contact's ABS_MT_TOOL_TYPE may
+    change over time while still touching the device, because the firmware may
+    not be able to determine which tool is being used when it first appears.
 
 ABS_MT_BLOB_ID
     The BLOB_ID groups several packets together into one arbitrarily shaped
index c54cb7c..864e740 100644 (file)
@@ -545,7 +545,7 @@ make KBUILD_KCONFIG=Documentation/kbuild/Kconfig.recursion-issue-02 allnoconfig
 Practical solutions to kconfig recursive issue
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-Developers who run into the recursive Kconfig issue have three options
+Developers who run into the recursive Kconfig issue have two options
 at their disposal. We document them below and also provide a list of
 historical issues resolved through these different solutions.
 
@@ -553,7 +553,6 @@ historical issues resolved through these different solutions.
   b) Match dependency semantics:
        b1) Swap all "select FOO" to "depends on FOO" or,
        b2) Swap all "depends on FOO" to "select FOO"
-  c) Consider the use of "imply" instead of "select"
 
 The resolution to a) can be tested with the sample Kconfig file
 Documentation/kbuild/Kconfig.recursion-issue-01 through the removal
index 766355b..7b6a2b2 100644 (file)
@@ -680,7 +680,7 @@ Both possibilities are described in the following.
 
        Example:
                #scripts/kconfig/Makefile
-               HOSTLOADLIBES_qconf := -L$(QTDIR)/lib
+               HOSTLDLIBS_qconf := -L$(QTDIR)/lib
 
        When linking qconf, it will be passed the extra option
        "-L$(QTDIR)/lib".
@@ -1,7 +1,15 @@
-Copyright 2016 NXP
+.. include:: <isonum.txt>
+
+DPAA2 DPIO (Data Path I/O) Overview
+===================================
+
+:Copyright: |copy| 2016-2018 NXP
+
+This document provides an overview of the Freescale DPAA2 DPIO
+drivers
 
 Introduction
-------------
+============
 
 A DPAA2 DPIO (Data Path I/O) is a hardware object that provides
 interfaces to enqueue and dequeue frames to/from network interfaces
@@ -27,8 +35,11 @@ provides services that:
 
 The Linux DPIO driver consists of 3 primary components--
    DPIO object driver-- fsl-mc driver that manages the DPIO object
+
    DPIO service-- provides APIs to other Linux drivers for services
+
    QBman portal interface-- sends portal commands, gets responses
+::
 
           fsl-mc          other
            bus           drivers
@@ -45,8 +56,9 @@ The Linux DPIO driver consists of 3 primary components--
                             |
                          hardware
 
+
 The diagram below shows how the DPIO driver components fit with the other
-DPAA2 Linux driver components:
+DPAA2 Linux driver components::
                                                    +------------+
                                                    | OS Network |
                                                    |   Stack    |
@@ -98,20 +110,29 @@ DPIO service  (dpio-service.c, dpaa2-io.h)
 
    Notification handling
       dpaa2_io_service_register()
+
       dpaa2_io_service_deregister()
+
       dpaa2_io_service_rearm()
 
    Queuing
       dpaa2_io_service_pull_fq()
+
       dpaa2_io_service_pull_channel()
+
       dpaa2_io_service_enqueue_fq()
+
       dpaa2_io_service_enqueue_qd()
+
       dpaa2_io_store_create()
+
       dpaa2_io_store_destroy()
+
       dpaa2_io_store_next()
 
    Buffer pool management
       dpaa2_io_service_release()
+
       dpaa2_io_service_acquire()
 
 QBman portal interface (qbman-portal.c)
@@ -120,7 +141,9 @@ QBman portal interface (qbman-portal.c)
    The qbman-portal component provides APIs to do the low level hardware
    bit twiddling for operations such as:
       -initializing Qman software portals
+
       -building and sending portal commands
+
       -portal interrupt configuration and processing
 
    The qbman-portal APIs are not public to other drivers, and are
index 4c6586c..10bea11 100644 (file)
@@ -6,3 +6,4 @@ DPAA2 Documentation
    :maxdepth: 1
 
    overview
+   dpio-driver
index 7a92a06..61f918b 100644 (file)
@@ -29,7 +29,7 @@ you probably needn't concern yourself with isdn4k-utils.
 ====================== ===============  ========================================
         Program        Minimal version       Command to check the version
 ====================== ===============  ========================================
-GNU C                  3.2              gcc --version
+GNU C                  4.6              gcc --version
 GNU make               3.81             make --version
 binutils               2.20             ld -v
 flex                   2.5.35           flex --version
index 6c00c1e..819caf8 100644 (file)
@@ -34,7 +34,9 @@ Currently, these files are in /proc/sys/fs:
 - overflowgid
 - pipe-user-pages-hard
 - pipe-user-pages-soft
+- protected_fifos
 - protected_hardlinks
+- protected_regular
 - protected_symlinks
 - suid_dumpable
 - super-max
@@ -182,6 +184,24 @@ applied.
 
 ==============================================================
 
+protected_fifos:
+
+The intent of this protection is to avoid unintentional writes to
+an attacker-controlled FIFO, where a program expected to create a regular
+file.
+
+When set to "0", writing to FIFOs is unrestricted.
+
+When set to "1" don't allow O_CREAT open on FIFOs that we don't own
+in world writable sticky directories, unless they are owned by the
+owner of the directory.
+
+When set to "2" it also applies to group writable sticky directories.
+
+This protection is based on the restrictions in Openwall.
+
+==============================================================
+
 protected_hardlinks:
 
 A long-standing class of security issues is the hardlink-based
@@ -202,6 +222,22 @@ This protection is based on the restrictions in Openwall and grsecurity.
 
 ==============================================================
 
+protected_regular:
+
+This protection is similar to protected_fifos, but it
+avoids writes to an attacker-controlled regular file, where a program
+expected to create one.
+
+When set to "0", writing to regular files is unrestricted.
+
+When set to "1" don't allow O_CREAT open on regular files that we
+don't own in world writable sticky directories, unless they are
+owned by the owner of the directory.
+
+When set to "2" it also applies to group writable sticky directories.
+
+==============================================================
+
 protected_symlinks:
 
 A long-standing class of security issues is the symlink-based
index 5958503..37a6795 100644 (file)
@@ -38,6 +38,7 @@ show up in /proc/sys/kernel:
 - hung_task_panic
 - hung_task_check_count
 - hung_task_timeout_secs
+- hung_task_check_interval_secs
 - hung_task_warnings
 - hyperv_record_panic_msg
 - kexec_load_disabled
@@ -355,7 +356,7 @@ This file shows up if CONFIG_DETECT_HUNG_TASK is enabled.
 
 hung_task_timeout_secs:
 
-Check interval. When a task in D state did not get scheduled
+When a task in D state did not get scheduled
 for more than this value report a warning.
 This file shows up if CONFIG_DETECT_HUNG_TASK is enabled.
 
@@ -364,6 +365,18 @@ Possible values to set are in range {0..LONG_MAX/HZ}.
 
 ==============================================================
 
+hung_task_check_interval_secs:
+
+Hung task check interval. If hung task checking is enabled
+(see hung_task_timeout_secs), the check is done every
+hung_task_check_interval_secs seconds.
+This file shows up if CONFIG_DETECT_HUNG_TASK is enabled.
+
+0 (default): means use hung_task_timeout_secs as checking interval.
+Possible values to set are in range {0..LONG_MAX/HZ}.
+
+==============================================================
+
 hung_task_warnings:
 
 The maximum number of warnings to report. During a check interval
@@ -451,7 +464,8 @@ Notes:
 1) kernel doesn't guarantee, that new object will have desired id. So,
 it's up to userspace, how to handle an object with "wrong" id.
 2) Toggle with non-default value will be set back to -1 by kernel after
-successful IPC object allocation.
+successful IPC object allocation. If an IPC object allocation syscall
+fails, it is undefined if the value remains unmodified or is reset to -1.
 
 ==============================================================
 
index e72853b..7d73882 100644 (file)
@@ -691,7 +691,7 @@ and don't use much of it.
 The default value is 0.
 
 See Documentation/vm/overcommit-accounting.rst and
-mm/mmap.c::__vm_enough_memory() for more information.
+mm/util.c::__vm_enough_memory() for more information.
 
 ==============================================================
 
index 7b83b17..c664064 100644 (file)
@@ -835,11 +835,13 @@ struct kvm_clock_data {
 
 Capability: KVM_CAP_VCPU_EVENTS
 Extended by: KVM_CAP_INTR_SHADOW
-Architectures: x86
-Type: vm ioctl
+Architectures: x86, arm, arm64
+Type: vcpu ioctl
 Parameters: struct kvm_vcpu_event (out)
 Returns: 0 on success, -1 on error
 
+X86:
+
 Gets currently pending exceptions, interrupts, and NMIs as well as related
 states of the vcpu.
 
@@ -881,15 +883,64 @@ Only two fields are defined in the flags field:
 - KVM_VCPUEVENT_VALID_SMM may be set in the flags field to signal that
   smi contains a valid state.
 
+ARM/ARM64:
+
+If the guest accesses a device that is being emulated by the host kernel in
+such a way that a real device would generate a physical SError, KVM may make
+a virtual SError pending for that VCPU. This system error interrupt remains
+pending until the guest takes the exception by unmasking PSTATE.A.
+
+Running the VCPU may cause it to take a pending SError, or make an access that
+causes an SError to become pending. The event's description is only valid while
+the VPCU is not running.
+
+This API provides a way to read and write the pending 'event' state that is not
+visible to the guest. To save, restore or migrate a VCPU the struct representing
+the state can be read then written using this GET/SET API, along with the other
+guest-visible registers. It is not possible to 'cancel' an SError that has been
+made pending.
+
+A device being emulated in user-space may also wish to generate an SError. To do
+this the events structure can be populated by user-space. The current state
+should be read first, to ensure no existing SError is pending. If an existing
+SError is pending, the architecture's 'Multiple SError interrupts' rules should
+be followed. (2.5.3 of DDI0587.a "ARM Reliability, Availability, and
+Serviceability (RAS) Specification").
+
+SError exceptions always have an ESR value. Some CPUs have the ability to
+specify what the virtual SError's ESR value should be. These systems will
+advertise KVM_CAP_ARM_INJECT_SERROR_ESR. In this case exception.has_esr will
+always have a non-zero value when read, and the agent making an SError pending
+should specify the ISS field in the lower 24 bits of exception.serror_esr. If
+the system supports KVM_CAP_ARM_INJECT_SERROR_ESR, but user-space sets the events
+with exception.has_esr as zero, KVM will choose an ESR.
+
+Specifying exception.has_esr on a system that does not support it will return
+-EINVAL. Setting anything other than the lower 24bits of exception.serror_esr
+will return -EINVAL.
+
+struct kvm_vcpu_events {
+       struct {
+               __u8 serror_pending;
+               __u8 serror_has_esr;
+               /* Align it to 8 bytes */
+               __u8 pad[6];
+               __u64 serror_esr;
+       } exception;
+       __u32 reserved[12];
+};
+
 4.32 KVM_SET_VCPU_EVENTS
 
 Capability: KVM_CAP_VCPU_EVENTS
 Extended by: KVM_CAP_INTR_SHADOW
-Architectures: x86
-Type: vm ioctl
+Architectures: x86, arm, arm64
+Type: vcpu ioctl
 Parameters: struct kvm_vcpu_event (in)
 Returns: 0 on success, -1 on error
 
+X86:
+
 Set pending exceptions, interrupts, and NMIs as well as related states of the
 vcpu.
 
@@ -910,6 +961,13 @@ shall be written into the VCPU.
 
 KVM_VCPUEVENT_VALID_SMM can only be set if KVM_CAP_X86_SMM is available.
 
+ARM/ARM64:
+
+Set the pending SError exception state for this VCPU. It is not possible to
+'cancel' an Serror that has been made pending.
+
+See KVM_GET_VCPU_EVENTS for the data structure.
+
 
 4.33 KVM_GET_DEBUGREGS
 
@@ -4690,3 +4748,17 @@ This capability indicates that KVM supports paravirtualized Hyper-V TLB Flush
 hypercalls:
 HvFlushVirtualAddressSpace, HvFlushVirtualAddressSpaceEx,
 HvFlushVirtualAddressList, HvFlushVirtualAddressListEx.
+
+8.19 KVM_CAP_ARM_INJECT_SERROR_ESR
+
+Architectures: arm, arm64
+
+This capability indicates that userspace can specify (via the
+KVM_SET_VCPU_EVENTS ioctl) the syndrome value reported to the guest when it
+takes a virtual SError interrupt exception.
+If KVM advertises this capability, userspace can only specify the ISS field for
+the ESR syndrome. Other parts of the ESR, such as the EC are generated by the
+CPU when the exception is taken. If this virtual SError is taken to EL1 using
+AArch64, this value will be reported in the ISS field of ESR_ELx.
+
+See KVM_CAP_VCPU_EVENTS for more details.
index 2408ab7..ff290b4 100644 (file)
@@ -100,6 +100,14 @@ Groups:
     Note that distributor fields are not banked, but return the same value
     regardless of the mpidr used to access the register.
 
+    GICD_IIDR.Revision is updated when the KVM implementation is changed in a
+    way directly observable by the guest or userspace.  Userspace should read
+    GICD_IIDR from KVM and write back the read value to confirm its expected
+    behavior is aligned with the KVM implementation.  Userspace should set
+    GICD_IIDR before setting any other registers to ensure the expected
+    behavior.
+
+
     The GICD_STATUSR and GICR_STATUSR registers are architecturally defined such
     that a write of a clear bit has no effect, whereas a write with a set bit
     clears that value.  To allow userspace to freely set the values of these two
index b3ce126..97b6518 100644 (file)
@@ -49,9 +49,15 @@ Groups:
     index is specified with the vcpu_index field.  Note that most distributor
     fields are not banked, but return the same value regardless of the
     vcpu_index used to access the register.
-  Limitations:
-    - Priorities are not implemented, and registers are RAZ/WI
-    - Currently only implemented for KVM_DEV_TYPE_ARM_VGIC_V2.
+
+    GICD_IIDR.Revision is updated when the KVM implementation of an emulated
+    GICv2 is changed in a way directly observable by the guest or userspace.
+    Userspace should read GICD_IIDR from KVM and write back the read value to
+    confirm its expected behavior is aligned with the KVM implementation.
+    Userspace should set GICD_IIDR before setting any other registers (both
+    KVM_DEV_ARM_VGIC_GRP_DIST_REGS and KVM_DEV_ARM_VGIC_GRP_CPU_REGS) to ensure
+    the expected behavior. Unless GICD_IIDR has been set from userspace, writes
+    to the interrupt group registers (GICD_IGROUPR) are ignored.
   Errors:
     -ENXIO: Getting or setting this register is not yet supported
     -EBUSY: One or more VCPUs are running
@@ -94,9 +100,6 @@ Groups:
     use the lower 5 bits to communicate with the KVM device and must shift the
     value left by 3 places to obtain the actual priority mask level.
 
-  Limitations:
-    - Priorities are not implemented, and registers are RAZ/WI
-    - Currently only implemented for KVM_DEV_TYPE_ARM_VGIC_V2.
   Errors:
     -ENXIO: Getting or setting this register is not yet supported
     -EBUSY: One or more VCPUs are running
index 955463f..9ad052a 100644 (file)
@@ -842,6 +842,13 @@ S: Supported
 F:     drivers/mux/adgs1408.c
 F:     Documentation/devicetree/bindings/mux/adgs1408.txt
 
+ANALOG DEVICES INC ADP5061 DRIVER
+M:     Stefan Popa <stefan.popa@analog.com>
+L:     linux-pm@vger.kernel.org
+W:     http://ez.analog.com/community/linux-device-drivers
+S:     Supported
+F:     drivers/power/supply/adp5061.c
+
 ANALOG DEVICES INC ADV7180 DRIVER
 M:     Lars-Peter Clausen <lars@metafoo.de>
 L:     linux-media@vger.kernel.org
@@ -1288,11 +1295,6 @@ F:       arch/arm/mach-aspeed/
 F:     arch/arm/boot/dts/aspeed-*
 N:     aspeed
 
-ARM/ATMEL AT91 Clock Support
-M:     Boris Brezillon <boris.brezillon@bootlin.com>
-S:     Maintained
-F:     drivers/clk/at91
-
 ARM/CALXEDA HIGHBANK ARCHITECTURE
 M:     Rob Herring <robh@kernel.org>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
@@ -1474,6 +1476,16 @@ T:       git git://git.kernel.org/pub/scm/linux/kernel/git/shawnguo/linux.git
 F:     arch/arm/mach-imx/*vf610*
 F:     arch/arm/boot/dts/vf*
 
+ARM/FREESCALE LAYERSCAPE ARM ARCHITECTURE
+M:     Shawn Guo <shawnguo@kernel.org>
+M:     Li Yang <leoyang.li@nxp.com>
+L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+S:     Maintained
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/shawnguo/linux.git
+F:     arch/arm/boot/dts/ls1021a*
+F:     arch/arm64/boot/dts/freescale/fsl-*
+F:     arch/arm64/boot/dts/freescale/qoriq-*
+
 ARM/GLOMATION GESBC9312SX MACHINE SUPPORT
 M:     Lennert Buytenhek <kernel@wantstofly.org>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
@@ -2002,6 +2014,7 @@ S:        Supported
 F:     arch/arm/boot/dts/emev2*
 F:     arch/arm/boot/dts/r7s*
 F:     arch/arm/boot/dts/r8a*
+F:     arch/arm/boot/dts/r9a*
 F:     arch/arm/boot/dts/sh*
 F:     arch/arm/configs/shmobile_defconfig
 F:     arch/arm/include/debug/renesas-scif.S
@@ -2120,6 +2133,15 @@ L:       linux-kernel@vger.kernel.org
 S:     Maintained
 F:     drivers/memory/*emif*
 
+ARM/TEXAS INSTRUMENTS K3 ARCHITECTURE
+M:     Tero Kristo <t-kristo@ti.com>
+M:     Nishanth Menon <nm@ti.com>
+L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+S:     Supported
+F:     Documentation/devicetree/bindings/arm/ti/k3.txt
+F:     arch/arm64/boot/dts/ti/Makefile
+F:     arch/arm64/boot/dts/ti/k3-*
+
 ARM/TEXAS INSTRUMENT KEYSTONE ARCHITECTURE
 M:     Santosh Shilimkar <ssantosh@kernel.org>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
@@ -3562,6 +3584,22 @@ M:       Christian Benvenuti <benve@cisco.com>
 S:     Supported
 F:     drivers/infiniband/hw/usnic/
 
+CIRRUS LOGIC MADERA CODEC DRIVERS
+M:     Charles Keepax <ckeepax@opensource.cirrus.com>
+M:     Richard Fitzgerald <rf@opensource.cirrus.com>
+L:     alsa-devel@alsa-project.org (moderated for non-subscribers)
+L:     patches@opensource.cirrus.com
+T:     git https://github.com/CirrusLogic/linux-drivers.git
+W:     https://github.com/CirrusLogic/linux-drivers/wiki
+S:     Supported
+F:     Documentation/devicetree/bindings/mfd/madera.txt
+F:     Documentation/devicetree/bindings/pinctrl/cirrus,madera-pinctrl.txt
+F:     include/linux/mfd/madera/*
+F:     drivers/gpio/gpio-madera*
+F:     drivers/mfd/madera*
+F:     drivers/mfd/cs47l*
+F:     drivers/pinctrl/cirrus/*
+
 CLANG-FORMAT FILE
 M:     Miguel Ojeda <miguel.ojeda.sandonis@gmail.com>
 S:     Maintained
@@ -4326,7 +4364,8 @@ F:        drivers/i2c/busses/i2c-diolan-u2c.c
 
 FILESYSTEM DIRECT ACCESS (DAX)
 M:     Matthew Wilcox <mawilcox@microsoft.com>
-M:     Ross Zwisler <ross.zwisler@linux.intel.com>
+M:     Ross Zwisler <zwisler@kernel.org>
+M:     Jan Kara <jack@suse.cz>
 L:     linux-fsdevel@vger.kernel.org
 S:     Supported
 F:     fs/dax.c
@@ -4336,7 +4375,7 @@ F:        include/trace/events/fs_dax.h
 DEVICE DIRECT ACCESS (DAX)
 M:     Dan Williams <dan.j.williams@intel.com>
 M:     Dave Jiang <dave.jiang@intel.com>
-M:     Ross Zwisler <ross.zwisler@linux.intel.com>
+M:     Ross Zwisler <zwisler@kernel.org>
 M:     Vishal Verma <vishal.l.verma@intel.com>
 L:     linux-nvdimm@lists.01.org
 S:     Supported
@@ -4484,7 +4523,7 @@ DPAA2 DATAPATH I/O (DPIO) DRIVER
 M:     Roy Pledge <Roy.Pledge@nxp.com>
 L:     linux-kernel@vger.kernel.org
 S:     Maintained
-F:     drivers/staging/fsl-mc/bus/dpio
+F:     drivers/soc/fsl/dpio
 
 DPAA2 ETHERNET DRIVER
 M:     Ioana Radulescu <ruxandra.radulescu@nxp.com>
@@ -4714,7 +4753,7 @@ F:        include/linux/vga*
 DRM DRIVERS AND MISC GPU PATCHES
 M:     Gustavo Padovan <gustavo@padovan.org>
 M:     Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
-M:     Sean Paul <seanpaul@chromium.org>
+M:     Sean Paul <sean@poorly.run>
 W:     https://01.org/linuxgraphics/gfx-docs/maintainer-tools/drm-misc.html
 S:     Maintained
 T:     git git://anongit.freedesktop.org/drm/drm-misc
@@ -5945,6 +5984,14 @@ F:       fs/crypto/
 F:     include/linux/fscrypt*.h
 F:     Documentation/filesystems/fscrypt.rst
 
+FSI-ATTACHED I2C DRIVER
+M:     Eddie James <eajames@linux.vnet.ibm.com>
+L:     linux-i2c@vger.kernel.org
+L:     openbmc@lists.ozlabs.org (moderated for non-subscribers)
+S:     Maintained
+F:     drivers/i2c/busses/i2c-fsi.c
+F:     Documentation/devicetree/bindings/i2c/i2c-fsi.txt
+
 FSNOTIFY: FILESYSTEM NOTIFICATION INFRASTRUCTURE
 M:     Jan Kara <jack@suse.cz>
 R:     Amir Goldstein <amir73il@gmail.com>
@@ -8208,9 +8255,9 @@ F:        drivers/ata/pata_arasan_cf.c
 
 LIBATA PATA DRIVERS
 M:     Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
-M:     Tejun Heo <tj@kernel.org>
+M:     Jens Axboe <axboe@kernel.dk>
 L:     linux-ide@vger.kernel.org
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/tj/libata.git
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/axboe/linux-block.git
 S:     Maintained
 F:     drivers/ata/pata_*.c
 F:     drivers/ata/ata_generic.c
@@ -8226,9 +8273,9 @@ F:        drivers/ata/sata_gemini.h
 
 LIBATA SATA AHCI PLATFORM devices support
 M:     Hans de Goede <hdegoede@redhat.com>
-M:     Tejun Heo <tj@kernel.org>
+M:     Jens Axboe <axboe@kernel.dk>
 L:     linux-ide@vger.kernel.org
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/tj/libata.git
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/axboe/linux-block.git
 S:     Maintained
 F:     drivers/ata/ahci_platform.c
 F:     drivers/ata/libahci_platform.c
@@ -8242,9 +8289,9 @@ S:        Maintained
 F:     drivers/ata/sata_promise.*
 
 LIBATA SUBSYSTEM (Serial and Parallel ATA drivers)
-M:     Tejun Heo <tj@kernel.org>
+M:     Jens Axboe <axboe@kernel.dk>
 L:     linux-ide@vger.kernel.org
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/tj/libata.git
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/axboe/linux-block.git
 S:     Maintained
 F:     drivers/ata/
 F:     include/linux/ata.h
@@ -8257,7 +8304,7 @@ S:        Maintained
 F:     tools/lib/lockdep/
 
 LIBNVDIMM BLK: MMIO-APERTURE DRIVER
-M:     Ross Zwisler <ross.zwisler@linux.intel.com>
+M:     Ross Zwisler <zwisler@kernel.org>
 M:     Dan Williams <dan.j.williams@intel.com>
 M:     Vishal Verma <vishal.l.verma@intel.com>
 M:     Dave Jiang <dave.jiang@intel.com>
@@ -8270,7 +8317,7 @@ F:        drivers/nvdimm/region_devs.c
 LIBNVDIMM BTT: BLOCK TRANSLATION TABLE
 M:     Vishal Verma <vishal.l.verma@intel.com>
 M:     Dan Williams <dan.j.williams@intel.com>
-M:     Ross Zwisler <ross.zwisler@linux.intel.com>
+M:     Ross Zwisler <zwisler@kernel.org>
 M:     Dave Jiang <dave.jiang@intel.com>
 L:     linux-nvdimm@lists.01.org
 Q:     https://patchwork.kernel.org/project/linux-nvdimm/list/
@@ -8278,7 +8325,7 @@ S:        Supported
 F:     drivers/nvdimm/btt*
 
 LIBNVDIMM PMEM: PERSISTENT MEMORY DRIVER
-M:     Ross Zwisler <ross.zwisler@linux.intel.com>
+M:     Ross Zwisler <zwisler@kernel.org>
 M:     Dan Williams <dan.j.williams@intel.com>
 M:     Vishal Verma <vishal.l.verma@intel.com>
 M:     Dave Jiang <dave.jiang@intel.com>
@@ -8297,7 +8344,7 @@ F:        Documentation/devicetree/bindings/pmem/pmem-region.txt
 
 LIBNVDIMM: NON-VOLATILE MEMORY DEVICE SUBSYSTEM
 M:     Dan Williams <dan.j.williams@intel.com>
-M:     Ross Zwisler <ross.zwisler@linux.intel.com>
+M:     Ross Zwisler <zwisler@kernel.org>
 M:     Vishal Verma <vishal.l.verma@intel.com>
 M:     Dave Jiang <dave.jiang@intel.com>
 L:     linux-nvdimm@lists.01.org
@@ -10540,6 +10587,7 @@ F:      arch/arm/plat-omap/
 F:     arch/arm/configs/omap1_defconfig
 F:     drivers/i2c/busses/i2c-omap.c
 F:     include/linux/platform_data/i2c-omap.h
+F:     include/linux/platform_data/ams-delta-fiq.h
 
 OMAP2+ SUPPORT
 M:     Tony Lindgren <tony@atomide.com>
@@ -10740,7 +10788,7 @@ F:      arch/*/boot/dts/
 F:     include/dt-bindings/
 
 OPENCORES I2C BUS DRIVER
-M:     Peter Korsgaard <jacmet@sunsite.dk>
+M:     Peter Korsgaard <peter@korsgaard.com>
 L:     linux-i2c@vger.kernel.org
 S:     Maintained
 F:     Documentation/i2c/busses/i2c-ocores
@@ -11998,6 +12046,14 @@ L:     netdev@vger.kernel.org
 S:     Maintained
 F:     drivers/net/ethernet/qualcomm/emac/
 
+QUALCOMM GENERIC INTERFACE I2C DRIVER
+M:     Alok Chauhan <alokc@codeaurora.org>
+M:     Karthikeyan Ramasubramanian <kramasub@codeaurora.org>
+L:     linux-i2c@vger.kernel.org
+L:     linux-arm-msm@vger.kernel.org
+S:     Supported
+F:     drivers/i2c/busses/i2c-qcom-geni.c
+
 QUALCOMM HEXAGON ARCHITECTURE
 M:     Richard Kuo <rkuo@codeaurora.org>
 L:     linux-hexagon@vger.kernel.org
@@ -13168,7 +13224,7 @@ L:      linux-input@vger.kernel.org
 L:     platform-driver-x86@vger.kernel.org
 S:     Maintained
 F:     drivers/input/touchscreen/silead.c
-F:     drivers/platform/x86/silead_dmi.c
+F:     drivers/platform/x86/touchscreen_dmi.c
 
 SILICON MOTION SM712 FRAME BUFFER DRIVER
 M:     Sudip Mukherjee <sudipm.mukherjee@gmail.com>
@@ -14355,6 +14411,7 @@ F:      drivers/media/radio/radio-raremono.c
 THERMAL
 M:     Zhang Rui <rui.zhang@intel.com>
 M:     Eduardo Valentin <edubezval@gmail.com>
+R:     Daniel Lezcano <daniel.lezcano@linaro.org>
 L:     linux-pm@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux.git
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/evalenti/linux-soc-thermal.git
index a0650bf..2b45880 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,8 +1,8 @@
 # SPDX-License-Identifier: GPL-2.0
 VERSION = 4
-PATCHLEVEL = 18
+PATCHLEVEL = 19
 SUBLEVEL = 0
-EXTRAVERSION =
+EXTRAVERSION = -rc1
 NAME = Merciless Moray
 
 # *DOCUMENTATION*
@@ -440,7 +440,7 @@ KBUILD_CFLAGS_KERNEL :=
 KBUILD_AFLAGS_MODULE  := -DMODULE
 KBUILD_CFLAGS_MODULE  := -DMODULE
 KBUILD_LDFLAGS_MODULE := -T $(srctree)/scripts/module-common.lds
-LDFLAGS :=
+KBUILD_LDFLAGS :=
 GCC_PLUGINS_CFLAGS :=
 
 export ARCH SRCARCH CONFIG_SHELL HOSTCC KBUILD_HOSTCFLAGS CROSS_COMPILE AS LD CC
@@ -448,7 +448,7 @@ export CPP AR NM STRIP OBJCOPY OBJDUMP KBUILD_HOSTLDFLAGS KBUILD_HOSTLDLIBS
 export MAKE LEX YACC AWK GENKSYMS INSTALLKERNEL PERL PYTHON PYTHON2 PYTHON3 UTS_MACHINE
 export HOSTCXX KBUILD_HOSTCXXFLAGS LDFLAGS_MODULE CHECK CHECKFLAGS
 
-export KBUILD_CPPFLAGS NOSTDINC_FLAGS LINUXINCLUDE OBJCOPYFLAGS LDFLAGS
+export KBUILD_CPPFLAGS NOSTDINC_FLAGS LINUXINCLUDE OBJCOPYFLAGS KBUILD_LDFLAGS
 export KBUILD_CFLAGS CFLAGS_KERNEL CFLAGS_MODULE
 export CFLAGS_KASAN CFLAGS_KASAN_NOSANITIZE CFLAGS_UBSAN
 export KBUILD_AFLAGS AFLAGS_KERNEL AFLAGS_MODULE
@@ -507,9 +507,13 @@ KBUILD_AFLAGS += $(call cc-option, -no-integrated-as)
 endif
 
 RETPOLINE_CFLAGS_GCC := -mindirect-branch=thunk-extern -mindirect-branch-register
+RETPOLINE_VDSO_CFLAGS_GCC := -mindirect-branch=thunk-inline -mindirect-branch-register
 RETPOLINE_CFLAGS_CLANG := -mretpoline-external-thunk
+RETPOLINE_VDSO_CFLAGS_CLANG := -mretpoline
 RETPOLINE_CFLAGS := $(call cc-option,$(RETPOLINE_CFLAGS_GCC),$(call cc-option,$(RETPOLINE_CFLAGS_CLANG)))
+RETPOLINE_VDSO_CFLAGS := $(call cc-option,$(RETPOLINE_VDSO_CFLAGS_GCC),$(call cc-option,$(RETPOLINE_VDSO_CFLAGS_CLANG)))
 export RETPOLINE_CFLAGS
+export RETPOLINE_VDSO_CFLAGS
 
 KBUILD_CFLAGS  += $(call cc-option,-fno-PIE)
 KBUILD_AFLAGS  += $(call cc-option,-fno-PIE)
@@ -754,12 +758,28 @@ ifdef CONFIG_FUNCTION_TRACER
 ifndef CC_FLAGS_FTRACE
 CC_FLAGS_FTRACE := -pg
 endif
-export CC_FLAGS_FTRACE
+ifdef CONFIG_FTRACE_MCOUNT_RECORD
+  # gcc 5 supports generating the mcount tables directly
+  ifeq ($(call cc-option-yn,-mrecord-mcount),y)
+    CC_FLAGS_FTRACE    += -mrecord-mcount
+    export CC_USING_RECORD_MCOUNT := 1
+  endif
+  ifdef CONFIG_HAVE_NOP_MCOUNT
+    ifeq ($(call cc-option-yn, -mnop-mcount),y)
+      CC_FLAGS_FTRACE  += -mnop-mcount
+      CC_FLAGS_USING   += -DCC_USING_NOP_MCOUNT
+    endif
+  endif
+endif
 ifdef CONFIG_HAVE_FENTRY
-CC_USING_FENTRY        := $(call cc-option, -mfentry -DCC_USING_FENTRY)
+  ifeq ($(call cc-option-yn, -mfentry),y)
+    CC_FLAGS_FTRACE    += -mfentry
+    CC_FLAGS_USING     += -DCC_USING_FENTRY
+  endif
 endif
-KBUILD_CFLAGS  += $(CC_FLAGS_FTRACE) $(CC_USING_FENTRY)
-KBUILD_AFLAGS  += $(CC_USING_FENTRY)
+export CC_FLAGS_FTRACE
+KBUILD_CFLAGS  += $(CC_FLAGS_FTRACE) $(CC_FLAGS_USING)
+KBUILD_AFLAGS  += $(CC_FLAGS_USING)
 ifdef CONFIG_DYNAMIC_FTRACE
        ifdef CONFIG_HAVE_C_RECORDMCOUNT
                BUILD_C_RECORDMCOUNT := y
@@ -774,8 +794,8 @@ KBUILD_CFLAGS += $(call cc-option, -fno-inline-functions-called-once)
 endif
 
 ifdef CONFIG_LD_DEAD_CODE_DATA_ELIMINATION
-KBUILD_CFLAGS_KERNEL   += $(call cc-option,-ffunction-sections,)
-KBUILD_CFLAGS_KERNEL   += $(call cc-option,-fdata-sections,)
+KBUILD_CFLAGS_KERNEL += -ffunction-sections -fdata-sections
+LDFLAGS_vmlinux += --gc-sections
 endif
 
 # arch Makefile may override CC so keep this after arch Makefile is included
@@ -841,10 +861,6 @@ LDFLAGS_BUILD_ID := $(call ld-option, --build-id)
 KBUILD_LDFLAGS_MODULE += $(LDFLAGS_BUILD_ID)
 LDFLAGS_vmlinux += $(LDFLAGS_BUILD_ID)
 
-ifdef CONFIG_LD_DEAD_CODE_DATA_ELIMINATION
-LDFLAGS_vmlinux        += $(call ld-option, --gc-sections,)
-endif
-
 ifeq ($(CONFIG_STRIP_ASM_SYMS),y)
 LDFLAGS_vmlinux        += $(call ld-option, -X,)
 endif
@@ -1008,7 +1024,7 @@ ARCH_POSTLINK := $(wildcard $(srctree)/arch/$(SRCARCH)/Makefile.postlink)
 
 # Final link of vmlinux with optional arch pass after final link
 cmd_link-vmlinux =                                                 \
-       $(CONFIG_SHELL) $< $(LD) $(LDFLAGS) $(LDFLAGS_vmlinux) ;    \
+       $(CONFIG_SHELL) $< $(LD) $(KBUILD_LDFLAGS) $(LDFLAGS_vmlinux) ;    \
        $(if $(ARCH_POSTLINK), $(MAKE) -f $(ARCH_POSTLINK) $@, true)
 
 vmlinux: scripts/link-vmlinux.sh autoksyms_recursive $(vmlinux-deps) FORCE
@@ -1338,16 +1354,12 @@ distclean: mrproper
 
 # Packaging of the kernel to various formats
 # ---------------------------------------------------------------------------
-# rpm target kept for backward compatibility
 package-dir    := scripts/package
 
 %src-pkg: FORCE
        $(Q)$(MAKE) $(build)=$(package-dir) $@
 %pkg: include/config/kernel.release FORCE
        $(Q)$(MAKE) $(build)=$(package-dir) $@
-rpm: rpm-pkg
-       @echo "  WARNING: \"rpm\" target will be removed after Linux 4.18"
-       @echo "           Please use \"rpm-pkg\" instead."
 
 
 # Brief documentation of the typical targets used
index c614816..6801123 100644 (file)
@@ -362,6 +362,9 @@ config HAVE_ARCH_JUMP_LABEL
 config HAVE_RCU_TABLE_FREE
        bool
 
+config HAVE_RCU_TABLE_INVALIDATE
+       bool
+
 config ARCH_HAVE_NMI_SAFE_CMPXCHG
        bool
 
@@ -841,6 +844,24 @@ config REFCOUNT_FULL
          against various use-after-free conditions that can be used in
          security flaw exploits.
 
+config HAVE_ARCH_COMPILER_H
+       bool
+       help
+         An architecture can select this if it provides an
+         asm/compiler.h header that should be included after
+         linux/compiler-*.h in order to override macro definitions that those
+         headers generally provide.
+
+config HAVE_ARCH_PREL32_RELOCATIONS
+       bool
+       help
+         May be selected by an architecture if it supports place-relative
+         32-bit relocations, both in the toolchain and in the module loader,
+         in which case relative references can be used in special sections
+         for PCI fixup, initcalls etc which are only half the size on 64 bit
+         architectures, and don't require runtime relocation on relocatable
+         kernels.
+
 source "kernel/gcov/Kconfig"
 
 source "scripts/gcc-plugins/Kconfig"
index c210a25..cff52d8 100644 (file)
@@ -530,24 +530,19 @@ SYSCALL_DEFINE4(osf_mount, unsigned long, typenr, const char __user *, path,
 SYSCALL_DEFINE1(osf_utsname, char __user *, name)
 {
        int error;
+       char tmp[5 * 32];
 
        down_read(&uts_sem);
-       error = -EFAULT;
-       if (copy_to_user(name + 0, utsname()->sysname, 32))
-               goto out;
-       if (copy_to_user(name + 32, utsname()->nodename, 32))
-               goto out;
-       if (copy_to_user(name + 64, utsname()->release, 32))
-               goto out;
-       if (copy_to_user(name + 96, utsname()->version, 32))
-               goto out;
-       if (copy_to_user(name + 128, utsname()->machine, 32))
-               goto out;
+       memcpy(tmp + 0 * 32, utsname()->sysname, 32);
+       memcpy(tmp + 1 * 32, utsname()->nodename, 32);
+       memcpy(tmp + 2 * 32, utsname()->release, 32);
+       memcpy(tmp + 3 * 32, utsname()->version, 32);
+       memcpy(tmp + 4 * 32, utsname()->machine, 32);
+       up_read(&uts_sem);
 
-       error = 0;
- out:
-       up_read(&uts_sem);      
-       return error;
+       if (copy_to_user(name, tmp, sizeof(tmp)))
+               return -EFAULT;
+       return 0;
 }
 
 SYSCALL_DEFINE0(getpagesize)
@@ -567,18 +562,21 @@ SYSCALL_DEFINE2(osf_getdomainname, char __user *, name, int, namelen)
 {
        int len, err = 0;
        char *kname;
+       char tmp[32];
 
-       if (namelen > 32)
+       if (namelen < 0 || namelen > 32)
                namelen = 32;
 
        down_read(&uts_sem);
        kname = utsname()->domainname;
        len = strnlen(kname, namelen);
-       if (copy_to_user(name, kname, min(len + 1, namelen)))
-               err = -EFAULT;
+       len = min(len + 1, namelen);
+       memcpy(tmp, kname, len);
        up_read(&uts_sem);
 
-       return err;
+       if (copy_to_user(name, tmp, len))
+               return -EFAULT;
+       return 0;
 }
 
 /*
@@ -739,13 +737,14 @@ SYSCALL_DEFINE3(osf_sysinfo, int, command, char __user *, buf, long, count)
        };
        unsigned long offset;
        const char *res;
-       long len, err = -EINVAL;
+       long len;
+       char tmp[__NEW_UTS_LEN + 1];
 
        offset = command-1;
        if (offset >= ARRAY_SIZE(sysinfo_table)) {
                /* Digital UNIX has a few unpublished interfaces here */
                printk("sysinfo(%d)", command);
-               goto out;
+               return -EINVAL;
        }
 
        down_read(&uts_sem);
@@ -753,13 +752,11 @@ SYSCALL_DEFINE3(osf_sysinfo, int, command, char __user *, buf, long, count)
        len = strlen(res)+1;
        if ((unsigned long)len > (unsigned long)count)
                len = count;
-       if (copy_to_user(buf, res, len))
-               err = -EFAULT;
-       else
-               err = 0;
+       memcpy(tmp, res, len);
        up_read(&uts_sem);
- out:
-       return err;
+       if (copy_to_user(buf, tmp, len))
+               return -EFAULT;
+       return 0;
 }
 
 SYSCALL_DEFINE5(osf_getsysinfo, unsigned long, op, void __user *, buffer,
index 6c1b20d..fb02619 100644 (file)
@@ -95,7 +95,7 @@ KBUILD_CFLAGS_MODULE  += -mlong-calls -mno-millicode
 # Finally dump eveything into kernel build system
 KBUILD_CFLAGS  += $(cflags-y)
 KBUILD_AFLAGS  += $(KBUILD_CFLAGS)
-LDFLAGS                += $(ldflags-y)
+KBUILD_LDFLAGS += $(ldflags-y)
 
 head-y         := arch/arc/kernel/head.o
 
index f69613f..e8cd55a 100644 (file)
@@ -603,13 +603,16 @@ config ARCH_S3C24XX
 config ARCH_DAVINCI
        bool "TI DaVinci"
        select ARCH_HAS_HOLES_MEMORYMODEL
-       select CLKDEV_LOOKUP
+       select COMMON_CLK
        select CPU_ARM926T
        select GENERIC_ALLOCATOR
        select GENERIC_CLOCKEVENTS
        select GENERIC_IRQ_CHIP
        select GPIOLIB
        select HAVE_IDE
+       select PM_GENERIC_DOMAINS if PM
+       select PM_GENERIC_DOMAINS_OF if PM && OF
+       select RESET_CONTROLLER
        select USE_OF
        select ZONE_DMA
        help
index b48dc08..f6fcb8a 100644 (file)
@@ -204,6 +204,14 @@ choice
                depends on ARCH_BCM_HR2
                select DEBUG_UART_8250
 
+       config DEBUG_BCM_IPROC_UART3
+               bool "Kernel low-level debugging on BCM IPROC UART3"
+               depends on ARCH_BCM_CYGNUS
+               select DEBUG_UART_8250
+               help
+                 Say Y here if you want the debug print routines to direct
+                 their output to the third serial port on these devices.
+
        config DEBUG_BCM_KONA_UART
                bool "Kernel low-level debugging messages via BCM KONA UART"
                depends on ARCH_BCM_MOBILE
@@ -1562,14 +1570,15 @@ config DEBUG_UART_PHYS
        default 0x18000400 if DEBUG_BCM_HR2
        default 0x18010000 if DEBUG_SIRFATLAS7_UART0
        default 0x18020000 if DEBUG_SIRFATLAS7_UART1
+       default 0x18023000 if DEBUG_BCM_IPROC_UART3
        default 0x1c090000 if DEBUG_VEXPRESS_UART0_RS1
        default 0x20001000 if DEBUG_HIP01_UART
        default 0x20060000 if DEBUG_RK29_UART0
        default 0x20064000 if DEBUG_RK29_UART1 || DEBUG_RK3X_UART2
        default 0x20068000 if DEBUG_RK29_UART2 || DEBUG_RK3X_UART3
        default 0x20201000 if DEBUG_BCM2835
-       default 0x3f201000 if DEBUG_BCM2836
        default 0x3e000000 if DEBUG_BCM_KONA_UART
+       default 0x3f201000 if DEBUG_BCM2836
        default 0x4000e400 if DEBUG_LL_UART_EFM32
        default 0x40028000 if DEBUG_AT91_SAMV7_USART1
        default 0x40081000 if DEBUG_LPC18XX_UART0
@@ -1682,6 +1691,7 @@ config DEBUG_UART_VIRT
        default 0xf1002000 if DEBUG_MT8127_UART0
        default 0xf1006000 if DEBUG_MT6589_UART0
        default 0xf1009000 if DEBUG_MT8135_UART3
+       default 0xf1023000 if DEBUG_BCM_IPROC_UART3
        default 0xf11f1000 if DEBUG_VERSATILE
        default 0xf1600000 if DEBUG_INTEGRATOR
        default 0xf1c28000 if DEBUG_SUNXI_UART0
@@ -1797,7 +1807,7 @@ config DEBUG_UART_8250_WORD
                DEBUG_KEYSTONE_UART0 || DEBUG_KEYSTONE_UART1 || \
                DEBUG_ALPINE_UART0 || \
                DEBUG_DAVINCI_DMx_UART0 || DEBUG_DAVINCI_DA8XX_UART1 || \
-               DEBUG_DAVINCI_DA8XX_UART2 || \
+               DEBUG_DAVINCI_DA8XX_UART2 || DEBUG_BCM_IPROC_UART3 || \
                DEBUG_BCM_KONA_UART || DEBUG_RK32_UART2
 
 config DEBUG_UART_8250_PALMCHIP
index e7d703d..d1516f8 100644 (file)
@@ -43,12 +43,12 @@ ifeq ($(CONFIG_CPU_BIG_ENDIAN),y)
 KBUILD_CPPFLAGS        += -mbig-endian
 CHECKFLAGS     += -D__ARMEB__
 AS             += -EB
-LDFLAGS                += -EB
+KBUILD_LDFLAGS += -EB
 else
 KBUILD_CPPFLAGS        += -mlittle-endian
 CHECKFLAGS     += -D__ARMEL__
 AS             += -EL
-LDFLAGS                += -EL
+KBUILD_LDFLAGS += -EL
 endif
 
 #
@@ -219,7 +219,6 @@ machine-$(CONFIG_ARCH_TANGO)                += tango
 machine-$(CONFIG_ARCH_TEGRA)           += tegra
 machine-$(CONFIG_ARCH_U300)            += u300
 machine-$(CONFIG_ARCH_U8500)           += ux500
-machine-$(CONFIG_ARCH_UNIPHIER)                += uniphier
 machine-$(CONFIG_ARCH_VERSATILE)       += versatile
 machine-$(CONFIG_ARCH_VEXPRESS)                += vexpress
 machine-$(CONFIG_ARCH_VT8500)          += vt8500
index 37a3de7..b5bd3de 100644 (file)
@@ -38,6 +38,7 @@ dtb-$(CONFIG_SOC_AT91SAM9) += \
        at91-ariettag25.dtb \
        at91-cosino_mega2560.dtb \
        at91-kizboxmini.dtb \
+       at91-wb45n.dtb \
        at91sam9g15ek.dtb \
        at91sam9g25ek.dtb \
        at91sam9g35ek.dtb \
@@ -50,7 +51,10 @@ dtb-$(CONFIG_SOC_SAM_V7) += \
        at91-sama5d2_ptc_ek.dtb \
        at91-sama5d2_xplained.dtb \
        at91-sama5d3_xplained.dtb \
+       at91-dvk_som60.dtb \
+       at91-gatwick.dtb \
        at91-tse850-3.dtb \
+       at91-wb50n.dtb \
        sama5d31ek.dtb \
        sama5d33ek.dtb \
        sama5d34ek.dtb \
@@ -73,6 +77,7 @@ dtb-$(CONFIG_ARCH_BCM2835) += \
        bcm2835-rpi-b-rev2.dtb \
        bcm2835-rpi-b-plus.dtb \
        bcm2835-rpi-a-plus.dtb \
+       bcm2835-rpi-cm1-io1.dtb \
        bcm2836-rpi-2-b.dtb \
        bcm2837-rpi-3-b.dtb \
        bcm2837-rpi-3-b-plus.dtb \
@@ -200,6 +205,7 @@ dtb-$(CONFIG_ARCH_GEMINI) += \
        gemini-dlink-dns-313.dtb \
        gemini-nas4220b.dtb \
        gemini-rut1xx.dtb \
+       gemini-sl93512r.dtb \
        gemini-sq201.dtb \
        gemini-wbd111.dtb \
        gemini-wbd222.dtb
@@ -345,7 +351,8 @@ dtb-$(CONFIG_SOC_IMX27) += \
        imx27-phytec-phycore-rdk.dtb \
        imx27-phytec-phycard-s-rdk.dtb
 dtb-$(CONFIG_SOC_IMX31) += \
-       imx31-bug.dtb
+       imx31-bug.dtb \
+       imx31-lite.dtb
 dtb-$(CONFIG_SOC_IMX35) += \
        imx35-eukrea-mbimxsd35-baseboard.dtb \
        imx35-pdk.dtb
@@ -358,10 +365,14 @@ dtb-$(CONFIG_SOC_IMX51) += \
        imx51-digi-connectcore-jsk.dtb \
        imx51-eukrea-mbimxsd51-baseboard.dtb \
        imx51-ts4800.dtb \
-       imx51-zii-rdu1.dtb
+       imx51-zii-rdu1.dtb \
+       imx51-zii-scu2-mezz.dtb \
+       imx51-zii-scu3-esb.dtb
 dtb-$(CONFIG_SOC_IMX53) += \
        imx53-ard.dtb \
        imx53-cx9020.dtb \
+       imx53-kp-ddc.dtb \
+       imx53-kp-hsc.dtb \
        imx53-m53evk.dtb \
        imx53-mba53.dtb \
        imx53-ppd.dtb \
@@ -400,6 +411,7 @@ dtb-$(CONFIG_SOC_IMX6Q) += \
        imx6dl-hummingboard2-emmc-som-v15.dtb \
        imx6dl-hummingboard2-som-v15.dtb \
        imx6dl-icore.dtb \
+       imx6dl-icore-mipi.dtb \
        imx6dl-icore-rqs.dtb \
        imx6dl-mamoj.dtb \
        imx6dl-nit6xlite.dtb \
@@ -521,6 +533,8 @@ dtb-$(CONFIG_SOC_IMX6Q) += \
 dtb-$(CONFIG_SOC_IMX6SL) += \
        imx6sl-evk.dtb \
        imx6sl-warp.dtb
+dtb-$(CONFIG_SOC_IMX6SLL) += \
+       imx6sll-evk.dtb
 dtb-$(CONFIG_SOC_IMX6SX) += \
        imx6sx-nitrogen6sx.dtb \
        imx6sx-sabreauto.dtb \
@@ -533,6 +547,7 @@ dtb-$(CONFIG_SOC_IMX6SX) += \
        imx6sx-udoo-neo-full.dtb
 dtb-$(CONFIG_SOC_IMX6UL) += \
        imx6ul-14x14-evk.dtb \
+       imx6ul-ccimx6ulsbcexpress.dtb \
        imx6ul-geam.dtb \
        imx6ul-isiot-emmc.dtb \
        imx6ul-isiot-nand.dtb \
@@ -567,8 +582,10 @@ dtb-$(CONFIG_SOC_VF610) += \
        vf610-cosmic.dtb \
        vf610m4-cosmic.dtb \
        vf610-twr.dtb \
+       vf610-zii-cfu1.dtb \
        vf610-zii-dev-rev-b.dtb \
-       vf610-zii-dev-rev-c.dtb
+       vf610-zii-dev-rev-c.dtb \
+       vf610-zii-ssmb-spu3.dtb
 dtb-$(CONFIG_ARCH_MXS) += \
        imx23-evk.dtb \
        imx23-olinuxino.dtb \
@@ -695,10 +712,12 @@ dtb-$(CONFIG_SOC_AM33XX) += \
        am335x-pepper.dtb \
        am335x-phycore-rdk.dtb \
        am335x-pocketbeagle.dtb \
+       am335x-sancloud-bbe.dtb \
        am335x-shc.dtb \
        am335x-sbc-t335.dtb \
        am335x-sl50.dtb \
-       am335x-wega-rdk.dtb
+       am335x-wega-rdk.dtb \
+       am335x-osd3358-sm-red.dtb
 dtb-$(CONFIG_ARCH_OMAP4) += \
        omap4-droid4-xt894.dtb \
        omap4-duovero-parlor.dtb \
@@ -819,6 +838,7 @@ dtb-$(CONFIG_ARCH_RENESAS) += \
        r8a7793-gose.dtb \
        r8a7794-alt.dtb \
        r8a7794-silk.dtb \
+       r9a06g032-rzn1d400-db.dtb \
        sh73a0-kzm9g.dtb
 dtb-$(CONFIG_ARCH_ROCKCHIP) += \
        rv1108-evb.dtb \
@@ -859,6 +879,8 @@ dtb-$(CONFIG_ARCH_S3C64XX) += \
        s3c6410-smdk6410.dtb
 dtb-$(CONFIG_ARCH_S5PV210) += \
        s5pv210-aquila.dtb \
+       s5pv210-fascinate4g.dtb \
+       s5pv210-galaxys.dtb \
        s5pv210-goni.dtb \
        s5pv210-smdkc110.dtb \
        s5pv210-smdkv210.dtb \
@@ -1039,7 +1061,7 @@ dtb-$(CONFIG_ARCH_TANGO) += \
        tango4-vantage-1172.dtb
 dtb-$(CONFIG_ARCH_TEGRA_2x_SOC) += \
        tegra20-harmony.dtb \
-       tegra20-iris-512.dtb \
+       tegra20-colibri-iris.dtb \
        tegra20-medcom-wide.dtb \
        tegra20-paz00.dtb \
        tegra20-plutux.dtb \
@@ -1109,6 +1131,7 @@ dtb-$(CONFIG_ARCH_ZYNQ) += \
        zynq-zc770-xm012.dtb \
        zynq-zc770-xm013.dtb \
        zynq-zed.dtb \
+       zynq-zturn.dtb \
        zynq-zybo.dtb \
        zynq-zybo-z7.dtb
 dtb-$(CONFIG_MACH_ARMADA_370) += \
@@ -1138,6 +1161,7 @@ dtb-$(CONFIG_MACH_ARMADA_38X) += \
        armada-388-clearfog-pro.dtb \
        armada-388-db.dtb \
        armada-388-gp.dtb \
+       armada-388-helios4.dtb \
        armada-388-rd.dtb
 dtb-$(CONFIG_MACH_ARMADA_39X) += \
        armada-398-db.dtb
@@ -1168,7 +1192,6 @@ dtb-$(CONFIG_ARCH_MEDIATEK) += \
        mt7623a-rfb-emmc.dtb \
        mt7623a-rfb-nand.dtb \
        mt7623n-rfb-emmc.dtb \
-       mt7623n-rfb-nand.dtb \
        mt7623n-bananapi-bpi-r2.dtb \
        mt8127-moose.dtb \
        mt8135-evbp1.dtb
index ed7a5a3..8c6fc41 100644 (file)
                compatible = "ti,wl1835";
                reg = <2>;
                interrupt-parent = <&gpio3>;
-               interrupts = <7 IRQ_TYPE_LEVEL_HIGH>;
+               interrupts = <7 IRQ_TYPE_EDGE_RISING>;
        };
 };
 
index 1356fd6..c87d012 100644 (file)
                compatible = "ti,wl1835";
                reg = <2>;
                interrupt-parent = <&gpio3>;
-               interrupts = <17 IRQ_TYPE_LEVEL_HIGH>;
+               interrupts = <17 IRQ_TYPE_EDGE_RISING>;
        };
 };
 
index 0c096a7..bf1a40e 100644 (file)
                compatible = "ti,wl1271";
                reg = <2>;
                interrupt-parent = <&gpio0>;
-               interrupts = <31 IRQ_TYPE_LEVEL_HIGH>; /* gpio 31 */
+               interrupts = <31 IRQ_TYPE_EDGE_RISING>; /* gpio 31 */
                ref-clock-frequency = <38400000>;
        };
 };
diff --git a/arch/arm/boot/dts/am335x-osd3358-sm-red.dts b/arch/arm/boot/dts/am335x-osd3358-sm-red.dts
new file mode 100755 (executable)
index 0000000..4d96901
--- /dev/null
@@ -0,0 +1,457 @@
+//SPDX-License-Identifier: GPL-2.0
+/* Copyright (C) 2018 Octavo Systems LLC - http://www.octavosystems.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.
+ */
+
+/dts-v1/;
+
+#include "am33xx.dtsi"
+#include "am335x-osd335x-common.dtsi"
+#include <dt-bindings/interrupt-controller/irq.h>
+
+#include <dt-bindings/display/tda998x.h>
+
+/ {
+       model = "Octavo Systems OSD3358-SM-RED";
+       compatible = "oct,osd3358-sm-refdesign", "ti,am335x-bone-black", "ti,am335x-bone", "ti,am33xx";
+};
+
+&ldo3_reg {
+       regulator-min-microvolt = <1800000>;
+       regulator-max-microvolt = <1800000>;
+       regulator-always-on;
+};
+
+&mmc1 {
+       vmmc-supply = <&vmmcsd_fixed>;
+};
+
+&mmc2 {
+       vmmc-supply = <&vmmcsd_fixed>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&emmc_pins>;
+       bus-width = <8>;
+       status = "okay";
+};
+
+&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 */
+               >;
+       };
+
+       nxp_hdmi_bonelt_off_pins: nxp-hdmi-bonelt-off-pins {
+               pinctrl-single,pins = <
+                       AM33XX_IOPAD(0x9b0, PIN_OUTPUT_PULLDOWN | MUX_MODE3)    /* xdma_event_intr0 */
+               >;
+       };
+
+       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 */
+               >;
+       };
+
+       flash_enable: flash-enable {
+               pinctrl-single,pins = <
+                       AM33XX_IOPAD(0x944, 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 */
+               >;
+       };
+
+       ethernet_interrupt: ethernet-interrupt{
+               pinctrl-single,pins = <
+                       AM33XX_IOPAD(0x908, PIN_INPUT_PULLDOWN | MUX_MODE7)             /* mii1_col.gpio3_0 */
+               >;
+       };
+};
+
+&lcdc {
+       status = "okay";
+
+       /* If you want to get 24 bit RGB and 16 BGR mode instead of
+        * current 16 bit RGB and 24 BGR modes, set the propety
+        * below to "crossed" and uncomment the video-ports -property
+        * in tda19988 node.
+        * AM335x errata for wiring:
+        * http://www.ti.com/lit/er/sprz360i/sprz360i.pdf
+        */
+
+       blue-and-red-wiring = "straight";
+
+       port {
+               lcdc_0: endpoint {
+                       remote-endpoint = <&hdmi_0>;
+               };
+       };
+};
+
+&i2c0 {
+       tda19988: hdmi-encoder@70 {
+               compatible = "nxp,tda998x";
+               reg = <0x70>;
+
+               pinctrl-names = "default", "off";
+               pinctrl-0 = <&nxp_hdmi_bonelt_pins>;
+               pinctrl-1 = <&nxp_hdmi_bonelt_off_pins>;
+
+               /* Convert 24bit BGR to RGB, e.g. cross red and blue wiring */
+               /* video-ports = <0x234501>; */
+
+               #sound-dai-cells = <0>;
+               audio-ports = < TDA998x_I2S     0x03>;
+
+               port {
+                       hdmi_0: endpoint {
+                               remote-endpoint = <&lcdc_0>;
+                       };
+               };
+       };
+
+       mpu9250: imu@68 {
+               compatible = "invensense,mpu6050";
+               reg = <0x68>;
+               interrupt-parent = <&gpio3>;
+               interrupts = <21 IRQ_TYPE_EDGE_RISING>;
+               i2c-gate {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       ax8975@c {
+                               compatible = "ak,ak8975";
+                               reg = <0x0c>;
+                       };
+               };
+               /*invensense,int_config = <0x10>;
+               invensense,level_shifter = <0>;
+               invensense,orientation = [01 00 00 00 01 00 00 00 01];
+               invensense,sec_slave_type = <0>;
+               invensense,key = [4e cc 7e eb f6 1e 35 22 00 34 0d 65 32 e9 94 89];*/
+       };
+
+       bmp280: pressure@78 {
+               compatible = "bosch,bmp280";
+               reg = <0x76>;
+       };
+};
+
+&rtc {
+       system-power-controller;
+};
+
+&mcasp0 {
+       #sound-dai-cells = <0>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&mcasp0_pins>;
+       status = "okay";
+       op-mode = <0>;  /* MCASP_IIS_MODE */
+       tdm-slots = <2>;
+       serial-dir = <  /* 0: INACTIVE, 1: TX, 2: RX */
+                       0 0 1 0
+               >;
+       tx-num-evt = <32>;
+       rx-num-evt = <32>;
+};
+
+/ {
+       clk_mcasp0_fixed: clk-mcasp0-fixed {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <24576000>;
+       };
+
+       clk_mcasp0: clk-mcasp0 {
+               #clock-cells = <0>;
+               compatible = "gpio-gate-clock";
+               clocks = <&clk_mcasp0_fixed>;
+               enable-gpios = <&gpio1 27 0>; /* BeagleBone Black Clk enable on GPIO1_27 */
+       };
+
+       sound {
+               compatible = "simple-audio-card";
+               simple-audio-card,name = "TI BeagleBone Black";
+               simple-audio-card,format = "i2s";
+               simple-audio-card,bitclock-master = <&dailink0_master>;
+               simple-audio-card,frame-master = <&dailink0_master>;
+
+               dailink0_master: simple-audio-card,cpu {
+                       sound-dai = <&mcasp0>;
+                       clocks = <&clk_mcasp0>;
+               };
+
+               simple-audio-card,codec {
+                       sound-dai = <&tda19988>;
+               };
+       };
+
+       chosen {
+               stdout-path = &uart0;
+       };
+
+       leds {
+               pinctrl-names = "default";
+               pinctrl-0 = <&user_leds_s0>;
+
+               compatible = "gpio-leds";
+
+               led2 {
+                       label = "beaglebone:green:usr0";
+                       gpios = <&gpio1 21 GPIO_ACTIVE_HIGH>;
+                       linux,default-trigger = "heartbeat";
+                       default-state = "off";
+               };
+
+               led3 {
+                       label = "beaglebone:green:usr1";
+                       gpios = <&gpio1 22 GPIO_ACTIVE_HIGH>;
+                       linux,default-trigger = "mmc0";
+                       default-state = "off";
+               };
+
+               led4 {
+                       label = "beaglebone:green:usr2";
+                       gpios = <&gpio1 23 GPIO_ACTIVE_HIGH>;
+                       linux,default-trigger = "cpu0";
+                       default-state = "off";
+               };
+
+               led5 {
+                       label = "beaglebone:green:usr3";
+                       gpios = <&gpio1 24 GPIO_ACTIVE_HIGH>;
+                       linux,default-trigger = "mmc1";
+                       default-state = "off";
+               };
+       };
+
+       vmmcsd_fixed: fixedregulator0 {
+               compatible = "regulator-fixed";
+               regulator-name = "vmmcsd_fixed";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+       };
+};
+
+&am33xx_pinmux {
+       pinctrl-names = "default";
+       pinctrl-0 = <&clkout2_pin>;
+
+       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 */
+               >;
+       };
+
+       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 */
+               >;
+       };
+
+       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 */
+               >;
+       };
+
+       clkout2_pin: pinmux-clkout2-pin {
+               pinctrl-single,pins = <
+                       AM33XX_IOPAD(0x9b4, 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 */
+               >;
+       };
+
+       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)
+               >;
+       };
+
+       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 */
+               >;
+       };
+
+       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)
+               >;
+       };
+
+       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 */
+               >;
+       };
+
+       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 */
+               >;
+       };
+};
+
+
+&uart0 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&uart0_pins>;
+
+       status = "okay";
+};
+
+&usb {
+       status = "okay";
+};
+
+&usb_ctrl_mod {
+       status = "okay";
+};
+
+&usb0_phy {
+       status = "okay";
+};
+
+&usb1_phy {
+       status = "okay";
+};
+
+&usb0 {
+       status = "okay";
+       dr_mode = "peripheral";
+       interrupts-extended = <&intc 18 &tps 0>;
+       interrupt-names = "mc", "vbus";
+};
+
+&usb1 {
+       status = "okay";
+       dr_mode = "host";
+};
+
+&cppi41dma  {
+       status = "okay";
+};
+
+&i2c2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&i2c2_pins>;
+       status = "okay";
+       clock-frequency = <100000>;
+};
+
+&cpsw_emac0 {
+       phy_id = <&davinci_mdio>, <4>;
+       phy-mode = "rgmii-txid";
+};
+
+&mac {
+       slaves = <1>;
+       pinctrl-names = "default", "sleep";
+       pinctrl-0 = <&cpsw_default>;
+       pinctrl-1 = <&cpsw_sleep>;
+       status = "okay";
+};
+
+&davinci_mdio {
+       pinctrl-names = "default", "sleep";
+       pinctrl-0 = <&davinci_mdio_default>;
+       pinctrl-1 = <&davinci_mdio_sleep>;
+       status = "okay";
+};
+
+&mmc1 {
+       status = "okay";
+       bus-width = <0x4>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&mmc1_pins>;
+       cd-gpios = <&gpio0 6 GPIO_ACTIVE_LOW>;
+};
+
+&rtc {
+       clocks = <&clk_32768_ck>, <&l4_per_clkctrl AM3_CLKDIV32K_CLKCTRL 0>;
+       clock-names = "ext-clk", "int-clk";
+};
diff --git a/arch/arm/boot/dts/am335x-sancloud-bbe.dts b/arch/arm/boot/dts/am335x-sancloud-bbe.dts
new file mode 100644 (file)
index 0000000..7b8e741
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.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.
+ */
+/dts-v1/;
+
+#include "am33xx.dtsi"
+#include "am335x-bone-common.dtsi"
+#include "am335x-boneblack-common.dtsi"
+#include <dt-bindings/interrupt-controller/irq.h>
+
+/ {
+       model = "SanCloud BeagleBone Enhanced";
+       compatible = "sancloud,am335x-boneenhanced", "ti,am335x-bone-black", "ti,am335x-bone", "ti,am33xx";
+};
+
+&am33xx_pinmux {
+       pinctrl-names = "default";
+
+       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 */
+               >;
+       };
+
+       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)
+               >;
+       };
+
+       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 */
+               >;
+       };
+
+       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)
+               >;
+       };
+
+       usb_hub_ctrl: usb_hub_ctrl {
+               pinctrl-single,pins = <
+                       AM33XX_IOPAD(0x944, 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 */
+               >;
+       };
+
+       lps3331ap_pins: pinmux_lps3331ap_pins {
+               pinctrl-single,pins = <
+                       AM33XX_IOPAD(0x868, PIN_INPUT | MUX_MODE7)     /* gpmc_a10.gpio1_26 */
+               >;
+       };
+};
+
+&mac {
+       pinctrl-names = "default", "sleep";
+       pinctrl-0 = <&cpsw_default>;
+       pinctrl-1 = <&cpsw_sleep>;
+       status = "okay";
+};
+
+&davinci_mdio {
+       pinctrl-names = "default", "sleep";
+       pinctrl-0 = <&davinci_mdio_default>;
+       pinctrl-1 = <&davinci_mdio_sleep>;
+       status = "okay";
+};
+
+&cpsw_emac0 {
+       phy_id = <&davinci_mdio>, <0>;
+       phy-mode = "rgmii-txid";
+};
+
+&i2c0 {
+       lps331ap: barometer@5c {
+               compatible = "st,lps331ap-press";
+               st,drdy-int-pin = <1>;
+               reg = <0x5c>;
+               interrupt-parent = <&gpio1>;
+               interrupts = <26 IRQ_TYPE_EDGE_RISING>;
+       };
+
+       mpu6050: accelerometer@68 {
+               compatible = "invensense,mpu6050";
+               reg = <0x68>;
+               interrupt-parent = <&gpio0>;
+               interrupts = <2 IRQ_TYPE_EDGE_RISING>;
+               orientation = <0xff 0 0 0 1 0 0 0 0xff>;
+       };
+
+       usb2512b: usb-hub@2c {
+               compatible = "microchip,usb2512b";
+               reg = <0x2c>;
+               reset-gpios = <&gpio0 29 GPIO_ACTIVE_LOW>;
+               /* wifi on port 4 */
+       };
+};
index 1bcc604..38d57b8 100644 (file)
@@ -8,6 +8,8 @@
 /dts-v1/;
 
 #include "am33xx.dtsi"
+#include <dt-bindings/pwm/pwm.h>
+#include <dt-bindings/interrupt-controller/irq.h>
 
 / {
        model = "Toby Churchill SL50 Series";
                pinctrl-0 = <&led_pins>;
 
                led0 {
-                       label = "sl50:green:usr0";
+                       label = "sl50:red:usr0";
                        gpios = <&gpio1 21 GPIO_ACTIVE_LOW>;
                        default-state = "off";
                };
 
                led1 {
-                       label = "sl50:red:usr1";
+                       label = "sl50:green:usr1";
                        gpios = <&gpio1 22 GPIO_ACTIVE_LOW>;
                        default-state = "off";
                };
 
                led2 {
-                       label = "sl50:green:usr2";
+                       label = "sl50:red:usr2";
                        gpios = <&gpio1 23 GPIO_ACTIVE_LOW>;
                        default-state = "off";
                };
 
                led3 {
-                       label = "sl50:red:usr3";
+                       label = "sl50:green:usr3";
                        gpios = <&gpio1 24 GPIO_ACTIVE_LOW>;
                        default-state = "off";
                };
 
        backlight0: disp0 {
                compatible = "pwm-backlight";
-               pwms = <&ehrpwm1 0 500000 0>;
-               brightness-levels = <0 10 20 30 40 50 60 70 80 90 99>;
-               default-brightness-level = <6>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&backlight0_pins>;
+               pwms = <&ehrpwm1 0 500000 PWM_POLARITY_INVERTED>;
+               brightness-levels = < 0  1  2  3  4  5  6  7  8  9
+                                    10 11 12 13 14 15 16 17 18 19
+                                    20 21 22 23 24 25 26 27 28 29
+                                    30 31 32 33 34 35 36 37 38 39
+                                    40 41 42 43 44 45 46 47 48 49
+                                    50 51 52 53 54 55 56 57 58 59
+                                    60 61 62 63 64 65 66 67 68 69
+                                    70 71 72 73 74 75 76 77 78 79
+                                    80 81 82 83 84 85 86 87 88 89
+                                    90 91 92 93 94 95 96 97 98 99
+                                   100>;
+               default-brightness-level = <50>;
+               enable-gpios = <&gpio2 4 GPIO_ACTIVE_HIGH>;
+               power-supply = <&vdd_sys_reg>;
        };
 
        backlight1: disp1 {
                compatible = "pwm-backlight";
-               pwms = <&ehrpwm1 1 500000 0>;
-               brightness-levels = <0 10 20 30 40 50 60 70 80 90 99>;
-               default-brightness-level = <6>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&backlight1_pins>;
+               pwms = <&ehrpwm1 1 500000 PWM_POLARITY_INVERTED>;
+               brightness-levels = < 0  1  2  3  4  5  6  7  8  9
+                                    10 11 12 13 14 15 16 17 18 19
+                                    20 21 22 23 24 25 26 27 28 29
+                                    30 31 32 33 34 35 36 37 38 39
+                                    40 41 42 43 44 45 46 47 48 49
+                                    50 51 52 53 54 55 56 57 58 59
+                                    60 61 62 63 64 65 66 67 68 69
+                                    70 71 72 73 74 75 76 77 78 79
+                                    80 81 82 83 84 85 86 87 88 89
+                                    90 91 92 93 94 95 96 97 98 99
+                                   100>;
+               default-brightness-level = <50>;
+               enable-gpios = <&gpio0 26 GPIO_ACTIVE_HIGH>;
+               power-supply = <&vdd_sys_reg>;
        };
 
        clocks {
                #size-cells = <0>;
 
                /* audio external oscillator */
-               tlv320aic3x_mclk: oscillator@0 {
+               audio_mclk_fixed: oscillator@0 {
                        compatible = "fixed-clock";
                        #clock-cells = <0>;
                        clock-frequency  = <24576000>;  /* 24.576MHz */
                };
+
+               audio_mclk: audio_mclk_gate@0 {
+                       compatible = "gpio-gate-clock";
+                       #clock-cells = <0>;
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&audio_mclk_pins>;
+                       clocks = <&audio_mclk_fixed>;
+                       enable-gpios = <&gpio1 27 0>;
+               };
+       };
+
+       panel: lcd_panel {
+               compatible = "ti,tilcdc,panel";
+               pinctrl-names = "default";
+               pinctrl-0 = <&lcd_pins>;
+
+               panel-info {
+                       ac-bias = <255>;
+                       ac-bias-intrpt = <0>;
+                       dma-burst-sz = <16>;
+                       bpp = <16>;
+                       fdd = <0x80>;
+                       tft-alt-mode = <0>;
+                       mono-8bit-mode = <0>;
+                       sync-edge = <0>;
+                       sync-ctrl = <1>;
+                       raster-order = <0>;
+                       fifo-th = <0>;
+               };
+
+               display-timings {
+                       native-mode = <&timing0>;
+                       timing0: 960x128 {
+                               clock-frequency = <18000000>;
+                               hactive = <960>;
+                               vactive = <272>;
+
+                               hback-porch = <40>;
+                               hfront-porch = <16>;
+                               hsync-len = <24>;
+                               hsync-active = <0>;
+
+                               vback-porch = <3>;
+                               vfront-porch = <8>;
+                               vsync-len = <4>;
+                               vsync-active = <0>;
+                       };
+               };
        };
 
        sound {
-               compatible = "ti,da830-evm-audio";
-               ti,model = "AM335x-SL50";
-               ti,audio-codec = <&audio_codec>;
-               ti,mcasp-controller = <&mcasp0>;
+               compatible = "audio-graph-card";
+               label = "sound-card";
+               pinctrl-names = "default";
+               pinctrl-0 = <&audio_pa_pins>;
+
+               widgets = "Headphone", "Headphone Jack",
+                         "Speaker", "Speaker External",
+                         "Line", "Line In",
+                         "Microphone", "Microphone Jack";
 
-               clocks = <&tlv320aic3x_mclk>;
-               clock-names = "mclk";
+               routing = "Headphone Jack",     "HPLOUT",
+                         "Headphone Jack",     "HPROUT",
+                         "Amplifier",          "MONO_LOUT",
+                         "Speaker External",   "Amplifier",
+                         "LINE1R",             "Line In",
+                         "LINE1L",             "Line In",
+                         "MIC3L",              "Microphone Jack",
+                         "MIC3R",              "Microphone Jack",
+                         "Microphone Jack",    "Mic Bias";
 
-               ti,audio-routing =
-                       "Headphone Jack",       "HPLOUT",
-                       "Headphone Jack",       "HPROUT",
-                       "LINE1R",               "Line In",
-                       "LINE1L",               "Line In";
+               dais = <&cpu_port>;
+
+               pa-gpios = <&gpio3 18 GPIO_ACTIVE_HIGH>;
        };
 
        emmc_pwrseq: pwrseq@0 {
                reset-gpios = <&gpio1 20 GPIO_ACTIVE_LOW>;
        };
 
+       vdd_sys_reg: regulator@0 {
+               compatible = "regulator-fixed";
+               regulator-name = "vdd_sys_reg";
+               regulator-min-microvolt = <5000000>;
+               regulator-max-microvolt = <5000000>;
+               regulator-always-on;
+       };
+
        vmmcsd_fixed: fixedregulator0 {
                compatible = "regulator-fixed";
                regulator-name = "vmmcsd_fixed";
        pinctrl-names = "default";
        pinctrl-0 = <&lwb_pins>;
 
+       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 */
+               >;
+       };
+
+       audio_pa_pins: pinmux_audio_pa_pins {
+               pinctrl-single,pins = <
+                       AM33XX_IOPAD(0x9a0, 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 */
+               >;
+       };
+
+       backlight0_pins: pinmux_backlight0_pins {
+               pinctrl-single,pins = <
+                       AM33XX_IOPAD(0x898, 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 */
+               >;
+       };
+
+       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 */
+               >;
+       };
+
        led_pins: pinmux_led_pins {
                pinctrl-single,pins = <
                        AM33XX_IOPAD(0x854, PIN_OUTPUT | MUX_MODE7)     /* gpmc_a5.gpio1_21 */
                        /* 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 */
+                       /* Ethernet */
+                       AM33XX_IOPAD(0x838, PIN_INPUT_PULLUP | MUX_MODE7)       /* Ethernet_nRST - gpmc_ad14.gpio1_14 */
                >;
        };
 
                >;
        };
 
-       audio_pins: pinmux_audio_pins {
+       ehrpwm1_pins: pinmux_ehrpwm1a_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_IOPAD(0x848, PIN_OUTPUT | MUX_MODE6)     /* gpmc_a2.ehrpwm1a */
+                       AM33XX_IOPAD(0x84c, PIN_OUTPUT | MUX_MODE6)     /* gpmc_a3.ehrpwm1b */
                >;
        };
 
-       ehrpwm1_pins: pinmux_ehrpwm1a_pins {
+       rtc0_irq_pins: pinmux_rtc0_irq_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_IOPAD(0x824, PIN_INPUT_PULLUP | MUX_MODE7)     /* gpmc_ad9.gpio0_23 */
                >;
        };
 
 
        lwb_pins: pinmux_lwb_pins {
                pinctrl-single,pins = <
-                       AM33XX_IOPAD(0x9a4, PIN_OUTPUT | MUX_MODE7)     /* SoundPA_en - mcasp0_fsr.gpio3_19 */
-                       AM33XX_IOPAD(0x828, PIN_OUTPUT | MUX_MODE7)     /* nKbdOnC - gpmc_ad10.gpio0_26 */
                        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(0x838, PIN_INPUT_PULLUP | MUX_MODE7)       /* nDispReset - gpmc_ad14.gpio1_14 */
                        AM33XX_IOPAD(0x844, 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 */
+                       /* 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 */
                >;
        };
 };
                reg = <0x24>;
        };
 
-       bq32000: rtc@68 {
-               compatible = "ti,bq32000";
-               trickle-resistor-ohms = <1120>;
+       rtc0: rtc@68 {
+               compatible = "dallas,ds1339";
+               pinctrl-names = "default";
+               pinctrl-0 = <&rtc0_irq_pins>;
+               interrupt-parent = <&gpio0>;
+               interrupts = <23 IRQ_TYPE_EDGE_FALLING>; /* gpio 23 */
+               wakeup-source;
+               trickle-resistor-ohms = <2000>;
                reg = <0x68>;
        };
 
        audio_codec: tlv320aic3106@1b {
                status = "okay";
                compatible = "ti,tlv320aic3106";
+               #sound-dai-cells = <0>;
                reg = <0x1b>;
+               ai3x-micbias-vg = <2>;  /* 2.5V */
 
                AVDD-supply = <&ldo4_reg>;
                IOVDD-supply = <&ldo4_reg>;
                DRVDD-supply = <&ldo4_reg>;
                DVDD-supply = <&ldo3_reg>;
+
+               codec_port: port {
+                       codec_endpoint: endpoint {
+                               remote-endpoint = <&cpu_endpoint>;
+                               clocks = <&audio_mclk>;
+                       };
+               };
        };
 
        /* Ambient Light Sensor */
 
 &usb0 {
        status = "okay";
-       dr_mode = "peripheral";
+       dr_mode = "otg";
 };
 
 &usb1 {
        status = "okay";
        pinctrl-names = "default";
        pinctrl-0 = <&audio_pins>;
-
+       #sound-dai-cells = <0>;
        op-mode = <0>;  /* MCASP_ISS_MODE */
        tdm-slots = <2>;
-       serial-dir = <
-               2 0 1 0
-               0 0 0 0
-               0 0 0 0
-               0 0 0 0
+       /* 4 serializers */
+       serial-dir = <  /* 0: INACTIVE, 1: TX, 2: RX */
+               0 0 1 2
        >;
-       tx-num-evt = <1>;
-       rx-num-evt = <1>;
+       tx-num-evt = <32>;
+       rx-num-evt = <32>;
+
+       cpu_port: port {
+               cpu_endpoint: endpoint {
+                       remote-endpoint = <&codec_endpoint>;
+
+                       dai-format = "dsp_b";
+                       bitclock-master = <&codec_port>;
+                       frame-master = <&codec_port>;
+                       bitclock-inversion;
+                       clocks = <&audio_mclk>;
+               };
+       };
 };
 
 &uart0 {
 };
 
 &cpsw_emac0 {
-       phy_id = <&davinci_mdio>, <0>;
-       phy-mode = "mii";
-};
-
-&cpsw_emac1 {
-       phy_id = <&davinci_mdio>, <1>;
        phy-mode = "mii";
+       phy-handle = <&ethphy0>;
 };
 
 &mac {
        pinctrl-names = "default", "sleep";
        pinctrl-0 = <&davinci_mdio_default>;
        pinctrl-1 = <&davinci_mdio_sleep>;
+       reset-gpios = <&gpio1 14 GPIO_ACTIVE_LOW>;
+       reset-delay-us = <100>;   /* PHY datasheet states 100us min */
+
+       ethphy0: ethernet-phy@0 {
+               reg = <0>;
+       };
 };
 
 &sham {
        pinctrl-names = "default";
        pinctrl-0 = <&ehrpwm1_pins>;
 };
+
+&lcdc {
+       status = "okay";
+};
+
+&tscadc {
+       status = "okay";
+};
+
+&am335x_adc {
+       ti,adc-channels = <0 1 2 3 4 5 6 7>;
+};
index 9cd62bc..d3dd6a1 100644 (file)
@@ -29,8 +29,8 @@
                serial3 = &uart3;
                serial4 = &uart4;
                serial5 = &uart5;
-               d_can0 = &dcan0;
-               d_can1 = &dcan1;
+               d-can0 = &dcan0;
+               d-can1 = &dcan1;
                usb0 = &usb0;
                usb1 = &usb1;
                phy0 = &usb0_phy;
index 98aadb0..1d158cf 100644 (file)
                status = "okay";
                pinctrl-names = "default";
                enable-gpios = <&gpio6 16 GPIO_ACTIVE_HIGH>;    /* gpio176, lcd INI */
+               vcc-supply = <&vdd_io_reg>;
 
                port {
                        lcd_in: endpoint {
        bl: backlight {
                compatible = "pwm-backlight";
                pinctrl-names = "default";
+               power-supply = <&vdd_io_reg>;
                pinctrl-0 = <&backlight_pins>;
                pwms = <&pwm11 0 5000000 0>;
                brightness-levels = <0 10 20 30 40 50 60 70 80 90 100>;
                ti,timers = <&timer11>;
                #pwm-cells = <3>;
        };
+
+       /* HS USB Host PHY on PORT 1 */
+       hsusb1_phy: hsusb1_phy {
+               compatible = "usb-nop-xceiv";
+               reset-gpios = <&gpio2 25 GPIO_ACTIVE_LOW>; /* gpio_57 */
+               #phy-cells = <0>;
+       };
 };
 
 &davinci_emac {
                reg = <0x21>;
                gpio-controller;
                #gpio-cells = <2>;
+               vcc-supply = <&vdd_io_reg>;
        };
 };
 
        cd-gpios = <&gpio4 31 GPIO_ACTIVE_HIGH>; /* gpio_127 */
 };
 
-&mmc2 {
+&mmc3 {
       status = "disabled";
 };
 
-&mmc3 {
-      status = "disabled";
+&usbhshost {
+       port1-mode = "ehci-phy";
+};
+
+&usbhsehci {
+       phys = <&hsusb1_phy>;
 };
 
 &omap3_pmx_core {
+       pinctrl-names = "default";
+       pinctrl-0 = <&hsusb1_rst_pins>;
 
        leds_pins: pinmux_leds_pins {
                pinctrl-single,pins = <
                        OMAP3_CORE1_IOPAD(0x20fa, PIN_OUTPUT | MUX_MODE0)       /* dss_data15.dss_data15 */
                >;
        };
+
+       hsusb1_rst_pins: pinmux_hsusb1_rst_pins {
+               pinctrl-single,pins = <
+                       OMAP3_CORE1_IOPAD(0x20ba, PIN_OUTPUT | MUX_MODE4)       /* gpmc_ncs6.gpio_57 */
+               >;
+       };
+};
+
+&omap3_pmx_core2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&hsusb1_pins>;
+
+       hsusb1_pins: pinmux_hsusb1_pins {
+               pinctrl-single,pins = <
+                       OMAP3430_CORE2_IOPAD(0x25d8, PIN_OUTPUT | MUX_MODE3)    /* etk_clk.hsusb1_stp */
+                       OMAP3430_CORE2_IOPAD(0x25da, PIN_OUTPUT | MUX_MODE3)    /* etk_ctl.hsusb1_clk */
+                       OMAP3430_CORE2_IOPAD(0x25ec, PIN_INPUT | MUX_MODE3)     /* etk_d8.hsusb1_dir */
+                       OMAP3430_CORE2_IOPAD(0x25ee, PIN_INPUT | MUX_MODE3)     /* etk_d9.hsusb1_nxt */
+                       OMAP3430_CORE2_IOPAD(0x25dc, PIN_INPUT | MUX_MODE3)     /* etk_d0.hsusb1_data0 */
+                       OMAP3430_CORE2_IOPAD(0x25de, PIN_INPUT | MUX_MODE3)     /* etk_d1.hsusb1_data1 */
+                       OMAP3430_CORE2_IOPAD(0x25e0, PIN_INPUT | MUX_MODE3)     /* etk_d2.hsusb1_data2 */
+                       OMAP3430_CORE2_IOPAD(0x25ea, PIN_INPUT | MUX_MODE3)     /* etk_d7.hsusb1_data3 */
+                       OMAP3430_CORE2_IOPAD(0x25e4, PIN_INPUT | MUX_MODE3)     /* etk_d4.hsusb1_data4 */
+                       OMAP3430_CORE2_IOPAD(0x25e6, PIN_INPUT | MUX_MODE3)     /* etk_d5.hsusb1_data5 */
+                       OMAP3430_CORE2_IOPAD(0x25e8, PIN_INPUT | MUX_MODE3)     /* etk_d6.hsusb1_data6 */
+                       OMAP3430_CORE2_IOPAD(0x25e2, PIN_INPUT | MUX_MODE3)     /* etk_d3.hsusb1_data7 */
+               >;
+       };
 };
index a6d5ff7..dae6e45 100644 (file)
                        cpu0-supply = <&vdd_core_reg>;
                };
        };
+
+       wl12xx_buffer: wl12xx_buf {
+               compatible = "regulator-fixed";
+               regulator-name = "wl1271_buf";
+               regulator-min-microvolt = <1800000>;
+               regulator-max-microvolt = <1800000>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&wl12xx_buffer_pins>;
+               gpio = <&gpio5 1 GPIO_ACTIVE_LOW>; /* gpio 129 */
+               regulator-always-on;
+               vin-supply = <&vdd_1v8_reg>;
+       };
+
+       wl12xx_vmmc2: wl12xx_vmmc2 {
+               compatible = "regulator-fixed";
+               regulator-name = "vwl1271";
+               regulator-min-microvolt = <1800000>;
+               regulator-max-microvolt = <1800000>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&wl12xx_wkup_pins>;
+               gpio = <&gpio1 3 GPIO_ACTIVE_HIGH >; /* gpio 3 */
+               startup-delay-us = <70000>;
+               enable-active-high;
+               regulator-always-on;
+               vin-supply = <&wl12xx_buffer>;
+       };
 };
 
 &gpmc {
@@ -64,7 +90,6 @@
                regulators {
                        vdd_core_reg: VDCDC1 {
                                regulator-name = "vdd_core";
-                               compatible = "regulator-fixed";
                                regulator-always-on;
                                regulator-min-microvolt = <1200000>;
                                regulator-max-microvolt = <1200000>;
@@ -72,7 +97,6 @@
 
                        vdd_io_reg: VDCDC2 {
                                regulator-name = "vdd_io";
-                               compatible = "regulator-fixed";
                                regulator-always-on;
                                regulator-min-microvolt = <3300000>;
                                regulator-max-microvolt = <3300000>;
 
                        vdd_1v8_reg: VDCDC3 {
                                regulator-name = "vdd_1v8";
-                               compatible = "regulator-fixed";
                                regulator-always-on;
                                regulator-min-microvolt = <1800000>;
                                regulator-max-microvolt = <1800000>;
 
                        vdd_usb18_reg: LDO1 {
                                regulator-name = "vdd_usb18";
-                               compatible = "regulator-fixed";
                                regulator-always-on;
                                regulator-min-microvolt = <1800000>;
                                regulator-max-microvolt = <1800000>;
 
                        vdd_usb33_reg: LDO2 {
                                regulator-name = "vdd_usb33";
-                               compatible = "regulator-fixed";
                                regulator-always-on;
                                regulator-min-microvolt = <3300000>;
                                regulator-max-microvolt = <3300000>;
        };
 };
 
+&mmc2 {
+       interrupts-extended = <&intc 86 /* &omap3_pmx_core 0x12c */>;
+
+       status = "okay";
+       pinctrl-names = "default";
+       pinctrl-0 = <&mmc2_pins>;
+       vmmc-supply = <&wl12xx_vmmc2>;
+       non-removable;
+       bus-width = <4>;
+       cap-power-off-card;
+       #address-cells = <1>;
+       #size-cells = <0>;
+       wlcore: wlcore@2 {
+               compatible = "ti,wl1271";
+               reg = <2>;
+               interrupt-parent = <&gpio6>;
+               interrupts = <10 IRQ_TYPE_LEVEL_HIGH>; /* gpio_170 */
+               ref-clock-frequency = <26000000>;
+               tcxo-clock-frequency = <26000000>;
+       };
+};
+
+&uart2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&uart2_pins>;
+
+       bluetooth {
+               compatible = "ti,wl1271-st";
+               enable-gpios = <&gpio2 24 GPIO_ACTIVE_HIGH>; /* gpio 56 */
+               max-speed = <3000000>;
+       };
+};
+
 &omap3_pmx_core {
 
+       wl12xx_buffer_pins: pinmux_wl12xx_buffer_pins {
+               pinctrl-single,pins = <
+                       OMAP3_CORE1_IOPAD(0x2156, PIN_OUTPUT | MUX_MODE4)  /* mmc1_dat7.gpio_129 */
+               >;
+       };
+
+       mmc2_pins: pinmux_mmc2_pins {
+               pinctrl-single,pins = <
+                       OMAP3_CORE1_IOPAD(0x2158, PIN_INPUT_PULLUP | MUX_MODE0)  /* mmc2_clk.mmc2_clk */
+                       OMAP3_CORE1_IOPAD(0x215a, PIN_INPUT_PULLUP | MUX_MODE0)  /* mmc2_cmd.mmc2_cmd */
+                       OMAP3_CORE1_IOPAD(0x215c, PIN_INPUT_PULLUP | MUX_MODE0)  /* mmc2_dat0.mmc2_dat0 */
+                       OMAP3_CORE1_IOPAD(0x215e, PIN_INPUT_PULLUP | MUX_MODE0)  /* mmc2_dat1.mmc2_dat1 */
+                       OMAP3_CORE1_IOPAD(0x2160, PIN_INPUT_PULLUP | MUX_MODE0)  /* mmc2_dat2.mmc2_dat2 */
+                       OMAP3_CORE1_IOPAD(0x2162, PIN_INPUT_PULLUP | MUX_MODE0)  /* mmc2_dat3.mmc2_dat3 */
+                       OMAP3_CORE1_IOPAD(0x2164, PIN_OUTPUT | MUX_MODE1) /* mmc2_dat4.mmc2_dir_dat0 */
+                       OMAP3_CORE1_IOPAD(0x2166, PIN_OUTPUT | MUX_MODE1) /* mmc2_dat5.mmc2_dir_dat1 */
+                       OMAP3_CORE1_IOPAD(0x2168, PIN_OUTPUT | MUX_MODE1) /* mmc2_dat6.mmc2_dir_cmd */
+                       OMAP3_CORE1_IOPAD(0x216a, PIN_INPUT | MUX_MODE1) /* mmc2_dat7.mmc2_clkin */
+                       OMAP3_CORE1_IOPAD(0x21c6, PIN_INPUT_PULLUP | MUX_MODE4) /* hdq_sio.gpio_170 */
+               >;
+       };
+
        rtc_pins: pinmux_rtc_pins {
                pinctrl-single,pins = <
                        OMAP3_CORE1_IOPAD(0x20b6, PIN_INPUT_PULLUP | MUX_MODE4) /* gpmc_ncs4.gpio_55 */
                        OMAP3_CORE1_IOPAD(0x20d2, PIN_INPUT | MUX_MODE4) /* gpmc_wait3.gpio_65 */
                >;
        };
+
+       uart2_pins: pinmux_uart2_pins {
+               pinctrl-single,pins = <
+                       OMAP3_CORE1_IOPAD(0x2174, PIN_INPUT_PULLUP | MUX_MODE0)         /* uart2_cts */
+                       OMAP3_CORE1_IOPAD(0x2176, PIN_OUTPUT_PULLUP | MUX_MODE0)        /* uart2_rts */
+                       OMAP3_CORE1_IOPAD(0x2178, PIN_OUTPUT | MUX_MODE0)               /* uart2_tx */
+                       OMAP3_CORE1_IOPAD(0x217a, PIN_INPUT | MUX_MODE0)                /* uart2_rx */
+                       OMAP3_CORE1_IOPAD(0x20b8, PIN_INPUT | MUX_MODE0)                /* gpio_56 */
+               >;
+       };
+};
+
+&omap3_pmx_wkup {
+
+       wl12xx_wkup_pins: pinmux_wl12xx_wkup_pins {
+               pinctrl-single,pins = <
+                       OMAP3_WKUP_IOPAD(0x2a0c, PIN_OUTPUT | MUX_MODE4)        /* sys_boot1.gpio_3 */
+               >;
+       };
 };
index 60414b1..5b97c20 100644 (file)
                compatible = "ti,wl1835";
                reg = <2>;
                interrupt-parent = <&gpio1>;
-               interrupts = <23 IRQ_TYPE_LEVEL_HIGH>;
+               interrupts = <23 IRQ_TYPE_EDGE_RISING>;
        };
 };
 
index 5bb9d68..d9a2049 100644 (file)
        };
 };
 
-&omap_dwc3_2 {
-       extcon = <&extcon_usb2>;
-};
-
 &extcon_usb2 {
        id-gpio = <&gpio5 7 GPIO_ACTIVE_HIGH>;
        vbus-gpio = <&gpio7 22 GPIO_ACTIVE_HIGH>;
index c6d858b..784639d 100644 (file)
        };
 };
 
-&omap_dwc3_2 {
-       extcon = <&extcon_usb2>;
-};
-
 &extcon_usb2 {
        id-gpio = <&gpio3 16 GPIO_ACTIVE_HIGH>;
        vbus-gpio = <&gpio3 26 GPIO_ACTIVE_HIGH>;
index ad87f1a..c9063ff 100644 (file)
        dr_mode = "host";
 };
 
+&omap_dwc3_2 {
+       extcon = <&extcon_usb2>;
+};
+
 &usb2 {
-       dr_mode = "peripheral";
+       extcon = <&extcon_usb2>;
+       dr_mode = "otg";
 };
 
 &mmc1 {
index 50ed4ae..53b4bd3 100644 (file)
@@ -3,11 +3,6 @@
  * Device Tree file for SolidRun Clearfog Base revision A1 rev 2.0 (88F6828)
  *
  *  Copyright (C) 2015 Russell King
- *
- * This board is in development; the contents of this file work with
- * the A1 rev 2.0 of the board, which does not represent final
- * production board.  Things will change, don't expect this file to
- * remain compatible info the future.
  */
 
 /dts-v1/;
index 24e4b5a..ff890c0 100644 (file)
@@ -3,11 +3,6 @@
  * Device Tree file for SolidRun Clearfog Pro revision A1 rev 2.0 (88F6828)
  *
  *  Copyright (C) 2015 Russell King
- *
- * This board is in development; the contents of this file work with
- * the A1 rev 2.0 of the board, which does not represent final
- * production board.  Things will change, don't expect this file to
- * remain compatible info the future.
  */
 #include "armada-388-clearfog.dts"
 
index 5fd0f6f..89a354b 100644 (file)
@@ -3,11 +3,6 @@
  * Device Tree file for SolidRun Clearfog Pro revision A1 rev 2.0 (88F6828)
  *
  *  Copyright (C) 2015 Russell King
- *
- * This board is in development; the contents of this file work with
- * the A1 rev 2.0 of the board, which does not represent final
- * production board.  Things will change, don't expect this file to
- * remain compatible info the future.
  */
 
 /dts-v1/;
 &spi1 {
        /*
         * Add SPI CS pins for clearfog:
-        * CS0: W25Q32 (not populated on uSOM)
+        * CS0: W25Q32
         * CS1:
         * CS2: mikrobus
         */
index 0d9dfdf..7c6ad2a 100644 (file)
@@ -3,11 +3,6 @@
  * Device Tree include file for SolidRun Clearfog 88F6828 based boards
  *
  *  Copyright (C) 2015 Russell King
- *
- * This board is in development; the contents of this file work with
- * the A1 rev 2.0 of the board, which does not represent final
- * production board.  Things will change, don't expect this file to
- * remain compatible info the future.
  */
 
 #include "armada-388.dtsi"
 &spi1 {
        /*
         * Add SPI CS pins for clearfog:
-        * CS0: W25Q32 (not populated on uSOM)
+        * CS0: W25Q32
         * CS1: PIC microcontroller (Pro models)
         * CS2: mikrobus
         */
diff --git a/arch/arm/boot/dts/armada-388-helios4.dts b/arch/arm/boot/dts/armada-388-helios4.dts
new file mode 100644 (file)
index 0000000..705adfa
--- /dev/null
@@ -0,0 +1,313 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Device Tree file for Helios4
+ * based on SolidRun Clearfog revision A1 rev 2.0 (88F6828)
+ *
+ *  Copyright (C) 2017 Aditya Prayoga <aditya@kobol.io>
+ *
+ */
+
+/dts-v1/;
+#include "armada-388.dtsi"
+#include "armada-38x-solidrun-microsom.dtsi"
+
+/ {
+       model = "Helios4";
+       compatible = "kobol,helios4", "marvell,armada388",
+               "marvell,armada385", "marvell,armada380";
+
+       memory {
+               device_type = "memory";
+               reg = <0x00000000 0x80000000>; /* 2 GB */
+       };
+
+       aliases {
+               /* So that mvebu u-boot can update the MAC addresses */
+               ethernet1 = &eth0;
+       };
+
+       chosen {
+               stdout-path = "serial0:115200n8";
+       };
+
+       reg_12v: regulator-12v {
+               compatible = "regulator-fixed";
+               regulator-name = "power_brick_12V";
+               regulator-min-microvolt = <12000000>;
+               regulator-max-microvolt = <12000000>;
+               regulator-always-on;
+       };
+
+       reg_3p3v: regulator-3p3v {
+               compatible = "regulator-fixed";
+               regulator-name = "3P3V";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               regulator-always-on;
+               vin-supply = <&reg_12v>;
+       };
+
+       reg_5p0v_hdd: regulator-5v-hdd {
+               compatible = "regulator-fixed";
+               regulator-name = "5V_HDD";
+               regulator-min-microvolt = <5000000>;
+               regulator-max-microvolt = <5000000>;
+               regulator-always-on;
+               vin-supply = <&reg_12v>;
+       };
+
+       reg_5p0v_usb: regulator-5v-usb {
+               compatible = "regulator-fixed";
+               regulator-name = "USB-PWR";
+               regulator-min-microvolt = <5000000>;
+               regulator-max-microvolt = <5000000>;
+               regulator-boot-on;
+               regulator-always-on;
+               enable-active-high;
+               gpio = <&expander0 6 GPIO_ACTIVE_HIGH>;
+               vin-supply = <&reg_12v>;
+       };
+
+       system-leds {
+               compatible = "gpio-leds";
+               status-led {
+                       label = "helios4:green:status";
+                       gpios = <&gpio0 24 GPIO_ACTIVE_LOW>;
+                       linux,default-trigger = "heartbeat";
+                       default-state = "on";
+               };
+
+               fault-led {
+                       label = "helios4:red:fault";
+                       gpios = <&gpio0 25 GPIO_ACTIVE_LOW>;
+                       default-state = "keep";
+               };
+       };
+
+       io-leds {
+               compatible = "gpio-leds";
+               sata1-led {
+                       label = "helios4:green:ata1";
+                       gpios = <&gpio1 17 GPIO_ACTIVE_LOW>;
+                       linux,default-trigger = "ata1";
+                       default-state = "off";
+               };
+               sata2-led {
+                       label = "helios4:green:ata2";
+                       gpios = <&gpio1 18 GPIO_ACTIVE_LOW>;
+                       linux,default-trigger = "ata2";
+                       default-state = "off";
+               };
+               sata3-led {
+                       label = "helios4:green:ata3";
+                       gpios = <&gpio1 20 GPIO_ACTIVE_LOW>;
+                       linux,default-trigger = "ata3";
+                       default-state = "off";
+               };
+               sata4-led {
+                       label = "helios4:green:ata4";
+                       gpios = <&gpio1 21 GPIO_ACTIVE_LOW>;
+                       linux,default-trigger = "ata4";
+                       default-state = "off";
+               };
+               usb-led {
+                       label = "helios4:green:usb";
+                       gpios = <&gpio1 22 GPIO_ACTIVE_LOW>;
+                       linux,default-trigger = "usb-host";
+                       default-state = "off";
+               };
+       };
+
+       fan1: j10-pwm {
+               compatible = "pwm-fan";
+               pwms = <&gpio1 9 40000>;        /* Target freq:25 kHz */
+       };
+
+       fan2: j17-pwm {
+               compatible = "pwm-fan";
+               pwms = <&gpio1 23 40000>;       /* Target freq:25 kHz */
+       };
+
+       usb2_phy: usb2-phy {
+               compatible = "usb-nop-xceiv";
+               vbus-regulator = <&reg_5p0v_usb>;
+       };
+
+       usb3_phy: usb3-phy {
+               compatible = "usb-nop-xceiv";
+       };
+
+       soc {
+               internal-regs {
+                       i2c@11000 {
+                               clock-frequency = <400000>;
+                               pinctrl-0 = <&i2c0_pins>;
+                               pinctrl-names = "default";
+                               status = "okay";
+
+                               /*
+                                * PCA9655 GPIO expander, up to 1MHz clock.
+                                *  0-Board Revision bit 0 #
+                                *  1-Board Revision bit 1 #
+                                *  5-USB3 overcurrent
+                                *  6-USB3 power
+                                */
+                               expander0: gpio-expander@20 {
+                                       /*
+                                        * This is how it should be:
+                                        * compatible = "onnn,pca9655",
+                                        *       "nxp,pca9555";
+                                        * but you can't do this because of
+                                        * the way I2C works.
+                                        */
+                                       compatible = "nxp,pca9555";
+                                       gpio-controller;
+                                       #gpio-cells = <2>;
+                                       reg = <0x20>;
+                                       pinctrl-names = "default";
+                                       pinctrl-0 = <&pca0_pins>;
+                                       interrupt-parent = <&gpio0>;
+                                       interrupts = <23 IRQ_TYPE_EDGE_FALLING>;
+                                       interrupt-controller;
+                                       #interrupt-cells = <2>;
+
+                                       board_rev_bit_0 {
+                                               gpio-hog;
+                                               gpios = <0 GPIO_ACTIVE_LOW>;
+                                               input;
+                                               line-name = "board-rev-0";
+                                       };
+                                       board_rev_bit_1 {
+                                               gpio-hog;
+                                               gpios = <1 GPIO_ACTIVE_LOW>;
+                                               input;
+                                               line-name = "board-rev-1";
+                                       };
+                                       usb3_ilimit {
+                                               gpio-hog;
+                                               gpios = <5 GPIO_ACTIVE_HIGH>;
+                                               input;
+                                               line-name = "usb-overcurrent-status";
+                                       };
+                               };
+
+                               temp_sensor: temp@4c {
+                                       compatible = "ti,lm75";
+                                       reg = <0x4c>;
+                                       vcc-supply = <&reg_3p3v>;
+                               };
+                       };
+
+                       i2c@11100 {
+                               /*
+                                * External I2C Bus for user peripheral
+                                */
+                               clock-frequency = <400000>;
+                               pinctrl-0 = <&helios_i2c1_pins>;
+                               pinctrl-names = "default";
+                               status = "okay";
+                       };
+
+                       sata@a8000 {
+                               status = "okay";
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+
+                               sata0: sata-port@0 {
+                                       reg = <0>;
+                               };
+
+                               sata1: sata-port@1 {
+                                       reg = <1>;
+                               };
+                       };
+
+                       sata@e0000 {
+                               status = "okay";
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+
+                               sata2: sata-port@0 {
+                                       reg = <0>;
+                               };
+
+                               sata3: sata-port@1 {
+                                       reg = <1>;
+                               };
+                       };
+
+                       spi@10680 {
+                               pinctrl-0 = <&spi1_pins
+                                            &microsom_spi1_cs_pins>;
+                               pinctrl-names = "default";
+                               status = "okay";
+                       };
+
+                       sdhci@d8000 {
+                               bus-width = <4>;
+                               cd-gpios = <&gpio0 20 GPIO_ACTIVE_LOW>;
+                               no-1-8-v;
+                               pinctrl-0 = <&helios_sdhci_pins
+                                            &helios_sdhci_cd_pins>;
+                               pinctrl-names = "default";
+                               status = "okay";
+                               vmmc = <&reg_3p3v>;
+                               wp-inverted;
+                       };
+
+                       usb@58000 {
+                               usb-phy = <&usb2_phy>;
+                               status = "okay";
+                       };
+
+                       usb3@f0000 {
+                               status = "okay";
+                       };
+
+                       usb3@f8000 {
+                               status = "okay";
+                       };
+
+                       pinctrl@18000 {
+                               pca0_pins: pca0-pins {
+                                       marvell,pins = "mpp23";
+                                       marvell,function = "gpio";
+                               };
+                               microsom_phy0_int_pins: microsom-phy0-int-pins {
+                                       marvell,pins = "mpp18";
+                                       marvell,function = "gpio";
+                               };
+                               helios_i2c1_pins: i2c1-pins {
+                                       marvell,pins = "mpp26", "mpp27";
+                                       marvell,function = "i2c1";
+                               };
+                               helios_sdhci_cd_pins: helios-sdhci-cd-pins {
+                                       marvell,pins = "mpp20";
+                                       marvell,function = "gpio";
+                               };
+                               helios_sdhci_pins: helios-sdhci-pins {
+                                       marvell,pins = "mpp21", "mpp28",
+                                                      "mpp37", "mpp38",
+                                                      "mpp39", "mpp40";
+                                       marvell,function = "sd0";
+                               };
+                               helios_led_pins: helios-led-pins {
+                                       marvell,pins = "mpp24", "mpp25",
+                                                      "mpp49", "mpp50",
+                                                      "mpp52", "mpp53",
+                                                      "mpp54";
+                                       marvell,function = "gpio";
+                               };
+                               helios_fan_pins: helios-fan-pins {
+                                       marvell,pins = "mpp41", "mpp43",
+                                                      "mpp48", "mpp55";
+                                       marvell,function = "gpio";
+                               };
+                               microsom_spi1_cs_pins: spi1-cs-pins {
+                                       marvell,pins = "mpp59";
+                                       marvell,function = "spi1";
+                               };
+                       };
+               };
+       };
+};
index 2d1cea1..3a7f9c1 100644 (file)
@@ -3,11 +3,6 @@
  * Device Tree file for SolidRun Armada 38x Microsom
  *
  *  Copyright (C) 2015 Russell King
- *
- * This board is in development; the contents of this file work with
- * the A1 rev 2.0 of the board, which does not represent final
- * production board.  Things will change, don't expect this file to
- * remain compatible info the future.
  */
 #include <dt-bindings/input/input.h>
 #include <dt-bindings/gpio/gpio.h>
@@ -99,7 +94,6 @@
                compatible = "w25q32", "jedec,spi-nor";
                reg = <0>; /* Chip select 0 */
                spi-max-frequency = <3000000>;
-               status = "disabled";
        };
 };
 
index ede11c5..2375449 100644 (file)
        };
 };
 
-&ehci0 {
+/*
+ * Enable port A as device (via the virtual hub) and port B as
+ * host by default on the eval board. This can be easily changed
+ * by replacing the override below with &ehci0 { ... } to enable
+ * host on both ports.
+ */
+&vhub {
        status = "okay";
-       pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_usb2ah_default>;
 };
 
 &ehci1 {
        status = "okay";
-       pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_usb2bh_default>;
 };
 
 &uhci {
        status = "okay";
-
-       /* No pinctrl, this follows the above EHCI settings */
 };
index 0b9b37d..7d28c03 100644 (file)
@@ -21,9 +21,9 @@
                #size-cells = <1>;
                ranges;
 
-               vga_memory: framebuffer@bf000000 {
+               vga_memory: framebuffer@9f000000 {
                        no-map;
-                       reg = <0xbf000000 0x01000000>; /* 16M */
+                       reg = <0x9f000000 0x01000000>; /* 16M */
                };
 
                flash_memory: region@98000000 {
index 75df157..b23a983 100644 (file)
                        reg = <0x1e6c0080 0x80>;
                };
 
+               cvic: copro-interrupt-controller@1e6c2000 {
+                       compatible = "aspeed,ast2400-cvic", "aspeed-cvic";
+                       valid-sources = <0x7fffffff>;
+                       reg = <0x1e6c2000 0x80>;
+               };
+
                mac0: ethernet@1e660000 {
                        compatible = "aspeed,ast2400-mac", "faraday,ftgmac100";
                        reg = <0x1e660000 0x180>;
                        reg = <0x1e6a1000 0x100>;
                        interrupts = <5>;
                        clocks = <&syscon ASPEED_CLK_GATE_USBPORT1CLK>;
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&pinctrl_usb2h_default>;
                        status = "disabled";
                };
 
                        #ports = <3>;
                        clocks = <&syscon ASPEED_CLK_GATE_USBUHCICLK>;
                        status = "disabled";
+                       /*
+                        * No default pinmux, it will follow EHCI, use an explicit pinmux
+                        * override if you don't enable EHCI
+                        */
+               };
+
+               vhub: usb-vhub@1e6a0000 {
+                       compatible = "aspeed,ast2400-usb-vhub";
+                       reg = <0x1e6a0000 0x300>;
+                       interrupts = <5>;
+                       clocks = <&syscon ASPEED_CLK_GATE_USBPORT1CLK>;
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&pinctrl_usb2d_default>;
+                       status = "disabled";
                };
 
                apb {
                                status = "disabled";
                        };
 
-                       sram@1e720000 {
+                       sram: sram@1e720000 {
                                compatible = "mmio-sram";
                                reg = <0x1e720000 0x8000>;      // 32K
                        };
                                #address-cells = <1>;
                                #size-cells = <0>;
                                reg = <0x1e786000 0x1000>;
-                               clocks = <&syscon ASPEED_CLK_APB>;
+                               clocks = <&syscon ASPEED_CLK_24M>;
                                resets = <&syscon ASPEED_RESET_PWM>;
                                status = "disabled";
                        };
index 17f2714..87fdc14 100644 (file)
                        reg = <0x1e6c0080 0x80>;
                };
 
+               cvic: copro-interrupt-controller@1e6c2000 {
+                       compatible = "aspeed,ast2500-cvic", "aspeed-cvic";
+                       valid-sources = <0xffffffff>;
+                       copro-sw-interrupts = <1>;
+                       reg = <0x1e6c2000 0x80>;
+               };
+
                mac0: ethernet@1e660000 {
                        compatible = "aspeed,ast2500-mac", "faraday,ftgmac100";
                        reg = <0x1e660000 0x180>;
                        reg = <0x1e6a1000 0x100>;
                        interrupts = <5>;
                        clocks = <&syscon ASPEED_CLK_GATE_USBPORT1CLK>;
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&pinctrl_usb2ah_default>;
                        status = "disabled";
                };
 
                        reg = <0x1e6a3000 0x100>;
                        interrupts = <13>;
                        clocks = <&syscon ASPEED_CLK_GATE_USBPORT2CLK>;
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&pinctrl_usb2bh_default>;
                        status = "disabled";
                };
 
                        #ports = <2>;
                        clocks = <&syscon ASPEED_CLK_GATE_USBUHCICLK>;
                        status = "disabled";
+                       /*
+                        * No default pinmux, it will follow EHCI, use an explicit pinmux
+                        * override if you don't enable EHCI
+                        */
+               };
+
+               vhub: usb-vhub@1e6a0000 {
+                       compatible = "aspeed,ast2500-usb-vhub";
+                       reg = <0x1e6a0000 0x300>;
+                       interrupts = <5>;
+                       clocks = <&syscon ASPEED_CLK_GATE_USBPORT1CLK>;
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&pinctrl_usb2ad_default>;
+                       status = "disabled";
                };
 
                apb {
                                status = "disabled";
                        };
 
-                       sram@1e720000 {
+                       sram: sram@1e720000 {
                                compatible = "mmio-sram";
                                reg = <0x1e720000 0x9000>;      // 36K
                        };
                                #address-cells = <1>;
                                #size-cells = <0>;
                                reg = <0x1e786000 0x1000>;
-                               clocks = <&syscon ASPEED_CLK_APB>;
+                               clocks = <&syscon ASPEED_CLK_24M>;
                                resets = <&syscon ASPEED_RESET_PWM>;
                                status = "disabled";
                        };
                groups = "USB2AH";
        };
 
+       pinctrl_usb2ad_default: usb2ad_default {
+               function = "USB2AD";
+               groups = "USB2AD";
+       };
+
        pinctrl_usb11bhid_default: usb11bhid_default {
                function = "USB11BHID";
                groups = "USB11BHID";
diff --git a/arch/arm/boot/dts/at91-dvk_som60.dts b/arch/arm/boot/dts/at91-dvk_som60.dts
new file mode 100644 (file)
index 0000000..ededd5b
--- /dev/null
@@ -0,0 +1,95 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * at91-dvk_som60.dts - Device Tree file for the DVK SOM60 board
+ *
+ *  Copyright (C) 2018 Laird,
+ *               2018 Ben Whitten <ben.whitten@lairdtech.com>
+ *
+ */
+/dts-v1/;
+#include "at91-som60.dtsi"
+#include "at91-dvk_su60_somc.dtsi"
+#include "at91-dvk_su60_somc_lcm.dtsi"
+
+/ {
+       model = "Laird DVK SOM60";
+       compatible = "laird,dvk-som60", "laird,som60", "atmel,sama5d36", "atmel,sama5d3", "atmel,sama5";
+
+       chosen {
+               stdout-path = &dbgu;
+               tick-timer = &pit;
+       };
+};
+
+&mmc0 {
+       status = "okay";
+};
+
+&spi0 {
+       status = "okay";
+};
+
+&ssc0 {
+       status = "okay";
+};
+
+&i2c0 {
+       status = "okay";
+};
+
+&i2c1 {
+       status = "okay";
+};
+
+&usart1 {
+       status = "okay";
+};
+
+&usart2 {
+       status = "okay";
+};
+
+&usart3 {
+       status = "okay";
+};
+
+&uart0 {
+       status = "okay";
+};
+
+&dbgu {
+       status = "okay";
+};
+
+&pit {
+       status = "okay";
+};
+
+&adc0 {
+       status = "okay";
+};
+
+&can1 {
+       status = "okay";
+};
+
+&macb0 {
+       status = "okay";
+};
+
+&macb1 {
+       status = "okay";
+};
+
+&usb0 {
+       status = "okay";
+};
+
+&usb1 {
+       status = "okay";
+};
+
+&usb2 {
+       status = "okay";
+};
+
diff --git a/arch/arm/boot/dts/at91-dvk_su60_somc.dtsi b/arch/arm/boot/dts/at91-dvk_su60_somc.dtsi
new file mode 100644 (file)
index 0000000..bb86f17
--- /dev/null
@@ -0,0 +1,159 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * at91-dvk_su60_somc.dtsi - Device Tree file for the DVK SOM60 base board
+ *
+ *  Copyright (C) 2018 Laird,
+ *               2018 Ben Whitten <ben.whitten@lairdtech.com>
+ *
+ */
+
+/ {
+       sound {
+               compatible = "atmel,asoc-wm8904";
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_pck2_as_audio_mck>;
+
+               atmel,model = "wm8904 @ DVK-SOM60";
+               atmel,audio-routing =
+                       "Headphone Jack", "HPOUTL",
+                       "Headphone Jack", "HPOUTR",
+                       "IN2L", "Line In Jack",
+                       "IN2R", "Line In Jack",
+                       "Mic", "MICBIAS",
+                       "IN1L", "Mic";
+
+               atmel,ssc-controller = <&ssc0>;
+               atmel,audio-codec = <&wm8904>;
+
+               status = "okay";
+       };
+};
+
+&mmc0 {
+       status = "okay";
+
+       pinctrl-0 = <&pinctrl_mmc0_clk_cmd_dat0 &pinctrl_mmc0_dat1_3 &pinctrl_mmc0_cd>;
+       slot@0 {
+               bus-width = <4>;
+               cd-gpios = <&pioE 31 GPIO_ACTIVE_HIGH>;
+               cd-inverted;
+       };
+};
+
+&spi0 {
+       status = "okay";
+
+       /* spi0.0: 4M Flash Macronix MX25R4035FM1IL0 */
+       spi-flash@0 {
+               compatible = "mxicy,mx25u4035", "jedec,spi-nor";
+               spi-max-frequency = <33000000>;
+               reg = <0>;
+       };
+};
+
+&ssc0 {
+       atmel,clk-from-rk-pin;
+       status = "okay";
+};
+
+&i2c0 {
+       status = "okay";
+
+       wm8904: wm8904@1a {
+               compatible = "wlf,wm8904";
+               reg = <0x1a>;
+               clocks = <&pck2>;
+               clock-names = "mclk";
+       };
+};
+
+&i2c1 {
+       status = "okay";
+
+       eeprom@87 {
+               compatible = "giantec,gt24c32a", "atmel,24c32";
+               reg = <87>;
+               pagesize = <32>;
+       };
+};
+
+&usart1 {
+       status = "okay";
+};
+
+&usart2 {
+       status = "okay";
+};
+
+&usart3 {
+       status = "okay";
+};
+
+&uart0 {
+       status = "okay";
+};
+
+&dbgu {
+       status = "okay";
+};
+
+&pit {
+       status = "okay";
+};
+
+&adc0 {
+       status = "okay";
+};
+
+&can1 {
+       status = "okay";
+};
+
+&macb0 {
+       #address-cells = <1>;
+       #size-cells = <0>;
+       status = "okay";
+
+       ethernet-phy@7 {
+               reg = <7>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_geth_int>;
+               interrupt-parent = <&pioB>;
+               interrupts = <25 IRQ_TYPE_EDGE_FALLING>;
+               txen-skew-ps = <800>;
+               txc-skew-ps = <3000>;
+               rxdv-skew-ps = <400>;
+               rxc-skew-ps = <3000>;
+               rxd0-skew-ps = <400>;
+               rxd1-skew-ps = <400>;
+               rxd2-skew-ps = <400>;
+               rxd3-skew-ps = <400>;
+       };
+};
+
+&macb1 {
+       #address-cells = <1>;
+       #size-cells = <0>;
+       status = "okay";
+
+       ethernet-phy@1 {
+               reg = <1>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_eth_int>;
+               interrupt-parent = <&pioC>;
+               interrupts = <10 IRQ_TYPE_EDGE_FALLING>;
+       };
+};
+
+&usb0 {
+       status = "okay";
+};
+
+&usb1 {
+       status = "okay";
+};
+
+&usb2 {
+       status = "okay";
+};
+
diff --git a/arch/arm/boot/dts/at91-dvk_su60_somc_lcm.dtsi b/arch/arm/boot/dts/at91-dvk_su60_somc_lcm.dtsi
new file mode 100644 (file)
index 0000000..4b9176d
--- /dev/null
@@ -0,0 +1,90 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * at91-dvk_su60_somc_lcm.dtsi - Device Tree file for the DVK SOM60 LCD board
+ *
+ *  Copyright (C) 2018 Laird,
+ *               2018 Ben Whitten <ben.whitten@lairdtech.com>
+ *
+ */
+
+/ {
+       backlight: backlight {
+               compatible = "pwm-backlight";
+               pwms = <&hlcdc_pwm 0 50000 0>;
+               brightness-levels = <0 4 8 16 32 64 128 255>;
+               default-brightness-level = <6>;
+               status = "okay";
+       };
+
+       panel: panel {
+               compatible = "winstar,wf70gtiagdng0", "innolux,at070tn92", "simple-panel";
+               backlight = <&backlight>;
+               power-supply = <&vcc_lcd_reg>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+               status = "okay";
+
+               port@0 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       reg = <0>;
+
+                       panel_input: endpoint@0 {
+                               reg = <0>;
+                               remote-endpoint = <&hlcdc_panel_output>;
+                       };
+               };
+       };
+
+       vcc_lcd_reg: fixedregulator_lcd {
+               compatible = "regulator-fixed";
+               regulator-name = "VCC LCM";
+               regulator-min-microvolt = <5000000>;
+               regulator-max-microvolt = <5000000>;
+               regulator-boot-on;
+               regulator-always-on;
+               status = "okay";
+       };
+};
+
+&pinctrl {
+       board {
+               pinctrl_lcd_ctp_int: lcd_ctp_int {
+                        atmel,pins =
+                                <AT91_PIOC 28 AT91_PERIPH_GPIO AT91_PINCTRL_PULL_UP_DEGLITCH>;
+               };
+       };
+};
+
+&i2c1 {
+       status = "okay";
+
+       ft5426@56 {
+               compatible = "focaltech,ft5426", "edt,edt-ft5406";
+               reg = <56>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_lcd_ctp_int>;
+
+               interrupt-parent = <&pioC>;
+               interrupts = <28 IRQ_TYPE_EDGE_FALLING>;
+
+               touchscreen-size-x = <800>;
+               touchscreen-size-y = <480>;
+       };
+};
+
+&hlcdc {
+       status = "okay";
+
+       hlcdc-display-controller {
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_lcd_base &pinctrl_lcd_rgb888>;
+
+               port@0 {
+                       hlcdc_panel_output: endpoint@0 {
+                               reg = <0>;
+                               remote-endpoint = <&panel_input>;
+                       };
+               };
+       };
+};
diff --git a/arch/arm/boot/dts/at91-gatwick.dts b/arch/arm/boot/dts/at91-gatwick.dts
new file mode 100644 (file)
index 0000000..5a81cab
--- /dev/null
@@ -0,0 +1,121 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * at91-gatwick.dts - Device Tree file for the Gatwick board
+ *
+ *  Copyright (C) 2018 Laird
+ *
+ */
+/dts-v1/;
+#include "at91-wb50n.dtsi"
+#include <dt-bindings/input/input.h>
+
+/ {
+       model = "Laird Workgroup Bridge 50N - Project Gatwick";
+       compatible = "laird,gatwick", "laird,wb50n", "atmel,sama5d31", "atmel,sama5d3", "atmel,sama5";
+
+       gpio_keys {
+               compatible = "gpio-keys";
+               autorepeat;
+
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_key_gpio>;
+
+               reset-button {
+                       label = "Reset Button";
+                       linux,code = <KEY_SETUP>;
+                       gpios = <&pioE 31 GPIO_ACTIVE_LOW>;
+                       wakeup-source;
+               };
+       };
+
+       leds {
+               compatible = "gpio-leds";
+
+               ethernet {
+                       label = "gatwick:yellow:ethernet";
+                       gpios = <&pioA 10 GPIO_ACTIVE_LOW>;
+                       default-state = "off";
+               };
+
+               wifi {
+                       label = "gatwick:green:wifi";
+                       gpios = <&pioA 28 GPIO_ACTIVE_LOW>;
+                       default-state = "off";
+               };
+
+               ble {
+                       label = "gatwick:blue:ble";
+                       gpios = <&pioA 22 GPIO_ACTIVE_LOW>;
+                       default-state = "off";
+               };
+
+               lora {
+                       label = "gatwick:orange:lora";
+                       gpios = <&pioA 26 GPIO_ACTIVE_LOW>;
+                       default-state = "off";
+               };
+
+               blank {
+                       label = "gatwick:green:blank";
+                       gpios = <&pioA 24 GPIO_ACTIVE_LOW>;
+                       default-state = "off";
+               };
+
+               user {
+                       label = "gatwick:yellow:user";
+                       gpios = <&pioA 12 GPIO_ACTIVE_LOW>;
+                       default-state = "off";
+               };
+       };
+};
+
+&pinctrl {
+       board {
+               pinctrl_key_gpio: key_gpio_0 {
+                 atmel,pins =
+                         <AT91_PIOE 31 AT91_PERIPH_GPIO AT91_PINCTRL_PULL_UP_DEGLITCH>; /* PE31 GPIO with pullup deglitch */
+         };
+       };
+};
+
+&mmc0 {
+       status = "okay";
+};
+
+&macb1 {
+       status = "okay";
+};
+
+&dbgu {
+       status = "okay";
+};
+
+/* FTDI USART */
+&usart0 {
+       status = "okay";
+};
+
+/* GPS USART */
+&usart1 {
+       pinctrl-0 = <&pinctrl_usart1>;
+       status = "okay";
+};
+
+&spi1 {
+       status = "okay";
+
+       spidev@0 {
+               compatible = "semtech,sx1301";
+               reg = <0>;
+               spi-max-frequency = <8000000>;
+       };
+};
+
+&usb1 {
+       status = "okay";
+       /delete-property/atmel,oc-gpio;
+};
+
+&usb2 {
+       status = "okay";
+};
diff --git a/arch/arm/boot/dts/at91-som60.dtsi b/arch/arm/boot/dts/at91-som60.dtsi
new file mode 100644 (file)
index 0000000..241682a
--- /dev/null
@@ -0,0 +1,230 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * at91-som60.dtsi - Device Tree file for the SOM60 module
+ *
+ *  Copyright (C) 2018 Laird,
+ *               2018 Ben Whitten <ben.whitten@lairdtech.com>
+ *
+ */
+#include "sama5d36.dtsi"
+
+/ {
+       model = "Laird SOM60";
+       compatible = "laird,som60", "atmel,sama5d36", "atmel,sama5d3", "atmel,sama5";
+
+       chosen {
+               stdout-path = &dbgu;
+       };
+
+       memory {
+               reg = <0x20000000 0x8000000>;
+       };
+
+       clocks {
+               slow_xtal {
+                       clock-frequency = <32768>;
+               };
+
+               main_xtal {
+                       clock-frequency = <12000000>;
+               };
+       };
+};
+
+&pinctrl {
+       board {
+               pinctrl_mmc0_cd: mmc0_cd {
+                       atmel,pins =
+                               <AT91_PIOE 31 AT91_PERIPH_GPIO AT91_PINCTRL_DEGLITCH>;
+               };
+
+               pinctrl_mmc0_en: mmc0_en {
+                       atmel,pins =
+                               <AT91_PIOE 30 AT91_PERIPH_GPIO AT91_PINCTRL_NONE>;
+               };
+
+               pinctrl_nand0_wp: nand0_wp {
+                       atmel,pins =
+                               <AT91_PIOE 14 AT91_PERIPH_GPIO AT91_PINCTRL_PULL_UP>;
+               };
+
+               pinctrl_usb_vbus: usb_vbus {
+                       atmel,pins =
+                               <AT91_PIOE 20 AT91_PERIPH_GPIO AT91_PINCTRL_NONE>;
+                               /* Conflicts with USART2_SCK */
+               };
+
+               pinctrl_usart2_sck: usart2_sck {
+                       atmel,pins =
+                               <AT91_PIOE 20 AT91_PERIPH_B AT91_PINCTRL_NONE>;
+                               /* Conflicts with USB_VBUS */
+               };
+
+               pinctrl_usb_oc: usb_oc {
+                       atmel,pins =
+                               <AT91_PIOE 15 AT91_PERIPH_GPIO AT91_PINCTRL_DEGLITCH>;
+                               /* Conflicts with USART3_SCK */
+               };
+
+               pinctrl_usart3_sck: usart3_sck {
+                       atmel,pins =
+                               <AT91_PIOE 15 AT91_PERIPH_B AT91_PINCTRL_NONE>;
+                               /* Conflicts with USB_OC */
+               };
+
+               pinctrl_usba_vbus: usba_vbus {
+                  atmel,pins =
+                               <AT91_PIOC 14 AT91_PERIPH_GPIO AT91_PINCTRL_DEGLITCH>;
+               };
+
+               pinctrl_geth_int: geth_int {
+                       atmel,pins =
+                               <AT91_PIOB 25 AT91_PERIPH_GPIO AT91_PINCTRL_DEGLITCH>;
+                               /* Conflicts with USART1_SCK */
+               };
+
+               pinctrl_usart1_sck: usart1_sck {
+                       atmel,pins =
+                               <AT91_PIOB 25 AT91_PERIPH_A AT91_PINCTRL_NONE>;
+                               /* Conflicts with GETH_INT */
+               };
+
+               pinctrl_eth_int: eth_int {
+                       atmel,pins =
+                               <AT91_PIOC 10 AT91_PERIPH_GPIO AT91_PINCTRL_DEGLITCH>;
+               };
+
+               pinctrl_pck2_as_audio_mck: pck2_as_audio_mck {
+                       atmel,pins =
+                               <AT91_PIOC 15 AT91_PERIPH_B AT91_PINCTRL_NONE>;
+               };
+       };
+};
+
+&mmc0 {
+       slot@0 {
+               reg = <0>;
+               bus-width = <8>;
+       };
+};
+
+&mmc1 {
+       status = "okay";
+       slot@0 {
+               reg = <0>;
+               bus-width = <4>;
+       };
+};
+
+&spi0 {
+       cs-gpios = <&pioD 13 0>, <0>, <0>, <0>;
+};
+
+&usart0 {
+       atmel,use-dma-rx;
+       atmel,use-dma-tx;
+       status = "okay";
+       pinctrl-0 = <&pinctrl_usart0 &pinctrl_usart0_rts_cts>;
+};
+
+&usart1 {
+       pinctrl-0 = <&pinctrl_usart1 &pinctrl_usart1_rts_cts>;
+};
+
+&usart2 {
+       pinctrl-0 = <&pinctrl_usart2 &pinctrl_usart2_rts_cts>;
+};
+
+&usart3 {
+       pinctrl-0 = <&pinctrl_usart3 &pinctrl_usart3_rts_cts>;
+};
+
+&adc0 {
+       pinctrl-0 = <
+               &pinctrl_adc0_adtrg
+               &pinctrl_adc0_ad0
+               &pinctrl_adc0_ad1
+               &pinctrl_adc0_ad2
+               &pinctrl_adc0_ad3
+               &pinctrl_adc0_ad4
+               &pinctrl_adc0_ad5
+               >;
+};
+
+&macb0 {
+       phy-mode = "rgmii";
+};
+
+&macb1 {
+       phy-mode = "rmii";
+};
+
+&ebi {
+       pinctrl-0 = <&pinctrl_ebi_nand_addr>;
+       pinctrl-names = "default";
+       status = "okay";
+};
+
+&nand_controller {
+       status = "okay";
+
+       nand: nand@3 {
+               reg = <0x3 0x0 0x2>;
+               atmel,rb = <0>;
+               nand-bus-width = <8>;
+               nand-ecc-mode = "hw";
+               nand-ecc-strength = <8>;
+               nand-ecc-step-size = <512>;
+               nand-on-flash-bbt;
+               label = "atmel_nand";
+
+               partitions {
+                       compatible = "fixed-partitions";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+
+                       ubootspl@0 {
+                               label = "u-boot-spl";
+                               reg = <0x0 0x20000>;
+                       };
+
+                       uboot@20000 {
+                               label = "u-boot";
+                               reg = <0x20000 0x80000>;
+                       };
+
+                       ubootenv@a0000 {
+                               label = "u-boot-env";
+                               reg = <0xa0000 0x20000>;
+                       };
+
+                       ubootenv@c0000 {
+                               label = "u-boot-env";
+                               reg = <0xc0000 0x20000>;
+                       };
+
+                       ubi@e0000 {
+                               label = "ubi";
+                               reg = <0xe0000 0xfe00000>;
+                       };
+               };
+       };
+};
+
+&usb0 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_usba_vbus>;
+       atmel,vbus-gpio = <&pioC 14 GPIO_ACTIVE_HIGH>;
+};
+
+&usb1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_usb_vbus &pinctrl_usb_oc>;
+       num-ports = <3>;
+       atmel,vbus-gpio = <0
+               &pioE 20 GPIO_ACTIVE_HIGH
+               0>;
+       atmel,oc-gpio = <0
+               &pioE 15 GPIO_ACTIVE_LOW
+               0>;
+};
diff --git a/arch/arm/boot/dts/at91-wb45n.dts b/arch/arm/boot/dts/at91-wb45n.dts
new file mode 100644 (file)
index 0000000..5b9512a
--- /dev/null
@@ -0,0 +1,64 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * at91-wb45n.dts - Device Tree file for WB45NBT board
+ *
+ *  Copyright (C) 2018 Laird
+ *
+ */
+/dts-v1/;
+#include "at91-wb45n.dtsi"
+
+/ {
+       model = "Laird Workgroup Bridge 45N - Atmel AT91SAM (dt)";
+       compatible = "laird,wb45n", "laird,wbxx", "atmel,at91sam9x5", "atmel,at91sam9";
+
+       gpio_keys {
+               compatible = "gpio-keys";
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               irqbtn@18 {
+                       reg = <18>;
+                       label = "IRQBTN";
+                       linux,code = <99>;
+                       gpios = <&pioB 18 GPIO_ACTIVE_LOW>;
+                       gpio-key,wakeup = <1>;
+               };
+       };
+};
+
+&watchdog {
+       status = "okay";
+};
+
+&usb0 {
+       status = "okay";
+};
+
+&mmc0 {
+       status = "okay";
+};
+
+&spi0 {
+       status = "okay";
+};
+
+&macb0 {
+       status = "okay";
+};
+
+&dbgu {
+       status = "okay";
+};
+
+&usart0 {
+       status = "okay";
+};
+
+&usart3 {
+       status = "okay";
+};
+
+&i2c1 {
+       status = "okay";
+};
diff --git a/arch/arm/boot/dts/at91-wb45n.dtsi b/arch/arm/boot/dts/at91-wb45n.dtsi
new file mode 100644 (file)
index 0000000..ebe61a2
--- /dev/null
@@ -0,0 +1,165 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * at91-wb45n.dtsi - Device Tree file for WB45NBT board
+ *
+ *  Copyright (C) 2018 Laird
+ *
+ */
+
+#include "at91sam9g25.dtsi"
+
+/ {
+       model = "Laird Workgroup Bridge 45N - Atmel AT91SAM (dt)";
+       compatible = "laird,wb45n", "laird,wbxx", "atmel,at91sam9x5", "atmel,at91sam9";
+
+       chosen {
+               bootargs = "ubi.mtd=6 root=ubi0:rootfs rootfstype=ubifs rw";
+               stdout-path = "serial0:115200n8";
+       };
+
+       memory {
+               reg = <0x20000000 0x4000000>;
+       };
+
+       atheros {
+               compatible = "atheros,ath6kl";
+               atheros,board-id = "SD32";
+       };
+};
+
+&reset_controller {
+       compatible = "atmel,sama5d3-rstc";
+};
+
+&shutdown_controller {
+       atmel,wakeup-mode = "low";
+};
+
+&slow_xtal {
+       clock-frequency = <32768>;
+};
+
+&main_xtal {
+       clock-frequency = <12000000>;
+};
+
+&ebi {
+       status = "okay";
+       nand_controller: nand-controller {
+               pinctrl-0 = <&pinctrl_nand_cs &pinctrl_nand_rb &pinctrl_nand_oe_we>;
+               pinctrl-names = "default";
+               status = "okay";
+
+               nand@3 {
+                       reg = <0x3 0x0 0x800000>;
+                       rb-gpios = <&pioD 5 GPIO_ACTIVE_HIGH>;
+                       cs-gpios = <&pioD 4 GPIO_ACTIVE_HIGH>;
+                       nand-bus-width = <8>;
+                       nand-ecc-mode = "hw";
+                       nand-ecc-strength = <4>;
+                       nand-ecc-step-size = <512>;
+                       nand-on-flash-bbt;
+                       label = "atmel_nand";
+
+                       partitions {
+                               compatible = "fixed-partitions";
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+
+                               at91bootstrap@0 {
+                                       label = "at91bs";
+                                       reg = <0x0 0x20000>;
+                               };
+
+                               uboot@20000 {
+                                       label = "u-boot";
+                                       reg = <0x20000 0x80000>;
+                               };
+
+                               ubootenv@a0000 {
+                                       label = "u-boot-env";
+                                       reg = <0xa0000 0x20000>;
+                               };
+
+                               ubootenv@c0000 {
+                                       label = "redund-env";
+                                       reg = <0xc0000 0x20000>;
+                               };
+
+                               kernel-a@e0000 {
+                                       label = "kernel-a";
+                                       reg = <0xe0000 0x280000>;
+                               };
+
+                               kernel-b@360000 {
+                                       label = "kernel-b";
+                                       reg = <0x360000 0x280000>;
+                               };
+
+                               rootfs-a@5e0000 {
+                                       label = "rootfs-a";
+                                       reg = <0x5e0000 0x2600000>;
+                               };
+
+                               rootfs-b@2be0000 {
+                                       label = "rootfs-b";
+                                       reg = <0x2be0000 0x2600000>;
+                               };
+
+                               user@51e0000 {
+                                       label = "user";
+                                       reg = <0x51e0000 0x2dc0000>;
+                               };
+
+                               logs@7fa0000 {
+                                       label = "logs";
+                                       reg = <0x7fa0000 0x60000>;
+                               };
+
+                       };
+               };
+       };
+};
+
+&usb0 {
+       num-ports = <2>;
+       atmel,vbus-gpio = <
+               &pioB 12 GPIO_ACTIVE_HIGH
+               &pioA 31 GPIO_ACTIVE_HIGH
+               >;
+       atmel,oc-gpio = <&pioB 13 GPIO_ACTIVE_LOW>;
+};
+
+&macb0 {
+       phy-mode = "rmii";
+};
+
+&spi0 {
+       cs-gpios = <&pioA 14 0>, <&pioA 7 0>, <0>, <0>;
+};
+
+&usb2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_board_usb2>;
+       atmel,vbus-gpio = <&pioB 11 GPIO_ACTIVE_HIGH>;
+};
+
+&mmc0 {
+       pinctrl-0 = <
+               &pinctrl_mmc0_slot0_clk_cmd_dat0
+               &pinctrl_mmc0_slot0_dat1_3>;
+       slot@0 {
+               reg = <0>;
+               bus-width = <4>;
+       };
+};
+
+&pinctrl {
+       usb2 {
+               pinctrl_board_usb2: usb2-board {
+                       atmel,pins =
+                               <AT91_PIOB 11 AT91_PERIPH_GPIO AT91_PINCTRL_DEGLITCH>;          /* PB11 gpio vbus sense, deglitch */
+               };
+       };
+};
+
diff --git a/arch/arm/boot/dts/at91-wb50n.dts b/arch/arm/boot/dts/at91-wb50n.dts
new file mode 100644 (file)
index 0000000..8cecc70
--- /dev/null
@@ -0,0 +1,112 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * at91-wb50n.dts - Device Tree file for wb50n evaluation board
+ *
+ *  Copyright (C) 2018 Laird
+ *
+ */
+
+/dts-v1/;
+#include "at91-wb50n.dtsi"
+
+/ {
+       model = "Laird Workgroup Bridge 50N - Atmel SAMA5D";
+       compatible = "laird,wb50n", "atmel,sama5d31", "atmel,sama5d3", "atmel,sama5";
+
+       gpio_keys {
+               compatible = "gpio-keys";
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               btn0@10 {
+                       reg = <10>;
+                       label = "BTNESC";
+                       linux,code = <1>; /* ESC button */
+                       gpios = <&pioA 10 GPIO_ACTIVE_LOW>;
+                       gpio-key,wakeup = <1>;
+               };
+
+               irqbtn@31 {
+                       reg = <31>;
+                       label = "IRQBTN";
+                       linux,code = <99>; /* SysReq button */
+                       gpios = <&pioE 31 GPIO_ACTIVE_LOW>;
+                       gpio-key,wakeup = <1>;
+               };
+       };
+
+       leds {
+               compatible = "gpio-leds";
+
+               led0 {
+                       label = "wb50n:blue:led0";
+                       gpios = <&pioA 12 GPIO_ACTIVE_LOW>;
+                       default-state = "off";
+               };
+
+               led1 {
+                       label = "wb50n:green:led1";
+                       gpios = <&pioA 24 GPIO_ACTIVE_LOW>;
+                       default-state = "off";
+               };
+
+               led2 {
+                       label = "wb50n:red:led2";
+                       gpios = <&pioA 26 GPIO_ACTIVE_LOW>;
+                       default-state = "off";
+               };
+       };
+};
+
+&watchdog {
+       status = "okay";
+};
+
+&mmc0 {
+       status = "okay";
+};
+
+&macb1 {
+       status = "okay";
+};
+
+&dbgu {
+       status = "okay";
+};
+
+/* On BB40 this port is labeled UART1 */
+&usart0 {
+       status = "okay";
+};
+
+/* On BB40 this port is labeled UART0 */
+&usart1 {
+       status = "okay";
+};
+
+&i2c0 {
+       status = "okay";
+};
+
+&spi1 {
+       status = "okay";
+
+       spidev@0 {
+               compatible = "spidev";
+               reg = <0>;
+               spi-max-frequency = <8000000>;
+       };
+};
+
+&usb0 {
+       status = "okay";
+};
+
+&usb1 {
+       status = "okay";
+};
+
+&usb2 {
+       status = "okay";
+};
+
diff --git a/arch/arm/boot/dts/at91-wb50n.dtsi b/arch/arm/boot/dts/at91-wb50n.dtsi
new file mode 100644 (file)
index 0000000..85692c8
--- /dev/null
@@ -0,0 +1,198 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * at91-wb50n.dtsi - Device Tree include file for wb50n cpu module
+ *
+ *  Copyright (C) 2018 Laird
+ *
+ */
+
+#include "sama5d31.dtsi"
+
+/ {
+       model = "Laird Workgroup Bridge 50N - Atmel SAMA5D";
+       compatible = "laird,wb50n", "atmel,sama5d31", "atmel,sama5d3", "atmel,sama5";
+
+       chosen {
+               bootargs = "ubi.mtd=6 root=ubi0:rootfs rootfstype=ubifs rw";
+               stdout-path = "serial0:115200n8";
+       };
+
+       memory {
+               reg = <0x20000000 0x4000000>;
+       };
+};
+
+&pinctrl {
+       board {
+               pinctrl_mmc0_cd: mmc0_cd {
+                       atmel,pins = <AT91_PIOC 26 AT91_PERIPH_GPIO AT91_PINCTRL_PULL_UP_DEGLITCH>; /* PC26 GPIO with pullup deglitch */
+               };
+
+               pinctrl_usba_vbus: usba_vbus {
+                       atmel,pins = <AT91_PIOB 13 AT91_PERIPH_GPIO AT91_PINCTRL_DEGLITCH>; /* PB13 GPIO with deglitch */
+               };
+       };
+};
+
+&slow_xtal {
+       clock-frequency = <32768>;
+};
+
+&main_xtal {
+       clock-frequency = <12000000>;
+};
+
+&slow_osc {
+       atmel,osc-bypass;
+};
+
+&usart1_clk {
+       atmel,clk-output-range = <0 132000000>;
+};
+
+&mmc0 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_mmc0_clk_cmd_dat0 &pinctrl_mmc0_dat1_3 &pinctrl_mmc0_cd>;
+       cd-gpios = <&pioC 26 GPIO_ACTIVE_LOW>;
+       slot@0 {
+               reg = <0>;
+               bus-width = <4>;
+       };
+};
+
+&mmc1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_mmc1_clk_cmd_dat0 &pinctrl_mmc1_dat1_3>;
+       status = "okay";
+       atheros@0 {
+               compatible = "atheros,ath6kl";
+               atheros,board-id = "SD32";
+               reg = <0>;
+               bus-width = <4>;
+       };
+};
+
+&macb1 {
+       phy-mode = "rmii";
+};
+
+&dbgu {
+       dmas = <0>, <0>;        /*  Do not use DMA for dbgu */
+};
+
+/* On BB40 this port is labeled UART1 */
+&usart0 {
+       atmel,use-dma-rx;
+       atmel,use-dma-tx;
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_usart0 &pinctrl_usart0_rts_cts>;
+};
+
+/* On BB40 this port is labeled UART0 */
+&usart1 {
+       atmel,use-dma-rx;
+       atmel,use-dma-tx;
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_usart1 &pinctrl_usart1_rts_cts>;
+       dtr-gpios = <&pioD 13 GPIO_ACTIVE_LOW>;
+       dsr-gpios = <&pioD 11 GPIO_ACTIVE_LOW>;
+       dcd-gpios = <&pioD 7 GPIO_ACTIVE_LOW>;
+       rng-gpios = <&pioD 8 GPIO_ACTIVE_LOW>;
+};
+
+/* USART3 is direct-connect to the Bluetooth UART on the radio SIP */
+&usart3 {
+       atmel,use-dma-rx;
+       atmel,use-dma-tx;
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_usart3 &pinctrl_usart3_rts_cts>;
+       status = "okay";
+};
+
+&spi1 {
+       cs-gpios = <&pioC 25 0>, <0>, <0>, <0>;
+};
+
+&ebi {
+       pinctrl-0 = <&pinctrl_ebi_nand_addr>;
+       pinctrl-names = "default";
+       status = "okay";
+};
+
+&nand_controller {
+       status = "okay";
+
+       nand: nand@3 {
+               reg = <0x3 0x0 0x2>;
+               atmel,rb = <0>;
+               nand-bus-width = <8>;
+               nand-ecc-mode = "hw";
+               nand-ecc-strength = <8>;
+               nand-ecc-step-size = <512>;
+               nand-on-flash-bbt;
+               label = "atmel_nand";
+
+               partitions {
+                       compatible = "fixed-partitions";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+
+                       at91bootstrap@0 {
+                               label = "at91bs";
+                               reg = <0x0 0x20000>;
+                       };
+
+                       uboot@20000 {
+                               label = "u-boot";
+                               reg = <0x20000 0x80000>;
+                       };
+
+                       ubootenv@a0000 {
+                               label = "u-boot-env";
+                               reg = <0xa0000 0x20000>;
+                       };
+
+                       ubootenv@c0000 {
+                               label = "u-boot-env";
+                               reg = <0xc0000 0x20000>;
+                       };
+
+                       kernel-a@e0000 {
+                               label = "kernel-a";
+                               reg = <0xe0000 0x500000>;
+                       };
+
+                       kernel-b@5e0000 {
+                               label = "kernel-b";
+                               reg = <0x5e0000 0x500000>;
+                       };
+
+                       rootfs-a@ae0000 {
+                               label = "rootfs-a";
+                               reg = <0xae0000 0x3000000>;
+                       };
+
+                       rootfs-b@3ae0000 {
+                               label = "rootfs-b";
+                               reg = <0x3ae0000 0x3000000>;
+                       };
+
+                       user@6ae0000 {
+                               label = "user";
+                               reg = <0x6ae0000 0x14e0000>;
+                       };
+               };
+       };
+};
+
+&usb0 {
+       atmel,vbus-gpio = <&pioB 13 GPIO_ACTIVE_LOW>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_usba_vbus>;
+};
+
+&usb1 {
+       num-ports = <3>;
+       atmel,vbus-gpio = <&pioA 2 GPIO_ACTIVE_LOW>;
+       atmel,oc-gpio = <&pioA 4 GPIO_ACTIVE_LOW>;
+};
index 53c63d0..33f09d5 100644 (file)
                        };
 
                        pmc: pmc@fffffc00 {
-                               compatible = "atmel,at91rm9200-pmc", "syscon";
+                               compatible = "atmel,at91sam9261-pmc", "syscon";
                                reg = <0xfffffc00 0x100>;
                                interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>;
                                interrupt-controller;
index 87fb066..af68a86 100644 (file)
@@ -93,7 +93,7 @@
                        };
 
                        pmc: pmc@fffffc00 {
-                               compatible = "atmel,at91rm9200-pmc", "syscon";
+                               compatible = "atmel,at91sam9263-pmc", "syscon";
                                reg = <0xfffffc00 0x100>;
                                interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>;
                                interrupt-controller;
index bd001cc..8fb2203 100644 (file)
                        };
 
                        pmc: pmc@fffffc00 {
-                               compatible = "atmel,at91sam9g45-pmc", "syscon";
+                               compatible = "atmel,at91sam9rl-pmc", "syscon";
                                reg = <0xfffffc00 0x100>;
                                interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>;
                                interrupt-controller;
index a3c3c31..11c0ef1 100644 (file)
                                };
                        };
 
-                       rstc@fffffe00 {
+                       reset_controller: rstc@fffffe00 {
                                compatible = "atmel,at91sam9g45-rstc";
                                reg = <0xfffffe00 0x10>;
                                clocks = <&clk32k>;
                        };
 
-                       shdwc@fffffe10 {
+                       shutdown_controller: shdwc@fffffe10 {
                                compatible = "atmel,at91sam9x5-shdwc";
                                reg = <0xfffffe10 0x10>;
                                clocks = <&clk32k>;
                                clock-names = "dma_clk";
                        };
 
-                       pinctrl@fffff400 {
+                       pinctrl: pinctrl@fffff400 {
                                #address-cells = <1>;
                                #size-cells = <1>;
                                compatible = "atmel,at91sam9x5-pinctrl", "atmel,at91rm9200-pinctrl", "simple-bus";
                                };
                        };
 
-                       watchdog@fffffe40 {
+                       watchdog: watchdog@fffffe40 {
                                compatible = "atmel,at91sam9260-wdt";
                                reg = <0xfffffe40 0x10>;
                                interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>;
index 2c4df2d..253df71 100644 (file)
        model = "Broadcom Cygnus SoC";
        interrupt-parent = <&gic>;
 
+       aliases {
+               ethernet0 = &eth0;
+       };
+
        cpus {
                #address-cells = <1>;
                #size-cells = <0>;
                        status = "disabled";
                };
 
+               rng: rng@18032000 {
+                       compatible = "brcm,iproc-rng200";
+                       reg = <0x18032000 0x28>;
+               };
+
                sdhci0: sdhci@18041000 {
                        compatible = "brcm,sdhci-iproc-cygnus";
                        reg = <0x18041000 0x100>;
diff --git a/arch/arm/boot/dts/bcm2835-rpi-cm1-io1.dts b/arch/arm/boot/dts/bcm2835-rpi-cm1-io1.dts
new file mode 100644 (file)
index 0000000..4764a25
--- /dev/null
@@ -0,0 +1,88 @@
+// SPDX-License-Identifier: GPL-2.0
+/dts-v1/;
+#include "bcm2835-rpi-cm1.dtsi"
+#include "bcm283x-rpi-usb-host.dtsi"
+
+/ {
+       compatible = "raspberrypi,compute-module", "brcm,bcm2835";
+       model = "Raspberry Pi Compute Module IO board rev1";
+};
+
+&gpio {
+       /*
+        * This is based on the official GPU firmware DT blob.
+        *
+        * Legend:
+        * "NC" = not connected (no rail from the SoC)
+        * "FOO" = GPIO line named "FOO" on the schematic
+        * "FOO_N" = GPIO line named "FOO" on schematic, active low
+        */
+       gpio-line-names = "GPIO0",
+                         "GPIO1",
+                         "GPIO2",
+                         "GPIO3",
+                         "GPIO4",
+                         "GPIO5",
+                         "GPIO6",
+                         "GPIO7",
+                         "GPIO8",
+                         "GPIO9",
+                         "GPIO10",
+                         "GPIO11",
+                         "GPIO12",
+                         "GPIO13",
+                         "GPIO14",
+                         "GPIO15",
+                         "GPIO16",
+                         "GPIO17",
+                         "GPIO18",
+                         "GPIO19",
+                         "GPIO20",
+                         "GPIO21",
+                         "GPIO22",
+                         "GPIO23",
+                         "GPIO24",
+                         "GPIO25",
+                         "GPIO26",
+                         "GPIO27",
+                         "GPIO28",
+                         "GPIO29",
+                         "GPIO30",
+                         "GPIO31",
+                         "GPIO32",
+                         "GPIO33",
+                         "GPIO34",
+                         "GPIO35",
+                         "GPIO36",
+                         "GPIO37",
+                         "GPIO38",
+                         "GPIO39",
+                         "GPIO40",
+                         "GPIO41",
+                         "GPIO42",
+                         "GPIO43",
+                         "GPIO44",
+                         "GPIO45",
+                         "HDMI_HPD_N",
+                         /* Also used as ACT LED */
+                         "EMMC_EN_N",
+                         /* Used by eMMC */
+                         "SD_CLK_R",
+                         "SD_CMD_R",
+                         "SD_DATA0_R",
+                         "SD_DATA1_R",
+                         "SD_DATA2_R",
+                         "SD_DATA3_R";
+
+       pinctrl-0 = <&gpioout &alt0>;
+};
+
+&hdmi {
+       hpd-gpios = <&gpio 46 GPIO_ACTIVE_LOW>;
+};
+
+&uart0 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&uart0_gpio14>;
+       status = "okay";
+};
diff --git a/arch/arm/boot/dts/bcm2835-rpi-cm1.dtsi b/arch/arm/boot/dts/bcm2835-rpi-cm1.dtsi
new file mode 100644 (file)
index 0000000..ef22c2d
--- /dev/null
@@ -0,0 +1,34 @@
+// SPDX-License-Identifier: GPL-2.0
+/dts-v1/;
+#include "bcm2835.dtsi"
+#include "bcm2835-rpi.dtsi"
+
+/ {
+       leds {
+               act {
+                       gpios = <&gpio 47 GPIO_ACTIVE_LOW>;
+               };
+       };
+
+       reg_3v3: fixed-regulator {
+               compatible = "regulator-fixed";
+               regulator-name = "3V3";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               regulator-always-on;
+       };
+
+       reg_1v8: fixed-regulator {
+               compatible = "regulator-fixed";
+               regulator-name = "1V8";
+               regulator-min-microvolt = <1800000>;
+               regulator-max-microvolt = <1800000>;
+               regulator-always-on;
+       };
+};
+
+&sdhost {
+       non-removable;
+       vmmc-supply = <&reg_3v3>;
+       vqmmc-supply = <&reg_1v8>;
+};
index 7704bb0..beb6c50 100644 (file)
                };
        };
 
+       arm-pmu {
+               compatible = "arm,cortex-a53-pmu";
+               interrupt-parent = <&local_intc>;
+               interrupts = <9 IRQ_TYPE_LEVEL_HIGH>;
+       };
+
        timer {
                compatible = "arm,armv7-timer";
                interrupt-parent = <&local_intc>;
index 61315cf..31b2964 100644 (file)
                        clock-frequency = <1000000>;
                };
 
+               txp@7e004000 {
+                       compatible = "brcm,bcm2835-txp";
+                       reg = <0x7e004000 0x20>;
+                       interrupts = <1 11>;
+               };
+
                dma: dma@7e007000 {
                        compatible = "brcm,bcm2835-dma";
                        reg = <0x7e007000 0xf00>;
index ff2e551..79d454f 100644 (file)
@@ -90,3 +90,7 @@
                };
        };
 };
+
+&usb3_phy {
+       status = "okay";
+};
index 3bcc037..99365bb 100644 (file)
@@ -80,3 +80,7 @@
                };
        };
 };
+
+&usb3_phy {
+       status = "okay";
+};
index a587384..bc330b1 100644 (file)
 &spi_nor {
        status = "okay";
 };
+
+&usb3_phy {
+       status = "okay";
+};
index 6c8f0ad..258d2b2 100644 (file)
@@ -38,3 +38,7 @@
                };
        };
 };
+
+&usb3_phy {
+       status = "okay";
+};
index ebda45f..e7fdaed 100644 (file)
@@ -57,3 +57,7 @@
 &spi_nor {
        status = "okay";
 };
+
+&usb3_phy {
+       status = "okay";
+};
index 9dd0e22..42bafc6 100644 (file)
@@ -64,3 +64,7 @@
 &spi_nor {
        status = "okay";
 };
+
+&usb3_phy {
+       status = "okay";
+};
index d7c34fa..dce35eb 100644 (file)
@@ -91,3 +91,7 @@
 &spi_nor {
        status = "okay";
 };
+
+&usb3_phy {
+       status = "okay";
+};
index 2642494..b7a024b 100644 (file)
@@ -83,3 +83,7 @@
 &spi_nor {
        status = "okay";
 };
+
+&usb3_phy {
+       status = "okay";
+};
index e7b09b7..f7f834c 100644 (file)
                };
        };
 };
+
+&usb3_phy {
+       status = "okay";
+};
index 16314fc..76a2bab 100644 (file)
@@ -74,3 +74,7 @@
                };
        };
 };
+
+&usb3_phy {
+       status = "okay";
+};
index 328aa90..69e3570 100644 (file)
                };
        };
 };
+
+&usb3_phy {
+       status = "okay";
+};
index 8ea46ee..0f6f0fe 100644 (file)
                };
        };
 };
+
+&usb3_phy {
+       status = "okay";
+};
index 5eeac73..f770897 100644 (file)
@@ -57,3 +57,7 @@
 &spi_nor {
        status = "okay";
 };
+
+&usb3_phy {
+       status = "okay";
+};
index da4d9ec..4d42786 100644 (file)
 &spi_nor {
        status = "okay";
 };
+
+&usb3_phy {
+       status = "okay";
+};
index c94c732..5f663f8 100644 (file)
@@ -99,3 +99,7 @@
 &usb2 {
        vcc-gpio = <&chipcommon 9 GPIO_ACTIVE_HIGH>;
 };
+
+&usb3_phy {
+       status = "okay";
+};
index 2227181..2033411 100644 (file)
@@ -62,3 +62,7 @@
                };
        };
 };
+
+&usb3_phy {
+       status = "okay";
+};
index 79a9633..77d1687 100644 (file)
 &spi_nor {
        status = "okay";
 };
+
+&usb3_phy {
+       status = "okay";
+};
index db744a5..983149b 100644 (file)
@@ -39,3 +39,7 @@
                };
        };
 };
+
+&usb3_phy {
+       status = "okay";
+};
index 9e267d3..ca41481 100644 (file)
 &usb3 {
        vcc-gpio = <&chipcommon 0 GPIO_ACTIVE_HIGH>;
 };
+
+&usb3_phy {
+       status = "okay";
+};
index d266131..aa69e65 100644 (file)
 &usb3 {
        vcc-gpio = <&chipcommon 0 GPIO_ACTIVE_HIGH>;
 };
+
+&usb3_phy {
+       status = "okay";
+};
index f5bf658..c7143a9 100644 (file)
 &spi_nor {
        status = "okay";
 };
+
+&usb3_phy {
+       status = "okay";
+};
index d173bcd..03c1ab1 100644 (file)
 &spi_nor {
        status = "okay";
 };
+
+&usb3_phy {
+       status = "okay";
+};
index f47afe3..36efe41 100644 (file)
                        linux,code = <KEY_WPS_BUTTON>;
                        gpios = <&chipcommon 3 GPIO_ACTIVE_LOW>;
                };
+
+               rfkill {
+                               label = "WiFi";
+                               linux,code = <KEY_RFKILL>;
+                               gpios = <&chipcommon 16 GPIO_ACTIVE_LOW>;
+               };
+
+               reset {
+                               label = "Reset";
+                               linux,code = <KEY_RESTART>;
+                               gpios = <&chipcommon 17 GPIO_ACTIVE_LOW>;
+               };
+       };
+
+       leds {
+               compatible = "gpio-leds";
+
+               wps {
+                       label = "bcm53xx:white:wps";
+                       gpios = <&chipcommon 22 GPIO_ACTIVE_LOW>;
+               };
+
+               usb2 {
+                       label = "bcm53xx:green:usb2";
+                       gpios = <&chipcommon 1 GPIO_ACTIVE_LOW>;
+                       trigger-sources = <&ohci_port2>, <&ehci_port2>;
+                       linux,default-trigger = "usbport";
+               };
+
+               usb3 {
+                       label = "bcm53xx:green:usb3";
+                       gpios = <&chipcommon 2 GPIO_ACTIVE_LOW>;
+                       trigger-sources = <&ohci_port1>, <&ehci_port1>,
+                                         <&xhci_port1>;
+                       linux,default-trigger = "usbport";
+               };
+
+               power {
+                       label = "bcm53xx:white:power";
+                       gpios = <&chipcommon 4 GPIO_ACTIVE_HIGH>;
+               };
+
+               wifi-disabled {
+                       label = "bcm53xx:amber:wifi-disabled";
+                       gpios = <&chipcommon 0 GPIO_ACTIVE_LOW>;
+               };
+
+               wifi-enabled {
+                       label = "bcm53xx:white:wifi-enabled";
+                       gpios = <&chipcommon 5 GPIO_ACTIVE_HIGH>;
+               };
+
+               bluebar1 {
+                       label = "bcm53xx:white:bluebar1";
+                       gpios = <&chipcommon 11 GPIO_ACTIVE_HIGH>;
+               };
+
+               bluebar2 {
+                       label = "bcm53xx:white:bluebar2";
+                       gpios = <&chipcommon 12 GPIO_ACTIVE_HIGH>;
+               };
+
+               bluebar3 {
+                       label = "bcm53xx:white:bluebar3";
+                       gpios = <&chipcommon 15 GPIO_ACTIVE_LOW>;
+               };
+
+               bluebar4 {
+                       label = "bcm53xx:white:bluebar4";
+                       gpios = <&chipcommon 18 GPIO_ACTIVE_HIGH>;
+               };
+
+               bluebar5 {
+                       label = "bcm53xx:white:bluebar5";
+                       gpios = <&chipcommon 19 GPIO_ACTIVE_HIGH>;
+               };
+
+               bluebar6 {
+                       label = "bcm53xx:white:bluebar6";
+                       gpios = <&chipcommon 20 GPIO_ACTIVE_HIGH>;
+               };
+
+               bluebar7 {
+                       label = "bcm53xx:white:bluebar7";
+                       gpios = <&chipcommon 21 GPIO_ACTIVE_HIGH>;
+               };
+
+               bluebar8 {
+                       label = "bcm53xx:white:bluebar8";
+                       gpios = <&chipcommon 8 GPIO_ACTIVE_HIGH>;
+               };
+       };
+
+       mdio-bus-mux {
+               /* BIT(9) = 1 => external mdio */
+               mdio_ext: mdio@200 {
+                       reg = <0x200>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+               };
+       };
+
+       mdio-mii-mux {
+               compatible = "mdio-mux-mmioreg";
+               mdio-parent-bus = <&mdio_ext>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+               reg = <0x1800c1c0 0x4>;
+
+               /* BIT(6) = mdc, BIT(7) = mdio */
+               mux-mask = <0xc0>;
+
+               mdio-mii@0 {
+                       /* Enable MII function */
+                       reg = <0x0>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+
+                       switch@0  {
+                               compatible = "brcm,bcm53125";
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               reset-gpios = <&chipcommon 10 GPIO_ACTIVE_LOW>;
+                               reset-names = "robo_reset";
+                               reg = <0>;
+                               dsa,member = <1 0>;
+
+                               ports {
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+
+                                       port@0 {
+                                               reg = <0>;
+                                               label = "lan1";
+                                       };
+
+                                       port@1 {
+                                               reg = <1>;
+                                               label = "lan5";
+                                       };
+
+                                       port@2 {
+                                               reg = <2>;
+                                               label = "lan2";
+                                       };
+
+                                       port@3 {
+                                               reg = <3>;
+                                               label = "lan6";
+                                       };
+
+                                       port@4 {
+                                               reg = <4>;
+                                               label = "lan3";
+                                       };
+
+                                       sw1_p8: port@8 {
+                                               reg = <8>;
+                                               ethernet = <&sw0_p0>;
+                                               label = "cpu";
+
+                                               fixed-link {
+                                                       speed = <1000>;
+                                                       full-duplex;
+                                               };
+                                       };
+                               };
+                       };
+               };
+       };
+};
+
+&usb2 {
+       vcc-gpio = <&chipcommon 13 GPIO_ACTIVE_HIGH>;
+};
+
+&usb3 {
+       vcc-gpio = <&chipcommon 14 GPIO_ACTIVE_HIGH>;
+};
+
+&srab {
+       compatible = "brcm,bcm53012-srab", "brcm,bcm5301x-srab";
+       status = "okay";
+       dsa,member = <0 0>;
+
+       ports {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               port@1 {
+                       reg = <1>;
+                       label = "lan7";
+               };
+
+               port@2 {
+                       reg = <2>;
+                       label = "lan4";
+               };
+
+               port@3 {
+                       reg = <3>;
+                       label = "lan8";
+               };
+
+               port@4 {
+                       reg = <4>;
+                       label = "wan";
+               };
+
+               port@8 {
+                       reg = <8>;
+                       ethernet = <&gmac2>;
+                       label = "cpu";
+
+                       fixed-link {
+                               speed = <1000>;
+                               full-duplex;
+                       };
+               };
+
+               sw0_p0: port@0 {
+                       reg = <0>;
+                       label = "extsw";
+
+                       fixed-link {
+                               speed = <1000>;
+                               full-duplex;
+                       };
+               };
        };
 };
+
+&usb3_phy {
+       status = "okay";
+};
index a5cef51..3e5e997 100644 (file)
@@ -60,3 +60,7 @@
 &spi_nor {
        status = "okay";
 };
+
+&usb3_phy {
+       status = "okay";
+};
index 7496aab..7acbecd 100644 (file)
@@ -60,3 +60,7 @@
 &spi_nor {
        status = "okay";
 };
+
+&usb3_phy {
+       status = "okay";
+};
index 53aaa52..f4558d9 100644 (file)
 &spi_nor {
        status = "okay";
 };
+
+&usb3_phy {
+       status = "okay";
+};
index 0e718ed..3071938 100644 (file)
@@ -91,3 +91,7 @@
                };
        };
 };
+
+&usb3_phy {
+       status = "okay";
+};
index 4840a78..f7c3e27 100644 (file)
@@ -7,9 +7,10 @@
 #include "bcm4708.dtsi"
 
 / {
-       usb3_phy: usb3-phy {
-               compatible = "brcm,ns-bx-usb3-phy";
-       };
+};
+
+&usb3_phy {
+       compatible = "brcm,ns-bx-usb3-phy";
 };
 
 &uart0 {
index ef995e5..bc607d1 100644 (file)
                clock-names = "phy-ref-clk";
        };
 
-       usb3_phy: usb3-phy {
-               compatible = "brcm,ns-ax-usb3-phy";
-               reg = <0x18105000 0x1000>, <0x18003000 0x1000>;
-               reg-names = "dmp", "ccb-mii";
-               #phy-cells = <0>;
-       };
-
        axi@18000000 {
                compatible = "brcm,bus-axi";
                reg = <0x18000000 0x1000>;
                reg = <0x18003000 0x8>;
                #size-cells = <1>;
                #address-cells = <0>;
-               status = "disabled";
+       };
+
+       mdio-bus-mux {
+               compatible = "mdio-mux-mmioreg";
+               mdio-parent-bus = <&mdio>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+               reg = <0x18003000 0x4>;
+               mux-mask = <0x200>;
+
+               mdio@0 {
+                       reg = <0x0>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+
+                       usb3_phy: usb3-phy@10 {
+                               compatible = "brcm,ns-ax-usb3-phy";
+                               reg = <0x10>;
+                               usb3-dmp-syscon = <&usb3_dmp>;
+                               #phy-cells = <0>;
+                               status = "disabled";
+                       };
+               };
+       };
+
+       usb3_dmp: syscon@18105000 {
+               reg = <0x18105000 0x1000>;
        };
 
        i2c0: i2c@18009000 {
index 16007d7..453a2a3 100644 (file)
                };
        };
 
+       timer {
+               compatible = "arm,armv7-timer";
+               interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_LOW>,
+                            <GIC_PPI 14 IRQ_TYPE_LEVEL_LOW>,
+                            <GIC_PPI 11 IRQ_TYPE_LEVEL_LOW>,
+                            <GIC_PPI 10 IRQ_TYPE_LEVEL_LOW>;
+       };
+
        clocks {
                #address-cells = <1>;
                #size-cells = <1>;
index 2e08c89..934f07a 100644 (file)
@@ -42,3 +42,7 @@
                reg = <0x00000000 0x08000000>;
        };
 };
+
+&usb3_phy {
+       status = "okay";
+};
index c37616c..31e4dd0 100644 (file)
@@ -42,3 +42,7 @@
                reg = <0x00000000 0x08000000>;
        };
 };
+
+&usb3_phy {
+       status = "okay";
+};
index 40e694b..17f63c7 100644 (file)
@@ -90,3 +90,7 @@
                };
        };
 };
+
+&usb3_phy {
+       status = "okay";
+};
index 3076e81..11b0f5e 100644 (file)
@@ -95,3 +95,7 @@
                reg = <0x00700000 0x00900000>;
        };
 };
+
+&usb3_phy {
+       status = "okay";
+};
index 79c168e..e798055 100644 (file)
 &uart1 {
        status = "okay";
 };
+
+&usb3_phy {
+       status = "okay";
+};
index db67377..d2f7d98 100644 (file)
                        device_type = "cpu";
                        next-level-cache = <&l2>;
                        reg = <1>;
+
+                       clocks = <&chip_clk CLKID_CPU>;
+                       clock-latency = <100000>;
+                       operating-points = <
+                               /* kHz    uV */
+                               1200000 1200000
+                               1000000 1200000
+                               800000  1200000
+                               600000  1200000
+                       >;
                };
        };
 
index 516a7ce..99d6872 100644 (file)
                        device_type = "cpu";
                        next-level-cache = <&l2>;
                        reg = <1>;
+
+                       clocks = <&chip_clk CLKID_CPU>;
+                       clock-latency = <100000>;
+                       /* Can be modified by the bootloader */
+                       operating-points = <
+                               /* kHz    uV */
+                               1200000 1200000
+                               1000000 1200000
+                               800000  1200000
+                               600000  1200000
+                       >;
                };
 
                cpu2: cpu@2 {
                        device_type = "cpu";
                        next-level-cache = <&l2>;
                        reg = <2>;
+
+                       clocks = <&chip_clk CLKID_CPU>;
+                       clock-latency = <100000>;
+                       /* Can be modified by the bootloader */
+                       operating-points = <
+                               /* kHz    uV */
+                               1200000 1200000
+                               1000000 1200000
+                               800000  1200000
+                               600000  1200000
+                       >;
                };
 
                cpu3: cpu@3 {
                        device_type = "cpu";
                        next-level-cache = <&l2>;
                        reg = <3>;
+
+                       clocks = <&chip_clk CLKID_CPU>;
+                       clock-latency = <100000>;
+                       /* Can be modified by the bootloader */
+                       operating-points = <
+                               /* kHz    uV */
+                               1200000 1200000
+                               1000000 1200000
+                               800000  1200000
+                               600000  1200000
+                       >;
                };
        };
 
index 14dff3e..0102ffc 100644 (file)
        };
 };
 
+&ref_clk {
+       clock-frequency = <24000000>;
+};
+
 &edma0 {
        ti,edma-reserved-slot-ranges = <32 50>;
 };
index 0e82bb9..f9b7579 100644 (file)
                spi0 = &spi1;
        };
 
+       backlight: backlight-pwm {
+               pinctrl-names = "default";
+               pinctrl-0 = <&ecap2_pins>;
+               power-supply = <&backlight_lcd>;
+               compatible = "pwm-backlight";
+               /*
+                * The PWM here corresponds to production hardware. The
+                * schematic needs to be 1015171 (15 March 2010), Rev A
+                * or newer.
+                */
+               pwms = <&ecap2 0 50000 0>;
+               brightness-levels = <0 10 20 30 40 50 60 70 80 90 99>;
+               default-brightness-level = <7>;
+       };
+
+       panel {
+               compatible = "ti,tilcdc,panel";
+               pinctrl-names = "default";
+               pinctrl-0 = <&lcd_pins>;
+               /*
+                * The vpif and the LCD are mutually exclusive.
+                * To enable VPIF, change the status below to 'disabled' then
+                * then change the status of the vpif below to 'okay'
+                */
+               status = "okay";
+               enable-gpios = <&gpio 40 GPIO_ACTIVE_HIGH>; /* lcd_panel_pwr */
+
+               panel-info {
+                       ac-bias         = <255>;
+                       ac-bias-intrpt  = <0>;
+                       dma-burst-sz    = <16>;
+                       bpp             = <16>;
+                       fdd             = <0x80>;
+                       sync-edge       = <0>;
+                       sync-ctrl       = <1>;
+                       raster-order    = <0>;
+                       fifo-th         = <0>;
+               };
+
+               display-timings {
+                       native-mode = <&timing0>;
+                       timing0: 480x272 {
+                               clock-frequency = <9000000>;
+                               hactive = <480>;
+                               vactive = <272>;
+                               hfront-porch = <3>;
+                               hback-porch = <2>;
+                               hsync-len = <42>;
+                               vback-porch = <3>;
+                               vfront-porch = <4>;
+                               vsync-len = <11>;
+                               hsync-active = <0>;
+                               vsync-active = <0>;
+                               de-active = <1>;
+                               pixelclk-active = <1>;
+                       };
+               };
+       };
+
        vbat: fixedregulator0 {
                compatible = "regulator-fixed";
                regulator-name = "vbat";
                regulator-boot-on;
        };
 
+       backlight_lcd: backlight-regulator {
+               compatible = "regulator-fixed";
+               regulator-name = "lcd_backlight_pwr";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               gpio = <&gpio 47 GPIO_ACTIVE_HIGH>; /* lcd_backlight_pwr */
+               enable-active-high;
+       };
+
        sound {
                compatible = "simple-audio-card";
                simple-audio-card,name = "DA850/OMAP-L138 EVM";
        };
 };
 
+&ecap2 {
+       status = "okay";
+};
+
+&ref_clk {
+       clock-frequency = <24000000>;
+};
+
 &pmx_core {
        status = "okay";
 
        };
 };
 
+&sata {
+       status = "okay";
+};
+
 &serial0 {
        status = "okay";
 };
        status = "okay";
 };
 
+&lcdc {
+       status = "okay";
+};
+
 &i2c0 {
        status = "okay";
        clock-frequency = <100000>;
 &vpif {
        pinctrl-names = "default";
        pinctrl-0 = <&vpif_capture_pins>, <&vpif_display_pins>;
-       status = "okay";
+       /*
+        * The vpif and the LCD are mutually exclusive.
+        * To enable VPIF, disable the ti,tilcdc,panel then
+        * change the status below to 'okay'
+        */
+       status = "disabled";
 };
index 0edf769..0177e3e 100644 (file)
        };
 };
 
+&ref_clk {
+       clock-frequency = <24000000>;
+};
+
 &pmx_core {
        status = "okay";
 
        status = "okay";
 };
 
+&sata_refclk {
+       status = "okay";
+       clock-frequency = <100000000>;
+};
+
 &sata {
        status = "okay";
 };
index ee39324..c4729d0 100644 (file)
                rechargeable-gpios = <&gpio 136 GPIO_ACTIVE_LOW>;
        };
 
+       bt_slow_clk: bt-clock {
+               pinctrl-names = "default";
+               pinctrl-0 = <&ecap2_pins>, <&bt_clock_bias>;
+               compatible = "pwm-clock";
+               #clock-cells = <0>;
+               clock-frequency = <32768>;
+               pwms = <&ecap2 0 30518 0>;
+       };
+
        /* ARM local RAM */
        memory@ffff0000 {
                compatible = "syscon", "simple-mfd";
        };
 };
 
+&ref_clk {
+       clock-frequency = <24000000>;
+};
+
 &pmx_core {
        status = "okay";
 
                        bias-disable;
                };
        };
+
+       bt_clock_bias: bt-clock-bias-groups {
+               disable {
+                       groups = "cp2";
+                       bias-disable;
+               };
+       };
+
+       bt_pic_bias: bt-pic-bias-groups {
+               disable {
+                       groups = "cp20";
+                       bias-disable;
+               };
+       };
 };
 
 /* Input port 1 */
        pinctrl-0 = <&serial1_rxtx_pins>;
 };
 
+&serial2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&serial2_rxtx_pins>, <&serial2_rtscts_pins>, <&bt_pic_bias>;
+       status = "okay";
+
+       bluetooth {
+               compatible = "ti,cc2560";
+               clocks = <&bt_slow_clk>;
+               clock-names = "ext_clock";
+               enable-gpios = <&gpio 73 GPIO_ACTIVE_HIGH>;
+               max-speed = <2000000>;
+               nvmem-cells = <&bdaddr>;
+               nvmem-cell-names = "bd-address";
+       };
+};
+
 &rtc0 {
        status = "okay";
 };
                pagesize = <64>;
                read-only;
                reg = <0x50>;
+               #address-cells = <1>;
+               #size-cells = <1>;
+
+               bdaddr: bdaddr@3f06 {
+                       reg = <0x3f06 0x06>;
+               };
        };
 };
 
        };
 };
 
+&ecap2 {
+       status = "okay";
+};
+
 &ehrpwm0 {
        status = "okay";
 };
                gpios = <6 GPIO_ACTIVE_HIGH>;
                output-high;
        };
+
+       /* Don't impede Bluetooth clock signal */
+       bt_clock_en {
+               gpio-hog;
+               gpios = <5 GPIO_ACTIVE_HIGH>;
+               input;
+       };
+
+       /*
+        * There is a PIC microcontroller for interfacing with an Apple MFi
+        * chip. This interferes with normal Bluetooth operation, so we need
+        * to make sure it is turned off. Note: The publicly available
+        * schematics from LEGO don't show that these pins are connected to
+        * anything, but they are present in the source code from LEGO.
+        */
+
+       bt_pic_en {
+               gpio-hog;
+               gpios = <51 GPIO_ACTIVE_HIGH>;
+               output-low;
+       };
+
+       bt_pic_rst {
+               gpio-hog;
+               gpios = <78 GPIO_ACTIVE_HIGH>;
+               output-high;
+       };
+
+       bt_pic_cts {
+               gpio-hog;
+               gpios = <87 GPIO_ACTIVE_HIGH>;
+               input;
+       };
 };
 
 &usb_phy {
index 0f4f817..47aa53b 100644 (file)
                        reg = <0xfffee000 0x2000>;
                };
        };
+       clocks: clocks {
+               ref_clk: ref_clk {
+                       compatible = "fixed-clock";
+                       #clock-cells = <0>;
+                       clock-output-names = "ref_clk";
+               };
+               sata_refclk: sata_refclk {
+                       compatible = "fixed-clock";
+                       #clock-cells = <0>;
+                       clock-output-names = "sata_refclk";
+                       status = "disabled";
+               };
+               usb_refclkin: usb_refclkin {
+                       compatible = "fixed-clock";
+                       #clock-cells = <0>;
+                       clock-output-names = "usb_refclkin";
+                       status = "disabled";
+               };
+       };
        dsp: dsp@11800000 {
                compatible = "ti,da850-dsp";
                reg = <0x11800000 0x40000>,
@@ -42,6 +61,8 @@
                reg-names = "l2sram", "l1pram", "l1dram", "host1cfg", "chipsig";
                interrupt-parent = <&intc>;
                interrupts = <28>;
+               clocks = <&psc0 15>;
+               resets = <&psc0 15>;
                status = "disabled";
        };
        soc@1c00000 {
                ranges = <0x0 0x01c00000 0x400000>;
                interrupt-parent = <&intc>;
 
+               psc0: clock-controller@10000 {
+                       compatible = "ti,da850-psc0";
+                       reg = <0x10000 0x1000>;
+                       #clock-cells = <1>;
+                       #reset-cells = <1>;
+                       #power-domain-cells = <1>;
+                       clocks = <&pll0_sysclk 1>, <&pll0_sysclk 2>,
+                                <&pll0_sysclk 4>, <&pll0_sysclk 6>,
+                                <&async1_clk>;
+                       clock-names = "pll0_sysclk1", "pll0_sysclk2",
+                                     "pll0_sysclk4", "pll0_sysclk6",
+                                     "async1";
+               };
+               pll0: clock-controller@11000 {
+                       compatible = "ti,da850-pll0";
+                       reg = <0x11000 0x1000>;
+                       clocks = <&ref_clk>, <&pll1_sysclk 3>;
+                       clock-names = "clksrc", "extclksrc";
+
+                       pll0_pllout: pllout {
+                               #clock-cells = <0>;
+                       };
+                       pll0_sysclk: sysclk {
+                               #clock-cells = <1>;
+                       };
+                       pll0_auxclk: auxclk {
+                               #clock-cells = <0>;
+                       };
+                       pll0_obsclk: obsclk {
+                               #clock-cells = <0>;
+                       };
+               };
                pmx_core: pinmux@14120 {
                        compatible = "pinctrl-single";
                        reg = <0x14120 0x50>;
                        usb_phy: usb-phy {
                                compatible = "ti,da830-usb-phy";
                                #phy-cells = <1>;
+                               clocks = <&usb_phy_clk 0>, <&usb_phy_clk 1>;
+                               clock-names = "usb0_clk48", "usb1_clk48";
                                status = "disabled";
                        };
+                       usb_phy_clk: usb-phy-clocks {
+                               compatible = "ti,da830-usb-phy-clocks";
+                               #clock-cells = <1>;
+                               clocks = <&psc1 1>, <&usb_refclkin>,
+                                        <&pll0_auxclk>;
+                               clock-names = "fck", "usb_refclkin", "auxclk";
+                       };
+                       ehrpwm_tbclk: ehrpwm_tbclk {
+                               compatible = "ti,da830-tbclksync";
+                               #clock-cells = <0>;
+                               clocks = <&psc1 17>;
+                               clock-names = "fck";
+                       };
+                       div4p5_clk: div4.5 {
+                               compatible = "ti,da830-div4p5ena";
+                               #clock-cells = <0>;
+                               clocks = <&pll0_pllout>;
+                               clock-names = "pll0_pllout";
+                       };
+                       async1_clk: async1 {
+                               compatible = "ti,da850-async1-clksrc";
+                               #clock-cells = <0>;
+                               clocks = <&pll0_sysclk 3>, <&div4p5_clk>;
+                               clock-names = "pll0_sysclk3", "div4.5";
+                       };
+                       async3_clk: async3 {
+                               compatible = "ti,da850-async3-clksrc";
+                               #clock-cells = <0>;
+                               clocks = <&pll0_sysclk 2>, <&pll1_sysclk 2>;
+                               clock-names = "pll0_sysclk2", "pll1_sysclk2";
+                       };
                };
                edma0: edma@0 {
                        compatible = "ti,edma3-tpcc";
                        #dma-cells = <2>;
 
                        ti,tptcs = <&edma0_tptc0 7>, <&edma0_tptc1 0>;
+                       power-domains = <&psc0 0>;
                };
                edma0_tptc0: tptc@8000 {
                        compatible = "ti,edma3-tptc";
                        reg =   <0x8000 0x400>;
                        interrupts = <13>;
                        interrupt-names = "edm3_tcerrint";
+                       power-domains = <&psc0 1>;
                };
                edma0_tptc1: tptc@8400 {
                        compatible = "ti,edma3-tptc";
                        reg =   <0x8400 0x400>;
                        interrupts = <32>;
                        interrupt-names = "edm3_tcerrint";
+                       power-domains = <&psc0 2>;
                };
                edma1: edma@230000 {
                        compatible = "ti,edma3-tpcc";
                        #dma-cells = <2>;
 
                        ti,tptcs = <&edma1_tptc0 7>;
+                       power-domains = <&psc1 0>;
                };
                edma1_tptc0: tptc@238000 {
                        compatible = "ti,edma3-tptc";
                        reg =   <0x238000 0x400>;
                        interrupts = <95>;
                        interrupt-names = "edm3_tcerrint";
+                       power-domains = <&psc1 21>;
                };
                serial0: serial@42000 {
                        compatible = "ti,da830-uart", "ns16550a";
                        reg-io-width = <4>;
                        reg-shift = <2>;
                        interrupts = <25>;
+                       clocks = <&psc0 9>;
+                       power-domains = <&psc0 9>;
                        status = "disabled";
                };
                serial1: serial@10c000 {
                        reg-io-width = <4>;
                        reg-shift = <2>;
                        interrupts = <53>;
+                       clocks = <&psc1 12>;
+                       power-domains = <&psc1 12>;
                        status = "disabled";
                };
                serial2: serial@10d000 {
                        reg-io-width = <4>;
                        reg-shift = <2>;
                        interrupts = <61>;
+                       clocks = <&psc1 13>;
+                       power-domains = <&psc1 13>;
                        status = "disabled";
                };
                rtc0: rtc@23000 {
                        reg = <0x23000 0x1000>;
                        interrupts = <19
                                      19>;
+                       clocks = <&pll0_auxclk>;
+                       clock-names = "int-clk";
                        status = "disabled";
                };
                i2c0: i2c@22000 {
                        interrupts = <15>;
                        #address-cells = <1>;
                        #size-cells = <0>;
+                       clocks = <&pll0_auxclk>;
                        status = "disabled";
                };
                i2c1: i2c@228000 {
                        interrupts = <51>;
                        #address-cells = <1>;
                        #size-cells = <0>;
+                       clocks = <&psc1 11>;
+                       power-domains = <&psc1 11>;
                        status = "disabled";
                };
+               clocksource: timer@20000 {
+                       compatible = "ti,da830-timer";
+                       reg = <0x20000 0x1000>;
+                       interrupts = <12>, <13>;
+                       interrupt-names = "tint12", "tint34";
+                       clocks = <&pll0_auxclk>;
+               };
                wdt: wdt@21000 {
                        compatible = "ti,davinci-wdt";
                        reg = <0x21000 0x1000>;
+                       clocks = <&pll0_auxclk>;
                        status = "disabled";
                };
                mmc0: mmc@40000 {
                        interrupts = <16>;
                        dmas = <&edma0 16 0>, <&edma0 17 0>;
                        dma-names = "rx", "tx";
+                       clocks = <&psc0 5>;
                        status = "disabled";
                };
                vpif: video@217000 {
                        compatible = "ti,da850-vpif";
                        reg = <0x217000 0x1000>;
                        interrupts = <92>;
+                       power-domains = <&psc1 9>;
                        status = "disabled";
 
                        /* VPIF capture port */
                        interrupts = <72>;
                        dmas = <&edma1 28 0>, <&edma1 29 0>;
                        dma-names = "rx", "tx";
+                       clocks = <&psc1 18>;
                        status = "disabled";
                };
                ehrpwm0: pwm@300000 {
                                     "ti,am33xx-ehrpwm";
                        #pwm-cells = <3>;
                        reg = <0x300000 0x2000>;
+                       clocks = <&psc1 17>, <&ehrpwm_tbclk>;
+                       clock-names = "fck", "tbclk";
+                       power-domains = <&psc1 17>;
                        status = "disabled";
                };
                ehrpwm1: pwm@302000 {
                                     "ti,am33xx-ehrpwm";
                        #pwm-cells = <3>;
                        reg = <0x302000 0x2000>;
+                       clocks = <&psc1 17>, <&ehrpwm_tbclk>;
+                       clock-names = "fck", "tbclk";
+                       power-domains = <&psc1 17>;
                        status = "disabled";
                };
                ecap0: ecap@306000 {
                                     "ti,am33xx-ecap";
                        #pwm-cells = <3>;
                        reg = <0x306000 0x80>;
+                       clocks = <&psc1 20>;
+                       clock-names = "fck";
+                       power-domains = <&psc1 20>;
                        status = "disabled";
                };
                ecap1: ecap@307000 {
                                     "ti,am33xx-ecap";
                        #pwm-cells = <3>;
                        reg = <0x307000 0x80>;
+                       clocks = <&psc1 20>;
+                       clock-names = "fck";
+                       power-domains = <&psc1 20>;
                        status = "disabled";
                };
                ecap2: ecap@308000 {
                                     "ti,am33xx-ecap";
                        #pwm-cells = <3>;
                        reg = <0x308000 0x80>;
+                       clocks = <&psc1 20>;
+                       clock-names = "fck";
+                       power-domains = <&psc1 20>;
                        status = "disabled";
                };
                spi0: spi@41000 {
                        interrupts = <20>;
                        dmas = <&edma0 14 0>, <&edma0 15 0>;
                        dma-names = "rx", "tx";
+                       clocks = <&psc0 4>;
+                       power-domains = <&psc0 4>;
                        status = "disabled";
                };
                spi1: spi@30e000 {
                        interrupts = <56>;
                        dmas = <&edma0 18 0>, <&edma0 19 0>;
                        dma-names = "rx", "tx";
+                       clocks = <&psc1 10>;
+                       power-domains = <&psc1 10>;
                        status = "disabled";
                };
                usb0: usb@200000 {
                        dr_mode = "otg";
                        phys = <&usb_phy 0>;
                        phy-names = "usb-phy";
+                       clocks = <&psc1 1>;
+                       clock-ranges;
                        status = "disabled";
 
                        #address-cells = <1>;
                                interrupts = <58>;
                                #dma-cells = <2>;
                                #dma-channels = <4>;
+                               power-domains = <&psc1 1>;
                                status = "okay";
                        };
                };
                        compatible = "ti,da850-ahci";
                        reg = <0x218000 0x2000>, <0x22c018 0x4>;
                        interrupts = <67>;
+                       clocks = <&psc1 8>, <&sata_refclk>;
+                       clock-names = "fck", "refclk";
                        status = "disabled";
                };
+               pll1: clock-controller@21a000 {
+                       compatible = "ti,da850-pll1";
+                       reg = <0x21a000 0x1000>;
+                       clocks = <&ref_clk>;
+                       clock-names = "clksrc";
+
+                       pll1_sysclk: sysclk {
+                               #clock-cells = <1>;
+                       };
+                       pll1_obsclk: obsclk {
+                               #clock-cells = <0>;
+                       };
+               };
                mdio: mdio@224000 {
                        compatible = "ti,davinci_mdio";
                        #address-cells = <1>;
                        #size-cells = <0>;
                        reg = <0x224000 0x1000>;
+                       clocks = <&psc1 5>;
+                       clock-names = "fck";
+                       power-domains = <&psc1 5>;
                        status = "disabled";
                };
                eth0: ethernet@220000 {
                                        35
                                        36
                                        >;
+                       clocks = <&psc1 5>;
+                       power-domains = <&psc1 5>;
                        status = "disabled";
                };
                usb1: usb@225000 {
                        interrupts = <59>;
                        phys = <&usb_phy 1>;
                        phy-names = "usb-phy";
+                       clocks = <&psc1 2>;
                        status = "disabled";
                };
                gpio: gpio@226000 {
                        interrupts = <42 43 44 45 46 47 48 49 50>;
                        ti,ngpio = <144>;
                        ti,davinci-gpio-unbanked = <0>;
+                       clocks = <&psc1 3>;
+                       clock-names = "gpio";
                        status = "disabled";
                        interrupt-controller;
                        #interrupt-cells = <2>;
                                      <&pmx_core 142 147 1>,
                                      <&pmx_core 143 146 1>;
                };
+               psc1: clock-controller@227000 {
+                       compatible = "ti,da850-psc1";
+                       reg = <0x227000 0x1000>;
+                       #clock-cells = <1>;
+                       #power-domain-cells = <1>;
+                       clocks = <&pll0_sysclk 2>, <&pll0_sysclk 4>,
+                                <&async3_clk>;
+                       clock-names = "pll0_sysclk2", "pll0_sysclk4", "async3";
+                       assigned-clocks = <&async3_clk>;
+                       assigned-clock-parents = <&pll1_sysclk 2>;
+               };
                pinconf: pin-controller@22c00c {
                        compatible = "ti,da850-pupd";
                        reg = <0x22c00c 0x8>;
                        reg-names = "mpu", "dat";
                        interrupts = <54>;
                        interrupt-names = "common";
+                       power-domains = <&psc1 7>;
                        status = "disabled";
                        dmas = <&edma0 1 1>,
                                <&edma0 0 1>;
                        reg = <0x213000 0x1000>;
                        interrupts = <52>;
                        max-pixelclock = <37500>;
+                       clocks = <&psc1 16>;
+                       clock-names = "fck";
+                       power-domains = <&psc1 16>;
                        status = "disabled";
                };
        };
                reg = <0x68000000 0x00008000>;
                ranges = <0 0 0x60000000 0x08000000
                          1 0 0x68000000 0x00008000>;
+               clocks = <&psc0 3>;
+               clock-names = "aemif";
+               clock-ranges;
                status = "disabled";
        };
        memctrl: memory-controller@b0000000 {
index 33230c8..7e18147 100644 (file)
                id-gpio = <&pcf_gpio_21 1 GPIO_ACTIVE_HIGH>;
        };
 
+       extcon_usb2: extcon_usb2 {
+               compatible = "linux,extcon-usb-gpio";
+               id-gpio = <&pcf_gpio_21 2 GPIO_ACTIVE_HIGH>;
+       };
+
        sound0: sound0 {
                compatible = "simple-audio-card";
                simple-audio-card,name = "DRA7xx-EVM";
        extcon = <&extcon_usb1>;
 };
 
+&omap_dwc3_2 {
+       extcon = <&extcon_usb2>;
+};
+
 &usb2 {
        dr_mode = "host";
+       extcon = <&extcon_usb2>;
 };
 
 &atl {
index 0894593..6ed5f91 100644 (file)
                enable-active-high;
        };
 
-       extcon_usb2: extcon_usb2 {
-               compatible = "linux,extcon-usb-gpio";
-               id-gpio = <&pcf_gpio_21 2 GPIO_ACTIVE_HIGH>;
-       };
-
        vtt_fixed: fixedregulator-vtt {
                compatible = "regulator-fixed";
                regulator-name = "vtt_fixed";
        vdd-supply = <&smps123_reg>;
 };
 
-&omap_dwc3_2 {
-       extcon = <&extcon_usb2>;
-};
-
 &elm {
        status = "okay";
 };
index e03495a..a0ddf49 100644 (file)
                        };
                };
 
-               dcan1: can@481cc000 {
+               dcan1: can@4ae3c000 {
                        compatible = "ti,dra7-d_can";
                        ti,hwmods = "dcan1";
                        reg = <0x4ae3c000 0x2000>;
                        status = "disabled";
                };
 
-               dcan2: can@481d0000 {
+               dcan2: can@48480000 {
                        compatible = "ti,dra7-d_can";
                        ti,hwmods = "dcan2";
                        reg = <0x48480000 0x2000>;
index b7aeaee..c471bf3 100644 (file)
        /* Supplied by VDA_1V8_PHY */
        vdda_video-supply = <&lp8732_ldo1_reg>;
 };
+
+&extcon_usb1 {
+       vbus-gpio = <&pcf_lcd 14 GPIO_ACTIVE_HIGH>;
+};
+
+&extcon_usb2 {
+       vbus-gpio = <&pcf_lcd 15 GPIO_ACTIVE_HIGH>;
+};
index df174f5..e297b92 100644 (file)
 
 &usb2 {
        dr_mode = "host";
+       extcon = <&extcon_usb2>;
 };
 
 &mmc1 {
index 91e93ab..8f9df09 100644 (file)
                        compatible = "arm,cortex-a15";
                        reg = <1>;
                        operating-points-v2 = <&cpu0_opp_table>;
+
+                       clocks = <&dpll_mpu_ck>;
+                       clock-names = "cpu";
+
+                       clock-latency = <300000>; /* From omap-cpufreq driver */
+
+                       /* cooling options */
+                       #cooling-cells = <2>; /* min followed by max */
+
+                       vbb-supply = <&abb_mpu>;
                };
        };
 
index c07f005..5a46163 100644 (file)
        phys = <&pcie1_phy>, <&pcie2_phy>;
        phy-names = "pcie-phy0", "pcie-phy1";
 };
+
+&extcon_usb1 {
+       vbus-gpio = <&pcf_lcd 14 GPIO_ACTIVE_HIGH>;
+};
+
+&extcon_usb2 {
+       vbus-gpio = <&pcf_lcd 15 GPIO_ACTIVE_HIGH>;
+};
+
+&m_can0 {
+       can-transceiver {
+               max-bitrate = <5000000>;
+       };
+};
index 1c88c58..613e4dc 100644 (file)
 / {
        compatible = "ti,dra762", "ti,dra7";
 
+       ocp {
+               target-module@42c01900 {
+                       compatible = "ti,sysc-dra7-mcan", "ti,sysc";
+                       ranges = <0x0 0x42c00000 0x2000>;
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       reg = <0x42c01900 0x4>,
+                             <0x42c01904 0x4>,
+                             <0x42c01908 0x4>;
+                       reg-names = "rev", "sysc", "syss";
+                       ti,sysc-mask = <(SYSC_OMAP4_SOFTRESET |
+                                        SYSC_DRA7_MCAN_ENAWAKEUP)>;
+                       ti,syss-mask = <1>;
+                       clocks = <&wkupaon_clkctrl DRA7_ADC_CLKCTRL 0>;
+                       clock-names = "fck";
+
+                       m_can0: mcan@1a00 {
+                               compatible = "bosch,m_can";
+                               reg = <0x1a00 0x4000>, <0x0 0x18FC>;
+                               reg-names = "m_can", "message_ram";
+                               interrupt-parent = <&gic>;
+                               interrupts = <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>,
+                                            <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>;
+                               interrupt-names = "int0", "int1";
+                               clocks = <&mcan_clk>, <&l3_iclk_div>;
+                               clock-names = "cclk", "hclk";
+                               bosch,mram-cfg = <0x0 0 0 32 0 0 1 1>;
+                       };
+               };
+       };
+
 };
 
 /* MCAN interrupts are hard-wired to irqs 67, 68 */
 &crossbar_mpu {
        ti,irqs-skip = <10 67 68 133 139 140>;
 };
+
+&scm_conf_clocks {
+       dpll_gmac_h14x2_ctrl_ck: dpll_gmac_h14x2_ctrl_ck@3fc {
+               #clock-cells = <0>;
+               compatible = "ti,divider-clock";
+               clocks = <&dpll_gmac_x2_ck>;
+               ti,max-div = <63>;
+               reg = <0x03fc>;
+               ti,bit-shift=<20>;
+               ti,latch-bit=<26>;
+               assigned-clocks = <&dpll_gmac_h14x2_ctrl_ck>;
+               assigned-clock-rates = <80000000>;
+       };
+
+       dpll_gmac_h14x2_ctrl_mux_ck: dpll_gmac_h14x2_ctrl_mux_ck@3fc {
+               #clock-cells = <0>;
+               compatible = "ti,mux-clock";
+               clocks = <&dpll_gmac_ck>, <&dpll_gmac_h14x2_ctrl_ck>;
+               reg = <0x3fc>;
+               ti,bit-shift = <29>;
+               ti,latch-bit=<26>;
+               assigned-clocks = <&dpll_gmac_h14x2_ctrl_mux_ck>;
+               assigned-clock-parents = <&dpll_gmac_h14x2_ctrl_ck>;
+       };
+
+       mcan_clk: mcan_clk@3fc {
+               #clock-cells = <0>;
+               compatible = "ti,gate-clock";
+               clocks = <&dpll_gmac_h14x2_ctrl_mux_ck>;
+               ti,bit-shift = <27>;
+               reg = <0x3fc>;
+       };
+};
index 0af44b7..1bb8e5c 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Device Tree Source for the KZM9D board
  *
  * Copyright (C) 2013 Renesas Solutions Corp.
- *
- * 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.
  */
 /dts-v1/;
 
index fec1241..373ea87 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Device Tree Source for the EMEV2 SoC
  *
  * Copyright (C) 2012 Renesas Solutions Corp.
- *
- * 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 <dt-bindings/interrupt-controller/arm-gic.h>
index 962af97..27a1ee2 100644 (file)
                        compatible = "arm,cortex-a7";
                        reg = <1>;
                        clock-frequency = <1000000000>;
+                       clocks = <&cmu CLK_ARM_CLK>;
+                       clock-names = "cpu";
+                       #cooling-cells = <2>;
+
+                       operating-points = <
+                               1000000 1150000
+                               900000  1112500
+                               800000  1075000
+                               700000  1037500
+                               600000  1000000
+                               500000  962500
+                               400000  925000
+                               300000  887500
+                               200000  850000
+                               100000  850000
+                       >;
                };
        };
 
                        interrupts = <GIC_SPI 216 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&cmu CLK_TMU_APBIF>;
                        clock-names = "tmu_apbif";
-                       #include "exynos4412-tmu-sensor-conf.dtsi"
+                       #thermal-sensor-cells = <0>;
                        status = "disabled";
                };
 
index dfe41b6..6085e92 100644 (file)
                        reg = <0x100C0000 0x100>;
                        interrupts = <2 4>;
                        status = "disabled";
-                       #include "exynos4412-tmu-sensor-conf.dtsi"
+                       #thermal-sensor-cells = <0>;
                };
 
                jpeg_codec: jpeg-codec@11840000 {
index 88fb47c..b6091c2 100644 (file)
                        device_type = "cpu";
                        compatible = "arm,cortex-a9";
                        reg = <0x901>;
+                       clocks = <&clock CLK_ARM_CLK>;
+                       clock-names = "cpu";
+                       clock-latency = <160000>;
+
+                       operating-points = <
+                               1200000 1250000
+                               1000000 1150000
+                               800000  1075000
+                               500000  975000
+                               400000  975000
+                               200000  950000
+                       >;
+                       #cooling-cells = <2>; /* min followed by max */
                };
        };
 
index dc11ca1..c0476c2 100644 (file)
@@ -94,6 +94,8 @@
 
        gpio-keys {
                compatible = "gpio-keys";
+               pinctrl-names = "default";
+               pinctrl-0 = <&gpio_keys>;
 
                key-down {
                        gpios = <&gpx3 3 GPIO_ACTIVE_LOW>;
                        compatible = "maxim,max77693";
                        interrupt-parent = <&gpx1>;
                        interrupts = <5 IRQ_TYPE_EDGE_FALLING>;
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&max77693_irq>;
                        reg = <0x66>;
 
                        regulators {
                        compatible = "maxim,max17047";
                        interrupt-parent = <&gpx2>;
                        interrupts = <3 IRQ_TYPE_EDGE_FALLING>;
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&max77693_fuel_irq>;
                        reg = <0x36>;
 
                        maxim,over-heat-temp = <700>;
                compatible = "maxim,max77686";
                interrupt-parent = <&gpx0>;
                interrupts = <7 IRQ_TYPE_NONE>;
+               pinctrl-0 = <&max77686_irq>;
+               pinctrl-names = "default";
                reg = <0x09>;
                #clock-cells = <1>;
 
        pinctrl-names = "default";
        pinctrl-0 = <&sleep1>;
 
+       gpio_keys: gpio-keys {
+               samsung,pins = "gpx0-1", "gpx2-2", "gpx2-7", "gpx3-3";
+               samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+       };
+
+       max77686_irq: max77686-irq {
+               samsung,pins = "gpx0-7";
+               samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+       };
+
+       max77693_irq: max77693-irq {
+               samsung,pins = "gpx1-5";
+               samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+       };
+
+       max77693_fuel_irq: max77693-fuel-irq {
+               samsung,pins = "gpx2-3";
+               samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+       };
+
+       sdhci2_cd: sdhci2-cd-irq {
+               samsung,pins = "gpx3-4";
+               samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+       };
+
        hdmi_hpd: hdmi-hpd {
                samsung,pins = "gpx3-7";
                samsung,pin-pud = <EXYNOS_PIN_PULL_DOWN>;
        bus-width = <4>;
        cd-gpios = <&gpx3 4 GPIO_ACTIVE_HIGH>;
        cd-inverted;
-       pinctrl-0 = <&sd2_clk &sd2_cmd &sd2_bus4>;
+       pinctrl-0 = <&sd2_clk &sd2_cmd &sd2_bus4 &sdhci2_cd>;
        pinctrl-names = "default";
        vmmc-supply = <&ldo21_reg>;
        status = "okay";
diff --git a/arch/arm/boot/dts/exynos4412-tmu-sensor-conf.dtsi b/arch/arm/boot/dts/exynos4412-tmu-sensor-conf.dtsi
deleted file mode 100644 (file)
index 489b58c..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Device tree sources for Exynos4412 TMU sensor configuration
- *
- * Copyright (c) 2014 Lukasz Majewski <l.majewski@samsung.com>
- */
-
-#include <dt-bindings/thermal/thermal_exynos.h>
-
-#thermal-sensor-cells = <0>;
-samsung,tmu_gain = <8>;
-samsung,tmu_reference_voltage = <16>;
-samsung,tmu_noise_cancel_mode = <4>;
-samsung,tmu_efuse_value = <55>;
-samsung,tmu_min_efuse_value = <40>;
-samsung,tmu_max_efuse_value = <100>;
-samsung,tmu_first_point_trim = <25>;
-samsung,tmu_second_point_trim = <85>;
-samsung,tmu_default_temp_offset = <50>;
-samsung,tmu_cal_type = <TYPE_ONE_POINT_TRIMMING>;
index 7b43c10..51f72f0 100644 (file)
                        device_type = "cpu";
                        compatible = "arm,cortex-a9";
                        reg = <0xA01>;
+                       clocks = <&clock CLK_ARM_CLK>;
+                       clock-names = "cpu";
                        operating-points-v2 = <&cpu0_opp_table>;
+                       #cooling-cells = <2>; /* min followed by max */
                };
 
                cpu@a02 {
                        device_type = "cpu";
                        compatible = "arm,cortex-a9";
                        reg = <0xA02>;
+                       clocks = <&clock CLK_ARM_CLK>;
+                       clock-names = "cpu";
                        operating-points-v2 = <&cpu0_opp_table>;
+                       #cooling-cells = <2>; /* min followed by max */
                };
 
                cpu@a03 {
                        device_type = "cpu";
                        compatible = "arm,cortex-a9";
                        reg = <0xA03>;
+                       clocks = <&clock CLK_ARM_CLK>;
+                       clock-names = "cpu";
                        operating-points-v2 = <&cpu0_opp_table>;
+                       #cooling-cells = <2>; /* min followed by max */
                };
        };
 
index 5d2f0a0..67f9b45 100644 (file)
                pwm: pwm@12dd0000 {
                        compatible = "samsung,exynos4210-pwm";
                        reg = <0x12DD0000 0x100>;
+                       interrupts = <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>,
+                                    <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
                        samsung,pwm-outputs = <0>, <1>, <2>, <3>;
                        #pwm-cells = <3>;
                };
index 2daf505..da163a4 100644 (file)
                        compatible = "arm,cortex-a15";
                        reg = <1>;
                        clock-frequency = <1700000000>;
+                       clocks = <&clock CLK_ARM_CLK>;
+                       clock-names = "cpu";
+                       clock-latency = <140000>;
+
+                       operating-points = <
+                               1700000 1300000
+                               1600000 1250000
+                               1500000 1225000
+                               1400000 1200000
+                               1300000 1150000
+                               1200000 1125000
+                               1100000 1100000
+                               1000000 1075000
+                                900000 1050000
+                                800000 1025000
+                                700000 1012500
+                                600000 1000000
+                                500000  975000
+                                400000  950000
+                                300000  937500
+                                200000  925000
+                       >;
+                       #cooling-cells = <2>; /* min followed by max */
                };
        };
 
                        interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&clock CLK_TMU>;
                        clock-names = "tmu_apbif";
-                       #include "exynos4412-tmu-sensor-conf.dtsi"
+                       #thermal-sensor-cells = <0>;
                };
 
                sata: sata@122f0000 {
index 20e789e..57fc9c9 100644 (file)
@@ -93,7 +93,7 @@
                        interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&clock CLK_TMU>;
                        clock-names = "tmu_apbif";
-                       #include "exynos4412-tmu-sensor-conf.dtsi"
+                       #thermal-sensor-cells = <0>;
                };
 
                tmu_cpu1: tmu@10064000 {
                        interrupts = <GIC_SPI 183 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&clock CLK_TMU>;
                        clock-names = "tmu_apbif";
-                       #include "exynos4412-tmu-sensor-conf.dtsi"
+                       #thermal-sensor-cells = <0>;
                };
 
                tmu_cpu2: tmu@10068000 {
                        interrupts = <GIC_SPI 184 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&clock CLK_TMU>;
                        clock-names = "tmu_apbif";
-                       #include "exynos4412-tmu-sensor-conf.dtsi"
+                       #thermal-sensor-cells = <0>;
                };
 
                tmu_cpu3: tmu@1006c000 {
                        interrupts = <GIC_SPI 185 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&clock CLK_TMU>;
                        clock-names = "tmu_apbif";
-                       #include "exynos4412-tmu-sensor-conf.dtsi"
+                       #thermal-sensor-cells = <0>;
                };
 
                mmc_0: mmc@12200000 {
index a8e4494..0ee6e92 100644 (file)
@@ -38,6 +38,7 @@
                        device_type = "cpu";
                        compatible = "arm,cortex-a15";
                        reg = <0x1>;
+                       clocks = <&clock CLK_ARM_CLK>;
                        clock-frequency = <1800000000>;
                        cci-control-port = <&cci_control1>;
                        operating-points-v2 = <&cluster_a15_opp_table>;
@@ -49,6 +50,7 @@
                        device_type = "cpu";
                        compatible = "arm,cortex-a15";
                        reg = <0x2>;
+                       clocks = <&clock CLK_ARM_CLK>;
                        clock-frequency = <1800000000>;
                        cci-control-port = <&cci_control1>;
                        operating-points-v2 = <&cluster_a15_opp_table>;
@@ -60,6 +62,7 @@
                        device_type = "cpu";
                        compatible = "arm,cortex-a15";
                        reg = <0x3>;
+                       clocks = <&clock CLK_ARM_CLK>;
                        clock-frequency = <1800000000>;
                        cci-control-port = <&cci_control1>;
                        operating-points-v2 = <&cluster_a15_opp_table>;
@@ -83,6 +86,7 @@
                        device_type = "cpu";
                        compatible = "arm,cortex-a7";
                        reg = <0x101>;
+                       clocks = <&clock CLK_KFC_CLK>;
                        clock-frequency = <1000000000>;
                        cci-control-port = <&cci_control0>;
                        operating-points-v2 = <&cluster_a7_opp_table>;
@@ -94,6 +98,7 @@
                        device_type = "cpu";
                        compatible = "arm,cortex-a7";
                        reg = <0x102>;
+                       clocks = <&clock CLK_KFC_CLK>;
                        clock-frequency = <1000000000>;
                        cci-control-port = <&cci_control0>;
                        operating-points-v2 = <&cluster_a7_opp_table>;
                        device_type = "cpu";
                        compatible = "arm,cortex-a7";
                        reg = <0x103>;
+                       clocks = <&clock CLK_KFC_CLK>;
                        clock-frequency = <1000000000>;
                        cci-control-port = <&cci_control0>;
                        operating-points-v2 = <&cluster_a7_opp_table>;
diff --git a/arch/arm/boot/dts/exynos5420-tmu-sensor-conf.dtsi b/arch/arm/boot/dts/exynos5420-tmu-sensor-conf.dtsi
deleted file mode 100644 (file)
index fbc77cb..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Device tree sources for Exynos5420 TMU sensor configuration
- *
- * Copyright (c) 2014 Lukasz Majewski <l.majewski@samsung.com>
- * Copyright (c) 2017 Krzysztof Kozlowski <krzk@kernel.org>
- */
-
-#include <dt-bindings/thermal/thermal_exynos.h>
-
-#thermal-sensor-cells = <0>;
-samsung,tmu_gain = <8>;
-samsung,tmu_reference_voltage = <16>;
-samsung,tmu_noise_cancel_mode = <4>;
-samsung,tmu_efuse_value = <55>;
-samsung,tmu_min_efuse_value = <0>;
-samsung,tmu_max_efuse_value = <100>;
-samsung,tmu_first_point_trim = <25>;
-samsung,tmu_second_point_trim = <85>;
-samsung,tmu_default_temp_offset = <50>;
-samsung,tmu_cal_type = <TYPE_ONE_POINT_TRIMMING>;
index f4e8c58..aaff158 100644 (file)
                        interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&clock CLK_TMU>;
                        clock-names = "tmu_apbif";
-                       #include "exynos5420-tmu-sensor-conf.dtsi"
+                       #thermal-sensor-cells = <0>;
                };
 
                tmu_cpu1: tmu@10064000 {
                        interrupts = <GIC_SPI 183 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&clock CLK_TMU>;
                        clock-names = "tmu_apbif";
-                       #include "exynos5420-tmu-sensor-conf.dtsi"
+                       #thermal-sensor-cells = <0>;
                };
 
                tmu_cpu2: tmu@10068000 {
                        interrupts = <GIC_SPI 184 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&clock CLK_TMU>, <&clock CLK_TMU>;
                        clock-names = "tmu_apbif", "tmu_triminfo_apbif";
-                       #include "exynos5420-tmu-sensor-conf.dtsi"
+                       #thermal-sensor-cells = <0>;
                };
 
                tmu_cpu3: tmu@1006c000 {
                        interrupts = <GIC_SPI 185 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&clock CLK_TMU>, <&clock CLK_TMU_GPU>;
                        clock-names = "tmu_apbif", "tmu_triminfo_apbif";
-                       #include "exynos5420-tmu-sensor-conf.dtsi"
+                       #thermal-sensor-cells = <0>;
                };
 
                tmu_gpu: tmu@100a0000 {
                        interrupts = <GIC_SPI 215 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&clock CLK_TMU_GPU>, <&clock CLK_TMU>;
                        clock-names = "tmu_apbif", "tmu_triminfo_apbif";
-                       #include "exynos5420-tmu-sensor-conf.dtsi"
+                       #thermal-sensor-cells = <0>;
                };
 
                sysmmu_g2dr: sysmmu@10a60000 {
index 7c130a0..e4a5857 100644 (file)
@@ -37,6 +37,7 @@
                        device_type = "cpu";
                        compatible = "arm,cortex-a7";
                        reg = <0x101>;
+                       clocks = <&clock CLK_KFC_CLK>;
                        clock-frequency = <1000000000>;
                        cci-control-port = <&cci_control0>;
                        operating-points-v2 = <&cluster_a7_opp_table>;
@@ -48,6 +49,7 @@
                        device_type = "cpu";
                        compatible = "arm,cortex-a7";
                        reg = <0x102>;
+                       clocks = <&clock CLK_KFC_CLK>;
                        clock-frequency = <1000000000>;
                        cci-control-port = <&cci_control0>;
                        operating-points-v2 = <&cluster_a7_opp_table>;
@@ -59,6 +61,7 @@
                        device_type = "cpu";
                        compatible = "arm,cortex-a7";
                        reg = <0x103>;
+                       clocks = <&clock CLK_KFC_CLK>;
                        clock-frequency = <1000000000>;
                        cci-control-port = <&cci_control0>;
                        operating-points-v2 = <&cluster_a7_opp_table>;
@@ -69,8 +72,8 @@
                cpu4: cpu@0 {
                        device_type = "cpu";
                        compatible = "arm,cortex-a15";
-                       clocks = <&clock CLK_ARM_CLK>;
                        reg = <0x0>;
+                       clocks = <&clock CLK_ARM_CLK>;
                        clock-frequency = <1800000000>;
                        cci-control-port = <&cci_control1>;
                        operating-points-v2 = <&cluster_a15_opp_table>;
@@ -82,6 +85,7 @@
                        device_type = "cpu";
                        compatible = "arm,cortex-a15";
                        reg = <0x1>;
+                       clocks = <&clock CLK_ARM_CLK>;
                        clock-frequency = <1800000000>;
                        cci-control-port = <&cci_control1>;
                        operating-points-v2 = <&cluster_a15_opp_table>;
@@ -93,6 +97,7 @@
                        device_type = "cpu";
                        compatible = "arm,cortex-a15";
                        reg = <0x2>;
+                       clocks = <&clock CLK_ARM_CLK>;
                        clock-frequency = <1800000000>;
                        cci-control-port = <&cci_control1>;
                        operating-points-v2 = <&cluster_a15_opp_table>;
                        device_type = "cpu";
                        compatible = "arm,cortex-a15";
                        reg = <0x3>;
+                       clocks = <&clock CLK_ARM_CLK>;
                        clock-frequency = <1800000000>;
                        cci-control-port = <&cci_control1>;
                        operating-points-v2 = <&cluster_a15_opp_table>;
diff --git a/arch/arm/boot/dts/gemini-sl93512r.dts b/arch/arm/boot/dts/gemini-sl93512r.dts
new file mode 100644 (file)
index 0000000..ebefb72
--- /dev/null
@@ -0,0 +1,328 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Device Tree file for the Storm Semiconductor SL93512R_BRD
+ * Gemini reference design, also initially called
+ * "Gemini324 EV-Board" before Storm acquired Storlink Semiconductor.
+ * The series were later acquired by Cortina Systems.
+ */
+
+/dts-v1/;
+
+#include "gemini.dtsi"
+#include <dt-bindings/input/input.h>
+
+/ {
+       model = "Storlink Semiconductor Gemini324 EV-Board / Storm Semiconductor SL93512R_BRD";
+       compatible = "storlink,gemini324", "storm,sl93512r", "cortina,gemini";
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       memory@0 {
+               /* 64 MB Samsung K4H511638B */
+               device_type = "memory";
+               reg = <0x00000000 0x4000000>;
+       };
+
+       chosen {
+               bootargs = "console=ttyS0,19200n8 root=/dev/sda1 rw rootwait";
+               stdout-path = &uart0;
+       };
+
+       gpio_keys {
+               compatible = "gpio-keys";
+
+               button-wps {
+                       debounce-interval = <50>;
+                       wakeup-source;
+                       linux,code = <KEY_WPS_BUTTON>;
+                       label = "WPS";
+                       /* Conflict with NAND flash */
+                       gpios = <&gpio0 17 GPIO_ACTIVE_LOW>;
+               };
+
+               button-setup {
+                       debounce-interval = <50>;
+                       wakeup-source;
+                       linux,code = <KEY_SETUP>;
+                       label = "factory reset";
+                       /* Conflict with NAND flash */
+                       gpios = <&gpio0 18 GPIO_ACTIVE_LOW>;
+               };
+       };
+
+       leds {
+               compatible = "gpio-leds";
+               led-green-harddisk {
+                       label = "sq201:green:harddisk";
+                       /* Conflict with LCD (no problem) */
+                       gpios = <&gpio0 16 GPIO_ACTIVE_LOW>;
+                       default-state = "off";
+                       linux,default-trigger = "disk-activity";
+               };
+               led-green-wireless {
+                       label = "sq201:green:wireless";
+                       /* Conflict with NAND flash CE0 (no problem) */
+                       gpios = <&gpio0 17 GPIO_ACTIVE_LOW>;
+                       default-state = "on";
+                       linux,default-trigger = "heartbeat";
+               };
+       };
+
+       mdio0: mdio {
+               compatible = "virtual,mdio-gpio";
+               /* Uses MDC and MDIO */
+               gpios = <&gpio0 22 GPIO_ACTIVE_HIGH>, /* MDC */
+                       <&gpio0 21 GPIO_ACTIVE_HIGH>; /* MDIO */
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               /* This is a Marvell 88E1111 ethernet transciever */
+               phy0: ethernet-phy@1 {
+                       reg = <1>;
+               };
+       };
+
+       spi {
+               compatible = "spi-gpio";
+               #address-cells = <1>;
+               #size-cells = <0>;
+               /* Check pin collisions */
+               gpio-sck = <&gpio1 28 GPIO_ACTIVE_HIGH>;
+               gpio-miso = <&gpio1 30 GPIO_ACTIVE_HIGH>;
+               gpio-mosi = <&gpio1 29 GPIO_ACTIVE_HIGH>;
+               cs-gpios = <&gpio1 31 GPIO_ACTIVE_HIGH>;
+               num-chipselects = <1>;
+
+               switch@0 {
+                       compatible = "vitesse,vsc7385";
+                       reg = <0>;
+                       /* Specified for 2.5 MHz or below */
+                       spi-max-frequency = <2500000>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       ports {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+
+                               port@0 {
+                                       reg = <0>;
+                                       label = "lan1";
+                               };
+                               port@1 {
+                                       reg = <1>;
+                                       label = "lan2";
+                               };
+                               port@2 {
+                                       reg = <2>;
+                                       label = "lan3";
+                               };
+                               port@3 {
+                                       reg = <3>;
+                                       label = "lan4";
+                               };
+                               vsc: port@6 {
+                                       reg = <6>;
+                                       label = "cpu";
+                                       ethernet = <&gmac1>;
+                                       phy-mode = "rgmii";
+                                       fixed-link {
+                                               speed = <1000>;
+                                               full-duplex;
+                                               pause;
+                                       };
+                               };
+                       };
+               };
+       };
+
+
+       soc {
+               flash@30000000 {
+                       status = "okay";
+                       /* 16MB of flash */
+                       reg = <0x30000000 0x01000000>;
+
+                       partition@0 {
+                               label = "BOOT";
+                               reg = <0x00000000 0x00020000>;
+                               read-only;
+                       };
+                       partition@120000 {
+                               label = "Kern";
+                               reg = <0x00020000 0x00300000>;
+                       };
+                       partition@320000 {
+                               label = "Ramdisk";
+                               reg = <0x00320000 0x00600000>;
+                       };
+                       partition@920000 {
+                               label = "Application";
+                               reg = <0x00920000 0x00600000>;
+                       };
+                       partition@f20000 {
+                               label = "VCTL";
+                               reg = <0x00f20000 0x00020000>;
+                               read-only;
+                       };
+                       partition@f40000 {
+                               label = "CurConf";
+                               reg = <0x00f40000 0x000a0000>;
+                               read-only;
+                       };
+                       partition@fe0000 {
+                               label = "FIS directory";
+                               reg = <0x00fe0000 0x00020000>;
+                               read-only;
+                       };
+               };
+
+               syscon: syscon@40000000 {
+                       pinctrl {
+                               /*
+                                * gpio0egrp cover line 16 used by HD LED
+                                * gpio0fgrp cover line 17, 18 used by wireless LED and reset button
+                                * gpio0hgrp cover line 21, 22 used by MDIO for Marvell PHY
+                                * gpio0kgrp cover line 31 used by USB LED
+                                */
+                               gpio0_default_pins: pinctrl-gpio0 {
+                                       mux {
+                                               function = "gpio0";
+                                               groups = "gpio0egrp",
+                                               "gpio0fgrp",
+                                               "gpio0hgrp";
+                                       };
+                               };
+                               /*
+                                * gpio1dgrp cover lines used by SPI for
+                                * the Vitesse chip (28-31)
+                                */
+                               gpio1_default_pins: pinctrl-gpio1 {
+                                       mux {
+                                               function = "gpio1";
+                                               groups = "gpio1dgrp";
+                                       };
+                               };
+                               pinctrl-gmii {
+                                       mux {
+                                               function = "gmii";
+                                               groups = "gmii_gmac0_grp", "gmii_gmac1_grp";
+                                       };
+                                       /* Control pad skew comes from sl_switch.c in the vendor code */
+                                       conf0 {
+                                               pins = "P10 GMAC1 TXC";
+                                               skew-delay = <5>;
+                                       };
+                                       conf1 {
+                                               pins = "V11 GMAC1 TXEN";
+                                               skew-delay = <7>;
+                                       };
+                                       conf2 {
+                                               pins = "T11 GMAC1 RXC";
+                                               skew-delay = <8>;
+                                       };
+                                       conf3 {
+                                               pins = "U11 GMAC1 RXDV";
+                                               skew-delay = <7>;
+                                       };
+                                       conf4 {
+                                               pins = "V7 GMAC0 TXC";
+                                               skew-delay = <10>;
+                                       };
+                                       conf5 {
+                                               pins = "P8 GMAC0 TXEN";
+                                               skew-delay = <7>; /* 5 at another place? */
+                                       };
+                                       conf6 {
+                                               pins = "T8 GMAC0 RXC";
+                                               skew-delay = <15>;
+                                       };
+                                       conf7 {
+                                               pins = "R8 GMAC0 RXDV";
+                                               skew-delay = <0>;
+                                       };
+                                       conf8 {
+                                               /* The data lines all have default skew */
+                                               pins = "U8 GMAC0 RXD0", "V8 GMAC0 RXD1",
+                                                      "P9 GMAC0 RXD2", "R9 GMAC0 RXD3",
+                                                      "R11 GMAC1 RXD0", "P11 GMAC1 RXD1",
+                                                      "V12 GMAC1 RXD2", "U12 GMAC1 RXD3",
+                                                      "R10 GMAC1 TXD0", "T10 GMAC1 TXD1",
+                                                      "U10 GMAC1 TXD2", "V10 GMAC1 TXD3";
+                                               skew-delay = <7>;
+                                       };
+                                       /* Appears in sl351x_gmac.c in the vendor code */
+                                       conf9 {
+                                               pins = "U7 GMAC0 TXD0", "T7 GMAC0 TXD1",
+                                                      "R7 GMAC0 TXD2", "P7 GMAC0 TXD3";
+                                               skew-delay = <5>;
+                                       };
+                               };
+                       };
+               };
+
+               /* Both interfaces brought out on SATA connectors */
+               sata: sata@46000000 {
+                       cortina,gemini-ata-muxmode = <0>;
+                       cortina,gemini-enable-sata-bridge;
+                       status = "okay";
+               };
+
+               gpio0: gpio@4d000000 {
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&gpio0_default_pins>;
+               };
+
+               gpio1: gpio@4e000000 {
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&gpio1_default_pins>;
+               };
+
+               pci@50000000 {
+                       status = "okay";
+                       interrupt-map-mask = <0xf800 0 0 7>;
+                       interrupt-map =
+                               <0x4800 0 0 1 &pci_intc 0>, /* Slot 9 */
+                               <0x4800 0 0 2 &pci_intc 1>,
+                               <0x4800 0 0 3 &pci_intc 2>,
+                               <0x4800 0 0 4 &pci_intc 3>,
+                               <0x5000 0 0 1 &pci_intc 1>, /* Slot 10 */
+                               <0x5000 0 0 2 &pci_intc 2>,
+                               <0x5000 0 0 3 &pci_intc 3>,
+                               <0x5000 0 0 4 &pci_intc 0>,
+                               <0x5800 0 0 1 &pci_intc 2>, /* Slot 11 */
+                               <0x5800 0 0 2 &pci_intc 3>,
+                               <0x5800 0 0 3 &pci_intc 0>,
+                               <0x5800 0 0 4 &pci_intc 1>,
+                               <0x6000 0 0 1 &pci_intc 3>, /* Slot 12 */
+                               <0x6000 0 0 2 &pci_intc 0>,
+                               <0x6000 0 0 3 &pci_intc 1>,
+                               <0x6000 0 0 4 &pci_intc 2>;
+               };
+
+               ethernet@60000000 {
+                       status = "okay";
+
+                       ethernet-port@0 {
+                               phy-mode = "rgmii";
+                               phy-handle = <&phy0>;
+                       };
+                       ethernet-port@1 {
+                               phy-mode = "rgmii";
+                               fixed-link {
+                                       speed = <1000>;
+                                       full-duplex;
+                                       pause;
+                               };
+                       };
+               };
+
+               ata@63000000 {
+                       status = "okay";
+               };
+
+               ata@63400000 {
+                       status = "okay";
+               };
+       };
+};
index e5cf9d1..3787cf3 100644 (file)
                };
        };
 
+       mdio0: mdio {
+               compatible = "virtual,mdio-gpio";
+               /* Uses MDC and MDIO */
+               gpios = <&gpio0 22 GPIO_ACTIVE_HIGH>, /* MDC */
+                       <&gpio0 21 GPIO_ACTIVE_HIGH>; /* MDIO */
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               /* This is a Marvell 88E1111 ethernet transciever */
+               phy0: ethernet-phy@1 {
+                       reg = <1>;
+               };
+       };
+
+       spi {
+               compatible = "spi-gpio";
+               #address-cells = <1>;
+               #size-cells = <0>;
+               /* Check pin collisions */
+               gpio-sck = <&gpio1 28 GPIO_ACTIVE_HIGH>;
+               gpio-miso = <&gpio1 30 GPIO_ACTIVE_HIGH>;
+               gpio-mosi = <&gpio1 29 GPIO_ACTIVE_HIGH>;
+               cs-gpios = <&gpio1 31 GPIO_ACTIVE_HIGH>;
+               num-chipselects = <1>;
+
+               switch@0 {
+                       compatible = "vitesse,vsc7395";
+                       reg = <0>;
+                       /* Specified for 2.5 MHz or below */
+                       spi-max-frequency = <2500000>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       ports {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+
+                               port@0 {
+                                       reg = <0>;
+                                       label = "lan1";
+                               };
+                               port@1 {
+                                       reg = <1>;
+                                       label = "lan2";
+                               };
+                               port@2 {
+                                       reg = <2>;
+                                       label = "lan3";
+                               };
+                               port@3 {
+                                       reg = <3>;
+                                       label = "lan4";
+                               };
+                               vsc: port@6 {
+                                       reg = <6>;
+                                       label = "cpu";
+                                       ethernet = <&gmac1>;
+                                       phy-mode = "rgmii";
+                                       fixed-link {
+                                               speed = <1000>;
+                                               full-duplex;
+                                               pause;
+                                       };
+                               };
+                       };
+               };
+       };
+
+
        soc {
                flash@30000000 {
                        /*
                                /*
                                 * gpio0fgrp cover line 18 used by reset button
                                 * gpio0ggrp cover line 20 used by info LED
+                                * gpio0hgrp cover line 21, 22 used by MDIO for Marvell PHY
                                 * gpio0kgrp cover line 31 used by USB LED
                                 */
                                gpio0_default_pins: pinctrl-gpio0 {
                                                function = "gpio0";
                                                groups = "gpio0fgrp",
                                                "gpio0ggrp",
+                                               "gpio0hgrp",
                                                "gpio0kgrp";
                                        };
                                };
+                               /*
+                                * gpio0dgrp cover lines used by the SPI
+                                * to the Vitesse G5x chip.
+                                */
+                               gpio1_default_pins: pinctrl-gpio1 {
+                                       mux {
+                                               function = "gpio1";
+                                               groups = "gpio1dgrp";
+                                       };
+                               };
+                               pinctrl-gmii {
+                                       mux {
+                                               function = "gmii";
+                                               groups = "gmii_gmac0_grp", "gmii_gmac1_grp";
+                                       };
+                                       /* Settings come from memory dump in PLATO */
+                                       conf0 {
+                                               pins = "V8 GMAC0 RXDV";
+                                               skew-delay = <0>;
+                                       };
+                                       conf1 {
+                                               pins = "Y7 GMAC0 RXC";
+                                               skew-delay = <15>;
+                                       };
+                                       conf2 {
+                                               pins = "T8 GMAC0 TXEN";
+                                               skew-delay = <7>;
+                                       };
+                                       conf3 {
+                                               pins = "U8 GMAC0 TXC";
+                                               skew-delay = <10>;
+                                       };
+                                       conf4 {
+                                               pins = "T10 GMAC1 RXDV";
+                                               skew-delay = <7>;
+                                       };
+                                       conf5 {
+                                               pins = "Y11 GMAC1 RXC";
+                                               skew-delay = <8>;
+                                       };
+                                       conf6 {
+                                               pins = "W11 GMAC1 TXEN";
+                                               skew-delay = <7>;
+                                       };
+                                       conf7 {
+                                               pins = "V11 GMAC1 TXC";
+                                               skew-delay = <5>;
+                                       };
+                                       conf8 {
+                                               /* The data lines all have default skew */
+                                               pins = "W8 GMAC0 RXD0", "V9 GMAC0 RXD1",
+                                                      "Y8 GMAC0 RXD2", "U9 GMAC0 RXD3",
+                                                      "T7 GMAC0 TXD0", "U6 GMAC0 TXD1",
+                                                      "V7 GMAC0 TXD2", "U7 GMAC0 TXD3",
+                                                      "Y12 GMAC1 RXD0", "V12 GMAC1 RXD1",
+                                                      "T11 GMAC1 RXD2", "W12 GMAC1 RXD3",
+                                                      "U10 GMAC1 TXD0", "Y10 GMAC1 TXD1",
+                                                      "W10 GMAC1 TXD2", "T9 GMAC1 TXD3";
+                                               skew-delay = <7>;
+                                       };
+                                       /* Set up drive strength on GMAC0 and GMAC1 to 16 mA */
+                                       conf9 {
+                                               groups = "gmii_gmac0_grp", "gmii_gmac1_grp";
+                                               drive-strength = <16>;
+                                       };
+                               };
                        };
                };
 
                        pinctrl-0 = <&gpio0_default_pins>;
                };
 
+               gpio1: gpio@4e000000 {
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&gpio1_default_pins>;
+               };
+
                pci@50000000 {
                        status = "okay";
                        interrupt-map-mask = <0xf800 0 0 7>;
                                <0x6000 0 0 4 &pci_intc 2>;
                };
 
+               ethernet@60000000 {
+                       status = "okay";
+
+                       ethernet-port@0 {
+                               phy-mode = "rgmii";
+                               phy-handle = <&phy0>;
+                       };
+                       ethernet-port@1 {
+                               phy-mode = "rgmii";
+                               fixed-link {
+                                       speed = <1000>;
+                                       full-duplex;
+                                       pause;
+                               };
+                       };
+               };
+
                ata@63000000 {
                        status = "okay";
                };
diff --git a/arch/arm/boot/dts/gr-peach-audiocamerashield.dtsi b/arch/arm/boot/dts/gr-peach-audiocamerashield.dtsi
new file mode 100644 (file)
index 0000000..e31a9e3
--- /dev/null
@@ -0,0 +1,79 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Device Tree Source for the GR-Peach audiocamera shield expansion board
+ *
+ * Copyright (C) 2017 Jacopo Mondi <jacopo+renesas@jmondi.org>
+ */
+
+#include "r7s72100.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/pinctrl/r7s72100-pinctrl.h>
+
+/ {
+       /* On-board camera clock. */
+       camera_clk: camera_clk {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <27000000>;
+       };
+};
+
+&pinctrl {
+       i2c1_pins: i2c1 {
+               /* P1_2 as SCL; P1_3 as SDA */
+               pinmux = <RZA1_PINMUX(1, 2, 1)>, <RZA1_PINMUX(1, 3, 1)>;
+       };
+
+       vio_pins: vio {
+               /* CEU pins: VIO_D[0-10], VIO_VD, VIO_HD, VIO_CLK */
+               pinmux = <RZA1_PINMUX(1, 0, 5)>, /* VIO_VD */
+                        <RZA1_PINMUX(1, 1, 5)>, /* VIO_HD */
+                        <RZA1_PINMUX(2, 0, 7)>, /* VIO_D0 */
+                        <RZA1_PINMUX(2, 1, 7)>, /* VIO_D1 */
+                        <RZA1_PINMUX(2, 2, 7)>, /* VIO_D2 */
+                        <RZA1_PINMUX(2, 3, 7)>, /* VIO_D3 */
+                        <RZA1_PINMUX(2, 4, 7)>, /* VIO_D4 */
+                        <RZA1_PINMUX(2, 5, 7)>, /* VIO_D5 */
+                        <RZA1_PINMUX(2, 6, 7)>, /* VIO_D6 */
+                        <RZA1_PINMUX(2, 7, 7)>, /* VIO_D7 */
+                        <RZA1_PINMUX(10, 0, 6)>; /* VIO_CLK */
+       };
+};
+
+&i2c1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&i2c1_pins>;
+
+       status = "okay";
+       clock-frequency = <100000>;
+
+       camera@48 {
+               compatible = "aptina,mt9v111";
+               reg = <0x48>;
+
+               clocks = <&camera_clk>;
+
+               port {
+                       mt9v111_out: endpoint {
+                               remote-endpoint = <&ceu_in>;
+                       };
+               };
+       };
+};
+
+&ceu {
+       pinctrl-names = "default";
+       pinctrl-0 = <&vio_pins>;
+
+       status = "okay";
+
+       port {
+               ceu_in: endpoint {
+                       hsync-active = <1>;
+                       vsync-active = <1>;
+                       bus-width = <8>;
+                       pclk-sample = <1>;
+                       remote-endpoint = <&mt9v111_out>;
+               };
+       };
+};
index ed14aea..5027871 100644 (file)
                        next-level-cache = <&L2>;
                        clocks = <&a9pll>;
                        clock-names = "cpu";
+                       operating-points = <
+                               /* kHz    ignored */
+                                1300000  1000000
+                                1200000  1000000
+                                1100000  1000000
+                                 800000  1000000
+                                 400000  1000000
+                                 200000  1000000
+                       >;
+                       clock-latency = <100000>;
                };
 
                cpu@902 {
                        next-level-cache = <&L2>;
                        clocks = <&a9pll>;
                        clock-names = "cpu";
+                       operating-points = <
+                               /* kHz    ignored */
+                                1300000  1000000
+                                1200000  1000000
+                                1100000  1000000
+                                 800000  1000000
+                                 400000  1000000
+                                 200000  1000000
+                       >;
+                       clock-latency = <100000>;
                };
 
                cpu@903 {
                        next-level-cache = <&L2>;
                        clocks = <&a9pll>;
                        clock-names = "cpu";
+                       operating-points = <
+                               /* kHz    ignored */
+                                1300000  1000000
+                                1200000  1000000
+                                1100000  1000000
+                                 800000  1000000
+                                 400000  1000000
+                                 200000  1000000
+                       >;
+                       clock-latency = <100000>;
                };
        };
 
diff --git a/arch/arm/boot/dts/imx31-lite.dts b/arch/arm/boot/dts/imx31-lite.dts
new file mode 100644 (file)
index 0000000..db52ddc
--- /dev/null
@@ -0,0 +1,177 @@
+// SPDX-License-Identifier: GPL-2.0+
+//
+// Copyright (C) 2016-2018 Vladimir Zapolskiy <vz@mleia.com>
+
+/dts-v1/;
+
+#include "imx31.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
+/ {
+       model = "LogicPD i.MX31 Lite";
+       compatible = "logicpd,imx31-lite", "fsl,imx31";
+
+       chosen {
+               stdout-path = &uart1;
+       };
+
+       memory@80000000 {
+               reg = <0x80000000 0x8000000>;
+       };
+
+       leds {
+               compatible = "gpio-leds";
+
+               led0 {
+                       gpios = <&gpio1 8 GPIO_ACTIVE_LOW>;
+               };
+
+               led1 {
+                       gpios = <&gpio1 7 GPIO_ACTIVE_LOW>;
+               };
+       };
+};
+
+&ata {
+       status = "okay";
+};
+
+&nfc {
+       nand-bus-width = <8>;
+       nand-ecc-mode = "hw";
+       nand-on-flash-bbt;
+       status = "okay";
+};
+
+&sdhci1 {
+       bus-width = <4>;
+       cd-gpios = <&gpio2 11 GPIO_ACTIVE_HIGH>;
+       wp-gpios = <&gpio1 6 GPIO_ACTIVE_HIGH>;
+       status = "okay";
+};
+
+&spi2 {
+       status = "okay";
+
+       pmic@0 {
+               compatible = "fsl,mc13783";
+               reg = <0>;
+               spi-cs-high;
+               spi-max-frequency = <1000000>;
+               interrupt-parent = <&gpio1>;
+               interrupts = <3 IRQ_TYPE_EDGE_RISING>;
+
+               fsl,mc13xxx-uses-adc;
+               fsl,mc13xxx-uses-rtc;
+
+               regulators {
+                       sw1a {          /* QVCC */
+                               regulator-min-microvolt = <1200000>;
+                               regulator-max-microvolt = <1500000>;
+                               regulator-always-on;
+                               regulator-boot-on;
+                       };
+
+                       sw1b {          /* QVCC */
+                               regulator-min-microvolt = <1200000>;
+                               regulator-max-microvolt = <1500000>;
+                               regulator-always-on;
+                               regulator-boot-on;
+                       };
+
+                       sw2a {          /* 1.8V_DDR, NVCC2, NVCC21 and NVCC22 */
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                               regulator-always-on;
+                               regulator-boot-on;
+                       };
+
+                       sw2b {          /* NVCC10 */
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                               regulator-always-on;
+                               regulator-boot-on;
+                       };
+
+                       violo {         /* NVCC1 and NVCC7 */
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                               regulator-always-on;
+                               regulator-boot-on;
+                       };
+
+                       viohi {         /* VIOHI */
+                               regulator-min-microvolt = <2775000>;
+                               regulator-max-microvolt = <2775000>;
+                               regulator-always-on;
+                               regulator-boot-on;
+                       };
+
+                       vaudio {        /* VAUDIO */
+                               regulator-min-microvolt = <2775000>;
+                               regulator-max-microvolt = <2775000>;
+                       };
+
+                       vcam {          /* NVCC4 */
+                               regulator-min-microvolt = <2800000>;
+                               regulator-max-microvolt = <2800000>;
+                       };
+
+                       vgen {          /* NVCC5 / NVCC8 and NVCC6 / NVCC9 */
+                               regulator-min-microvolt = <2775000>;
+                               regulator-max-microvolt = <2775000>;
+                               regulator-always-on;
+                               regulator-boot-on;
+                       };
+
+                       vmmc2 {         /* NVCC3 */
+                               regulator-min-microvolt = <1600000>;
+                               regulator-max-microvolt = <3000000>;
+                               regulator-always-on;
+                               regulator-boot-on;
+                       };
+               };
+       };
+};
+
+&uart1 {
+       uart-has-rtscts;
+       status = "okay";
+};
+
+/* Routed to the extension board */
+&uart2 {
+       uart-has-rtscts;
+       status = "okay";
+};
+
+/* Routed to the extension board */
+&uart3 {
+       uart-has-rtscts;
+       status = "okay";
+};
+
+&weim {
+       status = "okay";
+
+       nor@0,0 {
+               compatible = "cfi-flash";
+               reg = <0 0x0 0x200000>;
+               bank-width = <2>;
+               linux,mtd-name = "physmap-flash.0";
+               fsl,weim-cs-timing = <0x0000cf03 0xa0330d01 0x00220800>;
+       };
+
+       ethernet@4,0 {
+               compatible = "smsc,lan9117", "smsc,lan9115";
+               reg = <4 0x0 0x100>;
+               interrupt-parent = <&gpio1>;
+               interrupts = <26 IRQ_TYPE_EDGE_FALLING>;
+               phy-mode = "mii";
+               reg-io-width = <2>;
+               smsc,irq-push-pull;
+               fsl,weim-cs-timing = <0x00008701 0x04000541 0x00010000>;
+       };
+};
index 4642c81..ca1419c 100644 (file)
@@ -1,5 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0+
 //
+// Copyright 2016-2018 Vladimir Zapolskiy <vz@mleia.com>
 // Copyright 2012 Denis 'GNUtoo' Carikli <GNUtoo@no-log.org>
 
 / {
        memory { device_type = "memory"; };
 
        aliases {
+               gpio0 = &gpio1;
+               gpio1 = &gpio2;
+               gpio2 = &gpio3;
+               i2c0 = &i2c1;
+               i2c1 = &i2c2;
+               i2c2 = &i2c3;
                serial0 = &uart1;
                serial1 = &uart2;
                serial2 = &uart3;
                serial3 = &uart4;
                serial4 = &uart5;
+               spi0 = &spi1;
+               spi1 = &spi2;
+               spi2 = &spi3;
        };
 
        cpus {
                interrupt-parent = <&avic>;
                ranges;
 
+               iram: iram@1fffc000 {
+                       compatible = "mmio-sram";
+                       reg = <0x1fffc000 0x4000>;
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0 0x1fffc000 0x4000>;
+               };
+
                aips@43f00000 { /* AIPS1 */
                        compatible = "fsl,aips-bus", "simple-bus";
                        #address-cells = <1>;
                        reg = <0x43f00000 0x100000>;
                        ranges;
 
+                       i2c1: i2c@43f80000 {
+                               compatible = "fsl,imx31-i2c", "fsl,imx21-i2c";
+                               reg = <0x43f80000 0x4000>;
+                               interrupts = <10>;
+                               clocks = <&clks 33>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               status = "disabled";
+                       };
+
+                       i2c3: i2c@43f84000 {
+                               compatible = "fsl,imx31-i2c", "fsl,imx21-i2c";
+                               reg = <0x43f84000 0x4000>;
+                               interrupts = <3>;
+                               clocks = <&clks 35>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               status = "disabled";
+                       };
+
+                       ata: ata@43f8c000 {
+                               compatible = "fsl,imx31-pata", "fsl,imx27-pata";
+                               reg = <0x43f8c000 0x4000>;
+                               interrupts = <15>;
+                               clocks = <&clks 26>;
+                               status = "disabled";
+                       };
+
                        uart1: serial@43f90000 {
                                compatible = "fsl,imx31-uart", "fsl,imx21-uart";
                                reg = <0x43f90000 0x4000>;
                                status = "disabled";
                        };
 
+                       i2c2: i2c@43f98000 {
+                               compatible = "fsl,imx31-i2c", "fsl,imx21-i2c";
+                               reg = <0x43f98000 0x4000>;
+                               interrupts = <4>;
+                               clocks = <&clks 34>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               status = "disabled";
+                       };
+
+                       spi1: spi@43fa4000 {
+                               compatible = "fsl,imx31-cspi";
+                               reg = <0x43fa4000 0x4000>;
+                               interrupts = <14>;
+                               clocks = <&clks 10>, <&clks 53>;
+                               clock-names = "ipg", "per";
+                               dmas = <&sdma 8 8 0>, <&sdma 9 8 0>;
+                               dma-names = "rx", "tx";
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               status = "disabled";
+                       };
+
                        kpp: kpp@43fa8000 {
                                compatible = "fsl,imx31-kpp", "fsl,imx21-kpp";
                                reg = <0x43fa8000 0x4000>;
                        reg = <0x50000000 0x100000>;
                        ranges;
 
+                       sdhci1: sdhci@50004000 {
+                               compatible = "fsl,imx31-mmc";
+                               reg = <0x50004000 0x4000>;
+                               interrupts = <9>;
+                               clocks = <&clks 10>, <&clks 20>;
+                               clock-names = "ipg", "per";
+                               dmas = <&sdma 20 3 0>;
+                               dma-names = "rx-tx";
+                               status = "disabled";
+                       };
+
+                       sdhci2: sdhci@50008000 {
+                               compatible = "fsl,imx31-mmc";
+                               reg = <0x50008000 0x4000>;
+                               interrupts = <8>;
+                               clocks = <&clks 10>, <&clks 21>;
+                               clock-names = "ipg", "per";
+                               dmas = <&sdma 21 3 0>;
+                               dma-names = "rx-tx";
+                               status = "disabled";
+                       };
+
                        uart3: serial@5000c000 {
                                compatible = "fsl,imx31-uart", "fsl,imx21-uart";
                                reg = <0x5000c000 0x4000>;
                                status = "disabled";
                        };
 
+                       spi2: cspi@50010000 {
+                               compatible = "fsl,imx31-cspi";
+                               reg = <0x50010000 0x4000>;
+                               interrupts = <13>;
+                               clocks = <&clks 10>, <&clks 54>;
+                               clock-names = "ipg", "per";
+                               dmas = <&sdma 6 8 0>, <&sdma 7 8 0>;
+                               dma-names = "rx", "tx";
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               status = "disabled";
+                       };
+
                        iim: iim@5001c000 {
                                compatible = "fsl,imx31-iim", "fsl,imx27-iim";
                                reg = <0x5001c000 0x1000>;
                                #clock-cells = <1>;
                        };
 
+                       spi3: cspi@53f84000 {
+                               compatible = "fsl,imx31-cspi";
+                               reg = <0x53f84000 0x4000>;
+                               interrupts = <17>;
+                               clocks = <&clks 10>, <&clks 28>;
+                               clock-names = "ipg", "per";
+                               dmas = <&sdma 10 8 0>, <&sdma 11 8 0>;
+                               dma-names = "rx", "tx";
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               status = "disabled";
+                       };
+
                        gpt: timer@53f90000 {
                                compatible = "fsl,imx31-gpt";
                                reg = <0x53f90000 0x4000>;
                                clocks = <&clks 10>, <&clks 22>;
                                clock-names = "ipg", "per";
                        };
+
+                       gpio3: gpio@53fa4000 {
+                               compatible = "fsl,imx31-gpio";
+                               reg = <0x53fa4000 0x4000>;
+                               interrupts = <56>;
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               interrupt-controller;
+                               #interrupt-cells = <2>;
+                       };
+
+                       rng@53fb0000 {
+                               compatible = "fsl,imx31-rnga";
+                               reg = <0x53fb0000 0x4000>;
+                               interrupts = <22>;
+                               clocks = <&clks 29>;
+                       };
+
+                       gpio1: gpio@53fcc000 {
+                               compatible = "fsl,imx31-gpio";
+                               reg = <0x53fcc000 0x4000>;
+                               interrupts = <52>;
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               interrupt-controller;
+                               #interrupt-cells = <2>;
+                       };
+
+                       gpio2: gpio@53fd0000 {
+                               compatible = "fsl,imx31-gpio";
+                               reg = <0x53fd0000 0x4000>;
+                               interrupts = <51>;
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               interrupt-controller;
+                               #interrupt-cells = <2>;
+                       };
+
+                       sdma: sdma@53fd4000 {
+                               compatible = "fsl,imx31-sdma";
+                               reg = <0x53fd4000 0x4000>;
+                               interrupts = <34>;
+                               clocks = <&clks 10>, <&clks 27>;
+                               clock-names = "ipg", "ahb";
+                               #dma-cells = <3>;
+                               fsl,sdma-ram-script-name = "imx/sdma/sdma-imx31.bin";
+                       };
+
+                       rtc: rtc@53fd8000 {
+                               compatible = "fsl,imx31-rtc", "fsl,imx21-rtc";
+                               reg = <0x53fd8000 0x4000>;
+                               interrupts = <25>;
+                               clocks = <&clks 2>, <&clks 40>;
+                               clock-names = "ref", "ipg";
+                       };
+
+                       wdog: wdog@53fdc000 {
+                               compatible = "fsl,imx31-wdt", "fsl,imx21-wdt";
+                               reg = <0x53fdc000 0x4000>;
+                               clocks = <&clks 41>;
+                       };
+
+                       pwm: pwm@53fe0000 {
+                               compatible = "fsl,imx31-pwm", "fsl,imx27-pwm";
+                               reg = <0x53fe0000 0x4000>;
+                               interrupts = <26>;
+                               clocks = <&clks 10>, <&clks 42>;
+                               clock-names = "ipg", "per";
+                               #pwm-cells = <2>;
+                               status = "disabled";
+                       };
+               };
+
+               emi@b8000000 { /* External Memory Interface */
+                       compatible = "simple-bus";
+                       reg = <0xb8000000 0x5000>;
+                       ranges;
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+
+                       nfc: nand@b8000000 {
+                               compatible = "fsl,imx31-nand", "fsl,imx27-nand";
+                               reg = <0xb8000000 0x1000>;
+                               interrupts = <33>;
+                               clocks = <&clks 9>;
+                               dmas = <&sdma 30 17 0>;
+                               dma-names = "rx-tx";
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+                               status = "disabled";
+                       };
+
+                       weim: weim@b8002000 {
+                               compatible = "fsl,imx31-weim", "fsl,imx27-weim";
+                               reg = <0xb8002000 0x1000>;
+                               clocks = <&clks 56>;
+                               #address-cells = <2>;
+                               #size-cells = <1>;
+                               ranges = <0 0 0xa0000000 0x08000000
+                                         1 0 0xa8000000 0x08000000
+                                         2 0 0xb0000000 0x02000000
+                                         3 0 0xb2000000 0x02000000
+                                         4 0 0xb4000000 0x02000000
+                                         5 0 0xb6000000 0x02000000>;
+                               status = "disabled";
+                       };
                };
        };
 };
index f0622ec..682a997 100644 (file)
        status = "okay";
 };
 
-&usbh2 {
-       status = "okay";
-};
-
-&usbh3 {
-       status = "okay";
-};
-
 &usbotg {
        status = "okay";
 };
index 97e6e7f..4386334 100644 (file)
@@ -34,7 +34,7 @@
 #define MX50_PAD_KEY_ROW1__EIM_NANDF_CEN_1                     0x02c 0x2d8 0x000 0x2 0x0
 #define MX50_PAD_KEY_ROW1__CTI_TRIGOUT_ACK7                    0x02c 0x2d8 0x000 0x6 0x0
 #define MX50_PAD_KEY_ROW1__USBPHY1_RXERROR                     0x02c 0x2d8 0x000 0x7 0x0
-#define MX50_PAD_KEY_COL2__KPP_COL_1                           0x030 0x2dc 0x000 0x0 0x0
+#define MX50_PAD_KEY_COL2__KPP_COL_2                           0x030 0x2dc 0x000 0x0 0x0
 #define MX50_PAD_KEY_COL2__GPIO4_4                             0x030 0x2dc 0x000 0x1 0x0
 #define MX50_PAD_KEY_COL2__EIM_NANDF_CEN_2                     0x030 0x2dc 0x000 0x2 0x0
 #define MX50_PAD_KEY_COL2__CTI_TRIGOUT6                                0x030 0x2dc 0x000 0x6 0x0
@@ -44,7 +44,7 @@
 #define MX50_PAD_KEY_ROW2__EIM_NANDF_CEN_3                     0x034 0x2e0 0x000 0x2 0x0
 #define MX50_PAD_KEY_ROW2__CTI_TRIGOUT7                                0x034 0x2e0 0x000 0x6 0x0
 #define MX50_PAD_KEY_ROW2__USBPHY1_LINESTATE_0                 0x034 0x2e0 0x000 0x7 0x0
-#define MX50_PAD_KEY_COL3__KPP_COL_2                           0x038 0x2e4 0x000 0x0 0x0
+#define MX50_PAD_KEY_COL3__KPP_COL_3                           0x038 0x2e4 0x000 0x0 0x0
 #define MX50_PAD_KEY_COL3__GPIO4_6                             0x038 0x2e4 0x000 0x1 0x0
 #define MX50_PAD_KEY_COL3__EIM_NANDF_READY0                    0x038 0x2e4 0x7b4 0x2 0x0
 #define MX50_PAD_KEY_COL3__SDMA_EXT_EVENT_0                    0x038 0x2e4 0x7b8 0x6 0x0
index a9b712d..7fae2ff 100644 (file)
                                status = "disabled";
                        };
 
-                       usbh2: usb@53f80400 {
-                               compatible = "fsl,imx50-usb", "fsl,imx27-usb";
-                               reg = <0x53f80400 0x0200>;
-                               interrupts = <16>;
-                               clocks = <&clks IMX5_CLK_USBOH3_GATE>;
-                               dr_mode = "host";
-                               status = "disabled";
-                       };
-
-                       usbh3: usb@53f80600 {
-                               compatible = "fsl,imx50-usb", "fsl,imx27-usb";
-                               reg = <0x53f80600 0x0200>;
-                               interrupts = <17>;
-                               clocks = <&clks IMX5_CLK_USBOH3_GATE>;
-                               dr_mode = "host";
-                               status = "disabled";
-                       };
-
                        gpio1: gpio@53f84000 {
                                compatible = "fsl,imx50-gpio", "fsl,imx35-gpio";
                                reg = <0x53f84000 0x4000>;
index b8ca73d..ba60b0c 100644 (file)
                mux-ext-port = <3>;
        };
 
-       usbphy {
-               #address-cells = <1>;
-               #size-cells = <0>;
-               compatible = "simple-bus";
-
-               usbh1phy: usbh1phy@0 {
-                       compatible = "usb-nop-xceiv";
-                       reg = <0>;
-                       clocks = <&clk_usb>;
-                       clock-names = "main_clk";
-                       reset-gpios = <&gpio2 5 GPIO_ACTIVE_LOW>;
-                       vcc-supply = <&vusb_reg>;
-                       #phy-cells = <0>;
-               };
+       usbphy1: usbphy1 {
+               compatible = "usb-nop-xceiv";
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_usbh1reg>;
+               clocks = <&clk_usb>;
+               clock-names = "main_clk";
+               reset-gpios = <&gpio2 5 GPIO_ACTIVE_LOW>;
+               vcc-supply = <&vusb_reg>;
+               #phy-cells = <0>;
        };
 };
 
        status = "okay";
 };
 
+&pmu {
+       secure-reg-access;
+};
+
 &ssi2 {
        status = "okay";
 };
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_usbh1>;
        vbus-supply = <&reg_hub_reset>;
-       fsl,usbphy = <&usbh1phy>;
+       fsl,usbphy = <&usbphy1>;
        phy_type = "ulpi";
        status = "okay";
 };
index b3d952f..e9e819f 100644 (file)
                fsl,mux-ext-port = <3>;
        };
 
-       usbphy {
-               #address-cells = <1>;
-               #size-cells = <0>;
-               compatible = "simple-bus";
-
-               usbh1phy: usbh1phy@0 {
-                       compatible = "usb-nop-xceiv";
-                       reg = <0>;
-                       clocks = <&clks IMX5_CLK_USB_PHY_GATE>;
-                       clock-names = "main_clk";
-                       clock-frequency = <19200000>;
-                       #phy-cells = <0>;
-               };
+       usbphy1: usbphy1 {
+               compatible = "usb-nop-xceiv";
+               clocks = <&clks IMX5_CLK_USB_PHY_GATE>;
+               clock-names = "main_clk";
+               clock-frequency = <19200000>;
+               #phy-cells = <0>;
        };
 };
 
 &usbh1 {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_usbh1>;
-       fsl,usbphy = <&usbh1phy>;
+       fsl,usbphy = <&usbphy1>;
        dr_mode = "host";
        phy_type = "ulpi";
        status = "okay";
index 8a87868..469cce2 100644 (file)
        status = "okay";
 };
 
+&gpio1 {
+       unused-sd3-wp-gpio {
+               /*
+                * See pinctrl_esdhc1 below for more details on this
+                */
+               gpio-hog;
+               gpios = <1 GPIO_ACTIVE_HIGH>;
+               output-high;
+       };
+};
+
 &i2c2 {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_i2c2>;
 
                rmi4-f11@11 {
                        reg = <0x11>;
-                       touchscreen-inverted-y;
+                       touchscreen-inverted-x;
                        touchscreen-swapped-x-y;
                        syna,sensor-type = <1>;
                };
        remote-endpoint = <&display_in>;
 };
 
+&pmu {
+       secure-reg-access;
+};
+
 &ssi2 {
        status = "okay";
 };
        rave-sp {
                compatible = "zii,rave-sp-rdu1";
                current-speed = <38400>;
+               #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 0x2000>;
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       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";
+               };
+
+               eeprom@ae {
+                       compatible = "zii,rave-sp-eeprom";
+                       reg = <0xae 0x200>;
+                       zii,eeprom-name = "switch-eeprom";
+                       /*
+                        * Not all RDU1s have this functionality, so we
+                        * rely on the bootloader to enable this
+                        */
+                       status = "disabled";
+               };
        };
 };
 
        status = "okay";
 };
 
+&wdog1 {
+       status = "disabled";
+};
+
 &iomuxc {
        pinctrl_ampgpio: ampgpiogrp {
                fsl,pins = <
                        MX51_PAD_SD1_DATA1__SD1_DATA1           0x20d5
                        MX51_PAD_SD1_DATA2__SD1_DATA2           0x20d5
                        MX51_PAD_SD1_DATA3__SD1_DATA3           0x20d5
+                       /*
+                        * GPIO1_1 is not directly used by eSDHC1 in
+                        * any capacity, but earlier versions of RDU1
+                        * used that pin as WP GPIO for eSDHC3 and
+                        * because of that that pad has an external
+                        * pull-up resistor. This is problematic
+                        * because out of reset the pad is configured
+                        * as ALT0 which serves as SD1_WP, which, when
+                        * pulled high by and external pull-up, will
+                        * inhibit execution of any write request to
+                        * attached eMMC device.
+                        *
+                        * To avoid this problem we configure the pad
+                        * to ALT1/GPIO and avoid driving SD1_WP
+                        * signal high.
+                        */
+                       MX51_PAD_GPIO1_1__GPIO1_1               0x0000
                >;
        };
 
diff --git a/arch/arm/boot/dts/imx51-zii-scu2-mezz.dts b/arch/arm/boot/dts/imx51-zii-scu2-mezz.dts
new file mode 100644 (file)
index 0000000..26cf085
--- /dev/null
@@ -0,0 +1,448 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+
+/*
+ * Copyright (C) 2018 Zodiac Inflight Innovations
+ */
+
+/dts-v1/;
+
+#include "imx51.dtsi"
+
+/ {
+       model = "ZII SCU2 Mezz Board";
+       compatible = "zii,imx51-scu2-mezz", "fsl,imx51";
+
+       chosen {
+               stdout-path = &uart1;
+       };
+
+       /* Will be filled by the bootloader */
+       memory@90000000 {
+               reg = <0x90000000 0>;
+       };
+
+       aliases {
+               mdio-gpio0 = &mdio_gpio;
+       };
+
+       usb_vbus: regulator-usb-vbus {
+               compatible = "regulator-fixed";
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_usb_mmc_reset>;
+               gpio = <&gpio3 13 GPIO_ACTIVE_LOW>;
+               startup-delay-us = <150000>;
+               regulator-name = "usb_vbus";
+               regulator-min-microvolt = <5000000>;
+               regulator-max-microvolt = <5000000>;
+       };
+
+       mdio_gpio: mdio-gpio {
+               compatible = "virtual,mdio-gpio";
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_swmdio>;
+               gpios = <&gpio2 7 GPIO_ACTIVE_HIGH>, /* mdc */
+                       <&gpio2 6 GPIO_ACTIVE_HIGH>; /* mdio */
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               switch@0 {
+                       compatible = "marvell,mv88e6085";
+                       reg = <0>;
+                       dsa,member = <0 0>;
+                       eeprom-length = <512>;
+                       interrupt-parent = <&gpio1>;
+                       interrupts = <7 IRQ_TYPE_LEVEL_LOW>;
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+
+                       ports {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+
+                               port@0 {
+                                       reg = <0>;
+                                       label = "port4";
+                               };
+
+                               port@1 {
+                                       reg = <1>;
+                                       label = "port5";
+                               };
+
+                               port@2 {
+                                       reg = <2>;
+                                       label = "port6";
+                               };
+
+                               port@3 {
+                                       reg = <3>;
+                                       label = "port7";
+                               };
+
+                               port@4 {
+                                       reg = <4>;
+                                       label = "cpu";
+                                       ethernet = <&fec>;
+
+                                       fixed-link {
+                                               speed = <100>;
+                                               full-duplex;
+                                       };
+                               };
+
+                               port@5 {
+                                       reg = <5>;
+                                       label = "mezz2esb";
+                                       phy-mode = "sgmii";
+
+                                       fixed-link {
+                                               speed = <1000>;
+                                               full-duplex;
+                                       };
+                               };
+                       };
+               };
+       };
+};
+
+&cpu {
+       cpu-supply = <&sw1_reg>;
+};
+
+&ecspi1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_ecspi1>;
+       cs-gpios = <&gpio4 24 GPIO_ACTIVE_HIGH>,
+                  <&gpio4 25 GPIO_ACTIVE_LOW>;
+       status = "okay";
+
+       pmic@0 {
+               compatible = "fsl,mc13892";
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_pmic>;
+               spi-max-frequency = <6000000>;
+               spi-cs-high;
+               reg = <0>;
+               interrupt-parent = <&gpio1>;
+               interrupts = <8 IRQ_TYPE_LEVEL_HIGH>;
+               fsl,mc13xxx-uses-adc;
+
+               regulators {
+                       sw1_reg: sw1 {
+                               regulator-min-microvolt = <600000>;
+                               regulator-max-microvolt = <1375000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+
+                       sw2_reg: sw2 {
+                               regulator-min-microvolt = <900000>;
+                               regulator-max-microvolt = <1850000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+
+                       sw3_reg: sw3 {
+                               regulator-min-microvolt = <1100000>;
+                               regulator-max-microvolt = <1850000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+
+                       sw4_reg: sw4 {
+                               regulator-min-microvolt = <1100000>;
+                               regulator-max-microvolt = <1850000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+
+                       vpll_reg: vpll {
+                               regulator-min-microvolt = <1050000>;
+                               regulator-max-microvolt = <1800000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+
+                       vdig_reg: vdig {
+                               regulator-min-microvolt = <1650000>;
+                               regulator-max-microvolt = <1650000>;
+                               regulator-boot-on;
+                       };
+
+                       vsd_reg: vsd {
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <3150000>;
+                               regulator-always-on;
+                       };
+
+                       vusb_reg: vusb {
+                               regulator-always-on;
+                       };
+
+                       vusb2_reg: vusb2 {
+                               regulator-min-microvolt = <2400000>;
+                               regulator-max-microvolt = <2775000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+
+                       vvideo_reg: vvideo {
+                               regulator-min-microvolt = <2775000>;
+                               regulator-max-microvolt = <2775000>;
+                       };
+
+                       vaudio_reg: vaudio {
+                               regulator-min-microvolt = <2300000>;
+                               regulator-max-microvolt = <3000000>;
+                       };
+
+                       vcam_reg: vcam {
+                               regulator-min-microvolt = <2500000>;
+                               regulator-max-microvolt = <3000000>;
+                       };
+
+                       vgen1_reg: vgen1 {
+                               regulator-min-microvolt = <1200000>;
+                               regulator-max-microvolt = <1200000>;
+                       };
+
+                       vgen2_reg: vgen2 {
+                               regulator-min-microvolt = <1200000>;
+                               regulator-max-microvolt = <3150000>;
+                               regulator-always-on;
+                       };
+
+                       vgen3_reg: vgen3 {
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <2900000>;
+                               regulator-always-on;
+                       };
+               };
+
+               leds {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       led-control = <0x0 0x0 0x3f83f8 0x0>;
+
+                       sysled3: led3@3 {
+                               reg = <3>;
+                               label = "system:red:power";
+                               linux,default-trigger = "default-on";
+                       };
+
+                       sysled4: led4@4 {
+                               reg = <4>;
+                               label = "system:green:act";
+                               linux,default-trigger = "heartbeat";
+                       };
+               };
+       };
+
+       flash@1 {
+               compatible = "atmel,at45", "atmel,dataflash";
+               reg = <1>;
+               spi-max-frequency = <25000000>;
+       };
+};
+
+&esdhc1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_esdhc1>;
+       bus-width = <8>;
+       non-removable;
+       no-1-8-v;
+       no-sdio;
+       no-sd;
+       status = "okay";
+};
+
+&esdhc4 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_esdhc4>;
+       bus-width = <4>;
+       no-1-8-v;
+       no-sdio;
+       cd-gpios = <&gpio4 8 GPIO_ACTIVE_LOW>;
+       status = "okay";
+};
+
+&fec {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_fec>;
+       phy-mode = "mii";
+       status = "okay";
+       phy-reset-gpios = <&gpio2 14 GPIO_ACTIVE_LOW>;
+       phy-reset-duration = <1>;
+       phy-supply = <&vgen3_reg>;
+       phy-handle = <&ethphy>;
+
+       mdio {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               ethphy: ethernet-phy@0 {
+                       reg = <0>;
+                       max-speed = <100>;
+               };
+       };
+};
+
+&i2c2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_i2c2>;
+       status = "okay";
+
+       eeprom@50 {
+               compatible = "atmel,24c04";
+               pagesize = <16>;
+               reg = <0x50>;
+       };
+};
+
+&uart1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_uart1>;
+       status = "okay";
+};
+
+&uart3 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_uart3>;
+       status = "okay";
+
+       rave-sp {
+               compatible = "zii,rave-sp-mezz";
+               current-speed = <57600>;
+               #address-cells = <1>;
+               #size-cells = <1>;
+
+               watchdog {
+                       compatible = "zii,rave-sp-watchdog-legacy";
+               };
+
+               eeprom@a4 {
+                       compatible = "zii,rave-sp-eeprom";
+                       reg = <0xa4 0x4000>;
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       zii,eeprom-name = "main-eeprom";
+               };
+       };
+};
+
+&usbotg {
+       dr_mode = "host";
+       disable-over-current;
+       phy_type = "utmi_wide";
+       vbus-supply = <&usb_vbus>;
+       status = "okay";
+};
+
+&usbphy0 {
+       vcc-supply = <&vusb2_reg>;
+};
+
+&iomuxc {
+       pinctrl_ecspi1: ecspi1grp {
+               fsl,pins = <
+                       MX51_PAD_CSPI1_MISO__ECSPI1_MISO        0x185
+                       MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI        0x185
+                       MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK        0x185
+                       MX51_PAD_CSPI1_SS0__GPIO4_24            0x85
+                       MX51_PAD_CSPI1_SS1__GPIO4_25            0x85
+               >;
+       };
+
+       pinctrl_esdhc1: esdhc1grp {
+               fsl,pins = <
+                       MX51_PAD_SD1_CMD__SD1_CMD               0x400020d5
+                       MX51_PAD_SD1_CLK__SD1_CLK               0x20d5
+                       MX51_PAD_SD1_DATA0__SD1_DATA0           0x20d5
+                       MX51_PAD_SD1_DATA1__SD1_DATA1           0x20d5
+                       MX51_PAD_SD1_DATA2__SD1_DATA2           0x20d5
+                       MX51_PAD_SD1_DATA3__SD1_DATA3           0x20d5
+                       MX51_PAD_SD2_DATA0__SD1_DAT4            0x20d5
+                       MX51_PAD_SD2_DATA1__SD1_DAT5            0x20d5
+                       MX51_PAD_SD2_DATA2__SD1_DAT6            0x20d5
+                       MX51_PAD_SD2_DATA3__SD1_DAT7            0x20d5
+               >;
+       };
+
+       pinctrl_esdhc4: esdhc4grp {
+               fsl,pins = <
+                       MX51_PAD_NANDF_RB1__SD4_CMD             0x400020d5
+                       MX51_PAD_NANDF_CS2__SD4_CLK             0x20d5
+                       MX51_PAD_NANDF_CS3__SD4_DAT0            0x20d5
+                       MX51_PAD_NANDF_CS4__SD4_DAT1            0x20d5
+                       MX51_PAD_NANDF_CS5__SD4_DAT2            0x20d5
+                       MX51_PAD_NANDF_CS6__SD4_DAT3            0x20d5
+                       MX51_PAD_NANDF_D0__GPIO4_8              0x100
+               >;
+       };
+
+       pinctrl_fec: fecgrp {
+               fsl,pins = <
+                       MX51_PAD_DISP2_DAT15__FEC_TDATA0        0x2004
+                       MX51_PAD_DISP2_DAT6__FEC_TDATA1         0x2004
+                       MX51_PAD_DISP2_DAT7__FEC_TDATA2         0x2004
+                       MX51_PAD_DISP2_DAT8__FEC_TDATA3         0x2004
+                       MX51_PAD_DISP2_DAT9__FEC_TX_EN          0x2004
+                       MX51_PAD_DISP2_DAT10__FEC_COL           0x0180
+                       MX51_PAD_DISP2_DAT11__FEC_RX_CLK        0x0180
+                       MX51_PAD_DISP2_DAT12__FEC_RX_DV         0x20a4
+                       MX51_PAD_DISP2_DAT1__FEC_RX_ER          0x20a4
+                       MX51_PAD_DISP2_DAT13__FEC_TX_CLK        0x2180
+                       MX51_PAD_DI_GP3__FEC_TX_ER              0x2004
+                       MX51_PAD_DISP2_DAT14__FEC_RDATA0        0x2180
+                       MX51_PAD_DI2_DISP_CLK__FEC_RDATA1       0x0085
+                       MX51_PAD_DI_GP4__FEC_RDATA2             0x0085
+                       MX51_PAD_DISP2_DAT0__FEC_RDATA3         0x0085
+                       MX51_PAD_DI2_PIN2__FEC_MDC              0x2004
+                       MX51_PAD_DI2_PIN3__FEC_MDIO             0x01f5
+                       MX51_PAD_DI2_PIN4__FEC_CRS              0x0180
+                       MX51_PAD_EIM_A20__GPIO2_14              0x0085
+                       MX51_PAD_EIM_A21__GPIO2_15              0x00e5
+               >;
+       };
+
+       pinctrl_i2c2: i2c2grp {
+               fsl,pins = <
+                       MX51_PAD_KEY_COL4__I2C2_SCL             0x400001ed
+                       MX51_PAD_KEY_COL5__I2C2_SDA             0x400001ed
+               >;
+       };
+
+       pinctrl_pmic: pmicgrp {
+               fsl,pins = <
+                       MX51_PAD_GPIO1_4__GPIO1_4               0x85
+                       MX51_PAD_GPIO1_8__GPIO1_8               0xe5
+               >;
+       };
+
+       pinctrl_swmdio: swmdiogrp {
+               fsl,pins = <
+                       MX51_PAD_EIM_D22__GPIO2_6               0x100
+                       MX51_PAD_EIM_D23__GPIO2_7               0x100
+               >;
+       };
+
+       pinctrl_uart1: uart1grp {
+               fsl,pins = <
+                       MX51_PAD_UART1_RXD__UART1_RXD           0x1c5
+                       MX51_PAD_UART1_TXD__UART1_TXD           0x1c5
+               >;
+       };
+
+       pinctrl_uart3: uart3grp {
+               fsl,pins = <
+                       MX51_PAD_UART3_RXD__UART3_RXD           0x1c5
+                       MX51_PAD_UART3_TXD__UART3_TXD           0x1c5
+               >;
+       };
+
+       pinctrl_usb_mmc_reset: usbmmcgrp {
+               fsl,pins = <
+                       MX51_PAD_CSI1_D9__GPIO3_13              0x85
+               >;
+       };
+};
diff --git a/arch/arm/boot/dts/imx51-zii-scu3-esb.dts b/arch/arm/boot/dts/imx51-zii-scu3-esb.dts
new file mode 100644 (file)
index 0000000..e6ebac8
--- /dev/null
@@ -0,0 +1,467 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+
+/*
+ * Copyright (C) 2018 Zodiac Inflight Innovations
+ */
+
+/dts-v1/;
+
+#include "imx51.dtsi"
+
+/ {
+       model = "ZII SCU3 ESB board";
+       compatible = "zii,imx51-scu3-esb", "fsl,imx51";
+
+       chosen {
+               stdout-path = &uart1;
+       };
+
+       /* Will be filled by the bootloader */
+       memory@90000000 {
+               reg = <0x90000000 0>;
+       };
+
+       usb_vbus: regulator-usb-vbus {
+               compatible = "regulator-fixed";
+               regulator-name = "usb_vbus";
+               regulator-min-microvolt = <5000000>;
+               regulator-max-microvolt = <5000000>;
+
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_usb_mmc_reset>;
+               gpio = <&gpio4 19 GPIO_ACTIVE_LOW>;
+               startup-delay-us = <150000>;
+       };
+};
+
+&cpu {
+       cpu-supply = <&sw1_reg>;
+};
+
+&ecspi1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_ecspi1>;
+       cs-gpios = <&gpio4 24 GPIO_ACTIVE_HIGH>,
+                  <&gpio4 25 GPIO_ACTIVE_LOW>;
+       status = "okay";
+
+       pmic@0 {
+               compatible = "fsl,mc13892";
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_pmic>;
+               spi-max-frequency = <6000000>;
+               spi-cs-high;
+               reg = <0>;
+               interrupt-parent = <&gpio1>;
+               interrupts = <8 IRQ_TYPE_LEVEL_HIGH>;
+               fsl,mc13xxx-uses-adc;
+
+               regulators {
+                       sw1_reg: sw1 {
+                               regulator-min-microvolt = <600000>;
+                               regulator-max-microvolt = <1375000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+
+                       sw2_reg: sw2 {
+                               regulator-min-microvolt = <900000>;
+                               regulator-max-microvolt = <1850000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+
+                       sw3_reg: sw3 {
+                               regulator-min-microvolt = <1100000>;
+                               regulator-max-microvolt = <1850000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+
+                       sw4_reg: sw4 {
+                               regulator-min-microvolt = <1100000>;
+                               regulator-max-microvolt = <1850000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+
+                       vpll_reg: vpll {
+                               regulator-min-microvolt = <1050000>;
+                               regulator-max-microvolt = <1800000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+
+                       vdig_reg: vdig {
+                               regulator-min-microvolt = <1650000>;
+                               regulator-max-microvolt = <1650000>;
+                               regulator-boot-on;
+                       };
+
+                       vsd_reg: vsd {
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <3150000>;
+                       };
+
+                       vusb_reg: vusb {
+                               regulator-always-on;
+                       };
+
+                       vusb2_reg: vusb2 {
+                               regulator-min-microvolt = <2400000>;
+                               regulator-max-microvolt = <2775000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+
+                       vvideo_reg: vvideo {
+                               regulator-min-microvolt = <2775000>;
+                               regulator-max-microvolt = <2775000>;
+                       };
+
+                       vaudio_reg: vaudio {
+                               regulator-min-microvolt = <2300000>;
+                               regulator-max-microvolt = <3000000>;
+                       };
+
+                       vcam_reg: vcam {
+                               regulator-min-microvolt = <2500000>;
+                               regulator-max-microvolt = <3000000>;
+                       };
+
+                       vgen1_reg: vgen1 {
+                               regulator-min-microvolt = <1200000>;
+                               regulator-max-microvolt = <1200000>;
+                       };
+
+                       vgen2_reg: vgen2 {
+                               regulator-min-microvolt = <1200000>;
+                               regulator-max-microvolt = <3150000>;
+                               regulator-always-on;
+                       };
+
+                       vgen3_reg: vgen3 {
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <2900000>;
+                               regulator-always-on;
+                       };
+               };
+
+               leds {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       led-control = <0x0 0x0 0x3f83f8 0x0>;
+
+                       sysled3: led3@3 {
+                               reg = <3>;
+                               label = "system:red:power";
+                               linux,default-trigger = "default-on";
+                       };
+
+                       sysled4: led4@4 {
+                               reg = <4>;
+                               label = "system:green:act";
+                               linux,default-trigger = "heartbeat";
+                       };
+               };
+       };
+
+       flash@1 {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "atmel,at45", "atmel,dataflash";
+               spi-max-frequency = <25000000>;
+               reg = <1>;
+       };
+};
+
+&esdhc1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_esdhc1>;
+       bus-width = <8>;
+       non-removable;
+       no-1-8-v;
+       no-sdio;
+       no-sd;
+       status = "okay";
+};
+
+&esdhc4 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_esdhc4>;
+       bus-width = <4>;
+       no-1-8-v;
+       no-sdio;
+       cd-gpios = <&gpio4 8 GPIO_ACTIVE_LOW>;
+       status = "okay";
+};
+
+&fec {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_fec>;
+       phy-mode = "mii";
+       status = "okay";
+
+       fixed-link {
+               speed = <100>;
+               full-duplex;
+       };
+
+       fec_mdio: mdio {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               status = "okay";
+
+               switch@0 {
+                       compatible = "marvell,mv88e6085";
+                       reg = <0>;
+                       dsa,member = <0 0>;
+                       eeprom-length = <512>;
+                       interrupt-parent = <&gpio4>;
+                       interrupts = <20 IRQ_TYPE_LEVEL_HIGH>;
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&pinctrl_switch>;
+
+                       ports {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+
+                               port@0 {
+                                       reg = <0>;
+                                       label = "port1";
+                               };
+
+                               port@1 {
+                                       reg = <1>;
+                                       label = "port2";
+                               };
+
+                               port@2 {
+                                       reg = <2>;
+                                       label = "port3";
+                               };
+
+                               port@3 {
+                                       reg = <3>;
+                                       label = "scu2scu";
+                               };
+
+                               port@4 {
+                                       reg = <4>;
+                                       label = "esb2host";
+                               };
+
+                               port@5 {
+                                       reg = <5>;
+                                       label = "esb2mezz";
+                                       phy-mode = "sgmii";
+
+                                       fixed-link {
+                                               speed = <1000>;
+                                               full-duplex;
+                                       };
+                               };
+
+                               port@6 {
+                                       reg = <6>;
+                                       label = "cpu";
+                                       phy-mode = "mii";
+                                       ethernet = <&fec>;
+
+                                       fixed-link {
+                                               speed = <100>;
+                                               full-duplex;
+                                       };
+                               };
+                       };
+               };
+       };
+};
+
+&ipu {
+       status = "disabled";
+};
+
+&i2c2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_i2c2>;
+       status = "okay";
+
+       eeprom@50 {
+               compatible = "atmel,24c04";
+               pagesize = <16>;
+               reg = <0x50>;
+       };
+
+       lm75@48 {
+               compatible = "national,lm75";
+               reg = <0x48>;
+       };
+};
+
+&uart1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_uart1>;
+       status = "okay";
+};
+
+&uart2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_uart2>;
+       status = "okay";
+};
+
+&uart3 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_uart3>;
+       status = "okay";
+
+       rave-sp {
+               compatible = "zii,rave-sp-esb";
+               current-speed = <57600>;
+               #address-cells = <1>;
+               #size-cells = <1>;
+
+               watchdog {
+                       compatible = "zii,rave-sp-watchdog-legacy";
+               };
+
+               eeprom@a4 {
+                       compatible = "zii,rave-sp-eeprom";
+                       reg = <0xa4 0x4000>;
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       zii,eeprom-name = "main-eeprom";
+               };
+       };
+};
+
+&usbotg {
+       dr_mode = "host";
+       disable-over-current;
+       phy_type = "utmi_wide";
+       vbus-supply = <&usb_vbus>;
+       status = "okay";
+};
+
+&usbphy0 {
+       vcc-supply = <&vusb2_reg>;
+};
+
+&wdog1 {
+       status = "disabled";
+};
+
+&iomuxc {
+       pinctrl_ecspi1: ecspi1grp {
+               fsl,pins = <
+                       MX51_PAD_CSPI1_MISO__ECSPI1_MISO        0x185
+                       MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI        0x185
+                       MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK        0x185
+                       MX51_PAD_CSPI1_SS0__GPIO4_24            0x85
+                       MX51_PAD_CSPI1_SS1__GPIO4_25            0x85
+               >;
+       };
+
+       pinctrl_esdhc1: esdhc1grp {
+               fsl,pins = <
+                       MX51_PAD_SD1_CMD__SD1_CMD               0x400020d5
+                       MX51_PAD_SD1_CLK__SD1_CLK               0x20d5
+                       MX51_PAD_SD1_DATA0__SD1_DATA0           0x20d5
+                       MX51_PAD_SD1_DATA1__SD1_DATA1           0x20d5
+                       MX51_PAD_SD1_DATA2__SD1_DATA2           0x20d5
+                       MX51_PAD_SD1_DATA3__SD1_DATA3           0x20d5
+                       MX51_PAD_SD2_DATA0__SD1_DAT4            0x20d5
+                       MX51_PAD_SD2_DATA1__SD1_DAT5            0x20d5
+                       MX51_PAD_SD2_DATA2__SD1_DAT6            0x20d5
+                       MX51_PAD_SD2_DATA3__SD1_DAT7            0x20d5
+               >;
+       };
+
+       pinctrl_esdhc4: esdhc4grp {
+               fsl,pins = <
+                       MX51_PAD_NANDF_RB1__SD4_CMD             0x400020d5
+                       MX51_PAD_NANDF_CS2__SD4_CLK             0x20d5
+                       MX51_PAD_NANDF_CS3__SD4_DAT0            0x20d5
+                       MX51_PAD_NANDF_CS4__SD4_DAT1            0x20d5
+                       MX51_PAD_NANDF_CS5__SD4_DAT2            0x20d5
+                       MX51_PAD_NANDF_CS6__SD4_DAT3            0x20d5
+                       MX51_PAD_NANDF_D0__GPIO4_8              0x100
+               >;
+       };
+
+       pinctrl_fec: fecgrp {
+               fsl,pins = <
+                       MX51_PAD_DISP2_DAT15__FEC_TDATA0        0x2004
+                       MX51_PAD_DISP2_DAT6__FEC_TDATA1         0x2004
+                       MX51_PAD_DISP2_DAT7__FEC_TDATA2         0x2004
+                       MX51_PAD_DISP2_DAT8__FEC_TDATA3         0x2004
+                       MX51_PAD_DISP2_DAT9__FEC_TX_EN          0x2004
+                       MX51_PAD_DISP2_DAT10__FEC_COL           0x0180
+                       MX51_PAD_DISP2_DAT11__FEC_RX_CLK        0x0180
+                       MX51_PAD_DISP2_DAT12__FEC_RX_DV         0x20a4
+
+                       MX51_PAD_DISP2_DAT13__FEC_TX_CLK        0x2180
+                       MX51_PAD_DISP2_DAT14__FEC_RDATA0        0x2180
+                       MX51_PAD_DI2_DISP_CLK__FEC_RDATA1       0x0085
+                       MX51_PAD_DI_GP4__FEC_RDATA2             0x0085
+                       MX51_PAD_DISP2_DAT0__FEC_RDATA3         0x0085
+                       MX51_PAD_DI2_PIN2__FEC_MDC              0x2004
+                       MX51_PAD_DI2_PIN3__FEC_MDIO             0x01f5
+                       MX51_PAD_DI2_PIN4__FEC_CRS              0x0180
+               >;
+       };
+
+       pinctrl_i2c2: i2c2grp {
+               fsl,pins = <
+                       MX51_PAD_KEY_COL4__I2C2_SCL             0x400001ed
+                       MX51_PAD_KEY_COL5__I2C2_SDA             0x400001ed
+               >;
+       };
+
+       pinctrl_pmic: pmicgrp {
+               fsl,pins = <
+                       MX51_PAD_GPIO1_4__GPIO1_4               0x85
+                       MX51_PAD_GPIO1_8__GPIO1_8               0xe5
+               >;
+       };
+
+       pinctrl_switch: switchgrp {
+               fsl,pins = <
+                       MX51_PAD_AUD3_BB_CK__GPIO4_20           0xc5
+               >;
+       };
+
+       pinctrl_uart1: uart1grp {
+               fsl,pins = <
+                       MX51_PAD_UART1_RXD__UART1_RXD           0x1c5
+                       MX51_PAD_UART1_TXD__UART1_TXD           0x1c5
+                       MX51_PAD_UART1_RTS__UART1_RTS           0x1c5
+                       MX51_PAD_UART1_CTS__UART1_CTS           0x1c5
+               >;
+       };
+
+       pinctrl_uart2: uart2grp {
+               fsl,pins = <
+                       MX51_PAD_UART2_RXD__UART2_RXD           0x1c5
+                       MX51_PAD_UART2_TXD__UART2_TXD           0x1c5
+                       MX51_PAD_USBH1_DATA0__UART2_CTS         0x1c5
+                       MX51_PAD_USBH1_DATA3__UART2_RTS         0x1c5
+               >;
+       };
+
+       pinctrl_uart3: uart3grp {
+               fsl,pins = <
+                       MX51_PAD_UART3_RXD__UART3_RXD           0x1c5
+                       MX51_PAD_UART3_TXD__UART3_TXD           0x1c5
+               >;
+       };
+
+       pinctrl_usb_mmc_reset: usbmmcgrp {
+               fsl,pins = <
+                       MX51_PAD_AUD3_BB_RXD__GPIO4_19          0x100
+               >;
+       };
+};
index fe01b89..5c4ba91 100644 (file)
                };
        };
 
-       usbphy {
-               #address-cells = <1>;
-               #size-cells = <0>;
-               compatible = "simple-bus";
+       pmu: pmu {
+               compatible = "arm,cortex-a8-pmu";
+               interrupt-parent = <&tzic>;
+               interrupts = <77>;
+       };
 
-               usbphy0: usbphy@0 {
-                       compatible = "usb-nop-xceiv";
-                       reg = <0>;
-                       clocks = <&clks IMX5_CLK_USB_PHY_GATE>;
-                       clock-names = "main_clk";
-                       #phy-cells = <0>;
-               };
+       usbphy0: usbphy0 {
+               compatible = "usb-nop-xceiv";
+               clocks = <&clks IMX5_CLK_USB_PHY_GATE>;
+               clock-names = "main_clk";
+               #phy-cells = <0>;
        };
 
        display-subsystem {
                                };
                        };
 
+                       aipstz1: bridge@73f00000 {
+                               compatible = "fsl,imx51-aipstz";
+                               reg = <0x73f00000 0x60>;
+                       };
+
                        usbotg: usb@73f80000 {
                                compatible = "fsl,imx51-usb", "fsl,imx27-usb";
                                reg = <0x73f80000 0x0200>;
                        reg = <0x80000000 0x10000000>;
                        ranges;
 
+                       aipstz2: bridge@83f00000 {
+                               compatible = "fsl,imx51-aipstz";
+                               reg = <0x83f00000 0x60>;
+                       };
+
                        iim: iim@83f98000 {
                                compatible = "fsl,imx51-iim", "fsl,imx27-iim";
                                reg = <0x83f98000 0x4000>;
                                clocks = <&clks IMX5_CLK_IIM_GATE>;
                        };
 
+                       tigerp: tigerp@83fa0000 {
+                               compatible = "fsl,imx51-tigerp";
+                               reg = <0x83fa0000 0x28>;
+                       };
+
                        owire: owire@83fa4000 {
                                compatible = "fsl,imx51-owire", "fsl,imx21-owire";
                                reg = <0x83fa4000 0x4000>;
                                status = "disabled";
                        };
 
+                       m4if: m4if@83fd8000 {
+                               compatible = "fsl,imx51-m4if";
+                               reg = <0x83fd8000 0x1000>;
+                       };
+
                        weim: weim@83fda000 {
                                #address-cells = <2>;
                                #size-cells = <1>;
                                clock-names = "ipg", "ahb", "ptp";
                                status = "disabled";
                        };
+
+                       vpu@83ff4000 {
+                               compatible = "fsl,imx51-vpu", "cnm,codahx4";
+                               reg = <0x83ff4000 0x1000>;
+                               interrupts = <9>;
+                               clocks = <&clks IMX5_CLK_VPU_REFERENCE_GATE>,
+                                        <&clks IMX5_CLK_VPU_GATE>;
+                               clock-names = "per", "ahb";
+                               resets = <&src 1>;
+                               iram = <&iram>;
+                       };
+
+                       sahara: crypto@83ff8000 {
+                               compatible = "fsl,imx53-sahara", "fsl,imx51-sahara";
+                               reg = <0x83ff8000 0x4000>;
+                               interrupts = <19 20>;
+                               clocks = <&clks IMX5_CLK_SAHARA_IPG_GATE>,
+                                        <&clks IMX5_CLK_SAHARA_IPG_GATE>;
+                               clock-names = "ipg", "ahb";
+                       };
                };
        };
 };
diff --git a/arch/arm/boot/dts/imx53-kp-ddc.dts b/arch/arm/boot/dts/imx53-kp-ddc.dts
new file mode 100644 (file)
index 0000000..0e7f071
--- /dev/null
@@ -0,0 +1,146 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright 2018
+ * Lukasz Majewski, DENX Software Engineering, lukma@denx.de
+ */
+
+/dts-v1/;
+#include "imx53-kp.dtsi"
+
+/ {
+       model = "K+P imx53 DDC";
+       compatible = "kiebackpeter,imx53-ddc", "fsl,imx53";
+
+       backlight_lcd: backlight {
+               compatible = "pwm-backlight";
+               pwms = <&pwm2 0 50000>;
+               power-supply = <&reg_backlight>;
+               brightness-levels = <0 24 28 32 36
+                                    40 44 48 52 56
+                                    60 64 68 72 76
+                                    80 84 88 92 96 100>;
+               default-brightness-level = <20>;
+       };
+
+       lcd_display: display {
+               compatible = "fsl,imx-parallel-display";
+               #address-cells = <1>;
+               #size-cells = <0>;
+               interface-pix-fmt = "rgb24";
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_disp>;
+
+               port@0 {
+                       reg = <0>;
+
+                       display1_in: endpoint {
+                               remote-endpoint = <&ipu_di1_disp1>;
+                       };
+               };
+
+               port@1 {
+                       reg = <1>;
+
+                       lcd_display_out: endpoint {
+                               remote-endpoint = <&lcd_panel_in>;
+                       };
+               };
+       };
+
+       lcd_panel: lcd-panel {
+               compatible = "koe,tx14d24vm1bpa";
+               backlight = <&backlight_lcd>;
+               power-supply = <&reg_3v3>;
+
+               port {
+                       lcd_panel_in: endpoint {
+                               remote-endpoint = <&lcd_display_out>;
+                       };
+               };
+       };
+
+       reg_backlight: regulator-backlight {
+               compatible = "regulator-fixed";
+               regulator-name = "backlight-supply";
+               regulator-min-microvolt = <15000000>;
+               regulator-max-microvolt = <15000000>;
+               regulator-always-on;
+       };
+};
+
+&fec {
+       status = "okay";
+};
+
+&i2c3 {
+       adc@48 {
+               compatible = "ti,ads1015";
+               reg = <0x48>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               channel@4 {
+                       reg = <4>;
+                       ti,gain = <2>;
+                       ti,datarate = <4>;
+               };
+
+               channel@6 {
+                       reg = <6>;
+                       ti,gain = <2>;
+                       ti,datarate = <4>;
+               };
+       };
+
+       gpio-expander2@21 {
+               compatible = "nxp,pcf8574";
+               reg = <0x21>;
+               interrupts = <109>;
+               #gpio-cells = <2>;
+               gpio-controller;
+       };
+};
+
+&iomuxc {
+       imx53-kp-ddc {
+               pinctrl_disp: dispgrp {
+                       fsl,pins = <
+                               MX53_PAD_EIM_A16__IPU_DI1_DISP_CLK      0x4
+                               MX53_PAD_EIM_DA10__IPU_DI1_PIN15        0x4
+                               MX53_PAD_EIM_DA9__IPU_DISP1_DAT_0       0x4
+                               MX53_PAD_EIM_DA8__IPU_DISP1_DAT_1       0x4
+                               MX53_PAD_EIM_DA7__IPU_DISP1_DAT_2       0x4
+                               MX53_PAD_EIM_DA6__IPU_DISP1_DAT_3       0x4
+                               MX53_PAD_EIM_DA5__IPU_DISP1_DAT_4       0x4
+                               MX53_PAD_EIM_DA4__IPU_DISP1_DAT_5       0x4
+                               MX53_PAD_EIM_DA3__IPU_DISP1_DAT_6       0x4
+                               MX53_PAD_EIM_DA2__IPU_DISP1_DAT_7       0x4
+                               MX53_PAD_EIM_DA1__IPU_DISP1_DAT_8       0x4
+                               MX53_PAD_EIM_DA0__IPU_DISP1_DAT_9       0x4
+                               MX53_PAD_EIM_EB1__IPU_DISP1_DAT_10      0x4
+                               MX53_PAD_EIM_EB0__IPU_DISP1_DAT_11      0x4
+                               MX53_PAD_EIM_A17__IPU_DISP1_DAT_12      0x4
+                               MX53_PAD_EIM_A18__IPU_DISP1_DAT_13      0x4
+                               MX53_PAD_EIM_A19__IPU_DISP1_DAT_14      0x4
+                               MX53_PAD_EIM_A20__IPU_DISP1_DAT_15      0x4
+                               MX53_PAD_EIM_A21__IPU_DISP1_DAT_16      0x4
+                               MX53_PAD_EIM_A22__IPU_DISP1_DAT_17      0x4
+                               MX53_PAD_EIM_A23__IPU_DISP1_DAT_18      0x4
+                               MX53_PAD_EIM_A24__IPU_DISP1_DAT_19      0x4
+                               MX53_PAD_EIM_D31__IPU_DISP1_DAT_20      0x4
+                               MX53_PAD_EIM_D30__IPU_DISP1_DAT_21      0x4
+                               MX53_PAD_EIM_D26__IPU_DISP1_DAT_22      0x4
+                               MX53_PAD_EIM_D27__IPU_DISP1_DAT_23      0x4
+                               MX53_PAD_GPIO_1__PWM2_PWMO 0x4
+                       >;
+               };
+       };
+};
+
+&ipu_di1_disp1 {
+       remote-endpoint = <&display1_in>;
+};
+
+&pmic {
+       fsl,mc13xxx-uses-touch;
+};
diff --git a/arch/arm/boot/dts/imx53-kp-hsc.dts b/arch/arm/boot/dts/imx53-kp-hsc.dts
new file mode 100644 (file)
index 0000000..6e3d71b
--- /dev/null
@@ -0,0 +1,52 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright 2018
+ * Lukasz Majewski, DENX Software Engineering, lukma@denx.de
+ */
+
+/dts-v1/;
+#include "imx53-kp.dtsi"
+
+/ {
+       model = "K+P imx53 HSC";
+       compatible = "kiebackpeter,imx53-hsc", "fsl,imx53";
+};
+
+&fec {
+       status = "okay";
+
+       fixed-link { /* RMII fixed link to LAN9303 */
+               speed = <100>;
+               full-duplex;
+       };
+};
+
+&i2c3 {
+       switch: switch@a {
+               compatible = "smsc,lan9303-i2c";
+               reg = <0xa>;
+               reset-gpios = <&gpio7 6 GPIO_ACTIVE_LOW>;
+               reset-duration = <400>;
+
+               ports {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+
+                       port@0 { /* RMII fixed link to master */
+                               reg = <0>;
+                               label = "cpu";
+                               ethernet = <&fec>;
+                       };
+
+                       port@1 { /* external port 1 */
+                               reg = <1>;
+                               label = "lan1";
+                       };
+
+                       port@2 { /* external port 2 */
+                               reg = <2>;
+                               label = "lan2";
+                       };
+               };
+       };
+};
diff --git a/arch/arm/boot/dts/imx53-kp.dtsi b/arch/arm/boot/dts/imx53-kp.dtsi
new file mode 100644 (file)
index 0000000..8b25416
--- /dev/null
@@ -0,0 +1,189 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright 2018
+ * Lukasz Majewski, DENX Software Engineering, lukma@denx.de
+ */
+
+/dts-v1/;
+#include "imx53-tqma53.dtsi"
+#include <dt-bindings/input/input.h>
+
+/ {
+       buzzer {
+               compatible = "pwm-beeper";
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_buzzer>;
+               pwms = <&pwm1 0 500000>;
+       };
+
+       gpio-buttons {
+               compatible = "gpio-keys";
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_gpiobuttons>;
+
+               button-kalt {
+                       label = "Kaltstart";
+                       linux,code = <KEY_F6>;
+                       gpios = <&gpio2 26 GPIO_ACTIVE_HIGH>;
+               };
+
+               button-pwr {
+                       label = "PowerFailInterrupt";
+                       linux,code = <KEY_F7>;
+                       gpios = <&gpio3 22 GPIO_ACTIVE_HIGH>;
+               };
+       };
+
+       leds {
+               compatible = "gpio-leds";
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_leds>;
+
+               led-bus {
+                       label = "bus";
+                       gpios = <&gpio2 30 GPIO_ACTIVE_HIGH>;
+                       linux,default-trigger = "gpio";
+                       default-state = "off";
+               };
+
+               led-error {
+                       label = "error";
+                       gpios = <&gpio3 28 GPIO_ACTIVE_HIGH>;
+                       linux,default-trigger = "gpio";
+                       default-state = "off";
+               };
+
+               led-flash {
+                       label = "flash";
+                       gpios = <&gpio5 0 GPIO_ACTIVE_HIGH>;
+                       linux,default-trigger = "heartbeat";
+               };
+       };
+
+       reg_3v3: regulator-3v3 {
+               compatible = "regulator-fixed";
+               regulator-name = "3V3";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               regulator-always-on;
+       };
+};
+
+&can1 {
+       status = "okay";
+};
+
+&can2 {
+       status = "okay";
+};
+
+&i2c3 {
+       status = "okay";
+
+       gpio-expander1@22 {
+               compatible = "nxp,pcf8574";
+               reg = <0x22>;
+               interrupts = <109>;
+               #gpio-cells = <2>;
+               gpio-controller;
+       };
+
+       rtc@51 {
+               compatible = "nxp,pcf8563";
+               reg = <0x51>;
+       };
+};
+
+&iomuxc {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_kp_common>;
+
+       imx53-kp-common {
+               pinctrl_buzzer: buzzergrp {
+                       fsl,pins = <
+                               MX53_PAD_SD1_DATA3__PWM1_PWMO 0x1e4
+                       >;
+               };
+
+               pinctrl_gpiobuttons: gpiobuttonsgrp {
+                       fsl,pins = <
+                               MX53_PAD_EIM_RW__GPIO2_26 0x1e4
+                               MX53_PAD_EIM_D22__GPIO3_22 0x1e4
+                       >;
+               };
+
+               pinctrl_kp_common: kpcommongrp {
+                       fsl,pins = <
+                               MX53_PAD_EIM_CS0__GPIO2_23 0x1e4
+                               MX53_PAD_GPIO_19__GPIO4_5  0x1e4
+                               MX53_PAD_PATA_DATA6__GPIO2_6 0x1e4
+                               MX53_PAD_PATA_DATA7__GPIO2_7 0xe0
+                               MX53_PAD_CSI0_DAT14__GPIO6_0 0x1e4
+                               MX53_PAD_CSI0_DAT16__GPIO6_2 0x1e4
+                               MX53_PAD_CSI0_DAT18__GPIO6_4 0x1e4
+                               MX53_PAD_EIM_D17__GPIO3_17 0x1e4
+                               MX53_PAD_EIM_D18__GPIO3_18 0x1e4
+                               MX53_PAD_EIM_D21__GPIO3_21 0x1e4
+                               MX53_PAD_EIM_D29__GPIO3_29 0x1e4
+                               MX53_PAD_EIM_DA11__GPIO3_11 0x1e4
+                               MX53_PAD_EIM_DA13__GPIO3_13 0x1e4
+                               MX53_PAD_EIM_DA14__GPIO3_14 0x1e4
+                               MX53_PAD_SD1_DATA0__GPIO1_16 0x1e4
+                               MX53_PAD_SD1_CMD__GPIO1_18 0x1e4
+                               MX53_PAD_SD1_CLK__GPIO1_20 0x1e4
+                       >;
+               };
+
+               pinctrl_leds: ledgrp {
+                       fsl,pins = <
+                               MX53_PAD_EIM_EB2__GPIO2_30 0x1d4
+                               MX53_PAD_EIM_D28__GPIO3_28 0x1d4
+                               MX53_PAD_EIM_WAIT__GPIO5_0 0x1d4
+                       >;
+               };
+
+               pinctrl_uart4: uart4grp {
+                       fsl,pins = <
+                               MX53_PAD_CSI0_DAT12__UART4_TXD_MUX 0x1e4
+                               MX53_PAD_CSI0_DAT13__UART4_RXD_MUX 0x1e4
+                       >;
+               };
+       };
+};
+
+&pinctrl_uart1 {
+       fsl,pins = <
+               MX53_PAD_EIM_D23__GPIO3_23 0x1e4
+               MX53_PAD_EIM_EB3__GPIO2_31 0x1e4
+               MX53_PAD_EIM_D24__GPIO3_24 0x1e4
+               MX53_PAD_EIM_D25__GPIO3_25 0x1e4
+               MX53_PAD_EIM_D19__GPIO3_19 0x1e4
+               MX53_PAD_EIM_D20__GPIO3_20 0x1e4
+       >;
+};
+
+&uart1 {
+       status = "okay";
+};
+
+&uart2 {
+       status = "okay";
+};
+
+&uart3 {
+       status = "okay";
+};
+
+&uart4 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_uart4>;
+       status = "okay";
+};
+
+&usbh1 {
+       status = "okay";
+};
+
+&usbphy0 {
+       status = "disabled";
+};
index 3aa6f69..cdb90be 100644 (file)
                regulator-always-on;
        };
 
+       reg_3v3: regulator-3v3 {
+               /* TPS54320 */
+               compatible = "regulator-fixed";
+               regulator-name = "3V3";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               regulator-always-on;
+       };
+
+       reg_3v3_lcd: regulator-3v3-lcd {
+               /* MIC2009 */
+               compatible = "regulator-fixed";
+               regulator-name = "LCD_3V3";
+               vin-supply = <&reg_3v3>;
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               regulator-always-on;
+       };
+
        pwm_bl: backlight {
                compatible = "pwm-backlight";
                pwms = <&pwm2 0 50000>;
                                     234 237 239 242 244 247 249 252 255>;
                default-brightness-level = <0>;
                enable-gpios = <&gpio5 29 GPIO_ACTIVE_HIGH>;
+               power-supply = <&reg_3v3_lcd>;
        };
 
        leds {
                };
        };
 
-       usbphy2: usbphy2 {
+       usbphy2: usbphy-2 {
                compatible = "usb-nop-xceiv";
+               vcc-supply = <&reg_3v3>;
                reset-gpios = <&gpio4 4 GPIO_ACTIVE_LOW>;
                clock-names = "main_clk";
                clock-frequency = <24000000>;
                assigned-clock-parents = <&clks IMX5_CLK_OSC>;
        };
 
-       usbphy3: usbphy3 {
+       usbphy3: usbphy-3 {
                compatible = "usb-nop-xceiv";
+               vcc-supply = <&reg_3v3>;
                reset-gpios = <&gpio2 19 GPIO_ACTIVE_LOW>;
                clock-names = "main_clk";
 
 
        panel-lvds0 {
                compatible = "nvd,9128";
+               power-supply = <&reg_3v3_lcd>;
 
                port {
                        panel_in_lvds0: endpoint {
        };
 };
 
+&usbphy0 {
+       vcc-supply = <&reg_3v3>;
+};
+
+&usbphy1 {
+       vcc-supply = <&reg_3v3>;
+};
+
 &audmux {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_audmux>;
 &fec {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_fec>;
+       phy-supply = <&reg_3v3>;
        phy-mode = "rmii";
        phy-reset-gpios = <&gpio2 16 GPIO_ACTIVE_LOW>;
        status = "okay";
        };
 };
 
+&pmu {
+       secure-reg-access;
+};
+
 &pwm1 {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_pwm1>;
index ef7658a..7423d46 100644 (file)
        imx53-qsb {
                pinctrl_hog: hoggrp {
                        fsl,pins = <
-                               MX53_PAD_GPIO_0__CCM_SSI_EXT1_CLK 0x80000000
                                MX53_PAD_GPIO_8__GPIO1_8          0x80000000
                                MX53_PAD_PATA_DATA14__GPIO2_14    0x80000000
                                MX53_PAD_PATA_DATA15__GPIO2_15    0x80000000
                        >;
                };
 
+               pinctrl_codec: codecgrp {
+                       fsl,pins = <
+                               MX53_PAD_GPIO_0__CCM_SSI_EXT1_CLK       0x1c4
+                       >;
+               };
+
                pinctrl_esdhc1: esdhc1grp {
                        fsl,pins = <
                                MX53_PAD_SD1_DATA0__ESDHC1_DAT0         0x1d5
        sgtl5000: codec@a {
                compatible = "fsl,sgtl5000";
                reg = <0x0a>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_codec>;
                #sound-dai-cells = <0>;
                VDDA-supply = <&reg_3p2v>;
                VDDIO-supply = <&reg_3p2v>;
index 1a7a7bb..6386185 100644 (file)
                };
        };
 
-       pmu {
+       pmu: pmu {
                compatible = "arm,cortex-a8-pmu";
                interrupt-parent = <&tzic>;
                interrupts = <77>;
                                status = "disabled";
                        };
 
+                       tigerp: tigerp@63fa0000 {
+                               compatible = "fsl,imx53-tigerp", "fsl,imx51-tigerp";
+                               reg = <0x63fa0000 0x28>;
+                       };
+
                        owire: owire@63fa4000 {
                                compatible = "fsl,imx53-owire", "fsl,imx21-owire";
                                reg = <0x63fa4000 0x4000>;
index 3dee3af..9de45a7 100644 (file)
 
 /* Colibri MMC */
 &usdhc1 {
-       pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_mmc_cd>;
-       cd-gpios = <&gpio2 5 GPIO_ACTIVE_LOW>; /* MMCD */
        status = "okay";
 };
 
diff --git a/arch/arm/boot/dts/imx6dl-icore-mipi.dts b/arch/arm/boot/dts/imx6dl-icore-mipi.dts
new file mode 100644 (file)
index 0000000..bf53f05
--- /dev/null
@@ -0,0 +1,25 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (C) 2018 Engicam S.r.l.
+ * Copyright (C) 2018 Amarula Solutions B.V.
+ * Author: Jagan Teki <jagan@amarulasolutions.com>
+ */
+
+/dts-v1/;
+
+#include "imx6dl.dtsi"
+#include "imx6qdl-icore.dtsi"
+
+/ {
+       model = "Engicam i.CoreM6 DualLite/Solo MIPI Starter Kit";
+       compatible = "engicam,imx6-icore", "fsl,imx6dl";
+};
+
+&hdmi {
+       ddc-i2c-bus = <&i2c2>;
+       status = "okay";
+};
+
+&usdhc3 {
+       status = "okay";
+};
index 6b2d291..df8607f 100644 (file)
 
 /dts-v1/;
 
+#include <dt-bindings/gpio/gpio.h>
 #include "imx6dl.dtsi"
 
 / {
        model = "BTicino i.MX6DL Mamoj board";
        compatible = "bticino,imx6dl-mamoj", "fsl,imx6dl";
+
+       backlight_lcd: backlight-lcd {
+               compatible = "pwm-backlight";
+               pwms = <&pwm3 0 25000>; /* 25000ns -> 40kHz */
+               brightness-levels = <0 4 8 16 32 64 128 160 192 224 255>;
+               default-brightness-level = <7>;
+       };
+
+       display: disp0 {
+               compatible = "fsl,imx-parallel-display";
+               #address-cells = <1>;
+               #size-cells = <0>;
+               interface-pix-fmt = "rgb24";
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_ipu1_lcdif>;
+               status = "okay";
+
+               port@0 {
+                       reg = <0>;
+
+                       lcd_display_in: endpoint {
+                               remote-endpoint = <&ipu1_di0_disp0>;
+                       };
+               };
+
+               port@1 {
+                       reg = <1>;
+
+                       lcd_display_out: endpoint {
+                               remote-endpoint = <&lcd_panel_in>;
+                       };
+               };
+       };
+
+       panel-lcd {
+               compatible = "rocktech,rk070er9427";
+               backlight = <&backlight_lcd>;
+               power-supply = <&reg_lcd_lr>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_ipu1_lcdif_pwr>;
+
+               port {
+                       lcd_panel_in: endpoint {
+                               remote-endpoint = <&lcd_display_out>;
+                       };
+               };
+       };
+
+       reg_lcd_3v3: regulator-lcd-dvdd {
+               compatible = "regulator-fixed";
+               regulator-name = "lcd-dvdd";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               gpio = <&gpio3 1 0>;
+               enable-active-high;
+               startup-delay-us = <21000>;
+       };
+
+       reg_lcd_power: regulator-lcd-power {
+               compatible = "regulator-fixed";
+               regulator-name = "lcd-enable";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               gpio = <&gpio3 6 0>;
+               enable-active-high;
+               vin-supply = <&reg_lcd_3v3>;
+       };
+
+       reg_lcd_vgl: regulator-lcd-vgl {
+               compatible = "regulator-fixed";
+               regulator-name = "lcd-vgl";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               gpio = <&gpio2 20 GPIO_ACTIVE_HIGH>;
+               startup-delay-us = <6000>;
+               enable-active-high;
+               vin-supply = <&reg_lcd_power>;
+       };
+
+       reg_lcd_vgh: regulator-lcd-vgh {
+               compatible = "regulator-fixed";
+               regulator-name = "lcd-vgh";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               gpio = <&gpio3 31 GPIO_ACTIVE_HIGH>;
+               startup-delay-us = <6000>;
+               enable-active-high;
+               vin-supply = <&reg_lcd_avdd>;
+       };
+
+       reg_lcd_vcom: regulator-lcd-vcom {
+               compatible = "regulator-fixed";
+               regulator-name = "lcd-vcom";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               gpio = <&gpio4 14 GPIO_ACTIVE_HIGH>;
+               startup-delay-us = <11000>;
+               enable-active-high;
+               vin-supply = <&reg_lcd_vgh>;
+       };
+
+       reg_lcd_lr: regulator-lcd-lr {
+               compatible = "regulator-fixed";
+               regulator-name = "lcd-lr";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               gpio = <&gpio4 15 GPIO_ACTIVE_HIGH>;
+               enable-active-high;
+               vin-supply = <&reg_lcd_vcom>;
+       };
+
+       reg_lcd_avdd: regulator-lcd-avdd {
+               compatible = "regulator-fixed";
+               regulator-name = "lcd-avdd";
+               regulator-min-microvolt = <10280000>;
+               regulator-max-microvolt = <10280000>;
+               gpio = <&gpio2 13 GPIO_ACTIVE_HIGH>;
+               startup-delay-us = <6000>;
+               enable-active-high;
+               vin-supply = <&reg_lcd_vgl>;
+       };
+
+       reg_usb_host: regulator-usb-vbus {
+               compatible = "regulator-fixed";
+               regulator-name = "usbhost-vbus";
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_usbhost>;
+               regulator-min-microvolt = <50000000>;
+               regulator-max-microvolt = <50000000>;
+               gpio = <&gpio6 6 GPIO_ACTIVE_HIGH>;
+               enable-active-high;
+       };
+
+       reg_wl18xx_vmmc:  regulator-wl18xx-vmcc {
+               compatible = "regulator-fixed";
+               regulator-name = "vwl1807";
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_wlan>;
+               regulator-min-microvolt = <1800000>;
+               regulator-max-microvolt = <1800000>;
+               gpio = <&gpio6 21 GPIO_ACTIVE_HIGH>;
+               startup-delay-us = <70000>;
+               enable-active-high;
+       };
 };
 
 &fec {
        };
 };
 
+&ipu1_di0_disp0 {
+       remote-endpoint = <&lcd_display_in>;
+};
+
+&pwm3 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_pwm3>;
+       status = "okay";
+};
+
 &uart3 {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_uart3>;
        status = "okay";
 };
 
+&usbh1 {
+       vbus-supply = <&reg_usb_host>;
+       status = "okay";
+};
+
+&usbotg {
+       dr_mode = "peripheral";
+       status = "okay";
+};
+
+&usdhc1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_usdhc1>;
+       bus-width = <4>;
+       vmmc-supply = <&reg_wl18xx_vmmc>;
+       no-1-8-v;
+       non-removable;
+       wakeup-source;
+       keep-power-in-suspend;
+       cap-power-off-card;
+       max-frequency = <25000000>;
+       #address-cells = <1>;
+       #size-cells = <0>;
+       status = "okay";
+
+       wlcore: wlcore@2 {
+               compatible = "ti,wl1837";
+               reg = <2>;
+               interrupt-parent = <&gpio6>;
+               interrupts = <23 IRQ_TYPE_LEVEL_HIGH>;
+               tcxo-clock-frequency = <26000000>;
+       };
+};
+
 &usdhc3 {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_usdhc3>;
                >;
        };
 
+       pinctrl_ipu1_lcdif: pinctrlipu1lcdif { /* parallel port 24-bit */
+               fsl,pins = <
+                       MX6QDL_PAD_DI0_DISP_CLK__IPU1_DI0_DISP_CLK 0x10 /* VDOUT_PCLK */
+                       MX6QDL_PAD_DI0_PIN15__IPU1_DI0_PIN15       0x10
+                       MX6QDL_PAD_DI0_PIN2__IPU1_DI0_PIN02        0x10 /* VDOUT_HSYNC */
+                       MX6QDL_PAD_DI0_PIN3__IPU1_DI0_PIN03        0x10 /* VDOUT_VSYNC */
+                       MX6QDL_PAD_DI0_PIN4__IPU1_DI0_PIN04        0x10 /* VDOUT_RESET */
+                       MX6QDL_PAD_DISP0_DAT0__IPU1_DISP0_DATA00   0x10
+                       MX6QDL_PAD_DISP0_DAT1__IPU1_DISP0_DATA01   0x10
+                       MX6QDL_PAD_DISP0_DAT2__IPU1_DISP0_DATA02   0x10
+                       MX6QDL_PAD_DISP0_DAT3__IPU1_DISP0_DATA03   0x10
+                       MX6QDL_PAD_DISP0_DAT4__IPU1_DISP0_DATA04   0x10
+                       MX6QDL_PAD_DISP0_DAT5__IPU1_DISP0_DATA05   0x10
+                       MX6QDL_PAD_DISP0_DAT6__IPU1_DISP0_DATA06   0x10
+                       MX6QDL_PAD_DISP0_DAT7__IPU1_DISP0_DATA07   0x10
+                       MX6QDL_PAD_DISP0_DAT8__IPU1_DISP0_DATA08   0x10
+                       MX6QDL_PAD_DISP0_DAT9__IPU1_DISP0_DATA09   0x10
+                       MX6QDL_PAD_DISP0_DAT10__IPU1_DISP0_DATA10  0x10
+                       MX6QDL_PAD_DISP0_DAT11__IPU1_DISP0_DATA11  0x10
+                       MX6QDL_PAD_DISP0_DAT12__IPU1_DISP0_DATA12  0x10
+                       MX6QDL_PAD_DISP0_DAT13__IPU1_DISP0_DATA13  0x10
+                       MX6QDL_PAD_DISP0_DAT14__IPU1_DISP0_DATA14  0x10
+                       MX6QDL_PAD_DISP0_DAT15__IPU1_DISP0_DATA15  0x10
+                       MX6QDL_PAD_DISP0_DAT16__IPU1_DISP0_DATA16  0x10
+                       MX6QDL_PAD_DISP0_DAT17__IPU1_DISP0_DATA17  0x10
+                       MX6QDL_PAD_DISP0_DAT18__IPU1_DISP0_DATA18  0x10
+                       MX6QDL_PAD_DISP0_DAT19__IPU1_DISP0_DATA19  0x10
+                       MX6QDL_PAD_DISP0_DAT20__IPU1_DISP0_DATA20  0x10
+                       MX6QDL_PAD_DISP0_DAT21__IPU1_DISP0_DATA21  0x10
+                       MX6QDL_PAD_DISP0_DAT22__IPU1_DISP0_DATA22  0x10
+                       MX6QDL_PAD_DISP0_DAT23__IPU1_DISP0_DATA23  0x10
+               >;
+       };
+
+       pinctrl_ipu1_lcdif_pwr: ipu1lcdifpwrgrp {
+               fsl,pins = <
+                       MX6QDL_PAD_EIM_DA1__GPIO3_IO01          0x40013058 /* EN_LCD33V */
+                       MX6QDL_PAD_SD4_DAT5__GPIO2_IO13         0x4001b0b0 /* EN_AVDD */
+                       MX6QDL_PAD_EIM_D31__GPIO3_IO31          0x40013058 /* ENVGH */
+                       MX6QDL_PAD_EIM_A18__GPIO2_IO20          0x40013058 /* ENVGL */
+                       MX6QDL_PAD_EIM_DA6__GPIO3_IO06          0x40013058 /* LCD_POWER */
+                       MX6QDL_PAD_KEY_COL4__GPIO4_IO14         0x40013058 /* EN_VCOM_LCD */
+                       MX6QDL_PAD_KEY_ROW4__GPIO4_IO15         0x40013058 /* LCD_L_R */
+                       MX6QDL_PAD_EIM_DA2__GPIO3_IO02          0x40013058 /* LCD_U_D */
+               >;
+       };
+
+       pinctrl_pwm3: pwm3grp {
+               fsl,pins = <
+                       MX6QDL_PAD_SD4_DAT1__PWM3_OUT 0x1b0b1
+               >;
+       };
+
        pinctrl_uart3: uart3grp {
                fsl,pins = <
                        MX6QDL_PAD_EIM_D24__UART3_TX_DATA       0x1b0b1
                >;
        };
 
+       pinctrl_usbhost: usbhostgrp {
+               fsl,pins = <
+                       MX6QDL_PAD_EIM_A23__GPIO6_IO06          0x4001b0b0
+               >;
+       };
+
+       pinctrl_usdhc1: usdhc1grp {
+               fsl,pins = <
+                       MX6QDL_PAD_SD1_CMD__SD1_CMD    0x17069
+                       MX6QDL_PAD_SD1_CLK__SD1_CLK    0x10079
+                       MX6QDL_PAD_SD1_DAT0__SD1_DATA0 0x17069
+                       MX6QDL_PAD_SD1_DAT1__SD1_DATA1 0x17069
+                       MX6QDL_PAD_SD1_DAT2__SD1_DATA2 0x17069
+                       MX6QDL_PAD_SD1_DAT3__SD1_DATA3 0x17069
+               >;
+       };
+
        pinctrl_usdhc3: usdhc3grp {
                fsl,pins = <
                        MX6QDL_PAD_SD3_CMD__SD3_CMD     0x17059
                        MX6QDL_PAD_SD3_DAT7__SD3_DATA7  0x17059
                >;
        };
+
+       pinctrl_wlan: wlangrp {
+               fsl,pins = <
+                       MX6QDL_PAD_RGMII_TD1__GPIO6_IO21        0x4001b0b0
+               >;
+       };
 };
index 30ce2c0..61fa309 100644 (file)
@@ -1,42 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0 OR X11
 /*
  * Copyright 2015 Boundary Devices, 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/;
 
index ec53d7a..ef58d3b 100644 (file)
@@ -1,44 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0 OR X11
 /*
  * Copyright 2013 Boundary Devices, Inc.
  * Copyright 2012 Freescale Semiconductor, Inc.
  * Copyright 2011 Linaro Ltd.
- *
- * This file is dual-licensed: you can use it either under the terms
- * of the GPL or the X11 license, at your option. Note that this dual
- * licensing only applies to this file, and not this project as a
- * whole.
- *
- *  a) This file is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License
- *     version 2 as published by the Free Software Foundation.
- *
- *     This file is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- * Or, alternatively,
- *
- *  b) Permission is hereby granted, free of charge, to any person
- *     obtaining a copy of this software and associated documentation
- *     files (the "Software"), to deal in the Software without
- *     restriction, including without limitation the rights to use,
- *     copy, modify, merge, publish, distribute, sublicense, and/or
- *     sell copies of the Software, and to permit persons to whom the
- *     Software is furnished to do so, subject to the following
- *     conditions:
- *
- *     The above copyright notice and this permission notice shall be
- *     included in all copies or substantial portions of the Software.
- *
- *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- *     OTHER DEALINGS IN THE SOFTWARE.
  */
 
 /dts-v1/;
index 2e98c92..dd3226f 100644 (file)
                reg = <0x10000000 0x40000000>;
        };
 
-       regulators {
-               compatible = "simple-bus";
-               #address-cells = <1>;
-               #size-cells = <0>;
-
-               reg_2p5v: regulator@0 {
-                       compatible = "regulator-fixed";
-                       reg = <0>;
-                       regulator-name = "2P5V";
-                       regulator-min-microvolt = <2500000>;
-                       regulator-max-microvolt = <2500000>;
-               };
-
-               reg_3p3v: regulator@1 {
-                       compatible = "regulator-fixed";
-                       reg = <1>;
-                       regulator-name = "3P3V";
-                       regulator-min-microvolt = <3300000>;
-                       regulator-max-microvolt = <3300000>;
-               };
-
-               reg_usb_otg_vbus: regulator@2 {
-                       compatible = "regulator-fixed";
-                       reg = <2>;
-                       regulator-name = "usb_otg_vbus";
-                       regulator-min-microvolt = <5000000>;
-                       regulator-max-microvolt = <5000000>;
-                       gpio = <&gpio3 22 0>;
-                       enable-active-high;
-               };
+       chosen {
+               stdout-path = "serial1:115200n8";
        };
 
        leds {
                        mux-int-port = <1>;
                        mux-ext-port = <3>;
        };
+
+       reg_2p5v: regulator-2p5v {
+               compatible = "regulator-fixed";
+               regulator-name = "2P5V";
+               regulator-min-microvolt = <2500000>;
+               regulator-max-microvolt = <2500000>;
+       };
+
+       reg_3p3v: regulator-3p3v {
+               compatible = "regulator-fixed";
+               regulator-name = "3P3V";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+       };
+
+       reg_usb_otg_vbus: regulator-usbotgvbus {
+               compatible = "regulator-fixed";
+               regulator-name = "usb_otg_vbus";
+               regulator-min-microvolt = <5000000>;
+               regulator-max-microvolt = <5000000>;
+               gpio = <&gpio3 22 GPIO_ACTIVE_LOW>;
+       };
 };
 
 &audmux {
index b384913..f0607eb 100644 (file)
@@ -33,6 +33,7 @@
                                396000  1175000
                        >;
                        clock-latency = <61036>; /* two CLK32 periods */
+                       #cooling-cells = <2>;
                        clocks = <&clks IMX6QDL_CLK_ARM>,
                                 <&clks IMX6QDL_CLK_PLL2_PFD2_396M>,
                                 <&clks IMX6QDL_CLK_STEP>,
                        device_type = "cpu";
                        reg = <1>;
                        next-level-cache = <&L2>;
+                       operating-points = <
+                               /* kHz    uV */
+                               996000  1250000
+                               792000  1175000
+                               396000  1150000
+                       >;
+                       fsl,soc-operating-points = <
+                               /* ARM kHz  SOC-PU uV */
+                               996000  1175000
+                               792000  1175000
+                               396000  1175000
+                       >;
+                       clock-latency = <61036>; /* two CLK32 periods */
+                       clocks = <&clks IMX6QDL_CLK_ARM>,
+                                <&clks IMX6QDL_CLK_PLL2_PFD2_396M>,
+                                <&clks IMX6QDL_CLK_STEP>,
+                                <&clks IMX6QDL_CLK_PLL1_SW>,
+                                <&clks IMX6QDL_CLK_PLL1_SYS>;
+                       clock-names = "arm", "pll2_pfd2_396m", "step",
+                                     "pll1_sw", "pll1_sys";
+                       arm-supply = <&reg_arm>;
+                       pu-supply = <&reg_pu>;
+                       soc-supply = <&reg_soc>;
                };
        };
 
index aa0e631..707ac9a 100644 (file)
                rtc1 = &snvs_rtc;
        };
 
+       chosen {
+               stdout-path = "serial0:115200n8";
+       };
+
        gpio-keys {
                compatible = "gpio-keys";
                pinctrl-names = "default";
                 */
                compatible = "edt,et057090dhu";
                backlight = <&backlight>;
+               power-supply = <&reg_3v3_sw>;
 
                port {
                        lcd_panel_in: endpoint {
                enable-active-high;
                status = "okay";
        };
+
+       reg_3v3_sw: regulator-3v3-sw {
+               compatible = "regulator-fixed";
+               regulator-name = "3.3V_SW";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               regulator-always-on;
+       };
 };
 
 &backlight {
        brightness-levels = <0 127 191 223 239 247 251 255>;
        default-brightness-level = <1>;
+       power-supply = <&reg_3v3_sw>;
        status = "okay";
 };
 
 &can1 {
+       xceiver-supply = <&reg_3v3_sw>;
        status = "okay";
 };
 
 &can2 {
+       xceiver-supply = <&reg_3v3_sw>;
        status = "okay";
 };
 
index e8dccf5..4e1c8fe 100644 (file)
                rtc1 = &snvs_rtc;
        };
 
+       chosen {
+               stdout-path = "serial0:115200n8";
+       };
+
        gpio-keys {
                compatible = "gpio-keys";
                pinctrl-names = "default";
index 6831dfd..469e3d0 100644 (file)
                rtc1 = &snvs_rtc;
        };
 
+       chosen {
+               stdout-path = "serial0:115200n8";
+       };
+
        gpio-keys {
                compatible = "gpio-keys";
                pinctrl-names = "default";
index 65ef4ca..18ae4f3 100644 (file)
        >;
 };
 
+&cpu1 {
+       /*
+        * Although the imx6q fuse indicates that 1.2GHz operation is possible,
+        * the module behaves unstable at this frequency. Hence, remove the
+        * 1.2GHz operation point here.
+        */
+       operating-points = <
+               /* kHz  uV */
+               996000  1250000
+               852000  1250000
+               792000  1175000
+               396000  975000
+       >;
+       fsl,soc-operating-points = <
+               /* ARM kHz      SOC-PU uV */
+               996000          1250000
+               852000          1250000
+               792000          1175000
+               396000          1175000
+       >;
+};
+
+&cpu2 {
+       /*
+        * Although the imx6q fuse indicates that 1.2GHz operation is possible,
+        * the module behaves unstable at this frequency. Hence, remove the
+        * 1.2GHz operation point here.
+        */
+       operating-points = <
+               /* kHz  uV */
+               996000  1250000
+               852000  1250000
+               792000  1175000
+               396000  975000
+       >;
+       fsl,soc-operating-points = <
+               /* ARM kHz      SOC-PU uV */
+               996000          1250000
+               852000          1250000
+               792000          1175000
+               396000          1175000
+       >;
+};
+
+&cpu3 {
+       /*
+        * Although the imx6q fuse indicates that 1.2GHz operation is possible,
+        * the module behaves unstable at this frequency. Hence, remove the
+        * 1.2GHz operation point here.
+        */
+       operating-points = <
+               /* kHz  uV */
+               996000  1250000
+               852000  1250000
+               792000  1175000
+               396000  975000
+       >;
+       fsl,soc-operating-points = <
+               /* ARM kHz      SOC-PU uV */
+               996000          1250000
+               852000          1250000
+               792000          1175000
+               396000          1175000
+       >;
+};
+
 &ecspi1 {
        cs-gpios = <&gpio2 30 GPIO_ACTIVE_HIGH>, <&gpio3 19 GPIO_ACTIVE_HIGH>;
        pinctrl-names = "default";
index acd3d33..95b2efd 100644 (file)
        status = "okay";
 };
 
+&mipi_csi {
+       status = "okay";
+};
+
+&ov5640 {
+       status = "okay";
+};
+
 &usdhc3 {
        status = "okay";
 };
index 2a3c44f..03bec0c 100644 (file)
@@ -1,42 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0 OR X11
 /*
  * Copyright 2015 Boundary Devices, 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/;
 
index c5d59ba..eb4eecb 100644 (file)
@@ -1,42 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0 OR X11
 /*
  * Copyright 2016 Boundary Devices, 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/;
 
index df8ff39..435445a 100644 (file)
@@ -1,44 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0 OR X11
 /*
  * Copyright 2013 Boundary Devices, Inc.
  * Copyright 2012 Freescale Semiconductor, Inc.
  * Copyright 2011 Linaro Ltd.
- *
- * This file is dual-licensed: you can use it either under the terms
- * of the GPL or the X11 license, at your option. Note that this dual
- * licensing only applies to this file, and not this project as a
- * whole.
- *
- *  a) This file is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License
- *     version 2 as published by the Free Software Foundation.
- *
- *     This file is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- * Or, alternatively,
- *
- *  b) Permission is hereby granted, free of charge, to any person
- *     obtaining a copy of this software and associated documentation
- *     files (the "Software"), to deal in the Software without
- *     restriction, including without limitation the rights to use,
- *     copy, modify, merge, publish, distribute, sublicense, and/or
- *     sell copies of the Software, and to permit persons to whom the
- *     Software is furnished to do so, subject to the following
- *     conditions:
- *
- *     The above copyright notice and this permission notice shall be
- *     included in all copies or substantial portions of the Software.
- *
- *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- *     OTHER DEALINGS IN THE SOFTWARE.
  */
 
 /dts-v1/;
index f2368a0..c54362f 100644 (file)
                touchscreen-size-y = <480>;
                touchscreen-inverted-x;
                touchscreen-inverted-y;
+               wakeup-source;
        };
 
        rtc@68 {
index 77f8f03..0193ee6 100644 (file)
@@ -38,6 +38,7 @@
                                396000  1175000
                        >;
                        clock-latency = <61036>; /* two CLK32 periods */
+                       #cooling-cells = <2>;
                        clocks = <&clks IMX6QDL_CLK_ARM>,
                                 <&clks IMX6QDL_CLK_PLL2_PFD2_396M>,
                                 <&clks IMX6QDL_CLK_STEP>,
                        soc-supply = <&reg_soc>;
                };
 
-               cpu@1 {
+               cpu1: cpu@1 {
                        compatible = "arm,cortex-a9";
                        device_type = "cpu";
                        reg = <1>;
                        next-level-cache = <&L2>;
+                       operating-points = <
+                               /* kHz    uV */
+                               1200000 1275000
+                               996000  1250000
+                               852000  1250000
+                               792000  1175000
+                               396000  975000
+                       >;
+                       fsl,soc-operating-points = <
+                               /* ARM kHz  SOC-PU uV */
+                               1200000 1275000
+                               996000  1250000
+                               852000  1250000
+                               792000  1175000
+                               396000  1175000
+                       >;
+                       clock-latency = <61036>; /* two CLK32 periods */
+                       clocks = <&clks IMX6QDL_CLK_ARM>,
+                                <&clks IMX6QDL_CLK_PLL2_PFD2_396M>,
+                                <&clks IMX6QDL_CLK_STEP>,
+                                <&clks IMX6QDL_CLK_PLL1_SW>,
+                                <&clks IMX6QDL_CLK_PLL1_SYS>;
+                       clock-names = "arm", "pll2_pfd2_396m", "step",
+                                     "pll1_sw", "pll1_sys";
+                       arm-supply = <&reg_arm>;
+                       pu-supply = <&reg_pu>;
+                       soc-supply = <&reg_soc>;
                };
 
-               cpu@2 {
+               cpu2: cpu@2 {
                        compatible = "arm,cortex-a9";
                        device_type = "cpu";
                        reg = <2>;
                        next-level-cache = <&L2>;
+                       operating-points = <
+                               /* kHz    uV */
+                               1200000 1275000
+                               996000  1250000
+                               852000  1250000
+                               792000  1175000
+                               396000  975000
+                       >;
+                       fsl,soc-operating-points = <
+                               /* ARM kHz  SOC-PU uV */
+                               1200000 1275000
+                               996000  1250000
+                               852000  1250000
+                               792000  1175000
+                               396000  1175000
+                       >;
+                       clock-latency = <61036>; /* two CLK32 periods */
+                       clocks = <&clks IMX6QDL_CLK_ARM>,
+                                <&clks IMX6QDL_CLK_PLL2_PFD2_396M>,
+                                <&clks IMX6QDL_CLK_STEP>,
+                                <&clks IMX6QDL_CLK_PLL1_SW>,
+                                <&clks IMX6QDL_CLK_PLL1_SYS>;
+                       clock-names = "arm", "pll2_pfd2_396m", "step",
+                                     "pll1_sw", "pll1_sys";
+                       arm-supply = <&reg_arm>;
+                       pu-supply = <&reg_pu>;
+                       soc-supply = <&reg_soc>;
                };
 
-               cpu@3 {
+               cpu3: cpu@3 {
                        compatible = "arm,cortex-a9";
                        device_type = "cpu";
                        reg = <3>;
                        next-level-cache = <&L2>;
+                       operating-points = <
+                               /* kHz    uV */
+                               1200000 1275000
+                               996000  1250000
+                               852000  1250000
+                               792000  1175000
+                               396000  975000
+                       >;
+                       fsl,soc-operating-points = <
+                               /* ARM kHz  SOC-PU uV */
+                               1200000 1275000
+                               996000  1250000
+                               852000  1250000
+                               792000  1175000
+                               396000  1175000
+                       >;
+                       clock-latency = <61036>; /* two CLK32 periods */
+                       clocks = <&clks IMX6QDL_CLK_ARM>,
+                                <&clks IMX6QDL_CLK_PLL2_PFD2_396M>,
+                                <&clks IMX6QDL_CLK_STEP>,
+                                <&clks IMX6QDL_CLK_PLL1_SW>,
+                                <&clks IMX6QDL_CLK_PLL1_SYS>;
+                       clock-names = "arm", "pll2_pfd2_396m", "step",
+                                     "pll1_sw", "pll1_sys";
+                       arm-supply = <&reg_arm>;
+                       pu-supply = <&reg_pu>;
+                       soc-supply = <&reg_soc>;
                };
        };
 
index 64fbee6..05f07ea 100644 (file)
                status = "disabled";
        };
 
-       reg_1p8v: regulator-1p8v {
+       reg_module_3v3: regulator-module-3v3 {
                compatible = "regulator-fixed";
-               regulator-name = "1P8V";
-               regulator-min-microvolt = <1800000>;
-               regulator-max-microvolt = <1800000>;
-               regulator-always-on;
-       };
-
-       reg_2p5v: regulator-2p5v {
-               compatible = "regulator-fixed";
-               regulator-name = "2P5V";
-               regulator-min-microvolt = <2500000>;
-               regulator-max-microvolt = <2500000>;
+               regulator-name = "+V3.3";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
                regulator-always-on;
        };
 
-       reg_3p3v: regulator-3p3v {
+       reg_module_3v3_audio: regulator-module-3v3-audio {
                compatible = "regulator-fixed";
-               regulator-name = "3P3V";
+               regulator-name = "+V3.3_AUDIO";
                regulator-min-microvolt = <3300000>;
                regulator-max-microvolt = <3300000>;
                regulator-always-on;
 
                        vgen4_reg: vgen4 {
                                regulator-min-microvolt = <1800000>;
-                               regulator-max-microvolt = <3300000>;
+                               regulator-max-microvolt = <1800000>;
                                regulator-boot-on;
                                regulator-always-on;
                        };
                compatible = "fsl,sgtl5000";
                reg = <0x0a>;
                clocks = <&clks IMX6QDL_CLK_CKO>;
-               VDDA-supply = <&reg_2p5v>;
-               VDDIO-supply = <&reg_3p3v>;
+               VDDA-supply = <&reg_module_3v3_audio>;
+               VDDIO-supply = <&reg_module_3v3>;
+               VDDD-supply = <&vgen4_reg>;
        };
 
        /* STMPE811 touch screen controller */
 &usdhc1 {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_usdhc1_4bit &pinctrl_usdhc1_8bit>;
-       vqmmc-supply = <&reg_3p3v>;
+       vqmmc-supply = <&reg_module_3v3>;
        bus-width = <8>;
-       voltage-ranges = <3300 3300>;
+       disable-wp;
+       no-1-8-v;
        status = "disabled";
 };
 
 &usdhc2 {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_usdhc2>;
-       vqmmc-supply = <&reg_3p3v>;
+       vqmmc-supply = <&reg_module_3v3>;
        bus-width = <4>;
-       voltage-ranges = <3300 3300>;
+       disable-wp;
+       no-1-8-v;
        status = "disabled";
 };
 
 &usdhc3 {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_usdhc3>;
-       vqmmc-supply = <&reg_3p3v>;
+       vqmmc-supply = <&reg_module_3v3>;
        bus-width = <8>;
-       voltage-ranges = <3300 3300>;
+       no-1-8-v;
        non-removable;
        status = "okay";
 };
                        MX6QDL_PAD_SD3_RST__SD3_RESET  0x17059
                >;
        };
-
-       pinctrl_usdhc3_100mhz: usdhc3100mhzgrp {
-               fsl,pins = <
-                       MX6QDL_PAD_SD3_CMD__SD3_CMD    0x170b9
-                       MX6QDL_PAD_SD3_CLK__SD3_CLK    0x100b9
-                       MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x170b9
-                       MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x170b9
-                       MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x170b9
-                       MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x170b9
-                       MX6QDL_PAD_SD3_DAT4__SD3_DATA4 0x170b9
-                       MX6QDL_PAD_SD3_DAT5__SD3_DATA5 0x170b9
-                       MX6QDL_PAD_SD3_DAT6__SD3_DATA6 0x170b9
-                       MX6QDL_PAD_SD3_DAT7__SD3_DATA7 0x170b9
-                       /* eMMC reset */
-                       MX6QDL_PAD_SD3_RST__SD3_RESET  0x170b9
-               >;
-       };
-
-       pinctrl_usdhc3_200mhz: usdhc3200mhzgrp {
-               fsl,pins = <
-                       MX6QDL_PAD_SD3_CMD__SD3_CMD    0x170f9
-                       MX6QDL_PAD_SD3_CLK__SD3_CLK    0x100f9
-                       MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x170f9
-                       MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x170f9
-                       MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x170f9
-                       MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x170f9
-                       MX6QDL_PAD_SD3_DAT4__SD3_DATA4 0x170f9
-                       MX6QDL_PAD_SD3_DAT5__SD3_DATA5 0x170f9
-                       MX6QDL_PAD_SD3_DAT6__SD3_DATA6 0x170f9
-                       MX6QDL_PAD_SD3_DAT7__SD3_DATA7 0x170f9
-                       /* eMMC reset */
-                       MX6QDL_PAD_SD3_RST__SD3_RESET  0x170f9
-               >;
-       };
 };
index 76035db..87e15e7 100644 (file)
                status = "disabled";
        };
 
-       reg_1p8v: regulator-1p8v {
+       reg_module_3v3: regulator-module-3v3 {
                compatible = "regulator-fixed";
-               regulator-name = "1P8V";
-               regulator-min-microvolt = <1800000>;
-               regulator-max-microvolt = <1800000>;
-               regulator-always-on;
-       };
-
-       reg_2p5v: regulator-2p5v {
-               compatible = "regulator-fixed";
-               regulator-name = "2P5V";
-               regulator-min-microvolt = <2500000>;
-               regulator-max-microvolt = <2500000>;
+               regulator-name = "+V3.3";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
                regulator-always-on;
        };
 
-       reg_3p3v: regulator-3p3v {
+       reg_module_3v3_audio: regulator-module-3v3-audio {
                compatible = "regulator-fixed";
-               regulator-name = "3P3V";
+               regulator-name = "+V3.3_AUDIO";
                regulator-min-microvolt = <3300000>;
                regulator-max-microvolt = <3300000>;
                regulator-always-on;
 
                        vgen4_reg: vgen4 {
                                regulator-min-microvolt = <1800000>;
-                               regulator-max-microvolt = <3300000>;
+                               regulator-max-microvolt = <1800000>;
                                regulator-boot-on;
                                regulator-always-on;
                        };
                compatible = "fsl,sgtl5000";
                reg = <0x0a>;
                clocks = <&clks IMX6QDL_CLK_CKO>;
-               VDDA-supply = <&reg_2p5v>;
-               VDDIO-supply = <&reg_3p3v>;
+               VDDA-supply = <&reg_module_3v3_audio>;
+               VDDIO-supply = <&reg_module_3v3>;
+               VDDD-supply = <&vgen4_reg>;
                lrclk-strength = <3>;
        };
 
 /* Colibri MMC */
 &usdhc1 {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_usdhc1>;
-       vqmmc-supply = <&reg_3p3v>;
+       pinctrl-0 = <&pinctrl_usdhc1 &pinctrl_mmc_cd>;
+       cd-gpios = <&gpio2 5 GPIO_ACTIVE_LOW>; /* MMCD */
+       disable-wp;
+       vqmmc-supply = <&reg_module_3v3>;
        bus-width = <4>;
-       voltage-ranges = <3300 3300>;
+       no-1-8-v;
        status = "disabled";
 };
 
 &usdhc3 {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_usdhc3>;
-       vqmmc-supply = <&reg_3p3v>;
+       vqmmc-supply = <&reg_module_3v3>;
        bus-width = <8>;
-       voltage-ranges = <3300 3300>;
+       no-1-8-v;
        non-removable;
        status = "okay";
 };
 
        pinctrl_gpio_keys: gpiokeys {
                fsl,pins = <
-                       /* Power button */
-                       MX6QDL_PAD_EIM_A16__GPIO2_IO22          0x1b0b0
+                       MX6QDL_PAD_EIM_A16__GPIO2_IO22          0x130b0
                >;
        };
 
 
        pinctrl_mmc_cd: gpiommccd {
                fsl,pins = <
-                       MX6QDL_PAD_NANDF_D5__GPIO2_IO05 0x80000000
+                       MX6QDL_PAD_NANDF_D5__GPIO2_IO05 0x1b0b1
                >;
        };
 
                >;
        };
 
-       pinctrl_usdhc3_100mhz: usdhc3100mhzgrp {
-               fsl,pins = <
-                       MX6QDL_PAD_SD3_CMD__SD3_CMD     0x170b9
-                       MX6QDL_PAD_SD3_CLK__SD3_CLK     0x100b9
-                       MX6QDL_PAD_SD3_DAT0__SD3_DATA0  0x170b9
-                       MX6QDL_PAD_SD3_DAT1__SD3_DATA1  0x170b9
-                       MX6QDL_PAD_SD3_DAT2__SD3_DATA2  0x170b9
-                       MX6QDL_PAD_SD3_DAT3__SD3_DATA3  0x170b9
-                       MX6QDL_PAD_SD3_DAT4__SD3_DATA4  0x170b9
-                       MX6QDL_PAD_SD3_DAT5__SD3_DATA5  0x170b9
-                       MX6QDL_PAD_SD3_DAT6__SD3_DATA6  0x170b9
-                       MX6QDL_PAD_SD3_DAT7__SD3_DATA7  0x170b9
-                       /* eMMC reset */
-                       MX6QDL_PAD_SD3_RST__SD3_RESET   0x170b9
-               >;
-       };
-
-       pinctrl_usdhc3_200mhz: usdhc3200mhzgrp {
-               fsl,pins = <
-                       MX6QDL_PAD_SD3_CMD__SD3_CMD     0x170f9
-                       MX6QDL_PAD_SD3_CLK__SD3_CLK     0x100f9
-                       MX6QDL_PAD_SD3_DAT0__SD3_DATA0  0x170f9
-                       MX6QDL_PAD_SD3_DAT1__SD3_DATA1  0x170f9
-                       MX6QDL_PAD_SD3_DAT2__SD3_DATA2  0x170f9
-                       MX6QDL_PAD_SD3_DAT3__SD3_DATA3  0x170f9
-                       MX6QDL_PAD_SD3_DAT4__SD3_DATA4  0x170f9
-                       MX6QDL_PAD_SD3_DAT5__SD3_DATA5  0x170f9
-                       MX6QDL_PAD_SD3_DAT6__SD3_DATA6  0x170f9
-                       MX6QDL_PAD_SD3_DAT7__SD3_DATA7  0x170f9
-                       /* eMMC reset */
-                       MX6QDL_PAD_SD3_RST__SD3_RESET   0x170f9
-               >;
-       };
-
        pinctrl_weim_cs0: weimcs0grp {
                fsl,pins = <
                        /* nEXT_CS0 */
index 0a15749..9ce9937 100644 (file)
@@ -65,8 +65,7 @@
                regulator-always-on;
        };
 
-
-       reg_2p5v: regulator-3p3v {
+       reg_2p5v: regulator-2p5v {
                compatible = "regulator-fixed";
                regulator-name = "2P5V";
                regulator-min-microvolt = <2500000>;
        pinctrl-0 = <&pinctrl_i2c3>;
        status = "okay";
 
+       ov5640: camera@3c {
+               compatible = "ovti,ov5640";
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_ov5640>;
+               reg = <0x3c>;
+               clocks = <&clks IMX6QDL_CLK_CKO>;
+               clock-names = "xclk";
+               DOVDD-supply = <&reg_1p8v>;
+               AVDD-supply = <&reg_3p3v>;
+               DVDD-supply = <&reg_3p3v>;
+               powerdown-gpios = <&gpio5 30 GPIO_ACTIVE_HIGH>;
+               reset-gpios = <&gpio5 31 GPIO_ACTIVE_LOW>;
+               status = "disabled";
+
+               port {
+                       ov5640_to_mipi_csi2: endpoint {
+                               remote-endpoint = <&mipi_csi2_in>;
+                               clock-lanes = <0>;
+                               data-lanes = <1 2>;
+                       };
+               };
+       };
+
        sgtl5000: codec@a {
                #sound-dai-cells = <0>;
                compatible = "fsl,sgtl5000";
        };
 };
 
+&mipi_csi {
+       status = "disabled";
+
+       port@0 {
+               reg = <0>;
+
+               mipi_csi2_in: endpoint {
+                       remote-endpoint = <&ov5640_to_mipi_csi2>;
+                       clock-lanes = <0>;
+                       data-lanes = <1 2>;
+               };
+       };
+};
+
 &pwm3 {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_pwm3>;
                fsl,pins = <
                        MX6QDL_PAD_GPIO_5__I2C3_SCL  0x4001b8b1
                        MX6QDL_PAD_EIM_D18__I2C3_SDA 0x4001b8b1
-                       MX6QDL_PAD_GPIO_0__CCM_CLKO1    0x130b0
+               >;
+       };
+
+       pinctrl_ov5640: ov5640grp {
+               fsl,pins = <
+                       MX6QDL_PAD_CSI0_DAT12__GPIO5_IO30 0x1b0b0
+                       MX6QDL_PAD_CSI0_DAT13__GPIO5_IO31 0x1b0b0
+                       MX6QDL_PAD_GPIO_0__CCM_CLKO1      0x130b0
                >;
        };
 
index aab088f..29baf25 100644 (file)
@@ -1,42 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0 OR X11
 /*
  * Copyright 2015 Boundary Devices, 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.
  */
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/input/input.h>
                reg = <0x38>;
                interrupt-parent = <&gpio1>;
                interrupts = <9 IRQ_TYPE_EDGE_FALLING>;
+               wakeup-source;
        };
 
        rtc@6f {
index 87ca6ea..39200e5 100644 (file)
@@ -1,42 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0 OR X11
 /*
  * Copyright 2015 Boundary Devices, 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.
  */
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/input/input.h>
                reg = <0x38>;
                interrupt-parent = <&gpio1>;
                interrupts = <9 IRQ_TYPE_EDGE_FALLING>;
+               wakeup-source;
        };
 };
 
index f5b763d..572abd7 100644 (file)
@@ -1,42 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0 OR X11
 /*
  * Copyright 2016 Boundary Devices, 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.
  */
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/input/input.h>
                reg = <0x38>;
                interrupt-parent = <&gpio1>;
                interrupts = <9 IRQ_TYPE_EDGE_FALLING>;
+               wakeup-source;
        };
 };
 
index 596866b..98384a6 100644 (file)
@@ -1,44 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0 OR X11
 /*
  * Copyright 2013 Boundary Devices, Inc.
  * Copyright 2011 Freescale Semiconductor, Inc.
  * Copyright 2011 Linaro Ltd.
- *
- * This file is dual-licensed: you can use it either under the terms
- * of the GPL or the X11 license, at your option. Note that this dual
- * licensing only applies to this file, and not this project as a
- * whole.
- *
- *  a) This file is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License
- *     version 2 as published by the Free Software Foundation.
- *
- *     This file is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- * Or, alternatively,
- *
- *  b) Permission is hereby granted, free of charge, to any person
- *     obtaining a copy of this software and associated documentation
- *     files (the "Software"), to deal in the Software without
- *     restriction, including without limitation the rights to use,
- *     copy, modify, merge, publish, distribute, sublicense, and/or
- *     sell copies of the Software, and to permit persons to whom the
- *     Software is furnished to do so, subject to the following
- *     conditions:
- *
- *     The above copyright notice and this permission notice shall be
- *     included in all copies or substantial portions of the Software.
- *
- *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- *     OTHER DEALINGS IN THE SOFTWARE.
  */
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/input/input.h>
                reg = <0x38>;
                interrupt-parent = <&gpio1>;
                interrupts = <9 IRQ_TYPE_EDGE_FALLING>;
+               wakeup-source;
        };
 };
 
index 0e28e36..9f11f1f 100644 (file)
@@ -6,6 +6,10 @@
 #include <dt-bindings/gpio/gpio.h>
 
 / {
+       chosen {
+               stdout-path = &uart4;
+       };
+
        memory@10000000 {
                reg = <0x10000000 0x80000000>;
        };
                                gpio-controller;
                                #gpio-cells = <2>;
                        };
+
+                       light-sensor@44 {
+                               compatible = "isil,isl29023";
+                               reg = <0x44>;
+                               interrupt-parent = <&gpio5>;
+                               interrupts = <17 IRQ_TYPE_EDGE_FALLING>;
+                       };
+
+                       magnetometer@e {
+                               compatible = "fsl,mag3110";
+                               reg = <0x0e>;
+                               interrupt-parent = <&gpio2>;
+                               interrupts = <29 IRQ_TYPE_EDGE_RISING>;
+                       };
+
+                       accelerometer@1c {
+                               compatible = "fsl,mma8451";
+                               reg = <0x1c>;
+                               interrupt-parent = <&gpio6>;
+                               interrupts = <31 IRQ_TYPE_LEVEL_LOW>;
+                       };
                };
        };
 };
index 15744ad..6e46a19 100644 (file)
                        sw4_reg: sw4 {
                                regulator-min-microvolt = <800000>;
                                regulator-max-microvolt = <3300000>;
+                               regulator-always-on;
                        };
 
                        swbst_reg: swbst {
index e1afa54..381bf61 100644 (file)
@@ -8,30 +8,6 @@
 #include <dt-bindings/gpio/gpio.h>
 
 / {
-       regulators {
-               compatible = "simple-bus";
-               #address-cells = <1>;
-               #size-cells = <0>;
-
-               reg_2p5v: regulator@0 {
-                       compatible = "regulator-fixed";
-                       reg = <0>;
-                       regulator-name = "2P5V";
-                       regulator-min-microvolt = <2500000>;
-                       regulator-max-microvolt = <2500000>;
-                       regulator-always-on;
-               };
-
-               reg_3p3v: regulator@1 {
-                       compatible = "regulator-fixed";
-                       reg = <1>;
-                       regulator-name = "3P3V";
-                       regulator-min-microvolt = <3300000>;
-                       regulator-max-microvolt = <3300000>;
-                       regulator-always-on;
-               };
-       };
-
        sound {
                compatible = "fsl,imx6-wandboard-sgtl5000",
                             "fsl,imx-audio-sgtl5000";
                spdif-controller = <&spdif>;
                spdif-out;
        };
+
+       reg_2p5v: regulator-2p5v {
+               compatible = "regulator-fixed";
+               regulator-name = "2P5V";
+               regulator-min-microvolt = <2500000>;
+               regulator-max-microvolt = <2500000>;
+               regulator-always-on;
+       };
+
+       reg_3p3v: regulator-3p3v {
+               compatible = "regulator-fixed";
+               regulator-name = "3P3V";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               regulator-always-on;
+       };
+
+       reg_usb_otg_vbus: regulator-usbotgvbus {
+               compatible = "regulator-fixed";
+               regulator-name = "usb_otg_vbus";
+               regulator-min-microvolt = <5000000>;
+               regulator-max-microvolt = <5000000>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_usbotgvbus>;
+               gpio = <&gpio3 22 GPIO_ACTIVE_LOW>;
+       };
 };
 
 &audmux {
                        >;
                };
 
+               pinctrl_usbotgvbus: usbotgvbusgrp {
+                       fsl,pins = <
+                               MX6QDL_PAD_EIM_D22__GPIO3_IO22          0x130b0
+                       >;
+               };
+
                pinctrl_usdhc1: usdhc1grp {
                        fsl,pins = <
                                MX6QDL_PAD_SD1_CMD__SD1_CMD             0x17059
 };
 
 &usbotg {
+       vbus-supply = <&reg_usb_otg_vbus>;
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_usbotg>;
        disable-over-current;
-       dr_mode = "peripheral";
+       dr_mode = "otg";
        status = "okay";
 };
 
index f14df0b..7fff371 100644 (file)
        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>;
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       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";
+               };
        };
 };
 
 
                rmi4-f11@11 {
                        reg = <0x11>;
-                       touchscreen-inverted-y;
+                       touchscreen-inverted-x;
                        touchscreen-swapped-x-y;
                        syna,sensor-type = <1>;
                };
 
                rmi4-f12@12 {
                        reg = <0x12>;
-                       touchscreen-inverted-y;
+                       touchscreen-inverted-x;
                        touchscreen-swapped-x-y;
                        syna,sensor-type = <1>;
                };
index 911141e..61d2d26 100644 (file)
 
                        crypto: caam@2100000 {
                                compatible = "fsl,sec-v4.0";
-                               fsl,sec-era = <4>;
                                #address-cells = <1>;
                                #size-cells = <1>;
                                reg = <0x2100000 0x10000>;
index a39b860..741d1ed 100644 (file)
@@ -1,43 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0 OR X11
 /*
  * Copyright 2016 Boundary Devices, 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 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/;
index 011726c..1593ac8 100644 (file)
@@ -1,43 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0 OR X11
 /*
  * Copyright 2017 Boundary Devices, 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 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/;
index 92ad01f..679b448 100644 (file)
        model = "Freescale i.MX6 SoloLite EVK Board";
        compatible = "fsl,imx6sl-evk", "fsl,imx6sl";
 
+       chosen {
+               stdout-path = &uart1;
+       };
+
        memory@80000000 {
                reg = <0x80000000 0x40000000>;
        };
@@ -73,6 +77,8 @@
 
        reg_lcd_3v3: regulator-lcd-3v3 {
                compatible = "regulator-fixed";
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_reg_lcd_3v3>;
                regulator-name = "lcd-3v3";
                gpio = <&gpio4 3 GPIO_ACTIVE_HIGH>;
                enable-active-high;
                        sw4_reg: sw4 {
                                regulator-min-microvolt = <800000>;
                                regulator-max-microvolt = <3300000>;
+                               regulator-always-on;
                        };
 
                        swbst_reg: swbst {
                        >;
                };
 
+               pinctrl_reg_lcd_3v3: reglcd3v3grp {
+                       fsl,pins = <
+                               MX6SL_PAD_KEY_ROW5__GPIO4_IO03    0x17059
+                       >;
+               };
+
                pinctrl_uart1: uart1grp {
                        fsl,pins = <
                                MX6SL_PAD_UART1_RXD__UART1_RX_DATA      0x1b0b1
index 994e48d..7a4f5da 100644 (file)
@@ -60,6 +60,7 @@
                                396000          1175000
                        >;
                        clock-latency = <61036>; /* two CLK32 periods */
+                       #cooling-cells = <2>;
                        clocks = <&clks IMX6SL_CLK_ARM>, <&clks IMX6SL_CLK_PLL2_PFD2>,
                                        <&clks IMX6SL_CLK_STEP>, <&clks IMX6SL_CLK_PLL1_SW>,
                                        <&clks IMX6SL_CLK_PLL1_SYS>;
                                regulator-1p1 {
                                        compatible = "fsl,anatop-regulator";
                                        regulator-name = "vdd1p1";
-                                       regulator-min-microvolt = <800000>;
-                                       regulator-max-microvolt = <1375000>;
+                                       regulator-min-microvolt = <1000000>;
+                                       regulator-max-microvolt = <1200000>;
                                        regulator-always-on;
                                        anatop-reg-offset = <0x110>;
                                        anatop-vol-bit-shift = <8>;
                                regulator-2p5 {
                                        compatible = "fsl,anatop-regulator";
                                        regulator-name = "vdd2p5";
-                                       regulator-min-microvolt = <2100000>;
-                                       regulator-max-microvolt = <2850000>;
+                                       regulator-min-microvolt = <2250000>;
+                                       regulator-max-microvolt = <2750000>;
                                        regulator-always-on;
                                        anatop-reg-offset = <0x130>;
                                        anatop-vol-bit-shift = <8>;
                                #interrupt-cells = <3>;
                                interrupts = <0 89 IRQ_TYPE_LEVEL_HIGH>;
                                interrupt-parent = <&intc>;
-                               pu-supply = <&reg_pu>;
-                               clocks = <&clks IMX6SL_CLK_GPU2D_OVG>,
-                                        <&clks IMX6SL_CLK_GPU2D_PODF>;
-                               #power-domain-cells = <1>;
+                               clocks = <&clks IMX6SL_CLK_IPG>;
+                               clock-names = "ipg";
+
+                               pgc {
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+
+                                       power-domain@0 {
+                                               reg = <0>;
+                                               #power-domain-cells = <0>;
+                                       };
+
+                                       pd_pu: power-domain@1 {
+                                               reg = <1>;
+                                               #power-domain-cells = <0>;
+                                               power-supply = <&reg_pu>;
+                                               clocks = <&clks IMX6SL_CLK_GPU2D_OVG>,
+                                                        <&clks IMX6SL_CLK_GPU2D_PODF>;
+                                       };
+
+                                       pd_disp: power-domain@2 {
+                                               reg = <2>;
+                                               #power-domain-cells = <0>;
+                                               clocks = <&clks IMX6SL_CLK_LCDIF_AXI>,
+                                                        <&clks IMX6SL_CLK_LCDIF_PIX>,
+                                                        <&clks IMX6SL_CLK_EPDC_AXI>,
+                                                        <&clks IMX6SL_CLK_EPDC_PIX>,
+                                                        <&clks IMX6SL_CLK_PXP_AXI>;
+                                       };
+                               };
                        };
 
                        gpr: iomuxc-gpr@20e0000 {
                                         <&clks IMX6SL_CLK_DUMMY>;
                                clock-names = "pix", "axi", "disp_axi";
                                status = "disabled";
+                               power-domains = <&pd_disp>;
                        };
 
                        dcp: dcp@20fc000 {
                                status = "disabled";
                        };
                };
+
+               gpu_2d: gpu@2200000 {
+                       compatible = "vivante,gc";
+                       reg = <0x02200000 0x4000>;
+                       interrupts = <0 10 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&clks IMX6SL_CLK_MMDC_ROOT>,
+                                <&clks IMX6SL_CLK_GPU2D_OVG>;
+                       clock-names = "bus", "core";
+                       power-domains = <&pd_pu>;
+               };
+
+               gpu_vg: gpu@2204000 {
+                       compatible = "vivante,gc";
+                       reg = <0x02204000 0x4000>;
+                       interrupts = <0 11 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&clks IMX6SL_CLK_MMDC_ROOT>,
+                                <&clks IMX6SL_CLK_GPU2D_OVG>;
+                       clock-names = "bus", "core";
+                       power-domains = <&pd_pu>;
+               };
        };
 };
diff --git a/arch/arm/boot/dts/imx6sll-evk.dts b/arch/arm/boot/dts/imx6sll-evk.dts
new file mode 100644 (file)
index 0000000..c8e1155
--- /dev/null
@@ -0,0 +1,463 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright 2016 Freescale Semiconductor, Inc.
+ * Copyright 2017-2018 NXP.
+ *
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include "imx6sll.dtsi"
+
+/ {
+       model = "Freescale i.MX6SLL EVK Board";
+       compatible = "fsl,imx6sll-evk", "fsl,imx6sll";
+
+       chosen {
+               stdout-path = &uart1;
+       };
+
+       memory@80000000 {
+               reg = <0x80000000 0x80000000>;
+       };
+
+       backlight_display: backlight-display {
+               compatible = "pwm-backlight";
+               pwms = <&pwm1 0 5000000>;
+               brightness-levels = <0 4 8 16 32 64 128 255>;
+               default-brightness-level = <6>;
+               status = "okay";
+       };
+
+       reg_usb_otg1_vbus: regulator-otg1-vbus {
+               compatible = "regulator-fixed";
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_usb_otg1_vbus>;
+               regulator-name = "usb_otg1_vbus";
+               regulator-min-microvolt = <5000000>;
+               regulator-max-microvolt = <5000000>;
+               gpio = <&gpio4 0 GPIO_ACTIVE_HIGH>;
+               enable-active-high;
+       };
+
+       reg_usb_otg2_vbus: regulator-otg2-vbus {
+               compatible = "regulator-fixed";
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_usb_otg2_vbus>;
+               regulator-name = "usb_otg2_vbus";
+               regulator-min-microvolt = <5000000>;
+               regulator-max-microvolt = <5000000>;
+               gpio = <&gpio4 2 GPIO_ACTIVE_HIGH>;
+               enable-active-high;
+       };
+
+       reg_aud3v: regulator-aud3v {
+               compatible = "regulator-fixed";
+               regulator-name = "wm8962-supply-3v15";
+               regulator-min-microvolt = <3150000>;
+               regulator-max-microvolt = <3150000>;
+               regulator-boot-on;
+       };
+
+       reg_aud4v: regulator-aud4v {
+               compatible = "regulator-fixed";
+               regulator-name = "wm8962-supply-4v2";
+               regulator-min-microvolt = <4325000>;
+               regulator-max-microvolt = <4325000>;
+               regulator-boot-on;
+       };
+
+       reg_lcd_3v3: regulator-lcd-3v3 {
+               compatible = "regulator-fixed";
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_reg_lcd_3v3>;
+               regulator-name = "lcd-3v3";
+               gpio = <&gpio4 3 GPIO_ACTIVE_HIGH>;
+               enable-active-high;
+       };
+
+       reg_lcd_5v: regulator-lcd-5v {
+               compatible = "regulator-fixed";
+               regulator-name = "lcd-5v0";
+               regulator-min-microvolt = <5000000>;
+               regulator-max-microvolt = <5000000>;
+       };
+
+       reg_sd1_vmmc: regulator-sd1-vmmc {
+               compatible = "regulator-fixed";
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_reg_sd1_vmmc>;
+               regulator-name = "SD1_SPWR";
+               regulator-min-microvolt = <3000000>;
+               regulator-max-microvolt = <3000000>;
+               gpio = <&gpio3 30 GPIO_ACTIVE_HIGH>;
+               enable-active-high;
+       };
+
+       reg_sd3_vmmc: regulator-sd3-vmmc {
+               compatible = "regulator-fixed";
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_reg_sd3_vmmc>;
+               regulator-name = "SD3_WIFI";
+               regulator-min-microvolt = <3000000>;
+               regulator-max-microvolt = <3000000>;
+               gpio = <&gpio4 4 GPIO_ACTIVE_HIGH>;
+               enable-active-high;
+       };
+
+       panel {
+               compatible = "sii,43wvf1g";
+               backlight = <&backlight_display>;
+               dvdd-supply = <&reg_lcd_3v3>;
+               avdd-supply = <&reg_lcd_5v>;
+
+               port {
+                       panel_in: endpoint {
+                               remote-endpoint = <&display_out>;
+                       };
+               };
+       };
+};
+
+&cpu0 {
+       arm-supply = <&sw1a_reg>;
+       soc-supply = <&sw1c_reg>;
+};
+
+&i2c1 {
+       clock-frequency = <100000>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_i2c1>;
+       status = "okay";
+
+       pfuze100: pmic@8 {
+               compatible = "fsl,pfuze100";
+               reg = <0x08>;
+
+               regulators {
+                       sw1a_reg: sw1ab {
+                               regulator-min-microvolt = <300000>;
+                               regulator-max-microvolt = <1875000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                               regulator-ramp-delay = <6250>;
+                       };
+
+                       sw1c_reg: sw1c {
+                               regulator-min-microvolt = <300000>;
+                               regulator-max-microvolt = <1875000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                               regulator-ramp-delay = <6250>;
+                       };
+
+                       sw2_reg: sw2 {
+                               regulator-min-microvolt = <800000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+
+                       sw3a_reg: sw3a {
+                               regulator-min-microvolt = <400000>;
+                               regulator-max-microvolt = <1975000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+
+                       sw3b_reg: sw3b {
+                               regulator-min-microvolt = <400000>;
+                               regulator-max-microvolt = <1975000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+
+                       sw4_reg: sw4 {
+                               regulator-min-microvolt = <800000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-always-on;
+                       };
+
+                       swbst_reg: swbst {
+                               regulator-min-microvolt = <5000000>;
+                               regulator-max-microvolt = <5150000>;
+                       };
+
+                       snvs_reg: vsnvs {
+                               regulator-min-microvolt = <1000000>;
+                               regulator-max-microvolt = <3000000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+
+                       vref_reg: vrefddr {
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+
+                       vgen1_reg: vgen1 {
+                               regulator-min-microvolt = <800000>;
+                               regulator-max-microvolt = <1550000>;
+                               regulator-always-on;
+                       };
+
+                       vgen2_reg: vgen2 {
+                               regulator-min-microvolt = <800000>;
+                               regulator-max-microvolt = <1550000>;
+                       };
+
+                       vgen3_reg: vgen3 {
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <3300000>;
+                       };
+
+                       vgen4_reg: vgen4 {
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-always-on;
+                       };
+
+                       vgen5_reg: vgen5 {
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-always-on;
+                       };
+
+                       vgen6_reg: vgen6 {
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-always-on;
+                       };
+               };
+       };
+};
+
+&lcdif {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_lcd>;
+       status = "okay";
+
+       port {
+               display_out: endpoint {
+                       remote-endpoint = <&panel_in>;
+               };
+       };
+};
+
+&pwm1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_pwm1>;
+       status = "okay";
+};
+
+&uart1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_uart1>;
+       status = "okay";
+};
+
+&usdhc1 {
+       pinctrl-names = "default", "state_100mhz", "state_200mhz";
+       pinctrl-0 = <&pinctrl_usdhc1>;
+       pinctrl-1 = <&pinctrl_usdhc1_100mhz>;
+       pinctrl-2 = <&pinctrl_usdhc1_200mhz>;
+       cd-gpios = <&gpio4 7 GPIO_ACTIVE_LOW>;
+       wp-gpios = <&gpio4 22 GPIO_ACTIVE_HIGH>;
+       keep-power-in-suspend;
+       wakeup-source;
+       vmmc-supply = <&reg_sd1_vmmc>;
+       status = "okay";
+};
+
+&usbotg1 {
+       vbus-supply = <&reg_usb_otg1_vbus>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_usbotg1>;
+       disable-over-current;
+       srp-disable;
+       hnp-disable;
+       adp-disable;
+       status = "okay";
+};
+
+&usbotg2 {
+       vbus-supply = <&reg_usb_otg2_vbus>;
+       dr_mode = "host";
+       disable-over-current;
+       status = "okay";
+};
+
+&usdhc3 {
+       pinctrl-names = "default", "state_100mhz", "state_200mhz";
+       pinctrl-0 = <&pinctrl_usdhc3>;
+       pinctrl-1 = <&pinctrl_usdhc3_100mhz>;
+       pinctrl-2 = <&pinctrl_usdhc3_200mhz>;
+       cd-gpios = <&gpio3 22 GPIO_ACTIVE_LOW>;
+       keep-power-in-suspend;
+       enable-sdio-wakeup;
+       vmmc-supply = <&reg_sd3_vmmc>;
+       status = "okay";
+};
+
+&iomuxc {
+       pinctrl_reg_sd3_vmmc: sd3vmmcgrp {
+               fsl,pins = <
+                       MX6SLL_PAD_KEY_COL6__GPIO4_IO04 0x17059
+               >;
+       };
+
+       pinctrl_usb_otg1_vbus: vbus1grp {
+               fsl,pins = <
+                       MX6SLL_PAD_KEY_COL4__GPIO4_IO00 0x17059
+               >;
+       };
+
+       pinctrl_usb_otg2_vbus: vbus2grp {
+               fsl,pins = <
+                       MX6SLL_PAD_KEY_COL5__GPIO4_IO02 0x17059
+               >;
+       };
+
+       pinctrl_reg_lcd_3v3: reglcd3v3grp {
+               fsl,pins = <
+                       MX6SLL_PAD_KEY_ROW5__GPIO4_IO03 0x17059
+               >;
+       };
+
+       pinctrl_reg_sd1_vmmc: sd1vmmcgrp {
+               fsl,pins = <
+                       MX6SLL_PAD_KEY_COL3__GPIO3_IO30 0x17059
+               >;
+       };
+
+       pinctrl_uart1: uart1grp {
+               fsl,pins = <
+                       MX6SLL_PAD_UART1_TXD__UART1_DCE_TX 0x1b0b1
+                       MX6SLL_PAD_UART1_RXD__UART1_DCE_RX 0x1b0b1
+               >;
+       };
+
+       pinctrl_usdhc1: usdhc1grp {
+               fsl,pins = <
+                       MX6SLL_PAD_SD1_CMD__SD1_CMD     0x17059
+                       MX6SLL_PAD_SD1_CLK__SD1_CLK     0x13059
+                       MX6SLL_PAD_SD1_DATA0__SD1_DATA0 0x17059
+                       MX6SLL_PAD_SD1_DATA1__SD1_DATA1 0x17059
+                       MX6SLL_PAD_SD1_DATA2__SD1_DATA2 0x17059
+                       MX6SLL_PAD_SD1_DATA3__SD1_DATA3 0x17059
+               >;
+       };
+
+       pinctrl_usdhc1_100mhz: usdhc1grp_100mhz {
+               fsl,pins = <
+                       MX6SLL_PAD_SD1_CMD__SD1_CMD     0x170b9
+                       MX6SLL_PAD_SD1_CLK__SD1_CLK     0x130b9
+                       MX6SLL_PAD_SD1_DATA0__SD1_DATA0 0x170b9
+                       MX6SLL_PAD_SD1_DATA1__SD1_DATA1 0x170b9
+                       MX6SLL_PAD_SD1_DATA2__SD1_DATA2 0x170b9
+                       MX6SLL_PAD_SD1_DATA3__SD1_DATA3 0x170b9
+               >;
+       };
+
+       pinctrl_usdhc1_200mhz: usdhc1grp_200mhz {
+               fsl,pins = <
+                       MX6SLL_PAD_SD1_CMD__SD1_CMD     0x170f9
+                       MX6SLL_PAD_SD1_CLK__SD1_CLK     0x130f9
+                       MX6SLL_PAD_SD1_DATA0__SD1_DATA0 0x170f9
+                       MX6SLL_PAD_SD1_DATA1__SD1_DATA1 0x170f9
+                       MX6SLL_PAD_SD1_DATA2__SD1_DATA2 0x170f9
+                       MX6SLL_PAD_SD1_DATA3__SD1_DATA3 0x170f9
+               >;
+       };
+
+       pinctrl_usbotg1: usbotg1grp {
+               fsl,pins = <
+                       MX6SLL_PAD_EPDC_PWR_COM__USB_OTG1_ID 0x17059
+               >;
+       };
+
+       pinctrl_usdhc3: usdhc3grp {
+               fsl,pins = <
+                       MX6SLL_PAD_SD3_CMD__SD3_CMD             0x17061
+                       MX6SLL_PAD_SD3_CLK__SD3_CLK             0x13061
+                       MX6SLL_PAD_SD3_DATA0__SD3_DATA0         0x17061
+                       MX6SLL_PAD_SD3_DATA1__SD3_DATA1         0x17061
+                       MX6SLL_PAD_SD3_DATA2__SD3_DATA2         0x17061
+                       MX6SLL_PAD_SD3_DATA3__SD3_DATA3         0x17061
+                       MX6SLL_PAD_REF_CLK_32K__GPIO3_IO22      0x17059
+               >;
+       };
+
+       pinctrl_usdhc3_100mhz: usdhc3grp_100mhz {
+               fsl,pins = <
+                       MX6SLL_PAD_SD3_CMD__SD3_CMD             0x170a1
+                       MX6SLL_PAD_SD3_CLK__SD3_CLK             0x130a1
+                       MX6SLL_PAD_SD3_DATA0__SD3_DATA0         0x170a1
+                       MX6SLL_PAD_SD3_DATA1__SD3_DATA1         0x170a1
+                       MX6SLL_PAD_SD3_DATA2__SD3_DATA2         0x170a1
+                       MX6SLL_PAD_SD3_DATA3__SD3_DATA3         0x170a1
+                       MX6SLL_PAD_REF_CLK_32K__GPIO3_IO22      0x17059
+               >;
+       };
+
+       pinctrl_usdhc3_200mhz: usdhc3grp_200mhz {
+               fsl,pins = <
+                       MX6SLL_PAD_SD3_CMD__SD3_CMD             0x170e9
+                       MX6SLL_PAD_SD3_CLK__SD3_CLK             0x130f9
+                       MX6SLL_PAD_SD3_DATA0__SD3_DATA0         0x170e9
+                       MX6SLL_PAD_SD3_DATA1__SD3_DATA1         0x170e9
+                       MX6SLL_PAD_SD3_DATA2__SD3_DATA2         0x170e9
+                       MX6SLL_PAD_SD3_DATA3__SD3_DATA3         0x170e9
+                       MX6SLL_PAD_REF_CLK_32K__GPIO3_IO22      0x17059
+               >;
+       };
+
+       pinctrl_i2c1: i2c1grp {
+               fsl,pins = <
+                       MX6SLL_PAD_I2C1_SCL__I2C1_SCL    0x4001b8b1
+                       MX6SLL_PAD_I2C1_SDA__I2C1_SDA    0x4001b8b1
+               >;
+       };
+
+       pinctrl_lcd: lcdgrp {
+               fsl,pins = <
+                       MX6SLL_PAD_LCD_DATA00__LCD_DATA00       0x79
+                       MX6SLL_PAD_LCD_DATA01__LCD_DATA01       0x79
+                       MX6SLL_PAD_LCD_DATA02__LCD_DATA02       0x79
+                       MX6SLL_PAD_LCD_DATA03__LCD_DATA03       0x79
+                       MX6SLL_PAD_LCD_DATA04__LCD_DATA04       0x79
+                       MX6SLL_PAD_LCD_DATA05__LCD_DATA05       0x79
+                       MX6SLL_PAD_LCD_DATA06__LCD_DATA06       0x79
+                       MX6SLL_PAD_LCD_DATA07__LCD_DATA07       0x79
+                       MX6SLL_PAD_LCD_DATA08__LCD_DATA08       0x79
+                       MX6SLL_PAD_LCD_DATA09__LCD_DATA09       0x79
+                       MX6SLL_PAD_LCD_DATA10__LCD_DATA10       0x79
+                       MX6SLL_PAD_LCD_DATA11__LCD_DATA11       0x79
+                       MX6SLL_PAD_LCD_DATA12__LCD_DATA12       0x79
+                       MX6SLL_PAD_LCD_DATA13__LCD_DATA13       0x79
+                       MX6SLL_PAD_LCD_DATA14__LCD_DATA14       0x79
+                       MX6SLL_PAD_LCD_DATA15__LCD_DATA15       0x79
+                       MX6SLL_PAD_LCD_DATA16__LCD_DATA16       0x79
+                       MX6SLL_PAD_LCD_DATA17__LCD_DATA17       0x79
+                       MX6SLL_PAD_LCD_DATA18__LCD_DATA18       0x79
+                       MX6SLL_PAD_LCD_DATA19__LCD_DATA19       0x79
+                       MX6SLL_PAD_LCD_DATA20__LCD_DATA20       0x79
+                       MX6SLL_PAD_LCD_DATA21__LCD_DATA21       0x79
+                       MX6SLL_PAD_LCD_DATA22__LCD_DATA22       0x79
+                       MX6SLL_PAD_LCD_DATA23__LCD_DATA23       0x79
+                       MX6SLL_PAD_LCD_CLK__LCD_CLK             0x79
+                       MX6SLL_PAD_LCD_ENABLE__LCD_ENABLE       0x79
+                       MX6SLL_PAD_LCD_HSYNC__LCD_HSYNC         0x79
+                       MX6SLL_PAD_LCD_VSYNC__LCD_VSYNC         0x79
+                       MX6SLL_PAD_LCD_RESET__LCD_RESET         0x79
+               >;
+       };
+
+       pinctrl_pwm1: pmw1grp {
+               fsl,pins = <
+                       MX6SLL_PAD_PWM1__PWM1_OUT   0x110b0
+               >;
+       };
+};
diff --git a/arch/arm/boot/dts/imx6sll-pinfunc.h b/arch/arm/boot/dts/imx6sll-pinfunc.h
new file mode 100644 (file)
index 0000000..713a346
--- /dev/null
@@ -0,0 +1,880 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright 2016 Freescale Semiconductor, Inc.
+ * Copyright 2017-2018 NXP.
+ *
+ */
+
+#ifndef __DTS_IMX6SLL_PINFUNC_H
+#define __DTS_IMX6SLL_PINFUNC_H
+
+/*
+ * The pin function ID is a tuple of
+ * <mux_reg conf_reg input_reg mux_mode input_val>
+ */
+#define MX6SLL_PAD_WDOG_B__WDOG1_B                                0x0014 0x02DC 0x0000 0x0 0x0
+#define MX6SLL_PAD_WDOG_B__WDOG1_RESET_B_DEB                      0x0014 0x02DC 0x0000 0x1 0x0
+#define MX6SLL_PAD_WDOG_B__UART5_RI_B                             0x0014 0x02DC 0x0000 0x2 0x0
+#define MX6SLL_PAD_WDOG_B__GPIO3_IO18                             0x0014 0x02DC 0x0000 0x5 0x0
+#define MX6SLL_PAD_REF_CLK_24M__XTALOSC_REF_CLK_24M               0x0018 0x02E0 0x0000 0x0 0x0
+#define MX6SLL_PAD_REF_CLK_24M__I2C3_SCL                          0x0018 0x02E0 0x068C 0x1 0x0
+#define MX6SLL_PAD_REF_CLK_24M__PWM3_OUT                          0x0018 0x02E0 0x0000 0x2 0x0
+#define MX6SLL_PAD_REF_CLK_24M__USB_OTG2_ID                       0x0018 0x02E0 0x0560 0x3 0x0
+#define MX6SLL_PAD_REF_CLK_24M__CCM_PMIC_READY                    0x0018 0x02E0 0x05AC 0x4 0x0
+#define MX6SLL_PAD_REF_CLK_24M__GPIO3_IO21                        0x0018 0x02E0 0x0000 0x5 0x0
+#define MX6SLL_PAD_REF_CLK_24M__SD3_WP                            0x0018 0x02E0 0x0794 0x6 0x0
+#define MX6SLL_PAD_REF_CLK_32K__XTALOSC_REF_CLK_32K               0x001C 0x02E4 0x0000 0x0 0x0
+#define MX6SLL_PAD_REF_CLK_32K__I2C3_SDA                          0x001C 0x02E4 0x0690 0x1 0x0
+#define MX6SLL_PAD_REF_CLK_32K__PWM4_OUT                          0x001C 0x02E4 0x0000 0x2 0x0
+#define MX6SLL_PAD_REF_CLK_32K__USB_OTG1_ID                       0x001C 0x02E4 0x055C 0x3 0x0
+#define MX6SLL_PAD_REF_CLK_32K__SD1_LCTL                          0x001C 0x02E4 0x0000 0x4 0x0
+#define MX6SLL_PAD_REF_CLK_32K__GPIO3_IO22                        0x001C 0x02E4 0x0000 0x5 0x0
+#define MX6SLL_PAD_REF_CLK_32K__SD3_CD_B                          0x001C 0x02E4 0x0780 0x6 0x0
+#define MX6SLL_PAD_PWM1__PWM1_OUT                                 0x0020 0x02E8 0x0000 0x0 0x0
+#define MX6SLL_PAD_PWM1__CCM_CLKO                                 0x0020 0x02E8 0x0000 0x1 0x0
+#define MX6SLL_PAD_PWM1__AUDIO_CLK_OUT                            0x0020 0x02E8 0x0000 0x2 0x0
+#define MX6SLL_PAD_PWM1__CSI_MCLK                                 0x0020 0x02E8 0x0000 0x4 0x0
+#define MX6SLL_PAD_PWM1__GPIO3_IO23                               0x0020 0x02E8 0x0000 0x5 0x0
+#define MX6SLL_PAD_PWM1__EPIT1_OUT                                0x0020 0x02E8 0x0000 0x6 0x0
+#define MX6SLL_PAD_KEY_COL0__KEY_COL0                             0x0024 0x02EC 0x06A0 0x0 0x0
+#define MX6SLL_PAD_KEY_COL0__I2C2_SCL                             0x0024 0x02EC 0x0684 0x1 0x0
+#define MX6SLL_PAD_KEY_COL0__LCD_DATA00                           0x0024 0x02EC 0x06D8 0x2 0x0
+#define MX6SLL_PAD_KEY_COL0__SD1_CD_B                             0x0024 0x02EC 0x0770 0x4 0x1
+#define MX6SLL_PAD_KEY_COL0__GPIO3_IO24                           0x0024 0x02EC 0x0000 0x5 0x0
+#define MX6SLL_PAD_KEY_ROW0__KEY_ROW0                             0x0028 0x02F0 0x06C0 0x0 0x0
+#define MX6SLL_PAD_KEY_ROW0__I2C2_SDA                             0x0028 0x02F0 0x0688 0x1 0x0
+#define MX6SLL_PAD_KEY_ROW0__LCD_DATA01                           0x0028 0x02F0 0x06DC 0x2 0x0
+#define MX6SLL_PAD_KEY_ROW0__SD1_WP                               0x0028 0x02F0 0x0774 0x4 0x1
+#define MX6SLL_PAD_KEY_ROW0__GPIO3_IO25                           0x0028 0x02F0 0x0000 0x5 0x0
+#define MX6SLL_PAD_KEY_COL1__KEY_COL1                             0x002C 0x02F4 0x06A4 0x0 0x0
+#define MX6SLL_PAD_KEY_COL1__ECSPI4_MOSI                          0x002C 0x02F4 0x0658 0x1 0x1
+#define MX6SLL_PAD_KEY_COL1__LCD_DATA02                           0x002C 0x02F4 0x06E0 0x2 0x0
+#define MX6SLL_PAD_KEY_COL1__SD3_DATA4                            0x002C 0x02F4 0x0784 0x4 0x0
+#define MX6SLL_PAD_KEY_COL1__GPIO3_IO26                           0x002C 0x02F4 0x0000 0x5 0x0
+#define MX6SLL_PAD_KEY_ROW1__KEY_ROW1                             0x0030 0x02F8 0x06C4 0x0 0x0
+#define MX6SLL_PAD_KEY_ROW1__ECSPI4_MISO                          0x0030 0x02F8 0x0654 0x1 0x1
+#define MX6SLL_PAD_KEY_ROW1__LCD_DATA03                           0x0030 0x02F8 0x06E4 0x2 0x0
+#define MX6SLL_PAD_KEY_ROW1__CSI_FIELD                            0x0030 0x02F8 0x0000 0x3 0x0
+#define MX6SLL_PAD_KEY_ROW1__SD3_DATA5                            0x0030 0x02F8 0x0788 0x4 0x0
+#define MX6SLL_PAD_KEY_ROW1__GPIO3_IO27                           0x0030 0x02F8 0x0000 0x5 0x0
+#define MX6SLL_PAD_KEY_COL2__KEY_COL2                             0x0034 0x02FC 0x06A8 0x0 0x0
+#define MX6SLL_PAD_KEY_COL2__ECSPI4_SS0                           0x0034 0x02FC 0x065C 0x1 0x1
+#define MX6SLL_PAD_KEY_COL2__LCD_DATA04                           0x0034 0x02FC 0x06E8 0x2 0x0
+#define MX6SLL_PAD_KEY_COL2__CSI_DATA12                           0x0034 0x02FC 0x05B8 0x3 0x1
+#define MX6SLL_PAD_KEY_COL2__SD3_DATA6                            0x0034 0x02FC 0x078C 0x4 0x0
+#define MX6SLL_PAD_KEY_COL2__GPIO3_IO28                           0x0034 0x02FC 0x0000 0x5 0x0
+#define MX6SLL_PAD_KEY_ROW2__KEY_ROW2                             0x0038 0x0300 0x06C8 0x0 0x0
+#define MX6SLL_PAD_KEY_ROW2__ECSPI4_SCLK                          0x0038 0x0300 0x0650 0x1 0x1
+#define MX6SLL_PAD_KEY_ROW2__LCD_DATA05                           0x0038 0x0300 0x06EC 0x2 0x0
+#define MX6SLL_PAD_KEY_ROW2__CSI_DATA13                           0x0038 0x0300 0x05BC 0x3 0x1
+#define MX6SLL_PAD_KEY_ROW2__SD3_DATA7                            0x0038 0x0300 0x0790 0x4 0x0
+#define MX6SLL_PAD_KEY_ROW2__GPIO3_IO29                           0x0038 0x0300 0x0000 0x5 0x0
+#define MX6SLL_PAD_KEY_COL3__KEY_COL3                             0x003C 0x0304 0x06AC 0x0 0x0
+#define MX6SLL_PAD_KEY_COL3__AUD6_RXFS                            0x003C 0x0304 0x05A0 0x1 0x1
+#define MX6SLL_PAD_KEY_COL3__LCD_DATA06                           0x003C 0x0304 0x06F0 0x2 0x0
+#define MX6SLL_PAD_KEY_COL3__CSI_DATA14                           0x003C 0x0304 0x05C0 0x3 0x1
+#define MX6SLL_PAD_KEY_COL3__GPIO3_IO30                           0x003C 0x0304 0x0000 0x5 0x0
+#define MX6SLL_PAD_KEY_COL3__SD1_RESET                            0x003C 0x0304 0x0000 0x6 0x0
+#define MX6SLL_PAD_KEY_ROW3__KEY_ROW3                             0x0040 0x0308 0x06CC 0x0 0x1
+#define MX6SLL_PAD_KEY_ROW3__AUD6_RXC                             0x0040 0x0308 0x059C 0x1 0x1
+#define MX6SLL_PAD_KEY_ROW3__LCD_DATA07                           0x0040 0x0308 0x06F4 0x2 0x1
+#define MX6SLL_PAD_KEY_ROW3__CSI_DATA15                           0x0040 0x0308 0x05C4 0x3 0x2
+#define MX6SLL_PAD_KEY_ROW3__GPIO3_IO31                           0x0040 0x0308 0x0000 0x5 0x0
+#define MX6SLL_PAD_KEY_ROW3__SD1_VSELECT                          0x0040 0x0308 0x0000 0x6 0x0
+#define MX6SLL_PAD_KEY_COL4__KEY_COL4                             0x0044 0x030C 0x06B0 0x0 0x1
+#define MX6SLL_PAD_KEY_COL4__AUD6_RXD                             0x0044 0x030C 0x0594 0x1 0x1
+#define MX6SLL_PAD_KEY_COL4__LCD_DATA08                           0x0044 0x030C 0x06F8 0x2 0x1
+#define MX6SLL_PAD_KEY_COL4__CSI_DATA16                           0x0044 0x030C 0x0000 0x3 0x0
+#define MX6SLL_PAD_KEY_COL4__GPIO4_IO00                           0x0044 0x030C 0x0000 0x5 0x0
+#define MX6SLL_PAD_KEY_COL4__USB_OTG1_PWR                         0x0044 0x030C 0x0000 0x6 0x0
+#define MX6SLL_PAD_KEY_ROW4__KEY_ROW4                             0x0048 0x0310 0x06D0 0x0 0x1
+#define MX6SLL_PAD_KEY_ROW4__AUD6_TXC                             0x0048 0x0310 0x05A4 0x1 0x1
+#define MX6SLL_PAD_KEY_ROW4__LCD_DATA09                           0x0048 0x0310 0x06FC 0x2 0x1
+#define MX6SLL_PAD_KEY_ROW4__CSI_DATA17                           0x0048 0x0310 0x0000 0x3 0x0
+#define MX6SLL_PAD_KEY_ROW4__GPIO4_IO01                           0x0048 0x0310 0x0000 0x5 0x0
+#define MX6SLL_PAD_KEY_ROW4__USB_OTG1_OC                          0x0048 0x0310 0x076C 0x6 0x2
+#define MX6SLL_PAD_KEY_COL5__KEY_COL5                             0x004C 0x0314 0x0694 0x0 0x1
+#define MX6SLL_PAD_KEY_COL5__AUD6_TXFS                            0x004C 0x0314 0x05A8 0x1 0x1
+#define MX6SLL_PAD_KEY_COL5__LCD_DATA10                           0x004C 0x0314 0x0700 0x2 0x0
+#define MX6SLL_PAD_KEY_COL5__CSI_DATA18                           0x004C 0x0314 0x0000 0x3 0x0
+#define MX6SLL_PAD_KEY_COL5__GPIO4_IO02                           0x004C 0x0314 0x0000 0x5 0x0
+#define MX6SLL_PAD_KEY_COL5__USB_OTG2_PWR                         0x004C 0x0314 0x0000 0x6 0x0
+#define MX6SLL_PAD_KEY_ROW5__KEY_ROW5                             0x0050 0x0318 0x06B4 0x0 0x2
+#define MX6SLL_PAD_KEY_ROW5__AUD6_TXD                             0x0050 0x0318 0x0598 0x1 0x1
+#define MX6SLL_PAD_KEY_ROW5__LCD_DATA11                           0x0050 0x0318 0x0704 0x2 0x1
+#define MX6SLL_PAD_KEY_ROW5__CSI_DATA19                           0x0050 0x0318 0x0000 0x3 0x0
+#define MX6SLL_PAD_KEY_ROW5__GPIO4_IO03                           0x0050 0x0318 0x0000 0x5 0x0
+#define MX6SLL_PAD_KEY_ROW5__USB_OTG2_OC                          0x0050 0x0318 0x0768 0x6 0x3
+#define MX6SLL_PAD_KEY_COL6__KEY_COL6                             0x0054 0x031C 0x0698 0x0 0x2
+#define MX6SLL_PAD_KEY_COL6__UART4_DCE_RX                         0x0054 0x031C 0x075C 0x1 0x2
+#define MX6SLL_PAD_KEY_COL6__UART4_DTE_TX                         0x0054 0x031C 0x0000 0x1 0x0
+#define MX6SLL_PAD_KEY_COL6__LCD_DATA12                           0x0054 0x031C 0x0708 0x2 0x1
+#define MX6SLL_PAD_KEY_COL6__CSI_DATA20                           0x0054 0x031C 0x0000 0x3 0x0
+#define MX6SLL_PAD_KEY_COL6__GPIO4_IO04                           0x0054 0x031C 0x0000 0x5 0x0
+#define MX6SLL_PAD_KEY_COL6__SD3_RESET                            0x0054 0x031C 0x0000 0x6 0x0
+#define MX6SLL_PAD_KEY_ROW6__KEY_ROW6                             0x0058 0x0320 0x06B8 0x0 0x2
+#define MX6SLL_PAD_KEY_ROW6__UART4_DCE_TX                         0x0058 0x0320 0x0000 0x1 0x0
+#define MX6SLL_PAD_KEY_ROW6__UART4_DTE_RX                         0x0058 0x0320 0x075C 0x1 0x3
+#define MX6SLL_PAD_KEY_ROW6__LCD_DATA13                           0x0058 0x0320 0x070C 0x2 0x1
+#define MX6SLL_PAD_KEY_ROW6__CSI_DATA21                           0x0058 0x0320 0x0000 0x3 0x0
+#define MX6SLL_PAD_KEY_ROW6__GPIO4_IO05                           0x0058 0x0320 0x0000 0x5 0x0
+#define MX6SLL_PAD_KEY_ROW6__SD3_VSELECT                          0x0058 0x0320 0x0000 0x6 0x0
+#define MX6SLL_PAD_KEY_COL7__KEY_COL7                             0x005C 0x0324 0x069C 0x0 0x2
+#define MX6SLL_PAD_KEY_COL7__UART4_DCE_RTS                        0x005C 0x0324 0x0758 0x1 0x2
+#define MX6SLL_PAD_KEY_COL7__UART4_DTE_CTS                        0x005C 0x0324 0x0000 0x1 0x0
+#define MX6SLL_PAD_KEY_COL7__LCD_DATA14                           0x005C 0x0324 0x0710 0x2 0x1
+#define MX6SLL_PAD_KEY_COL7__CSI_DATA22                           0x005C 0x0324 0x0000 0x3 0x0
+#define MX6SLL_PAD_KEY_COL7__GPIO4_IO06                           0x005C 0x0324 0x0000 0x5 0x0
+#define MX6SLL_PAD_KEY_COL7__SD1_WP                               0x005C 0x0324 0x0774 0x6 0x3
+#define MX6SLL_PAD_KEY_ROW7__KEY_ROW7                             0x0060 0x0328 0x06BC 0x0 0x2
+#define MX6SLL_PAD_KEY_ROW7__UART4_DCE_CTS                        0x0060 0x0328 0x0000 0x1 0x0
+#define MX6SLL_PAD_KEY_ROW7__UART4_DTE_RTS                        0x0060 0x0328 0x0758 0x1 0x3
+#define MX6SLL_PAD_KEY_ROW7__LCD_DATA15                           0x0060 0x0328 0x0714 0x2 0x1
+#define MX6SLL_PAD_KEY_ROW7__CSI_DATA23                           0x0060 0x0328 0x0000 0x3 0x0
+#define MX6SLL_PAD_KEY_ROW7__GPIO4_IO07                           0x0060 0x0328 0x0000 0x5 0x0
+#define MX6SLL_PAD_KEY_ROW7__SD1_CD_B                             0x0060 0x0328 0x0770 0x6 0x3
+#define MX6SLL_PAD_EPDC_DATA00__EPDC_DATA00                       0x0064 0x032C 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_DATA00__ECSPI4_MOSI                       0x0064 0x032C 0x0658 0x1 0x2
+#define MX6SLL_PAD_EPDC_DATA00__LCD_DATA24                        0x0064 0x032C 0x0000 0x2 0x0
+#define MX6SLL_PAD_EPDC_DATA00__CSI_DATA00                        0x0064 0x032C 0x05C8 0x3 0x2
+#define MX6SLL_PAD_EPDC_DATA00__GPIO1_IO07                        0x0064 0x032C 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_DATA01__EPDC_DATA01                       0x0068 0x0330 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_DATA01__ECSPI4_MISO                       0x0068 0x0330 0x0654 0x1 0x2
+#define MX6SLL_PAD_EPDC_DATA01__LCD_DATA25                        0x0068 0x0330 0x0000 0x2 0x0
+#define MX6SLL_PAD_EPDC_DATA01__CSI_DATA01                        0x0068 0x0330 0x05CC 0x3 0x2
+#define MX6SLL_PAD_EPDC_DATA01__GPIO1_IO08                        0x0068 0x0330 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_DATA02__EPDC_DATA02                       0x006C 0x0334 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_DATA02__ECSPI4_SS0                        0x006C 0x0334 0x065C 0x1 0x2
+#define MX6SLL_PAD_EPDC_DATA02__LCD_DATA26                        0x006C 0x0334 0x0000 0x2 0x0
+#define MX6SLL_PAD_EPDC_DATA02__CSI_DATA02                        0x006C 0x0334 0x05D0 0x3 0x2
+#define MX6SLL_PAD_EPDC_DATA02__GPIO1_IO09                        0x006C 0x0334 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_DATA03__EPDC_DATA03                       0x0070 0x0338 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_DATA03__ECSPI4_SCLK                       0x0070 0x0338 0x0650 0x1 0x2
+#define MX6SLL_PAD_EPDC_DATA03__LCD_DATA27                        0x0070 0x0338 0x0000 0x2 0x0
+#define MX6SLL_PAD_EPDC_DATA03__CSI_DATA03                        0x0070 0x0338 0x05D4 0x3 0x2
+#define MX6SLL_PAD_EPDC_DATA03__GPIO1_IO10                        0x0070 0x0338 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_DATA04__EPDC_DATA04                       0x0074 0x033C 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_DATA04__ECSPI4_SS1                        0x0074 0x033C 0x0660 0x1 0x1
+#define MX6SLL_PAD_EPDC_DATA04__LCD_DATA28                        0x0074 0x033C 0x0000 0x2 0x0
+#define MX6SLL_PAD_EPDC_DATA04__CSI_DATA04                        0x0074 0x033C 0x05D8 0x3 0x2
+#define MX6SLL_PAD_EPDC_DATA04__GPIO1_IO11                        0x0074 0x033C 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_DATA05__EPDC_DATA05                       0x0078 0x0340 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_DATA05__ECSPI4_SS2                        0x0078 0x0340 0x0664 0x1 0x1
+#define MX6SLL_PAD_EPDC_DATA05__LCD_DATA29                        0x0078 0x0340 0x0000 0x2 0x0
+#define MX6SLL_PAD_EPDC_DATA05__CSI_DATA05                        0x0078 0x0340 0x05DC 0x3 0x2
+#define MX6SLL_PAD_EPDC_DATA05__GPIO1_IO12                        0x0078 0x0340 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_DATA06__EPDC_DATA06                       0x007C 0x0344 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_DATA06__ECSPI4_SS3                        0x007C 0x0344 0x0000 0x1 0x0
+#define MX6SLL_PAD_EPDC_DATA06__LCD_DATA30                        0x007C 0x0344 0x0000 0x2 0x0
+#define MX6SLL_PAD_EPDC_DATA06__CSI_DATA06                        0x007C 0x0344 0x05E0 0x3 0x2
+#define MX6SLL_PAD_EPDC_DATA06__GPIO1_IO13                        0x007C 0x0344 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_DATA07__EPDC_DATA07                       0x0080 0x0348 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_DATA07__ECSPI4_RDY                        0x0080 0x0348 0x0000 0x1 0x0
+#define MX6SLL_PAD_EPDC_DATA07__LCD_DATA31                        0x0080 0x0348 0x0000 0x2 0x0
+#define MX6SLL_PAD_EPDC_DATA07__CSI_DATA07                        0x0080 0x0348 0x05E4 0x3 0x2
+#define MX6SLL_PAD_EPDC_DATA07__GPIO1_IO14                        0x0080 0x0348 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_DATA08__EPDC_DATA08                       0x0084 0x034C 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_DATA08__ECSPI3_MOSI                       0x0084 0x034C 0x063C 0x1 0x2
+#define MX6SLL_PAD_EPDC_DATA08__EPDC_PWR_CTRL0                    0x0084 0x034C 0x0000 0x2 0x0
+#define MX6SLL_PAD_EPDC_DATA08__GPIO1_IO15                        0x0084 0x034C 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_DATA09__EPDC_DATA09                       0x0088 0x0350 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_DATA09__ECSPI3_MISO                       0x0088 0x0350 0x0638 0x1 0x2
+#define MX6SLL_PAD_EPDC_DATA09__EPDC_PWR_CTRL1                    0x0088 0x0350 0x0000 0x2 0x0
+#define MX6SLL_PAD_EPDC_DATA09__GPIO1_IO16                        0x0088 0x0350 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_DATA10__EPDC_DATA10                       0x008C 0x0354 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_DATA10__ECSPI3_SS0                        0x008C 0x0354 0x0648 0x1 0x2
+#define MX6SLL_PAD_EPDC_DATA10__EPDC_PWR_CTRL2                    0x008C 0x0354 0x0000 0x2 0x0
+#define MX6SLL_PAD_EPDC_DATA10__GPIO1_IO17                        0x008C 0x0354 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_DATA11__EPDC_DATA11                       0x0090 0x0358 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_DATA11__ECSPI3_SCLK                       0x0090 0x0358 0x0630 0x1 0x2
+#define MX6SLL_PAD_EPDC_DATA11__EPDC_PWR_CTRL3                    0x0090 0x0358 0x0000 0x2 0x0
+#define MX6SLL_PAD_EPDC_DATA11__GPIO1_IO18                        0x0090 0x0358 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_DATA12__EPDC_DATA12                       0x0094 0x035C 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_DATA12__UART2_DCE_RX                      0x0094 0x035C 0x074C 0x1 0x4
+#define MX6SLL_PAD_EPDC_DATA12__UART2_DTE_TX                      0x0094 0x035C 0x0000 0x1 0x0
+#define MX6SLL_PAD_EPDC_DATA12__EPDC_PWR_COM                      0x0094 0x035C 0x0000 0x2 0x0
+#define MX6SLL_PAD_EPDC_DATA12__GPIO1_IO19                        0x0094 0x035C 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_DATA12__ECSPI3_SS1                        0x0094 0x035C 0x064C 0x6 0x1
+#define MX6SLL_PAD_EPDC_DATA13__EPDC_DATA13                       0x0098 0x0360 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_DATA13__UART2_DCE_TX                      0x0098 0x0360 0x0000 0x1 0x0
+#define MX6SLL_PAD_EPDC_DATA13__UART2_DTE_RX                      0x0098 0x0360 0x074C 0x1 0x5
+#define MX6SLL_PAD_EPDC_DATA13__EPDC_PWR_IRQ                      0x0098 0x0360 0x0668 0x2 0x0
+#define MX6SLL_PAD_EPDC_DATA13__GPIO1_IO20                        0x0098 0x0360 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_DATA13__ECSPI3_SS2                        0x0098 0x0360 0x0640 0x6 0x1
+#define MX6SLL_PAD_EPDC_DATA14__EPDC_DATA14                       0x009C 0x0364 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_DATA14__UART2_DCE_RTS                     0x009C 0x0364 0x0748 0x1 0x4
+#define MX6SLL_PAD_EPDC_DATA14__UART2_DTE_CTS                     0x009C 0x0364 0x0000 0x1 0x0
+#define MX6SLL_PAD_EPDC_DATA14__EPDC_PWR_STAT                     0x009C 0x0364 0x066C 0x2 0x0
+#define MX6SLL_PAD_EPDC_DATA14__GPIO1_IO21                        0x009C 0x0364 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_DATA14__ECSPI3_SS3                        0x009C 0x0364 0x0644 0x6 0x1
+#define MX6SLL_PAD_EPDC_DATA15__EPDC_DATA15                       0x00A0 0x0368 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_DATA15__UART2_DCE_CTS                     0x00A0 0x0368 0x0000 0x1 0x0
+#define MX6SLL_PAD_EPDC_DATA15__UART2_DTE_RTS                     0x00A0 0x0368 0x0748 0x1 0x5
+#define MX6SLL_PAD_EPDC_DATA15__EPDC_PWR_WAKE                     0x00A0 0x0368 0x0000 0x2 0x0
+#define MX6SLL_PAD_EPDC_DATA15__GPIO1_IO22                        0x00A0 0x0368 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_DATA15__ECSPI3_RDY                        0x00A0 0x0368 0x0634 0x6 0x1
+#define MX6SLL_PAD_EPDC_SDCLK__EPDC_SDCLK_P                       0x00A4 0x036C 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_SDCLK__ECSPI2_MOSI                        0x00A4 0x036C 0x0624 0x1 0x2
+#define MX6SLL_PAD_EPDC_SDCLK__I2C2_SCL                           0x00A4 0x036C 0x0684 0x2 0x2
+#define MX6SLL_PAD_EPDC_SDCLK__CSI_DATA08                         0x00A4 0x036C 0x05E8 0x3 0x2
+#define MX6SLL_PAD_EPDC_SDCLK__GPIO1_IO23                         0x00A4 0x036C 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_SDLE__EPDC_SDLE                           0x00A8 0x0370 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_SDLE__ECSPI2_MISO                         0x00A8 0x0370 0x0620 0x1 0x2
+#define MX6SLL_PAD_EPDC_SDLE__I2C2_SDA                            0x00A8 0x0370 0x0688 0x2 0x2
+#define MX6SLL_PAD_EPDC_SDLE__CSI_DATA09                          0x00A8 0x0370 0x05EC 0x3 0x2
+#define MX6SLL_PAD_EPDC_SDLE__GPIO1_IO24                          0x00A8 0x0370 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_SDOE__EPDC_SDOE                           0x00AC 0x0374 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_SDOE__ECSPI2_SS0                          0x00AC 0x0374 0x0628 0x1 0x1
+#define MX6SLL_PAD_EPDC_SDOE__CSI_DATA10                          0x00AC 0x0374 0x05B0 0x3 0x2
+#define MX6SLL_PAD_EPDC_SDOE__GPIO1_IO25                          0x00AC 0x0374 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_SDSHR__EPDC_SDSHR                         0x00B0 0x0378 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_SDSHR__ECSPI2_SCLK                        0x00B0 0x0378 0x061C 0x1 0x2
+#define MX6SLL_PAD_EPDC_SDSHR__EPDC_SDCE4                         0x00B0 0x0378 0x0000 0x2 0x0
+#define MX6SLL_PAD_EPDC_SDSHR__CSI_DATA11                         0x00B0 0x0378 0x05B4 0x3 0x2
+#define MX6SLL_PAD_EPDC_SDSHR__GPIO1_IO26                         0x00B0 0x0378 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_SDCE0__EPDC_SDCE0                         0x00B4 0x037C 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_SDCE0__ECSPI2_SS1                         0x00B4 0x037C 0x062C 0x1 0x1
+#define MX6SLL_PAD_EPDC_SDCE0__PWM3_OUT                           0x00B4 0x037C 0x0000 0x2 0x0
+#define MX6SLL_PAD_EPDC_SDCE0__GPIO1_IO27                         0x00B4 0x037C 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_SDCE1__EPDC_SDCE1                         0x00B8 0x0380 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_SDCE1__WDOG2_B                            0x00B8 0x0380 0x0000 0x1 0x0
+#define MX6SLL_PAD_EPDC_SDCE1__PWM4_OUT                           0x00B8 0x0380 0x0000 0x2 0x0
+#define MX6SLL_PAD_EPDC_SDCE1__GPIO1_IO28                         0x00B8 0x0380 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_SDCE2__EPDC_SDCE2                         0x00BC 0x0384 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_SDCE2__I2C3_SCL                           0x00BC 0x0384 0x068C 0x1 0x2
+#define MX6SLL_PAD_EPDC_SDCE2__PWM1_OUT                           0x00BC 0x0384 0x0000 0x2 0x0
+#define MX6SLL_PAD_EPDC_SDCE2__GPIO1_IO29                         0x00BC 0x0384 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_SDCE3__EPDC_SDCE3                         0x00C0 0x0388 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_SDCE3__I2C3_SDA                           0x00C0 0x0388 0x0690 0x1 0x2
+#define MX6SLL_PAD_EPDC_SDCE3__PWM2_OUT                           0x00C0 0x0388 0x0000 0x2 0x0
+#define MX6SLL_PAD_EPDC_SDCE3__GPIO1_IO30                         0x00C0 0x0388 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_GDCLK__EPDC_GDCLK                         0x00C4 0x038C 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_GDCLK__ECSPI2_SS2                         0x00C4 0x038C 0x0000 0x1 0x0
+#define MX6SLL_PAD_EPDC_GDCLK__CSI_PIXCLK                         0x00C4 0x038C 0x05F4 0x3 0x2
+#define MX6SLL_PAD_EPDC_GDCLK__GPIO1_IO31                         0x00C4 0x038C 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_GDCLK__SD2_RESET                          0x00C4 0x038C 0x0000 0x6 0x0
+#define MX6SLL_PAD_EPDC_GDOE__EPDC_GDOE                           0x00C8 0x0390 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_GDOE__ECSPI2_SS3                          0x00C8 0x0390 0x0000 0x1 0x0
+#define MX6SLL_PAD_EPDC_GDOE__CSI_HSYNC                           0x00C8 0x0390 0x05F0 0x3 0x2
+#define MX6SLL_PAD_EPDC_GDOE__GPIO2_IO00                          0x00C8 0x0390 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_GDOE__SD2_VSELECT                         0x00C8 0x0390 0x0000 0x6 0x0
+#define MX6SLL_PAD_EPDC_GDRL__EPDC_GDRL                           0x00CC 0x0394 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_GDRL__ECSPI2_RDY                          0x00CC 0x0394 0x0000 0x1 0x0
+#define MX6SLL_PAD_EPDC_GDRL__CSI_MCLK                            0x00CC 0x0394 0x0000 0x3 0x0
+#define MX6SLL_PAD_EPDC_GDRL__GPIO2_IO01                          0x00CC 0x0394 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_GDRL__SD2_WP                              0x00CC 0x0394 0x077C 0x6 0x2
+#define MX6SLL_PAD_EPDC_GDSP__EPDC_GDSP                           0x00D0 0x0398 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_GDSP__PWM4_OUT                            0x00D0 0x0398 0x0000 0x1 0x0
+#define MX6SLL_PAD_EPDC_GDSP__CSI_VSYNC                           0x00D0 0x0398 0x05F8 0x3 0x2
+#define MX6SLL_PAD_EPDC_GDSP__GPIO2_IO02                          0x00D0 0x0398 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_GDSP__SD2_CD_B                            0x00D0 0x0398 0x0778 0x6 0x2
+#define MX6SLL_PAD_EPDC_VCOM0__EPDC_VCOM0                         0x00D4 0x039C 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_VCOM0__AUD5_RXFS                          0x00D4 0x039C 0x0588 0x1 0x1
+#define MX6SLL_PAD_EPDC_VCOM0__UART3_DCE_RX                       0x00D4 0x039C 0x0754 0x2 0x4
+#define MX6SLL_PAD_EPDC_VCOM0__UART3_DTE_TX                       0x00D4 0x039C 0x0000 0x2 0x0
+#define MX6SLL_PAD_EPDC_VCOM0__GPIO2_IO03                         0x00D4 0x039C 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_VCOM0__EPDC_SDCE5                         0x00D4 0x039C 0x0000 0x6 0x0
+#define MX6SLL_PAD_EPDC_VCOM1__EPDC_VCOM1                         0x00D8 0x03A0 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_VCOM1__AUD5_RXD                           0x00D8 0x03A0 0x057C 0x1 0x1
+#define MX6SLL_PAD_EPDC_VCOM1__UART3_DCE_TX                       0x00D8 0x03A0 0x0000 0x2 0x0
+#define MX6SLL_PAD_EPDC_VCOM1__UART3_DTE_RX                       0x00D8 0x03A0 0x0754 0x2 0x5
+#define MX6SLL_PAD_EPDC_VCOM1__GPIO2_IO04                         0x00D8 0x03A0 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_VCOM1__EPDC_SDCE6                         0x00D8 0x03A0 0x0000 0x6 0x0
+#define MX6SLL_PAD_EPDC_BDR0__EPDC_BDR0                           0x00DC 0x03A4 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_BDR0__UART3_DCE_RTS                       0x00DC 0x03A4 0x0750 0x2 0x2
+#define MX6SLL_PAD_EPDC_BDR0__UART3_DTE_CTS                       0x00DC 0x03A4 0x0000 0x2 0x0
+#define MX6SLL_PAD_EPDC_BDR0__GPIO2_IO05                          0x00DC 0x03A4 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_BDR0__EPDC_SDCE7                          0x00DC 0x03A4 0x0000 0x6 0x0
+#define MX6SLL_PAD_EPDC_BDR1__EPDC_BDR1                           0x00E0 0x03A8 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_BDR1__UART3_DCE_CTS                       0x00E0 0x03A8 0x0000 0x2 0x0
+#define MX6SLL_PAD_EPDC_BDR1__UART3_DTE_RTS                       0x00E0 0x03A8 0x0750 0x2 0x3
+#define MX6SLL_PAD_EPDC_BDR1__GPIO2_IO06                          0x00E0 0x03A8 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_BDR1__EPDC_SDCE8                          0x00E0 0x03A8 0x0000 0x6 0x0
+#define MX6SLL_PAD_EPDC_PWR_CTRL0__EPDC_PWR_CTRL0                 0x00E4 0x03AC 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_PWR_CTRL0__AUD5_RXC                       0x00E4 0x03AC 0x0584 0x1 0x1
+#define MX6SLL_PAD_EPDC_PWR_CTRL0__LCD_DATA16                     0x00E4 0x03AC 0x0718 0x2 0x1
+#define MX6SLL_PAD_EPDC_PWR_CTRL0__GPIO2_IO07                     0x00E4 0x03AC 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_PWR_CTRL1__EPDC_PWR_CTRL1                 0x00E8 0x03B0 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_PWR_CTRL1__AUD5_TXFS                      0x00E8 0x03B0 0x0590 0x1 0x1
+#define MX6SLL_PAD_EPDC_PWR_CTRL1__LCD_DATA17                     0x00E8 0x03B0 0x071C 0x2 0x1
+#define MX6SLL_PAD_EPDC_PWR_CTRL1__GPIO2_IO08                     0x00E8 0x03B0 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_PWR_CTRL2__EPDC_PWR_CTRL2                 0x00EC 0x03B4 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_PWR_CTRL2__AUD5_TXD                       0x00EC 0x03B4 0x0580 0x1 0x1
+#define MX6SLL_PAD_EPDC_PWR_CTRL2__LCD_DATA18                     0x00EC 0x03B4 0x0720 0x2 0x1
+#define MX6SLL_PAD_EPDC_PWR_CTRL2__GPIO2_IO09                     0x00EC 0x03B4 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_PWR_CTRL3__EPDC_PWR_CTRL3                 0x00F0 0x03B8 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_PWR_CTRL3__AUD5_TXC                       0x00F0 0x03B8 0x058C 0x1 0x1
+#define MX6SLL_PAD_EPDC_PWR_CTRL3__LCD_DATA19                     0x00F0 0x03B8 0x0724 0x2 0x1
+#define MX6SLL_PAD_EPDC_PWR_CTRL3__GPIO2_IO10                     0x00F0 0x03B8 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_PWR_COM__EPDC_PWR_COM                     0x00F4 0x03BC 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_PWR_COM__LCD_DATA20                       0x00F4 0x03BC 0x0728 0x2 0x1
+#define MX6SLL_PAD_EPDC_PWR_COM__USB_OTG1_ID                      0x00F4 0x03BC 0x055C 0x4 0x4
+#define MX6SLL_PAD_EPDC_PWR_COM__GPIO2_IO11                       0x00F4 0x03BC 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_PWR_COM__SD3_RESET                        0x00F4 0x03BC 0x0000 0x6 0x0
+#define MX6SLL_PAD_EPDC_PWR_IRQ__EPDC_PWR_IRQ                     0x00F8 0x03C0 0x0668 0x0 0x1
+#define MX6SLL_PAD_EPDC_PWR_IRQ__LCD_DATA21                       0x00F8 0x03C0 0x072C 0x2 0x1
+#define MX6SLL_PAD_EPDC_PWR_IRQ__USB_OTG2_ID                      0x00F8 0x03C0 0x0560 0x4 0x3
+#define MX6SLL_PAD_EPDC_PWR_IRQ__GPIO2_IO12                       0x00F8 0x03C0 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_PWR_IRQ__SD3_VSELECT                      0x00F8 0x03C0 0x0000 0x6 0x0
+#define MX6SLL_PAD_EPDC_PWR_STAT__EPDC_PWR_STAT                   0x00FC 0x03C4 0x066C 0x0 0x1
+#define MX6SLL_PAD_EPDC_PWR_STAT__LCD_DATA22                      0x00FC 0x03C4 0x0730 0x2 0x1
+#define MX6SLL_PAD_EPDC_PWR_STAT__ARM_EVENTI                      0x00FC 0x03C4 0x0000 0x4 0x0
+#define MX6SLL_PAD_EPDC_PWR_STAT__GPIO2_IO13                      0x00FC 0x03C4 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_PWR_STAT__SD3_WP                          0x00FC 0x03C4 0x0794 0x6 0x2
+#define MX6SLL_PAD_EPDC_PWR_WAKE__EPDC_PWR_WAKE                   0x0100 0x03C8 0x0000 0x0 0x0
+#define MX6SLL_PAD_EPDC_PWR_WAKE__LCD_DATA23                      0x0100 0x03C8 0x0734 0x2 0x1
+#define MX6SLL_PAD_EPDC_PWR_WAKE__ARM_EVENTO                      0x0100 0x03C8 0x0000 0x4 0x0
+#define MX6SLL_PAD_EPDC_PWR_WAKE__GPIO2_IO14                      0x0100 0x03C8 0x0000 0x5 0x0
+#define MX6SLL_PAD_EPDC_PWR_WAKE__SD3_CD_B                        0x0100 0x03C8 0x0780 0x6 0x2
+#define MX6SLL_PAD_LCD_CLK__LCD_CLK                               0x0104 0x03CC 0x0000 0x0 0x0
+#define MX6SLL_PAD_LCD_CLK__LCD_WR_RWN                            0x0104 0x03CC 0x0000 0x2 0x0
+#define MX6SLL_PAD_LCD_CLK__PWM4_OUT                              0x0104 0x03CC 0x0000 0x4 0x0
+#define MX6SLL_PAD_LCD_CLK__GPIO2_IO15                            0x0104 0x03CC 0x0000 0x5 0x0
+#define MX6SLL_PAD_LCD_ENABLE__LCD_ENABLE                         0x0108 0x03D0 0x0000 0x0 0x0
+#define MX6SLL_PAD_LCD_ENABLE__LCD_RD_E                           0x0108 0x03D0 0x0000 0x2 0x0
+#define MX6SLL_PAD_LCD_ENABLE__UART2_DCE_RX                       0x0108 0x03D0 0x0000 0x4 0x0
+#define MX6SLL_PAD_LCD_ENABLE__UART2_DTE_TX                       0x0108 0x03D0 0x0000 0x4 0x0
+#define MX6SLL_PAD_LCD_ENABLE__GPIO2_IO16                         0x0108 0x03D0 0x0000 0x5 0x0
+#define MX6SLL_PAD_LCD_HSYNC__LCD_HSYNC                           0x010C 0x03D4 0x06D4 0x0 0x0
+#define MX6SLL_PAD_LCD_HSYNC__LCD_CS                              0x010C 0x03D4 0x0000 0x2 0x0
+#define MX6SLL_PAD_LCD_HSYNC__UART2_DCE_TX                        0x010C 0x03D4 0x0000 0x4 0x0
+#define MX6SLL_PAD_LCD_HSYNC__UART2_DTE_RX                        0x010C 0x03D4 0x074C 0x4 0x1
+#define MX6SLL_PAD_LCD_HSYNC__GPIO2_IO17                          0x010C 0x03D4 0x0000 0x5 0x0
+#define MX6SLL_PAD_LCD_HSYNC__ARM_TRACE_CLK                       0x010C 0x03D4 0x0000 0x6 0x0
+#define MX6SLL_PAD_LCD_VSYNC__LCD_VSYNC                           0x0110 0x03D8 0x0000 0x0 0x0
+#define MX6SLL_PAD_LCD_VSYNC__LCD_RS                              0x0110 0x03D8 0x0000 0x2 0x0
+#define MX6SLL_PAD_LCD_VSYNC__UART2_DCE_RTS                       0x0110 0x03D8 0x0748 0x4 0x0
+#define MX6SLL_PAD_LCD_VSYNC__UART2_DTE_CTS                       0x0110 0x03D8 0x0000 0x4 0x0
+#define MX6SLL_PAD_LCD_VSYNC__GPIO2_IO18                          0x0110 0x03D8 0x0000 0x5 0x0
+#define MX6SLL_PAD_LCD_VSYNC__ARM_TRACE_CTL                       0x0110 0x03D8 0x0000 0x6 0x0
+#define MX6SLL_PAD_LCD_RESET__LCD_RESET                           0x0114 0x03DC 0x0000 0x0 0x0
+#define MX6SLL_PAD_LCD_RESET__LCD_BUSY                            0x0114 0x03DC 0x06D4 0x2 0x1
+#define MX6SLL_PAD_LCD_RESET__UART2_DCE_CTS                       0x0114 0x03DC 0x0000 0x4 0x0
+#define MX6SLL_PAD_LCD_RESET__UART2_DTE_RTS                       0x0114 0x03DC 0x0748 0x4 0x1
+#define MX6SLL_PAD_LCD_RESET__GPIO2_IO19                          0x0114 0x03DC 0x0000 0x5 0x0
+#define MX6SLL_PAD_LCD_RESET__CCM_PMIC_READY                      0x0114 0x03DC 0x05AC 0x6 0x2
+#define MX6SLL_PAD_LCD_DATA00__LCD_DATA00                         0x0118 0x03E0 0x06D8 0x0 0x1
+#define MX6SLL_PAD_LCD_DATA00__ECSPI1_MOSI                        0x0118 0x03E0 0x0608 0x1 0x0
+#define MX6SLL_PAD_LCD_DATA00__USB_OTG2_ID                        0x0118 0x03E0 0x0560 0x2 0x2
+#define MX6SLL_PAD_LCD_DATA00__PWM1_OUT                           0x0118 0x03E0 0x0000 0x3 0x0
+#define MX6SLL_PAD_LCD_DATA00__UART5_DTR_B                        0x0118 0x03E0 0x0000 0x4 0x0
+#define MX6SLL_PAD_LCD_DATA00__GPIO2_IO20                         0x0118 0x03E0 0x0000 0x5 0x0
+#define MX6SLL_PAD_LCD_DATA00__ARM_TRACE00                        0x0118 0x03E0 0x0000 0x6 0x0
+#define MX6SLL_PAD_LCD_DATA00__SRC_BOOT_CFG00                     0x0118 0x03E0 0x0000 0x7 0x0
+#define MX6SLL_PAD_LCD_DATA01__LCD_DATA01                         0x011C 0x03E4 0x06DC 0x0 0x1
+#define MX6SLL_PAD_LCD_DATA01__ECSPI1_MISO                        0x011C 0x03E4 0x0604 0x1 0x0
+#define MX6SLL_PAD_LCD_DATA01__USB_OTG1_ID                        0x011C 0x03E4 0x055C 0x2 0x3
+#define MX6SLL_PAD_LCD_DATA01__PWM2_OUT                           0x011C 0x03E4 0x0000 0x3 0x0
+#define MX6SLL_PAD_LCD_DATA01__AUD4_RXFS                          0x011C 0x03E4 0x0570 0x4 0x0
+#define MX6SLL_PAD_LCD_DATA01__GPIO2_IO21                         0x011C 0x03E4 0x0000 0x5 0x0
+#define MX6SLL_PAD_LCD_DATA01__ARM_TRACE01                        0x011C 0x03E4 0x0000 0x6 0x0
+#define MX6SLL_PAD_LCD_DATA01__SRC_BOOT_CFG01                     0x011C 0x03E4 0x0000 0x7 0x0
+#define MX6SLL_PAD_LCD_DATA02__LCD_DATA02                         0x0120 0x03E8 0x06E0 0x0 0x1
+#define MX6SLL_PAD_LCD_DATA02__ECSPI1_SS0                         0x0120 0x03E8 0x0614 0x1 0x0
+#define MX6SLL_PAD_LCD_DATA02__EPIT2_OUT                          0x0120 0x03E8 0x0000 0x2 0x0
+#define MX6SLL_PAD_LCD_DATA02__PWM3_OUT                           0x0120 0x03E8 0x0000 0x3 0x0
+#define MX6SLL_PAD_LCD_DATA02__AUD4_RXC                           0x0120 0x03E8 0x056C 0x4 0x0
+#define MX6SLL_PAD_LCD_DATA02__GPIO2_IO22                         0x0120 0x03E8 0x0000 0x5 0x0
+#define MX6SLL_PAD_LCD_DATA02__ARM_TRACE02                        0x0120 0x03E8 0x0000 0x6 0x0
+#define MX6SLL_PAD_LCD_DATA02__SRC_BOOT_CFG02                     0x0120 0x03E8 0x0000 0x7 0x0
+#define MX6SLL_PAD_LCD_DATA03__LCD_DATA03                         0x0124 0x03EC 0x06E4 0x0 0x1
+#define MX6SLL_PAD_LCD_DATA03__ECSPI1_SCLK                        0x0124 0x03EC 0x05FC 0x1 0x0
+#define MX6SLL_PAD_LCD_DATA03__UART5_DSR_B                        0x0124 0x03EC 0x0000 0x2 0x0
+#define MX6SLL_PAD_LCD_DATA03__PWM4_OUT                           0x0124 0x03EC 0x0000 0x3 0x0
+#define MX6SLL_PAD_LCD_DATA03__AUD4_RXD                           0x0124 0x03EC 0x0564 0x4 0x0
+#define MX6SLL_PAD_LCD_DATA03__GPIO2_IO23                         0x0124 0x03EC 0x0000 0x5 0x0
+#define MX6SLL_PAD_LCD_DATA03__ARM_TRACE03                        0x0124 0x03EC 0x0000 0x6 0x0
+#define MX6SLL_PAD_LCD_DATA03__SRC_BOOT_CFG03                     0x0124 0x03EC 0x0000 0x7 0x0
+#define MX6SLL_PAD_LCD_DATA04__LCD_DATA04                         0x0128 0x03F0 0x06E8 0x0 0x1
+#define MX6SLL_PAD_LCD_DATA04__ECSPI1_SS1                         0x0128 0x03F0 0x060C 0x1 0x1
+#define MX6SLL_PAD_LCD_DATA04__CSI_VSYNC                          0x0128 0x03F0 0x05F8 0x2 0x0
+#define MX6SLL_PAD_LCD_DATA04__WDOG2_RESET_B_DEB                  0x0128 0x03F0 0x0000 0x3 0x0
+#define MX6SLL_PAD_LCD_DATA04__AUD4_TXC                           0x0128 0x03F0 0x0574 0x4 0x0
+#define MX6SLL_PAD_LCD_DATA04__GPIO2_IO24                         0x0128 0x03F0 0x0000 0x5 0x0
+#define MX6SLL_PAD_LCD_DATA04__ARM_TRACE04                        0x0128 0x03F0 0x0000 0x6 0x0
+#define MX6SLL_PAD_LCD_DATA04__SRC_BOOT_CFG04                     0x0128 0x03F0 0x0000 0x7 0x0
+#define MX6SLL_PAD_LCD_DATA05__LCD_DATA05                         0x012C 0x03F4 0x06EC 0x0 0x1
+#define MX6SLL_PAD_LCD_DATA05__ECSPI1_SS2                         0x012C 0x03F4 0x0610 0x1 0x1
+#define MX6SLL_PAD_LCD_DATA05__CSI_HSYNC                          0x012C 0x03F4 0x05F0 0x2 0x0
+#define MX6SLL_PAD_LCD_DATA05__AUD4_TXFS                          0x012C 0x03F4 0x0578 0x4 0x0
+#define MX6SLL_PAD_LCD_DATA05__GPIO2_IO25                         0x012C 0x03F4 0x0000 0x5 0x0
+#define MX6SLL_PAD_LCD_DATA05__ARM_TRACE05                        0x012C 0x03F4 0x0000 0x6 0x0
+#define MX6SLL_PAD_LCD_DATA05__SRC_BOOT_CFG05                     0x012C 0x03F4 0x0000 0x7 0x0
+#define MX6SLL_PAD_LCD_DATA06__LCD_DATA06                         0x0130 0x03F8 0x06F0 0x0 0x1
+#define MX6SLL_PAD_LCD_DATA06__ECSPI1_SS3                         0x0130 0x03F8 0x0618 0x1 0x0
+#define MX6SLL_PAD_LCD_DATA06__CSI_PIXCLK                         0x0130 0x03F8 0x05F4 0x2 0x0
+#define MX6SLL_PAD_LCD_DATA06__AUD4_TXD                           0x0130 0x03F8 0x0568 0x4 0x0
+#define MX6SLL_PAD_LCD_DATA06__GPIO2_IO26                         0x0130 0x03F8 0x0000 0x5 0x0
+#define MX6SLL_PAD_LCD_DATA06__ARM_TRACE06                        0x0130 0x03F8 0x0000 0x6 0x0
+#define MX6SLL_PAD_LCD_DATA06__SRC_BOOT_CFG06                     0x0130 0x03F8 0x0000 0x7 0x0
+#define MX6SLL_PAD_LCD_DATA07__LCD_DATA07                         0x0134 0x03FC 0x06F4 0x0 0x0
+#define MX6SLL_PAD_LCD_DATA07__ECSPI1_RDY                         0x0134 0x03FC 0x0600 0x1 0x0
+#define MX6SLL_PAD_LCD_DATA07__CSI_MCLK                           0x0134 0x03FC 0x0000 0x2 0x0
+#define MX6SLL_PAD_LCD_DATA07__AUDIO_CLK_OUT                      0x0134 0x03FC 0x0000 0x4 0x0
+#define MX6SLL_PAD_LCD_DATA07__GPIO2_IO27                         0x0134 0x03FC 0x0000 0x5 0x0
+#define MX6SLL_PAD_LCD_DATA07__ARM_TRACE07                        0x0134 0x03FC 0x0000 0x6 0x0
+#define MX6SLL_PAD_LCD_DATA07__SRC_BOOT_CFG07                     0x0134 0x03FC 0x0000 0x7 0x0
+#define MX6SLL_PAD_LCD_DATA08__LCD_DATA08                         0x0138 0x0400 0x06F8 0x0 0x0
+#define MX6SLL_PAD_LCD_DATA08__KEY_COL0                           0x0138 0x0400 0x06A0 0x1 0x1
+#define MX6SLL_PAD_LCD_DATA08__CSI_DATA09                         0x0138 0x0400 0x05EC 0x2 0x0
+#define MX6SLL_PAD_LCD_DATA08__ECSPI2_SCLK                        0x0138 0x0400 0x061C 0x4 0x0
+#define MX6SLL_PAD_LCD_DATA08__GPIO2_IO28                         0x0138 0x0400 0x0000 0x5 0x0
+#define MX6SLL_PAD_LCD_DATA08__ARM_TRACE08                        0x0138 0x0400 0x0000 0x6 0x0
+#define MX6SLL_PAD_LCD_DATA08__SRC_BOOT_CFG08                     0x0138 0x0400 0x0000 0x7 0x0
+#define MX6SLL_PAD_LCD_DATA09__LCD_DATA09                         0x013C 0x0404 0x06FC 0x0 0x0
+#define MX6SLL_PAD_LCD_DATA09__KEY_ROW0                           0x013C 0x0404 0x06C0 0x1 0x1
+#define MX6SLL_PAD_LCD_DATA09__CSI_DATA08                         0x013C 0x0404 0x05E8 0x2 0x0
+#define MX6SLL_PAD_LCD_DATA09__ECSPI2_MOSI                        0x013C 0x0404 0x0624 0x4 0x0
+#define MX6SLL_PAD_LCD_DATA09__GPIO2_IO29                         0x013C 0x0404 0x0000 0x5 0x0
+#define MX6SLL_PAD_LCD_DATA09__ARM_TRACE09                        0x013C 0x0404 0x0000 0x6 0x0
+#define MX6SLL_PAD_LCD_DATA09__SRC_BOOT_CFG09                     0x013C 0x0404 0x0000 0x7 0x0
+#define MX6SLL_PAD_LCD_DATA10__LCD_DATA10                         0x0140 0x0408 0x0700 0x0 0x1
+#define MX6SLL_PAD_LCD_DATA10__KEY_COL1                           0x0140 0x0408 0x06A4 0x1 0x1
+#define MX6SLL_PAD_LCD_DATA10__CSI_DATA07                         0x0140 0x0408 0x05E4 0x2 0x0
+#define MX6SLL_PAD_LCD_DATA10__ECSPI2_MISO                        0x0140 0x0408 0x0620 0x4 0x0
+#define MX6SLL_PAD_LCD_DATA10__GPIO2_IO30                         0x0140 0x0408 0x0000 0x5 0x0
+#define MX6SLL_PAD_LCD_DATA10__ARM_TRACE10                        0x0140 0x0408 0x0000 0x6 0x0
+#define MX6SLL_PAD_LCD_DATA10__SRC_BOOT_CFG10                     0x0140 0x0408 0x0000 0x7 0x0
+#define MX6SLL_PAD_LCD_DATA11__LCD_DATA11                         0x0144 0x040C 0x0704 0x0 0x0
+#define MX6SLL_PAD_LCD_DATA11__KEY_ROW1                           0x0144 0x040C 0x06C4 0x1 0x1
+#define MX6SLL_PAD_LCD_DATA11__CSI_DATA06                         0x0144 0x040C 0x05E0 0x2 0x0
+#define MX6SLL_PAD_LCD_DATA11__ECSPI2_SS1                         0x0144 0x040C 0x062C 0x4 0x0
+#define MX6SLL_PAD_LCD_DATA11__GPIO2_IO31                         0x0144 0x040C 0x0000 0x5 0x0
+#define MX6SLL_PAD_LCD_DATA11__ARM_TRACE11                        0x0144 0x040C 0x0000 0x6 0x0
+#define MX6SLL_PAD_LCD_DATA11__SRC_BOOT_CFG11                     0x0144 0x040C 0x0000 0x7 0x0
+#define MX6SLL_PAD_LCD_DATA12__LCD_DATA12                         0x0148 0x0410 0x0708 0x0 0x0
+#define MX6SLL_PAD_LCD_DATA12__KEY_COL2                           0x0148 0x0410 0x06A8 0x1 0x1
+#define MX6SLL_PAD_LCD_DATA12__CSI_DATA05                         0x0148 0x0410 0x05DC 0x2 0x0
+#define MX6SLL_PAD_LCD_DATA12__UART5_DCE_RTS                      0x0148 0x0410 0x0760 0x4 0x0
+#define MX6SLL_PAD_LCD_DATA12__UART5_DTE_CTS                      0x0148 0x0410 0x0000 0x4 0x0
+#define MX6SLL_PAD_LCD_DATA12__GPIO3_IO00                         0x0148 0x0410 0x0000 0x5 0x0
+#define MX6SLL_PAD_LCD_DATA12__ARM_TRACE12                        0x0148 0x0410 0x0000 0x6 0x0
+#define MX6SLL_PAD_LCD_DATA12__SRC_BOOT_CFG12                     0x0148 0x0410 0x0000 0x7 0x0
+#define MX6SLL_PAD_LCD_DATA13__LCD_DATA13                         0x014C 0x0414 0x070C 0x0 0x0
+#define MX6SLL_PAD_LCD_DATA13__KEY_ROW2                           0x014C 0x0414 0x06C8 0x1 0x1
+#define MX6SLL_PAD_LCD_DATA13__CSI_DATA04                         0x014C 0x0414 0x05D8 0x2 0x0
+#define MX6SLL_PAD_LCD_DATA13__UART5_DCE_CTS                      0x014C 0x0414 0x0000 0x4 0x0
+#define MX6SLL_PAD_LCD_DATA13__UART5_DTE_RTS                      0x014C 0x0414 0x0760 0x4 0x1
+#define MX6SLL_PAD_LCD_DATA13__GPIO3_IO01                         0x014C 0x0414 0x0000 0x5 0x0
+#define MX6SLL_PAD_LCD_DATA13__ARM_TRACE13                        0x014C 0x0414 0x0000 0x6 0x0
+#define MX6SLL_PAD_LCD_DATA13__SRC_BOOT_CFG13                     0x014C 0x0414 0x0000 0x7 0x0
+#define MX6SLL_PAD_LCD_DATA14__LCD_DATA14                         0x0150 0x0418 0x0710 0x0 0x0
+#define MX6SLL_PAD_LCD_DATA14__KEY_COL3                           0x0150 0x0418 0x06AC 0x1 0x1
+#define MX6SLL_PAD_LCD_DATA14__CSI_DATA03                         0x0150 0x0418 0x05D4 0x2 0x0
+#define MX6SLL_PAD_LCD_DATA14__UART5_DCE_RX                       0x0150 0x0418 0x0764 0x4 0x0
+#define MX6SLL_PAD_LCD_DATA14__UART5_DTE_TX                       0x0150 0x0418 0x0000 0x4 0x0
+#define MX6SLL_PAD_LCD_DATA14__GPIO3_IO02                         0x0150 0x0418 0x0000 0x5 0x0
+#define MX6SLL_PAD_LCD_DATA14__ARM_TRACE14                        0x0150 0x0418 0x0000 0x6 0x0
+#define MX6SLL_PAD_LCD_DATA14__SRC_BOOT_CFG14                     0x0150 0x0418 0x0000 0x7 0x0
+#define MX6SLL_PAD_LCD_DATA15__LCD_DATA15                         0x0154 0x041C 0x0714 0x0 0x0
+#define MX6SLL_PAD_LCD_DATA15__KEY_ROW3                           0x0154 0x041C 0x06CC 0x1 0x0
+#define MX6SLL_PAD_LCD_DATA15__CSI_DATA02                         0x0154 0x041C 0x05D0 0x2 0x0
+#define MX6SLL_PAD_LCD_DATA15__UART5_DCE_TX                       0x0154 0x041C 0x0000 0x4 0x0
+#define MX6SLL_PAD_LCD_DATA15__UART5_DTE_RX                       0x0154 0x041C 0x0764 0x4 0x1
+#define MX6SLL_PAD_LCD_DATA15__GPIO3_IO03                         0x0154 0x041C 0x0000 0x5 0x0
+#define MX6SLL_PAD_LCD_DATA15__ARM_TRACE15                        0x0154 0x041C 0x0000 0x6 0x0
+#define MX6SLL_PAD_LCD_DATA15__SRC_BOOT_CFG15                     0x0154 0x041C 0x0000 0x7 0x0
+#define MX6SLL_PAD_LCD_DATA16__LCD_DATA16                         0x0158 0x0420 0x0718 0x0 0x0
+#define MX6SLL_PAD_LCD_DATA16__KEY_COL4                           0x0158 0x0420 0x06B0 0x1 0x0
+#define MX6SLL_PAD_LCD_DATA16__CSI_DATA01                         0x0158 0x0420 0x05CC 0x2 0x0
+#define MX6SLL_PAD_LCD_DATA16__I2C2_SCL                           0x0158 0x0420 0x0684 0x4 0x1
+#define MX6SLL_PAD_LCD_DATA16__GPIO3_IO04                         0x0158 0x0420 0x0000 0x5 0x0
+#define MX6SLL_PAD_LCD_DATA16__SRC_BOOT_CFG24                     0x0158 0x0420 0x0000 0x7 0x0
+#define MX6SLL_PAD_LCD_DATA17__LCD_DATA17                         0x015C 0x0424 0x071C 0x0 0x0
+#define MX6SLL_PAD_LCD_DATA17__KEY_ROW4                           0x015C 0x0424 0x06D0 0x1 0x0
+#define MX6SLL_PAD_LCD_DATA17__CSI_DATA00                         0x015C 0x0424 0x05C8 0x2 0x0
+#define MX6SLL_PAD_LCD_DATA17__I2C2_SDA                           0x015C 0x0424 0x0688 0x4 0x1
+#define MX6SLL_PAD_LCD_DATA17__GPIO3_IO05                         0x015C 0x0424 0x0000 0x5 0x0
+#define MX6SLL_PAD_LCD_DATA17__SRC_BOOT_CFG25                     0x015C 0x0424 0x0000 0x7 0x0
+#define MX6SLL_PAD_LCD_DATA18__LCD_DATA18                         0x0160 0x0428 0x0720 0x0 0x0
+#define MX6SLL_PAD_LCD_DATA18__KEY_COL5                           0x0160 0x0428 0x0694 0x1 0x2
+#define MX6SLL_PAD_LCD_DATA18__CSI_DATA15                         0x0160 0x0428 0x05C4 0x2 0x1
+#define MX6SLL_PAD_LCD_DATA18__GPT_CAPTURE1                       0x0160 0x0428 0x0670 0x4 0x1
+#define MX6SLL_PAD_LCD_DATA18__GPIO3_IO06                         0x0160 0x0428 0x0000 0x5 0x0
+#define MX6SLL_PAD_LCD_DATA18__SRC_BOOT_CFG26                     0x0160 0x0428 0x0000 0x7 0x0
+#define MX6SLL_PAD_LCD_DATA19__LCD_DATA19                         0x0164 0x042C 0x0724 0x0 0x0
+#define MX6SLL_PAD_LCD_DATA19__KEY_ROW5                           0x0164 0x042C 0x06B4 0x1 0x1
+#define MX6SLL_PAD_LCD_DATA19__CSI_DATA14                         0x0164 0x042C 0x05C0 0x2 0x2
+#define MX6SLL_PAD_LCD_DATA19__GPT_CAPTURE2                       0x0164 0x042C 0x0674 0x4 0x1
+#define MX6SLL_PAD_LCD_DATA19__GPIO3_IO07                         0x0164 0x042C 0x0000 0x5 0x0
+#define MX6SLL_PAD_LCD_DATA19__SRC_BOOT_CFG27                     0x0164 0x042C 0x0000 0x7 0x0
+#define MX6SLL_PAD_LCD_DATA20__LCD_DATA20                         0x0168 0x0430 0x0728 0x0 0x0
+#define MX6SLL_PAD_LCD_DATA20__KEY_COL6                           0x0168 0x0430 0x0698 0x1 0x1
+#define MX6SLL_PAD_LCD_DATA20__CSI_DATA13                         0x0168 0x0430 0x05BC 0x2 0x2
+#define MX6SLL_PAD_LCD_DATA20__GPT_COMPARE1                       0x0168 0x0430 0x0000 0x4 0x0
+#define MX6SLL_PAD_LCD_DATA20__GPIO3_IO08                         0x0168 0x0430 0x0000 0x5 0x0
+#define MX6SLL_PAD_LCD_DATA20__SRC_BOOT_CFG28                     0x0168 0x0430 0x0000 0x7 0x0
+#define MX6SLL_PAD_LCD_DATA21__LCD_DATA21                         0x016C 0x0434 0x072C 0x0 0x0
+#define MX6SLL_PAD_LCD_DATA21__KEY_ROW6                           0x016C 0x0434 0x06B8 0x1 0x1
+#define MX6SLL_PAD_LCD_DATA21__CSI_DATA12                         0x016C 0x0434 0x05B8 0x2 0x2
+#define MX6SLL_PAD_LCD_DATA21__GPT_COMPARE2                       0x016C 0x0434 0x0000 0x4 0x0
+#define MX6SLL_PAD_LCD_DATA21__GPIO3_IO09                         0x016C 0x0434 0x0000 0x5 0x0
+#define MX6SLL_PAD_LCD_DATA21__SRC_BOOT_CFG29                     0x016C 0x0434 0x0000 0x7 0x0
+#define MX6SLL_PAD_LCD_DATA22__LCD_DATA22                         0x0170 0x0438 0x0730 0x0 0x0
+#define MX6SLL_PAD_LCD_DATA22__KEY_COL7                           0x0170 0x0438 0x069C 0x1 0x1
+#define MX6SLL_PAD_LCD_DATA22__CSI_DATA11                         0x0170 0x0438 0x05B4 0x2 0x1
+#define MX6SLL_PAD_LCD_DATA22__GPT_COMPARE3                       0x0170 0x0438 0x0000 0x4 0x0
+#define MX6SLL_PAD_LCD_DATA22__GPIO3_IO10                         0x0170 0x0438 0x0000 0x5 0x0
+#define MX6SLL_PAD_LCD_DATA22__SRC_BOOT_CFG30                     0x0170 0x0438 0x0000 0x7 0x0
+#define MX6SLL_PAD_LCD_DATA23__LCD_DATA23                         0x0174 0x043C 0x0734 0x0 0x0
+#define MX6SLL_PAD_LCD_DATA23__KEY_ROW7                           0x0174 0x043C 0x06BC 0x1 0x1
+#define MX6SLL_PAD_LCD_DATA23__CSI_DATA10                         0x0174 0x043C 0x05B0 0x2 0x1
+#define MX6SLL_PAD_LCD_DATA23__GPT_CLKIN                          0x0174 0x043C 0x0678 0x4 0x1
+#define MX6SLL_PAD_LCD_DATA23__GPIO3_IO11                         0x0174 0x043C 0x0000 0x5 0x0
+#define MX6SLL_PAD_LCD_DATA23__SRC_BOOT_CFG31                     0x0174 0x043C 0x0000 0x7 0x0
+#define MX6SLL_PAD_AUD_RXFS__AUD3_RXFS                            0x0178 0x0440 0x0000 0x0 0x0
+#define MX6SLL_PAD_AUD_RXFS__I2C1_SCL                             0x0178 0x0440 0x067C 0x1 0x1
+#define MX6SLL_PAD_AUD_RXFS__UART3_DCE_RX                         0x0178 0x0440 0x0754 0x2 0x0
+#define MX6SLL_PAD_AUD_RXFS__UART3_DTE_TX                         0x0178 0x0440 0x0000 0x2 0x0
+#define MX6SLL_PAD_AUD_RXFS__I2C3_SCL                             0x0178 0x0440 0x068C 0x4 0x1
+#define MX6SLL_PAD_AUD_RXFS__GPIO1_IO00                           0x0178 0x0440 0x0000 0x5 0x0
+#define MX6SLL_PAD_AUD_RXFS__ECSPI3_SS0                           0x0178 0x0440 0x0648 0x6 0x0
+#define MX6SLL_PAD_AUD_RXFS__MBIST_BEND                           0x0178 0x0440 0x0000 0x7 0x0
+#define MX6SLL_PAD_AUD_RXC__AUD3_RXC                              0x017C 0x0444 0x0000 0x0 0x0
+#define MX6SLL_PAD_AUD_RXC__I2C1_SDA                              0x017C 0x0444 0x0680 0x1 0x1
+#define MX6SLL_PAD_AUD_RXC__UART3_DCE_TX                          0x017C 0x0444 0x0000 0x2 0x0
+#define MX6SLL_PAD_AUD_RXC__UART3_DTE_RX                          0x017C 0x0444 0x0754 0x2 0x1
+#define MX6SLL_PAD_AUD_RXC__I2C3_SDA                              0x017C 0x0444 0x0690 0x4 0x1
+#define MX6SLL_PAD_AUD_RXC__GPIO1_IO01                            0x017C 0x0444 0x0000 0x5 0x0
+#define MX6SLL_PAD_AUD_RXC__ECSPI3_SS1                            0x017C 0x0444 0x064C 0x6 0x0
+#define MX6SLL_PAD_AUD_RXD__AUD3_RXD                              0x0180 0x0448 0x0000 0x0 0x0
+#define MX6SLL_PAD_AUD_RXD__ECSPI3_MOSI                           0x0180 0x0448 0x063C 0x1 0x0
+#define MX6SLL_PAD_AUD_RXD__UART4_DCE_RX                          0x0180 0x0448 0x075C 0x2 0x0
+#define MX6SLL_PAD_AUD_RXD__UART4_DTE_TX                          0x0180 0x0448 0x0000 0x2 0x0
+#define MX6SLL_PAD_AUD_RXD__SD1_LCTL                              0x0180 0x0448 0x0000 0x4 0x0
+#define MX6SLL_PAD_AUD_RXD__GPIO1_IO02                            0x0180 0x0448 0x0000 0x5 0x0
+#define MX6SLL_PAD_AUD_TXC__AUD3_TXC                              0x0184 0x044C 0x0000 0x0 0x0
+#define MX6SLL_PAD_AUD_TXC__ECSPI3_MISO                           0x0184 0x044C 0x0638 0x1 0x0
+#define MX6SLL_PAD_AUD_TXC__UART4_DCE_TX                          0x0184 0x044C 0x0000 0x2 0x0
+#define MX6SLL_PAD_AUD_TXC__UART4_DTE_RX                          0x0184 0x044C 0x075C 0x2 0x1
+#define MX6SLL_PAD_AUD_TXC__SD2_LCTL                              0x0184 0x044C 0x0000 0x4 0x0
+#define MX6SLL_PAD_AUD_TXC__GPIO1_IO03                            0x0184 0x044C 0x0000 0x5 0x0
+#define MX6SLL_PAD_AUD_TXFS__AUD3_TXFS                            0x0188 0x0450 0x0000 0x0 0x0
+#define MX6SLL_PAD_AUD_TXFS__PWM3_OUT                             0x0188 0x0450 0x0000 0x1 0x0
+#define MX6SLL_PAD_AUD_TXFS__UART4_DCE_RTS                        0x0188 0x0450 0x0758 0x2 0x0
+#define MX6SLL_PAD_AUD_TXFS__UART4_DTE_CTS                        0x0188 0x0450 0x0000 0x2 0x0
+#define MX6SLL_PAD_AUD_TXFS__SD3_LCTL                             0x0188 0x0450 0x0000 0x4 0x0
+#define MX6SLL_PAD_AUD_TXFS__GPIO1_IO04                           0x0188 0x0450 0x0000 0x5 0x0
+#define MX6SLL_PAD_AUD_TXD__AUD3_TXD                              0x018C 0x0454 0x0000 0x0 0x0
+#define MX6SLL_PAD_AUD_TXD__ECSPI3_SCLK                           0x018C 0x0454 0x0630 0x1 0x0
+#define MX6SLL_PAD_AUD_TXD__UART4_DCE_CTS                         0x018C 0x0454 0x0000 0x2 0x0
+#define MX6SLL_PAD_AUD_TXD__UART4_DTE_RTS                         0x018C 0x0454 0x0758 0x2 0x1
+#define MX6SLL_PAD_AUD_TXD__GPIO1_IO05                            0x018C 0x0454 0x0000 0x5 0x0
+#define MX6SLL_PAD_AUD_MCLK__AUDIO_CLK_OUT                        0x0190 0x0458 0x0000 0x0 0x0
+#define MX6SLL_PAD_AUD_MCLK__PWM4_OUT                             0x0190 0x0458 0x0000 0x1 0x0
+#define MX6SLL_PAD_AUD_MCLK__ECSPI3_RDY                           0x0190 0x0458 0x0634 0x2 0x0
+#define MX6SLL_PAD_AUD_MCLK__WDOG2_RESET_B_DEB                    0x0190 0x0458 0x0000 0x4 0x0
+#define MX6SLL_PAD_AUD_MCLK__GPIO1_IO06                           0x0190 0x0458 0x0000 0x5 0x0
+#define MX6SLL_PAD_AUD_MCLK__SPDIF_EXT_CLK                        0x0190 0x0458 0x073C 0x6 0x1
+#define MX6SLL_PAD_UART1_RXD__UART1_DCE_RX                        0x0194 0x045C 0x0744 0x0 0x0
+#define MX6SLL_PAD_UART1_RXD__UART1_DTE_TX                        0x0194 0x045C 0x0000 0x0 0x0
+#define MX6SLL_PAD_UART1_RXD__PWM1_OUT                            0x0194 0x045C 0x0000 0x1 0x0
+#define MX6SLL_PAD_UART1_RXD__UART4_DCE_RX                        0x0194 0x045C 0x075C 0x2 0x4
+#define MX6SLL_PAD_UART1_RXD__UART4_DTE_TX                        0x0194 0x045C 0x0000 0x2 0x0
+#define MX6SLL_PAD_UART1_RXD__UART5_DCE_RX                        0x0194 0x045C 0x0764 0x4 0x6
+#define MX6SLL_PAD_UART1_RXD__UART5_DTE_TX                        0x0194 0x045C 0x0000 0x4 0x0
+#define MX6SLL_PAD_UART1_RXD__GPIO3_IO16                          0x0194 0x045C 0x0000 0x5 0x0
+#define MX6SLL_PAD_UART1_TXD__UART1_DCE_TX                        0x0198 0x0460 0x0000 0x0 0x0
+#define MX6SLL_PAD_UART1_TXD__UART1_DTE_RX                        0x0198 0x0460 0x0744 0x0 0x1
+#define MX6SLL_PAD_UART1_TXD__PWM2_OUT                            0x0198 0x0460 0x0000 0x1 0x0
+#define MX6SLL_PAD_UART1_TXD__UART4_DCE_TX                        0x0198 0x0460 0x0000 0x2 0x0
+#define MX6SLL_PAD_UART1_TXD__UART4_DTE_RX                        0x0198 0x0460 0x075C 0x2 0x5
+#define MX6SLL_PAD_UART1_TXD__UART5_DCE_TX                        0x0198 0x0460 0x0000 0x4 0x0
+#define MX6SLL_PAD_UART1_TXD__UART5_DTE_RX                        0x0198 0x0460 0x0764 0x4 0x7
+#define MX6SLL_PAD_UART1_TXD__GPIO3_IO17                          0x0198 0x0460 0x0000 0x5 0x0
+#define MX6SLL_PAD_UART1_TXD__UART5_DCD_B                         0x0198 0x0460 0x0000 0x7 0x0
+#define MX6SLL_PAD_I2C1_SCL__I2C1_SCL                             0x019C 0x0464 0x067C 0x0 0x0
+#define MX6SLL_PAD_I2C1_SCL__UART1_DCE_RTS                        0x019C 0x0464 0x0740 0x1 0x0
+#define MX6SLL_PAD_I2C1_SCL__UART1_DTE_CTS                        0x019C 0x0464 0x0000 0x1 0x0
+#define MX6SLL_PAD_I2C1_SCL__ECSPI3_SS2                           0x019C 0x0464 0x0640 0x2 0x0
+#define MX6SLL_PAD_I2C1_SCL__SD3_RESET                            0x019C 0x0464 0x0000 0x4 0x0
+#define MX6SLL_PAD_I2C1_SCL__GPIO3_IO12                           0x019C 0x0464 0x0000 0x5 0x0
+#define MX6SLL_PAD_I2C1_SCL__ECSPI1_SS1                           0x019C 0x0464 0x060C 0x6 0x0
+#define MX6SLL_PAD_I2C1_SDA__I2C1_SDA                             0x01A0 0x0468 0x0680 0x0 0x0
+#define MX6SLL_PAD_I2C1_SDA__UART1_DCE_CTS                        0x01A0 0x0468 0x0000 0x1 0x0
+#define MX6SLL_PAD_I2C1_SDA__UART1_DTE_RTS                        0x01A0 0x0468 0x0740 0x1 0x1
+#define MX6SLL_PAD_I2C1_SDA__ECSPI3_SS3                           0x01A0 0x0468 0x0644 0x2 0x0
+#define MX6SLL_PAD_I2C1_SDA__SD3_VSELECT                          0x01A0 0x0468 0x0000 0x4 0x0
+#define MX6SLL_PAD_I2C1_SDA__GPIO3_IO13                           0x01A0 0x0468 0x0000 0x5 0x0
+#define MX6SLL_PAD_I2C1_SDA__ECSPI1_SS2                           0x01A0 0x0468 0x0610 0x6 0x0
+#define MX6SLL_PAD_I2C2_SCL__I2C2_SCL                             0x01A4 0x046C 0x0684 0x0 0x3
+#define MX6SLL_PAD_I2C2_SCL__AUD4_RXFS                            0x01A4 0x046C 0x0570 0x1 0x2
+#define MX6SLL_PAD_I2C2_SCL__SPDIF_IN                             0x01A4 0x046C 0x0738 0x2 0x2
+#define MX6SLL_PAD_I2C2_SCL__SD3_WP                               0x01A4 0x046C 0x0794 0x4 0x3
+#define MX6SLL_PAD_I2C2_SCL__GPIO3_IO14                           0x01A4 0x046C 0x0000 0x5 0x0
+#define MX6SLL_PAD_I2C2_SCL__ECSPI1_RDY                           0x01A4 0x046C 0x0600 0x6 0x1
+#define MX6SLL_PAD_I2C2_SDA__I2C2_SDA                             0x01A8 0x0470 0x0688 0x0 0x3
+#define MX6SLL_PAD_I2C2_SDA__AUD4_RXC                             0x01A8 0x0470 0x056C 0x1 0x2
+#define MX6SLL_PAD_I2C2_SDA__SPDIF_OUT                            0x01A8 0x0470 0x0000 0x2 0x0
+#define MX6SLL_PAD_I2C2_SDA__SD3_CD_B                             0x01A8 0x0470 0x0780 0x4 0x3
+#define MX6SLL_PAD_I2C2_SDA__GPIO3_IO15                           0x01A8 0x0470 0x0000 0x5 0x0
+#define MX6SLL_PAD_ECSPI1_SCLK__ECSPI1_SCLK                       0x01AC 0x0474 0x05FC 0x0 0x1
+#define MX6SLL_PAD_ECSPI1_SCLK__AUD4_TXD                          0x01AC 0x0474 0x0568 0x1 0x1
+#define MX6SLL_PAD_ECSPI1_SCLK__UART5_DCE_RX                      0x01AC 0x0474 0x0764 0x2 0x2
+#define MX6SLL_PAD_ECSPI1_SCLK__UART5_DTE_TX                      0x01AC 0x0474 0x0000 0x2 0x0
+#define MX6SLL_PAD_ECSPI1_SCLK__EPDC_VCOM0                        0x01AC 0x0474 0x0000 0x3 0x0
+#define MX6SLL_PAD_ECSPI1_SCLK__SD2_RESET                         0x01AC 0x0474 0x0000 0x4 0x0
+#define MX6SLL_PAD_ECSPI1_SCLK__GPIO4_IO08                        0x01AC 0x0474 0x0000 0x5 0x0
+#define MX6SLL_PAD_ECSPI1_SCLK__USB_OTG2_OC                       0x01AC 0x0474 0x0768 0x6 0x1
+#define MX6SLL_PAD_ECSPI1_MOSI__ECSPI1_MOSI                       0x01B0 0x0478 0x0608 0x0 0x1
+#define MX6SLL_PAD_ECSPI1_MOSI__AUD4_TXC                          0x01B0 0x0478 0x0574 0x1 0x1
+#define MX6SLL_PAD_ECSPI1_MOSI__UART5_DCE_TX                      0x01B0 0x0478 0x0000 0x2 0x0
+#define MX6SLL_PAD_ECSPI1_MOSI__UART5_DTE_RX                      0x01B0 0x0478 0x0764 0x2 0x3
+#define MX6SLL_PAD_ECSPI1_MOSI__EPDC_VCOM1                        0x01B0 0x0478 0x0000 0x3 0x0
+#define MX6SLL_PAD_ECSPI1_MOSI__SD2_VSELECT                       0x01B0 0x0478 0x0000 0x4 0x0
+#define MX6SLL_PAD_ECSPI1_MOSI__GPIO4_IO09                        0x01B0 0x0478 0x0000 0x5 0x0
+#define MX6SLL_PAD_ECSPI1_MISO__ECSPI1_MISO                       0x01B4 0x047C 0x0604 0x0 0x1
+#define MX6SLL_PAD_ECSPI1_MISO__AUD4_TXFS                         0x01B4 0x047C 0x0578 0x1 0x1
+#define MX6SLL_PAD_ECSPI1_MISO__UART5_DCE_RTS                     0x01B4 0x047C 0x0760 0x2 0x2
+#define MX6SLL_PAD_ECSPI1_MISO__UART5_DTE_CTS                     0x01B4 0x047C 0x0000 0x2 0x0
+#define MX6SLL_PAD_ECSPI1_MISO__EPDC_BDR0                         0x01B4 0x047C 0x0000 0x3 0x0
+#define MX6SLL_PAD_ECSPI1_MISO__SD2_WP                            0x01B4 0x047C 0x077C 0x4 0x0
+#define MX6SLL_PAD_ECSPI1_MISO__GPIO4_IO10                        0x01B4 0x047C 0x0000 0x5 0x0
+#define MX6SLL_PAD_ECSPI1_SS0__ECSPI1_SS0                         0x01B8 0x0480 0x0614 0x0 0x1
+#define MX6SLL_PAD_ECSPI1_SS0__AUD4_RXD                           0x01B8 0x0480 0x0564 0x1 0x1
+#define MX6SLL_PAD_ECSPI1_SS0__UART5_DCE_CTS                      0x01B8 0x0480 0x0000 0x2 0x0
+#define MX6SLL_PAD_ECSPI1_SS0__UART5_DTE_RTS                      0x01B8 0x0480 0x0760 0x2 0x3
+#define MX6SLL_PAD_ECSPI1_SS0__EPDC_BDR1                          0x01B8 0x0480 0x0000 0x3 0x0
+#define MX6SLL_PAD_ECSPI1_SS0__SD2_CD_B                           0x01B8 0x0480 0x0778 0x4 0x0
+#define MX6SLL_PAD_ECSPI1_SS0__GPIO4_IO11                         0x01B8 0x0480 0x0000 0x5 0x0
+#define MX6SLL_PAD_ECSPI1_SS0__USB_OTG2_PWR                       0x01B8 0x0480 0x0000 0x6 0x0
+#define MX6SLL_PAD_ECSPI2_SCLK__ECSPI2_SCLK                       0x01BC 0x0484 0x061C 0x0 0x1
+#define MX6SLL_PAD_ECSPI2_SCLK__SPDIF_EXT_CLK                     0x01BC 0x0484 0x073C 0x1 0x2
+#define MX6SLL_PAD_ECSPI2_SCLK__UART3_DCE_RX                      0x01BC 0x0484 0x0754 0x2 0x2
+#define MX6SLL_PAD_ECSPI2_SCLK__UART3_DTE_TX                      0x01BC 0x0484 0x0000 0x2 0x0
+#define MX6SLL_PAD_ECSPI2_SCLK__CSI_PIXCLK                        0x01BC 0x0484 0x05F4 0x3 0x1
+#define MX6SLL_PAD_ECSPI2_SCLK__SD1_RESET                         0x01BC 0x0484 0x0000 0x4 0x0
+#define MX6SLL_PAD_ECSPI2_SCLK__GPIO4_IO12                        0x01BC 0x0484 0x0000 0x5 0x0
+#define MX6SLL_PAD_ECSPI2_SCLK__USB_OTG2_OC                       0x01BC 0x0484 0x0768 0x6 0x2
+#define MX6SLL_PAD_ECSPI2_MOSI__ECSPI2_MOSI                       0x01C0 0x0488 0x0624 0x0 0x1
+#define MX6SLL_PAD_ECSPI2_MOSI__SDMA_EXT_EVENT1                   0x01C0 0x0488 0x0000 0x1 0x0
+#define MX6SLL_PAD_ECSPI2_MOSI__UART3_DCE_TX                      0x01C0 0x0488 0x0000 0x2 0x0
+#define MX6SLL_PAD_ECSPI2_MOSI__UART3_DTE_RX                      0x01C0 0x0488 0x0754 0x2 0x3
+#define MX6SLL_PAD_ECSPI2_MOSI__CSI_HSYNC                         0x01C0 0x0488 0x05F0 0x3 0x1
+#define MX6SLL_PAD_ECSPI2_MOSI__SD1_VSELECT                       0x01C0 0x0488 0x0000 0x4 0x0
+#define MX6SLL_PAD_ECSPI2_MOSI__GPIO4_IO13                        0x01C0 0x0488 0x0000 0x5 0x0
+#define MX6SLL_PAD_ECSPI2_MISO__ECSPI2_MISO                       0x01C4 0x048C 0x0620 0x0 0x1
+#define MX6SLL_PAD_ECSPI2_MISO__SDMA_EXT_EVENT0                   0x01C4 0x048C 0x0000 0x1 0x0
+#define MX6SLL_PAD_ECSPI2_MISO__UART3_DCE_RTS                     0x01C4 0x048C 0x0750 0x2 0x0
+#define MX6SLL_PAD_ECSPI2_MISO__UART3_DTE_CTS                     0x01C4 0x048C 0x0000 0x2 0x0
+#define MX6SLL_PAD_ECSPI2_MISO__CSI_MCLK                          0x01C4 0x048C 0x0000 0x3 0x0
+#define MX6SLL_PAD_ECSPI2_MISO__SD1_WP                            0x01C4 0x048C 0x0774 0x4 0x2
+#define MX6SLL_PAD_ECSPI2_MISO__GPIO4_IO14                        0x01C4 0x048C 0x0000 0x5 0x0
+#define MX6SLL_PAD_ECSPI2_MISO__USB_OTG1_OC                       0x01C4 0x048C 0x076C 0x6 0x1
+#define MX6SLL_PAD_ECSPI2_SS0__ECSPI2_SS0                         0x01C8 0x0490 0x0628 0x0 0x0
+#define MX6SLL_PAD_ECSPI2_SS0__ECSPI1_SS3                         0x01C8 0x0490 0x0618 0x1 0x1
+#define MX6SLL_PAD_ECSPI2_SS0__UART3_DCE_CTS                      0x01C8 0x0490 0x0000 0x2 0x0
+#define MX6SLL_PAD_ECSPI2_SS0__UART3_DTE_RTS                      0x01C8 0x0490 0x0750 0x2 0x1
+#define MX6SLL_PAD_ECSPI2_SS0__CSI_VSYNC                          0x01C8 0x0490 0x05F8 0x3 0x1
+#define MX6SLL_PAD_ECSPI2_SS0__SD1_CD_B                           0x01C8 0x0490 0x0770 0x4 0x2
+#define MX6SLL_PAD_ECSPI2_SS0__GPIO4_IO15                         0x01C8 0x0490 0x0000 0x5 0x0
+#define MX6SLL_PAD_ECSPI2_SS0__USB_OTG1_PWR                       0x01C8 0x0490 0x0000 0x6 0x0
+#define MX6SLL_PAD_SD1_CLK__SD1_CLK                               0x01CC 0x0494 0x0000 0x0 0x0
+#define MX6SLL_PAD_SD1_CLK__KEY_COL0                              0x01CC 0x0494 0x06A0 0x2 0x2
+#define MX6SLL_PAD_SD1_CLK__EPDC_SDCE4                            0x01CC 0x0494 0x0000 0x3 0x0
+#define MX6SLL_PAD_SD1_CLK__GPIO5_IO15                            0x01CC 0x0494 0x0000 0x5 0x0
+#define MX6SLL_PAD_SD1_CMD__SD1_CMD                               0x01D0 0x0498 0x0000 0x0 0x0
+#define MX6SLL_PAD_SD1_CMD__KEY_ROW0                              0x01D0 0x0498 0x06C0 0x2 0x2
+#define MX6SLL_PAD_SD1_CMD__EPDC_SDCE5                            0x01D0 0x0498 0x0000 0x3 0x0
+#define MX6SLL_PAD_SD1_CMD__GPIO5_IO14                            0x01D0 0x0498 0x0000 0x5 0x0
+#define MX6SLL_PAD_SD1_DATA0__SD1_DATA0                           0x01D4 0x049C 0x0000 0x0 0x0
+#define MX6SLL_PAD_SD1_DATA0__KEY_COL1                            0x01D4 0x049C 0x06A4 0x2 0x2
+#define MX6SLL_PAD_SD1_DATA0__EPDC_SDCE6                          0x01D4 0x049C 0x0000 0x3 0x0
+#define MX6SLL_PAD_SD1_DATA0__GPIO5_IO11                          0x01D4 0x049C 0x0000 0x5 0x0
+#define MX6SLL_PAD_SD1_DATA1__SD1_DATA1                           0x01D8 0x04A0 0x0000 0x0 0x0
+#define MX6SLL_PAD_SD1_DATA1__KEY_ROW1                            0x01D8 0x04A0 0x06C4 0x2 0x2
+#define MX6SLL_PAD_SD1_DATA1__EPDC_SDCE7                          0x01D8 0x04A0 0x0000 0x3 0x0
+#define MX6SLL_PAD_SD1_DATA1__GPIO5_IO08                          0x01D8 0x04A0 0x0000 0x5 0x0
+#define MX6SLL_PAD_SD1_DATA2__SD1_DATA2                           0x01DC 0x04A4 0x0000 0x0 0x0
+#define MX6SLL_PAD_SD1_DATA2__KEY_COL2                            0x01DC 0x04A4 0x06A8 0x2 0x2
+#define MX6SLL_PAD_SD1_DATA2__EPDC_SDCE8                          0x01DC 0x04A4 0x0000 0x3 0x0
+#define MX6SLL_PAD_SD1_DATA2__GPIO5_IO13                          0x01DC 0x04A4 0x0000 0x5 0x0
+#define MX6SLL_PAD_SD1_DATA3__SD1_DATA3                           0x01E0 0x04A8 0x0000 0x0 0x0
+#define MX6SLL_PAD_SD1_DATA3__KEY_ROW2                            0x01E0 0x04A8 0x06C8 0x2 0x2
+#define MX6SLL_PAD_SD1_DATA3__EPDC_SDCE9                          0x01E0 0x04A8 0x0000 0x3 0x0
+#define MX6SLL_PAD_SD1_DATA3__GPIO5_IO06                          0x01E0 0x04A8 0x0000 0x5 0x0
+#define MX6SLL_PAD_SD1_DATA4__SD1_DATA4                           0x01E4 0x04AC 0x0000 0x0 0x0
+#define MX6SLL_PAD_SD1_DATA4__KEY_COL3                            0x01E4 0x04AC 0x06AC 0x2 0x2
+#define MX6SLL_PAD_SD1_DATA4__EPDC_SDCLK_N                        0x01E4 0x04AC 0x0000 0x3 0x0
+#define MX6SLL_PAD_SD1_DATA4__UART4_DCE_RX                        0x01E4 0x04AC 0x075C 0x4 0x6
+#define MX6SLL_PAD_SD1_DATA4__UART4_DTE_TX                        0x01E4 0x04AC 0x0000 0x4 0x0
+#define MX6SLL_PAD_SD1_DATA4__GPIO5_IO12                          0x01E4 0x04AC 0x0000 0x5 0x0
+#define MX6SLL_PAD_SD1_DATA5__SD1_DATA5                           0x01E8 0x04B0 0x0000 0x0 0x0
+#define MX6SLL_PAD_SD1_DATA5__KEY_ROW3                            0x01E8 0x04B0 0x06CC 0x2 0x2
+#define MX6SLL_PAD_SD1_DATA5__EPDC_SDOED                          0x01E8 0x04B0 0x0000 0x3 0x0
+#define MX6SLL_PAD_SD1_DATA5__UART4_DCE_TX                        0x01E8 0x04B0 0x0000 0x4 0x0
+#define MX6SLL_PAD_SD1_DATA5__UART4_DTE_RX                        0x01E8 0x04B0 0x075C 0x4 0x7
+#define MX6SLL_PAD_SD1_DATA5__GPIO5_IO09                          0x01E8 0x04B0 0x0000 0x5 0x0
+#define MX6SLL_PAD_SD1_DATA6__SD1_DATA6                           0x01EC 0x04B4 0x0000 0x0 0x0
+#define MX6SLL_PAD_SD1_DATA6__KEY_COL4                            0x01EC 0x04B4 0x06B0 0x2 0x2
+#define MX6SLL_PAD_SD1_DATA6__EPDC_SDOEZ                          0x01EC 0x04B4 0x0000 0x3 0x0
+#define MX6SLL_PAD_SD1_DATA6__UART4_DCE_RTS                       0x01EC 0x04B4 0x0758 0x4 0x4
+#define MX6SLL_PAD_SD1_DATA6__UART4_DTE_CTS                       0x01EC 0x04B4 0x0000 0x4 0x0
+#define MX6SLL_PAD_SD1_DATA6__GPIO5_IO07                          0x01EC 0x04B4 0x0000 0x5 0x0
+#define MX6SLL_PAD_SD1_DATA7__SD1_DATA7                           0x01F0 0x04B8 0x0000 0x0 0x0
+#define MX6SLL_PAD_SD1_DATA7__KEY_ROW4                            0x01F0 0x04B8 0x06D0 0x2 0x2
+#define MX6SLL_PAD_SD1_DATA7__CCM_PMIC_READY                      0x01F0 0x04B8 0x05AC 0x3 0x3
+#define MX6SLL_PAD_SD1_DATA7__UART4_DCE_CTS                       0x01F0 0x04B8 0x0000 0x4 0x0
+#define MX6SLL_PAD_SD1_DATA7__UART4_DTE_RTS                       0x01F0 0x04B8 0x0758 0x4 0x5
+#define MX6SLL_PAD_SD1_DATA7__GPIO5_IO10                          0x01F0 0x04B8 0x0000 0x5 0x0
+#define MX6SLL_PAD_SD2_RESET__SD2_RESET                           0x01F4 0x04BC 0x0000 0x0 0x0
+#define MX6SLL_PAD_SD2_RESET__WDOG2_B                             0x01F4 0x04BC 0x0000 0x2 0x0
+#define MX6SLL_PAD_SD2_RESET__SPDIF_OUT                           0x01F4 0x04BC 0x0000 0x3 0x0
+#define MX6SLL_PAD_SD2_RESET__CSI_MCLK                            0x01F4 0x04BC 0x0000 0x4 0x0
+#define MX6SLL_PAD_SD2_RESET__GPIO4_IO27                          0x01F4 0x04BC 0x0000 0x5 0x0
+#define MX6SLL_PAD_SD2_CLK__SD2_CLK                               0x01F8 0x04C0 0x0000 0x0 0x0
+#define MX6SLL_PAD_SD2_CLK__AUD4_RXFS                             0x01F8 0x04C0 0x0570 0x1 0x1
+#define MX6SLL_PAD_SD2_CLK__ECSPI3_SCLK                           0x01F8 0x04C0 0x0630 0x2 0x1
+#define MX6SLL_PAD_SD2_CLK__CSI_DATA00                            0x01F8 0x04C0 0x05C8 0x3 0x1
+#define MX6SLL_PAD_SD2_CLK__GPIO5_IO05                            0x01F8 0x04C0 0x0000 0x5 0x0
+#define MX6SLL_PAD_SD2_CMD__SD2_CMD                               0x01FC 0x04C4 0x0000 0x0 0x0
+#define MX6SLL_PAD_SD2_CMD__AUD4_RXC                              0x01FC 0x04C4 0x056C 0x1 0x1
+#define MX6SLL_PAD_SD2_CMD__ECSPI3_SS0                            0x01FC 0x04C4 0x0648 0x2 0x1
+#define MX6SLL_PAD_SD2_CMD__CSI_DATA01                            0x01FC 0x04C4 0x05CC 0x3 0x1
+#define MX6SLL_PAD_SD2_CMD__EPIT1_OUT                             0x01FC 0x04C4 0x0000 0x4 0x0
+#define MX6SLL_PAD_SD2_CMD__GPIO5_IO04                            0x01FC 0x04C4 0x0000 0x5 0x0
+#define MX6SLL_PAD_SD2_DATA0__SD2_DATA0                           0x0200 0x04C8 0x0000 0x0 0x0
+#define MX6SLL_PAD_SD2_DATA0__AUD4_RXD                            0x0200 0x04C8 0x0564 0x1 0x2
+#define MX6SLL_PAD_SD2_DATA0__ECSPI3_MOSI                         0x0200 0x04C8 0x063C 0x2 0x1
+#define MX6SLL_PAD_SD2_DATA0__CSI_DATA02                          0x0200 0x04C8 0x05D0 0x3 0x1
+#define MX6SLL_PAD_SD2_DATA0__UART5_DCE_RTS                       0x0200 0x04C8 0x0760 0x4 0x4
+#define MX6SLL_PAD_SD2_DATA0__UART5_DTE_CTS                       0x0200 0x04C8 0x0000 0x4 0x0
+#define MX6SLL_PAD_SD2_DATA0__GPIO5_IO01                          0x0200 0x04C8 0x0000 0x5 0x0
+#define MX6SLL_PAD_SD2_DATA1__SD2_DATA1                           0x0204 0x04CC 0x0000 0x0 0x0
+#define MX6SLL_PAD_SD2_DATA1__AUD4_TXC                            0x0204 0x04CC 0x0574 0x1 0x2
+#define MX6SLL_PAD_SD2_DATA1__ECSPI3_MISO                         0x0204 0x04CC 0x0638 0x2 0x1
+#define MX6SLL_PAD_SD2_DATA1__CSI_DATA03                          0x0204 0x04CC 0x05D4 0x3 0x1
+#define MX6SLL_PAD_SD2_DATA1__UART5_DCE_CTS                       0x0204 0x04CC 0x0000 0x4 0x0
+#define MX6SLL_PAD_SD2_DATA1__UART5_DTE_RTS                       0x0204 0x04CC 0x0760 0x4 0x5
+#define MX6SLL_PAD_SD2_DATA1__GPIO4_IO30                          0x0204 0x04CC 0x0000 0x5 0x0
+#define MX6SLL_PAD_SD2_DATA2__SD2_DATA2                           0x0208 0x04D0 0x0000 0x0 0x0
+#define MX6SLL_PAD_SD2_DATA2__AUD4_TXFS                           0x0208 0x04D0 0x0578 0x1 0x2
+#define MX6SLL_PAD_SD2_DATA2__CSI_DATA04                          0x0208 0x04D0 0x05D8 0x3 0x1
+#define MX6SLL_PAD_SD2_DATA2__UART5_DCE_RX                        0x0208 0x04D0 0x0764 0x4 0x4
+#define MX6SLL_PAD_SD2_DATA2__UART5_DTE_TX                        0x0208 0x04D0 0x0000 0x4 0x0
+#define MX6SLL_PAD_SD2_DATA2__GPIO5_IO03                          0x0208 0x04D0 0x0000 0x5 0x0
+#define MX6SLL_PAD_SD2_DATA3__SD2_DATA3                           0x020C 0x04D4 0x0000 0x0 0x0
+#define MX6SLL_PAD_SD2_DATA3__AUD4_TXD                            0x020C 0x04D4 0x0568 0x1 0x2
+#define MX6SLL_PAD_SD2_DATA3__CSI_DATA05                          0x020C 0x04D4 0x05DC 0x3 0x1
+#define MX6SLL_PAD_SD2_DATA3__UART5_DCE_TX                        0x020C 0x04D4 0x0000 0x4 0x0
+#define MX6SLL_PAD_SD2_DATA3__UART5_DTE_RX                        0x020C 0x04D4 0x0764 0x4 0x5
+#define MX6SLL_PAD_SD2_DATA3__GPIO4_IO28                          0x020C 0x04D4 0x0000 0x5 0x0
+#define MX6SLL_PAD_SD2_DATA4__SD2_DATA4                           0x0210 0x04D8 0x0000 0x0 0x0
+#define MX6SLL_PAD_SD2_DATA4__SD3_DATA4                           0x0210 0x04D8 0x0784 0x1 0x1
+#define MX6SLL_PAD_SD2_DATA4__UART2_DCE_RX                        0x0210 0x04D8 0x074C 0x2 0x2
+#define MX6SLL_PAD_SD2_DATA4__UART2_DTE_TX                        0x0210 0x04D8 0x0000 0x2 0x0
+#define MX6SLL_PAD_SD2_DATA4__CSI_DATA06                          0x0210 0x04D8 0x05E0 0x3 0x1
+#define MX6SLL_PAD_SD2_DATA4__SPDIF_OUT                           0x0210 0x04D8 0x0000 0x4 0x0
+#define MX6SLL_PAD_SD2_DATA4__GPIO5_IO02                          0x0210 0x04D8 0x0000 0x5 0x0
+#define MX6SLL_PAD_SD2_DATA5__SD2_DATA5                           0x0214 0x04DC 0x0000 0x0 0x0
+#define MX6SLL_PAD_SD2_DATA5__SD3_DATA5                           0x0214 0x04DC 0x0788 0x1 0x1
+#define MX6SLL_PAD_SD2_DATA5__UART2_DCE_TX                        0x0214 0x04DC 0x0000 0x2 0x0
+#define MX6SLL_PAD_SD2_DATA5__UART2_DTE_RX                        0x0214 0x04DC 0x074C 0x2 0x3
+#define MX6SLL_PAD_SD2_DATA5__CSI_DATA07                          0x0214 0x04DC 0x05E4 0x3 0x1
+#define MX6SLL_PAD_SD2_DATA5__SPDIF_IN                            0x0214 0x04DC 0x0738 0x4 0x1
+#define MX6SLL_PAD_SD2_DATA5__GPIO4_IO31                          0x0214 0x04DC 0x0000 0x5 0x0
+#define MX6SLL_PAD_SD2_DATA6__SD2_DATA6                           0x0218 0x04E0 0x0000 0x0 0x0
+#define MX6SLL_PAD_SD2_DATA6__SD3_DATA6                           0x0218 0x04E0 0x078C 0x1 0x1
+#define MX6SLL_PAD_SD2_DATA6__UART2_DCE_RTS                       0x0218 0x04E0 0x0748 0x2 0x2
+#define MX6SLL_PAD_SD2_DATA6__UART2_DTE_CTS                       0x0218 0x04E0 0x0000 0x2 0x0
+#define MX6SLL_PAD_SD2_DATA6__CSI_DATA08                          0x0218 0x04E0 0x05E8 0x3 0x1
+#define MX6SLL_PAD_SD2_DATA6__SD2_WP                              0x0218 0x04E0 0x077C 0x4 0x1
+#define MX6SLL_PAD_SD2_DATA6__GPIO4_IO29                          0x0218 0x04E0 0x0000 0x5 0x0
+#define MX6SLL_PAD_SD2_DATA7__SD2_DATA7                           0x021C 0x04E4 0x0000 0x0 0x0
+#define MX6SLL_PAD_SD2_DATA7__SD3_DATA7                           0x021C 0x04E4 0x0790 0x1 0x1
+#define MX6SLL_PAD_SD2_DATA7__UART2_DCE_CTS                       0x021C 0x04E4 0x0000 0x2 0x0
+#define MX6SLL_PAD_SD2_DATA7__UART2_DTE_RTS                       0x021C 0x04E4 0x0748 0x2 0x3
+#define MX6SLL_PAD_SD2_DATA7__CSI_DATA09                          0x021C 0x04E4 0x05EC 0x3 0x1
+#define MX6SLL_PAD_SD2_DATA7__SD2_CD_B                            0x021C 0x04E4 0x0778 0x4 0x1
+#define MX6SLL_PAD_SD2_DATA7__GPIO5_IO00                          0x021C 0x04E4 0x0000 0x5 0x0
+#define MX6SLL_PAD_SD3_CLK__SD3_CLK                               0x0220 0x04E8 0x0000 0x0 0x0
+#define MX6SLL_PAD_SD3_CLK__AUD5_RXFS                             0x0220 0x04E8 0x0588 0x1 0x0
+#define MX6SLL_PAD_SD3_CLK__KEY_COL5                              0x0220 0x04E8 0x0694 0x2 0x0
+#define MX6SLL_PAD_SD3_CLK__CSI_DATA10                            0x0220 0x04E8 0x05B0 0x3 0x0
+#define MX6SLL_PAD_SD3_CLK__WDOG1_RESET_B_DEB                     0x0220 0x04E8 0x0000 0x4 0x0
+#define MX6SLL_PAD_SD3_CLK__GPIO5_IO18                            0x0220 0x04E8 0x0000 0x5 0x0
+#define MX6SLL_PAD_SD3_CLK__USB_OTG1_PWR                          0x0220 0x04E8 0x0000 0x6 0x0
+#define MX6SLL_PAD_SD3_CMD__SD3_CMD                               0x0224 0x04EC 0x0000 0x0 0x0
+#define MX6SLL_PAD_SD3_CMD__AUD5_RXC                              0x0224 0x04EC 0x0584 0x1 0x0
+#define MX6SLL_PAD_SD3_CMD__KEY_ROW5                              0x0224 0x04EC 0x06B4 0x2 0x0
+#define MX6SLL_PAD_SD3_CMD__CSI_DATA11                            0x0224 0x04EC 0x05B4 0x3 0x0
+#define MX6SLL_PAD_SD3_CMD__USB_OTG2_ID                           0x0224 0x04EC 0x0560 0x4 0x1
+#define MX6SLL_PAD_SD3_CMD__GPIO5_IO21                            0x0224 0x04EC 0x0000 0x5 0x0
+#define MX6SLL_PAD_SD3_CMD__USB_OTG2_PWR                          0x0224 0x04EC 0x0000 0x6 0x0
+#define MX6SLL_PAD_SD3_DATA0__SD3_DATA0                           0x0228 0x04F0 0x0000 0x0 0x0
+#define MX6SLL_PAD_SD3_DATA0__AUD5_RXD                            0x0228 0x04F0 0x057C 0x1 0x0
+#define MX6SLL_PAD_SD3_DATA0__KEY_COL6                            0x0228 0x04F0 0x0698 0x2 0x0
+#define MX6SLL_PAD_SD3_DATA0__CSI_DATA12                          0x0228 0x04F0 0x05B8 0x3 0x0
+#define MX6SLL_PAD_SD3_DATA0__USB_OTG1_ID                         0x0228 0x04F0 0x055C 0x4 0x1
+#define MX6SLL_PAD_SD3_DATA0__GPIO5_IO19                          0x0228 0x04F0 0x0000 0x5 0x0
+#define MX6SLL_PAD_SD3_DATA1__SD3_DATA1                           0x022C 0x04F4 0x0000 0x0 0x0
+#define MX6SLL_PAD_SD3_DATA1__AUD5_TXC                            0x022C 0x04F4 0x058C 0x1 0x0
+#define MX6SLL_PAD_SD3_DATA1__KEY_ROW6                            0x022C 0x04F4 0x06B8 0x2 0x0
+#define MX6SLL_PAD_SD3_DATA1__CSI_DATA13                          0x022C 0x04F4 0x05BC 0x3 0x0
+#define MX6SLL_PAD_SD3_DATA1__SD1_VSELECT                         0x022C 0x04F4 0x0000 0x4 0x0
+#define MX6SLL_PAD_SD3_DATA1__GPIO5_IO20                          0x022C 0x04F4 0x0000 0x5 0x0
+#define MX6SLL_PAD_SD3_DATA1__JTAG_DE_B                           0x022C 0x04F4 0x0000 0x6 0x0
+#define MX6SLL_PAD_SD3_DATA2__SD3_DATA2                           0x0230 0x04F8 0x0000 0x0 0x0
+#define MX6SLL_PAD_SD3_DATA2__AUD5_TXFS                           0x0230 0x04F8 0x0590 0x1 0x0
+#define MX6SLL_PAD_SD3_DATA2__KEY_COL7                            0x0230 0x04F8 0x069C 0x2 0x0
+#define MX6SLL_PAD_SD3_DATA2__CSI_DATA14                          0x0230 0x04F8 0x05C0 0x3 0x0
+#define MX6SLL_PAD_SD3_DATA2__EPIT1_OUT                           0x0230 0x04F8 0x0000 0x4 0x0
+#define MX6SLL_PAD_SD3_DATA2__GPIO5_IO16                          0x0230 0x04F8 0x0000 0x5 0x0
+#define MX6SLL_PAD_SD3_DATA2__USB_OTG2_OC                         0x0230 0x04F8 0x0768 0x6 0x0
+#define MX6SLL_PAD_SD3_DATA3__SD3_DATA3                           0x0234 0x04FC 0x0000 0x0 0x0
+#define MX6SLL_PAD_SD3_DATA3__AUD5_TXD                            0x0234 0x04FC 0x0580 0x1 0x0
+#define MX6SLL_PAD_SD3_DATA3__KEY_ROW7                            0x0234 0x04FC 0x06BC 0x2 0x0
+#define MX6SLL_PAD_SD3_DATA3__CSI_DATA15                          0x0234 0x04FC 0x05C4 0x3 0x0
+#define MX6SLL_PAD_SD3_DATA3__EPIT2_OUT                           0x0234 0x04FC 0x0000 0x4 0x0
+#define MX6SLL_PAD_SD3_DATA3__GPIO5_IO17                          0x0234 0x04FC 0x0000 0x5 0x0
+#define MX6SLL_PAD_SD3_DATA3__USB_OTG1_OC                         0x0234 0x04FC 0x076C 0x6 0x0
+#define MX6SLL_PAD_GPIO4_IO20__SD1_STROBE                         0x0238 0x0500 0x0000 0x0 0x0
+#define MX6SLL_PAD_GPIO4_IO20__AUD6_RXFS                          0x0238 0x0500 0x05A0 0x2 0x0
+#define MX6SLL_PAD_GPIO4_IO20__ECSPI4_SS0                         0x0238 0x0500 0x065C 0x3 0x0
+#define MX6SLL_PAD_GPIO4_IO20__GPT_CAPTURE1                       0x0238 0x0500 0x0670 0x4 0x0
+#define MX6SLL_PAD_GPIO4_IO20__GPIO4_IO20                         0x0238 0x0500 0x0000 0x5 0x0
+#define MX6SLL_PAD_GPIO4_IO21__SD2_STROBE                         0x023C 0x0504 0x0000 0x0 0x0
+#define MX6SLL_PAD_GPIO4_IO21__AUD6_RXC                           0x023C 0x0504 0x059C 0x2 0x0
+#define MX6SLL_PAD_GPIO4_IO21__ECSPI4_SCLK                        0x023C 0x0504 0x0650 0x3 0x0
+#define MX6SLL_PAD_GPIO4_IO21__GPT_CAPTURE2                       0x023C 0x0504 0x0674 0x4 0x0
+#define MX6SLL_PAD_GPIO4_IO21__GPIO4_IO21                         0x023C 0x0504 0x0000 0x5 0x0
+#define MX6SLL_PAD_GPIO4_IO19__SD3_STROBE                         0x0240 0x0508 0x0000 0x0 0x0
+#define MX6SLL_PAD_GPIO4_IO19__AUD6_RXD                           0x0240 0x0508 0x0594 0x2 0x0
+#define MX6SLL_PAD_GPIO4_IO19__ECSPI4_MOSI                        0x0240 0x0508 0x0658 0x3 0x0
+#define MX6SLL_PAD_GPIO4_IO19__GPT_COMPARE1                       0x0240 0x0508 0x0000 0x4 0x0
+#define MX6SLL_PAD_GPIO4_IO19__GPIO4_IO19                         0x0240 0x0508 0x0000 0x5 0x0
+#define MX6SLL_PAD_GPIO4_IO25__AUD6_TXC                           0x0244 0x050C 0x05A4 0x2 0x0
+#define MX6SLL_PAD_GPIO4_IO25__ECSPI4_MISO                        0x0244 0x050C 0x0654 0x3 0x0
+#define MX6SLL_PAD_GPIO4_IO25__GPT_COMPARE2                       0x0244 0x050C 0x0000 0x4 0x0
+#define MX6SLL_PAD_GPIO4_IO25__GPIO4_IO25                         0x0244 0x050C 0x0000 0x5 0x0
+#define MX6SLL_PAD_GPIO4_IO18__AUD6_TXFS                          0x0248 0x0510 0x05A8 0x2 0x0
+#define MX6SLL_PAD_GPIO4_IO18__ECSPI4_SS1                         0x0248 0x0510 0x0660 0x3 0x0
+#define MX6SLL_PAD_GPIO4_IO18__GPT_COMPARE3                       0x0248 0x0510 0x0000 0x4 0x0
+#define MX6SLL_PAD_GPIO4_IO18__GPIO4_IO18                         0x0248 0x0510 0x0000 0x5 0x0
+#define MX6SLL_PAD_GPIO4_IO24__AUD6_TXD                           0x024C 0x0514 0x0598 0x2 0x0
+#define MX6SLL_PAD_GPIO4_IO24__ECSPI4_SS2                         0x024C 0x0514 0x0664 0x3 0x0
+#define MX6SLL_PAD_GPIO4_IO24__GPT_CLKIN                          0x024C 0x0514 0x0678 0x4 0x0
+#define MX6SLL_PAD_GPIO4_IO24__GPIO4_IO24                         0x024C 0x0514 0x0000 0x5 0x0
+#define MX6SLL_PAD_GPIO4_IO23__AUDIO_CLK_OUT                      0x0250 0x0518 0x0000 0x2 0x0
+#define MX6SLL_PAD_GPIO4_IO23__SD1_RESET                          0x0250 0x0518 0x0000 0x3 0x0
+#define MX6SLL_PAD_GPIO4_IO23__SD3_RESET                          0x0250 0x0518 0x0000 0x4 0x0
+#define MX6SLL_PAD_GPIO4_IO23__GPIO4_IO23                         0x0250 0x0518 0x0000 0x5 0x0
+#define MX6SLL_PAD_GPIO4_IO17__USB_OTG1_ID                        0x0254 0x051C 0x055C 0x2 0x2
+#define MX6SLL_PAD_GPIO4_IO17__SD1_VSELECT                        0x0254 0x051C 0x0000 0x3 0x0
+#define MX6SLL_PAD_GPIO4_IO17__SD3_VSELECT                        0x0254 0x051C 0x0000 0x4 0x0
+#define MX6SLL_PAD_GPIO4_IO17__GPIO4_IO17                         0x0254 0x051C 0x0000 0x5 0x0
+#define MX6SLL_PAD_GPIO4_IO22__SPDIF_IN                           0x0258 0x0520 0x0738 0x2 0x0
+#define MX6SLL_PAD_GPIO4_IO22__SD1_WP                             0x0258 0x0520 0x0774 0x3 0x0
+#define MX6SLL_PAD_GPIO4_IO22__SD3_WP                             0x0258 0x0520 0x0794 0x4 0x1
+#define MX6SLL_PAD_GPIO4_IO22__GPIO4_IO22                         0x0258 0x0520 0x0000 0x5 0x0
+#define MX6SLL_PAD_GPIO4_IO16__SPDIF_OUT                          0x025C 0x0524 0x0000 0x2 0x0
+#define MX6SLL_PAD_GPIO4_IO16__SD1_CD_B                           0x025C 0x0524 0x0770 0x3 0x0
+#define MX6SLL_PAD_GPIO4_IO16__SD3_CD_B                           0x025C 0x0524 0x0780 0x4 0x1
+#define MX6SLL_PAD_GPIO4_IO16__GPIO4_IO16                         0x025C 0x0524 0x0000 0x5 0x0
+#define MX6SLL_PAD_GPIO4_IO26__WDOG1_B                            0x0260 0x0528 0x0000 0x2 0x0
+#define MX6SLL_PAD_GPIO4_IO26__PWM4_OUT                           0x0260 0x0528 0x0000 0x3 0x0
+#define MX6SLL_PAD_GPIO4_IO26__CCM_PMIC_READY                     0x0260 0x0528 0x05AC 0x4 0x1
+#define MX6SLL_PAD_GPIO4_IO26__GPIO4_IO26                         0x0260 0x0528 0x0000 0x5 0x0
+#define MX6SLL_PAD_GPIO4_IO26__SPDIF_EXT_CLK                      0x0260 0x0528 0x073C 0x6 0x0
+
+#endif /* __DTS_IMX6SLL_PINFUNC_H */
diff --git a/arch/arm/boot/dts/imx6sll.dtsi b/arch/arm/boot/dts/imx6sll.dtsi
new file mode 100644 (file)
index 0000000..000e613
--- /dev/null
@@ -0,0 +1,780 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright 2016 Freescale Semiconductor, Inc.
+ * Copyright 2017-2018 NXP.
+ *
+ */
+
+#include <dt-bindings/clock/imx6sll-clock.h>
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include "imx6sll-pinfunc.h"
+
+/ {
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       aliases {
+               gpio0 = &gpio1;
+               gpio1 = &gpio2;
+               gpio2 = &gpio3;
+               gpio3 = &gpio4;
+               gpio4 = &gpio5;
+               gpio5 = &gpio6;
+               i2c0 = &i2c1;
+               i2c1 = &i2c2;
+               i2c2 = &i2c3;
+               mmc0 = &usdhc1;
+               mmc1 = &usdhc2;
+               mmc2 = &usdhc3;
+               serial0 = &uart1;
+               serial1 = &uart2;
+               serial2 = &uart3;
+               serial3 = &uart4;
+               serial4 = &uart5;
+               spi0 = &ecspi1;
+               spi1 = &ecspi2;
+               spi3 = &ecspi3;
+               spi4 = &ecspi4;
+               usbphy0 = &usbphy1;
+               usbphy1 = &usbphy2;
+       };
+
+       cpus {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               cpu0: cpu@0 {
+                       compatible = "arm,cortex-a9";
+                       device_type = "cpu";
+                       reg = <0>;
+                       next-level-cache = <&L2>;
+                       operating-points = <
+                               /* kHz    uV */
+                               996000  1275000
+                               792000  1175000
+                               396000  1075000
+                               198000  975000
+                       >;
+                       fsl,soc-operating-points = <
+                               /* ARM kHz      SOC-PU uV */
+                               996000          1175000
+                               792000          1175000
+                               396000          1175000
+                               198000          1175000
+                       >;
+                       clock-latency = <61036>; /* two CLK32 periods */
+                       clocks = <&clks IMX6SLL_CLK_ARM>,
+                                <&clks IMX6SLL_CLK_PLL2_PFD2>,
+                                <&clks IMX6SLL_CLK_STEP>,
+                                <&clks IMX6SLL_CLK_PLL1_SW>,
+                                <&clks IMX6SLL_CLK_PLL1_SYS>;
+                       clock-names = "arm", "pll2_pfd2_396m", "step",
+                                     "pll1_sw", "pll1_sys";
+               };
+       };
+
+       intc: interrupt-controller@a01000 {
+               compatible = "arm,cortex-a9-gic";
+               #interrupt-cells = <3>;
+               interrupt-controller;
+               reg = <0x00a01000 0x1000>,
+                     <0x00a00100 0x100>;
+               interrupt-parent = <&intc>;
+       };
+
+       ckil: clock-ckil {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <32768>;
+               clock-output-names = "ckil";
+       };
+
+       osc: clock-osc-24m {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <24000000>;
+               clock-output-names = "osc";
+       };
+
+       ipp_di0: clock-ipp-di0 {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <0>;
+               clock-output-names = "ipp_di0";
+       };
+
+       ipp_di1: clock-ipp-di1 {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <0>;
+               clock-output-names = "ipp_di1";
+       };
+
+       tempmon: temperature-sensor {
+               compatible = "fsl,imx6sll-tempmon", "fsl,imx6sx-tempmon";
+               interrupts = <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>;
+               interrupt-parent = <&gpc>;
+               fsl,tempmon = <&anatop>;
+               nvmem-cells = <&tempmon_calib>, <&tempmon_temp_grade>;
+               nvmem-cell-names = "calib", "temp_grade";
+               clocks = <&clks IMX6SLL_CLK_PLL3_USB_OTG>;
+       };
+
+       soc {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "simple-bus";
+               interrupt-parent = <&gpc>;
+               ranges;
+
+               ocram: sram@900000 {
+                       compatible = "mmio-sram";
+                       reg = <0x00900000 0x20000>;
+               };
+
+               L2: l2-cache@a02000 {
+                       compatible = "arm,pl310-cache";
+                       reg = <0x00a02000 0x1000>;
+                       interrupts = <GIC_SPI 92 IRQ_TYPE_LEVEL_HIGH>;
+                       cache-unified;
+                       cache-level = <2>;
+                       arm,tag-latency = <4 2 3>;
+                       arm,data-latency = <4 2 3>;
+               };
+
+               aips1: aips-bus@2000000 {
+                       compatible = "fsl,aips-bus", "simple-bus";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       reg = <0x02000000 0x100000>;
+                       ranges;
+
+                       spba: spba-bus@2000000 {
+                               compatible = "fsl,spba-bus", "simple-bus";
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+                               reg = <0x02000000 0x40000>;
+                               ranges;
+
+                               spdif: spdif@2004000 {
+                                       compatible = "fsl,imx6sl-spdif", "fsl,imx35-spdif";
+                                       reg = <0x02004000 0x4000>;
+                                       interrupts = <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>;
+                                       dmas = <&sdma 14 18 0>, <&sdma 15 18 0>;
+                                       dma-names = "rx", "tx";
+                                       clocks = <&clks IMX6SLL_CLK_SPDIF_GCLK>,
+                                                <&clks IMX6SLL_CLK_OSC>,
+                                                <&clks IMX6SLL_CLK_SPDIF>,
+                                                <&clks IMX6SLL_CLK_DUMMY>,
+                                                <&clks IMX6SLL_CLK_DUMMY>,
+                                                <&clks IMX6SLL_CLK_DUMMY>,
+                                                <&clks IMX6SLL_CLK_IPG>,
+                                                <&clks IMX6SLL_CLK_DUMMY>,
+                                                <&clks IMX6SLL_CLK_DUMMY>,
+                                                <&clks IMX6SLL_CLK_SPBA>;
+                                       clock-names = "core", "rxtx0",
+                                                     "rxtx1", "rxtx2",
+                                                     "rxtx3", "rxtx4",
+                                                     "rxtx5", "rxtx6",
+                                                     "rxtx7", "dma";
+                                       status = "disabled";
+                               };
+
+                               ecspi1: spi@2008000 {
+                                       compatible = "fsl,imx6ul-ecspi", "fsl,imx51-ecspi";
+                                       reg = <0x02008000 0x4000>;
+                                       interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
+                                       dmas = <&sdma 3 7 1>, <&sdma 4 7 2>;
+                                       dma-names = "rx", "tx";
+                                       clocks = <&clks IMX6SLL_CLK_ECSPI1>,
+                                                <&clks IMX6SLL_CLK_ECSPI1>;
+                                       clock-names = "ipg", "per";
+                                       status = "disabled";
+                               };
+
+                               ecspi2: spi@200c000 {
+                                       compatible = "fsl,imx6ul-ecspi", "fsl,imx51-ecspi";
+                                       reg = <0x0200c000 0x4000>;
+                                       interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
+                                       dmas = <&sdma 5 7 1>, <&sdma 6 7 2>;
+                                       dma-names = "rx", "tx";
+                                       clocks = <&clks IMX6SLL_CLK_ECSPI2>,
+                                                <&clks IMX6SLL_CLK_ECSPI2>;
+                                       clock-names = "ipg", "per";
+                                       status = "disabled";
+                               };
+
+                               ecspi3: spi@2010000 {
+                                       compatible = "fsl,imx6ul-ecspi", "fsl,imx51-ecspi";
+                                       reg = <0x02010000 0x4000>;
+                                       interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
+                                       dmas = <&sdma 7 7 1>, <&sdma 8 7 2>;
+                                       dma-names = "rx", "tx";
+                                       clocks = <&clks IMX6SLL_CLK_ECSPI3>,
+                                                <&clks IMX6SLL_CLK_ECSPI3>;
+                                       clock-names = "ipg", "per";
+                                       status = "disabled";
+                               };
+
+                               ecspi4: spi@2014000 {
+                                       compatible = "fsl,imx6ul-ecspi", "fsl,imx51-ecspi";
+                                       reg = <0x02014000 0x4000>;
+                                       interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
+                                       dmas = <&sdma 9 7 1>, <&sdma 10 7 2>;
+                                       dma-names = "rx", "tx";
+                                       clocks = <&clks IMX6SLL_CLK_ECSPI4>,
+                                                <&clks IMX6SLL_CLK_ECSPI4>;
+                                       clock-names = "ipg", "per";
+                                       status = "disabled";
+                               };
+
+                               uart4: serial@2018000 {
+                                       compatible = "fsl,imx6sl-uart", "fsl,imx6q-uart",
+                                                    "fsl,imx21-uart";
+                                       reg = <0x02018000 0x4000>;
+                                       interrupts =<GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
+                                       dmas = <&sdma 31 4 0>, <&sdma 32 4 0>;
+                                       dma-names = "rx", "tx";
+                                       clocks = <&clks IMX6SLL_CLK_UART4_IPG>,
+                                                <&clks IMX6SLL_CLK_UART4_SERIAL>;
+                                       clock-names = "ipg", "per";
+                                       status = "disabled";
+                               };
+
+                               uart1: serial@2020000 {
+                                       compatible = "fsl,imx6sl-uart", "fsl,imx6q-uart",
+                                                    "fsl,imx21-uart";
+                                       reg = <0x02020000 0x4000>;
+                                       interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
+                                       dmas = <&sdma 25 4 0>, <&sdma 26 4 0>;
+                                       dma-names = "rx", "tx";
+                                       clocks = <&clks IMX6SLL_CLK_UART1_IPG>,
+                                                <&clks IMX6SLL_CLK_UART1_SERIAL>;
+                                       clock-names = "ipg", "per";
+                                       status = "disabled";
+                               };
+
+                               uart2: serial@2024000 {
+                                       compatible = "fsl,imx6sl-uart", "fsl,imx6q-uart",
+                                                    "fsl,imx21-uart";
+                                       reg = <0x02024000 0x4000>;
+                                       interrupts = <GIC_SPI 27 IRQ_TYPE_LEVEL_HIGH>;
+                                       dmas = <&sdma 27 4 0>, <&sdma 28 4 0>;
+                                       dma-names = "rx", "tx";
+                                       clocks = <&clks IMX6SLL_CLK_UART2_IPG>,
+                                                <&clks IMX6SLL_CLK_UART2_SERIAL>;
+                                       clock-names = "ipg", "per";
+                                       status = "disabled";
+                               };
+
+                               ssi1: ssi-controller@2028000 {
+                                       compatible = "fsl,imx6sl-ssi", "fsl,imx51-ssi";
+                                       reg = <0x02028000 0x4000>;
+                                       interrupts = <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>;
+                                       dmas = <&sdma 37 22 0>, <&sdma 38 22 0>;
+                                       dma-names = "rx", "tx";
+                                       fsl,fifo-depth = <15>;
+                                       clocks = <&clks IMX6SLL_CLK_SSI1_IPG>,
+                                                <&clks IMX6SLL_CLK_SSI1>;
+                                       clock-names = "ipg", "baud";
+                                       status = "disabled";
+                               };
+
+                               ssi2: ssi-controller@202c000 {
+                                       compatible = "fsl,imx6sl-ssi", "fsl,imx51-ssi";
+                                       reg = <0x0202c000 0x4000>;
+                                       interrupts = <GIC_SPI 47 IRQ_TYPE_LEVEL_HIGH>;
+                                       dmas = <&sdma 41 22 0>, <&sdma 42 22 0>;
+                                       dma-names = "rx", "tx";
+                                       fsl,fifo-depth = <15>;
+                                       clocks = <&clks IMX6SLL_CLK_SSI2_IPG>,
+                                                <&clks IMX6SLL_CLK_SSI2>;
+                                       clock-names = "ipg", "baud";
+                                       status = "disabled";
+                               };
+
+                               ssi3: ssi-controller@2030000 {
+                                       compatible = "fsl,imx6sl-ssi", "fsl,imx51-ssi";
+                                       reg = <0x02030000 0x4000>;
+                                       interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
+                                       dmas = <&sdma 45 22 0>, <&sdma 46 22 0>;
+                                       dma-names = "rx", "tx";
+                                       fsl,fifo-depth = <15>;
+                                       clocks = <&clks IMX6SLL_CLK_SSI3_IPG>,
+                                                <&clks IMX6SLL_CLK_SSI3>;
+                                       clock-names = "ipg", "baud";
+                                       status = "disabled";
+                               };
+
+                               uart3: serial@2034000 {
+                                       compatible = "fsl,imx6sl-uart", "fsl,imx6q-uart",
+                                                    "fsl,imx21-uart";
+                                       reg = <0x02034000 0x4000>;
+                                       interrupts = <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>;
+                                       dmas = <&sdma 29 4 0>, <&sdma 30 4 0>;
+                                       dma-name = "rx", "tx";
+                                       clocks = <&clks IMX6SLL_CLK_UART3_IPG>,
+                                                <&clks IMX6SLL_CLK_UART3_SERIAL>;
+                                       clock-names = "ipg", "per";
+                                       status = "disabled";
+                               };
+                       };
+
+                       pwm1: pwm@2080000 {
+                               compatible = "fsl,imx6sll-pwm", "fsl,imx27-pwm";
+                               reg = <0x02080000 0x4000>;
+                               interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&clks IMX6SLL_CLK_PWM1>,
+                                        <&clks IMX6SLL_CLK_PWM1>;
+                               clock-names = "ipg", "per";
+                               #pwm-cells = <2>;
+                       };
+
+                       pwm2: pwm@2084000 {
+                               compatible = "fsl,imx6sll-pwm", "fsl,imx27-pwm";
+                               reg = <0x02084000 0x4000>;
+                               interrupts = <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&clks IMX6SLL_CLK_PWM2>,
+                                        <&clks IMX6SLL_CLK_PWM2>;
+                               clock-names = "ipg", "per";
+                               #pwm-cells = <2>;
+                       };
+
+                       pwm3: pwm@2088000 {
+                               compatible = "fsl,imx6sll-pwm", "fsl,imx27-pwm";
+                               reg = <0x02088000 0x4000>;
+                               interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&clks IMX6SLL_CLK_PWM3>,
+                                        <&clks IMX6SLL_CLK_PWM3>;
+                               clock-names = "ipg", "per";
+                               #pwm-cells = <2>;
+                       };
+
+                       pwm4: pwm@208c000 {
+                               compatible = "fsl,imx6sll-pwm", "fsl,imx27-pwm";
+                               reg = <0x0208c000 0x4000>;
+                               interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&clks IMX6SLL_CLK_PWM4>,
+                                        <&clks IMX6SLL_CLK_PWM4>;
+                               clock-names = "ipg", "per";
+                               #pwm-cells = <2>;
+                       };
+
+                       gpt1: timer@2098000 {
+                               compatible = "fsl,imx6sl-gpt";
+                               reg = <0x02098000 0x4000>;
+                               interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&clks IMX6SLL_CLK_GPT_BUS>,
+                                        <&clks IMX6SLL_CLK_GPT_SERIAL>;
+                               clock-names = "ipg", "per";
+                       };
+
+                       gpio1: gpio@209c000 {
+                               compatible = "fsl,imx6sll-gpio", "fsl,imx35-gpio";
+                               reg = <0x0209c000 0x4000>;
+                               interrupts = <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>,
+                                            <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>;
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               interrupt-controller;
+                               #interrupt-cells = <2>;
+                       };
+
+                       gpio2: gpio@20a0000 {
+                               compatible = "fsl,imx6sll-gpio", "fsl,imx35-gpio";
+                               reg = <0x020a0000 0x4000>;
+                               interrupts = <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>,
+                                            <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>;
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               interrupt-controller;
+                               #interrupt-cells = <2>;
+                       };
+
+                       gpio3: gpio@20a4000 {
+                               compatible = "fsl,imx6sll-gpio", "fsl,imx35-gpio";
+                               reg = <0x020a4000 0x4000>;
+                               interrupts = <GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>,
+                                            <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               interrupt-controller;
+                               #interrupt-cells = <2>;
+                       };
+
+                       gpio4: gpio@20a8000 {
+                               compatible = "fsl,imx6sll-gpio", "fsl,imx35-gpio";
+                               reg = <0x020a8000 0x4000>;
+                               interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>,
+                                            <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               interrupt-controller;
+                               #interrupt-cells = <2>;
+                       };
+
+                       gpio5: gpio@20ac000 {
+                               compatible = "fsl,imx6sll-gpio", "fsl,imx35-gpio";
+                               reg = <0x020ac000 0x4000>;
+                               interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>,
+                                            <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>;
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               interrupt-controller;
+                               #interrupt-cells = <2>;
+                       };
+
+                       gpio6: gpio@20b0000 {
+                               compatible = "fsl,imx6sll-gpio", "fsl,imx35-gpio";
+                               reg = <0x020b0000 0x4000>;
+                               interrupts = <GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>,
+                                            <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>;
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               interrupt-controller;
+                               #interrupt-cells = <2>;
+                       };
+
+                       kpp: keypad@20b8000 {
+                               compatible = "fsl,imx6sll-kpp", "fsl,imx21-kpp";
+                               reg = <0x020b8000 0x4000>;
+                               interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&clks IMX6SLL_CLK_KPP>;
+                               status = "disabled";
+                       };
+
+                       wdog1: watchdog@20bc000 {
+                               compatible = "fsl,imx6sll-wdt", "fsl,imx21-wdt";
+                               reg = <0x020bc000 0x4000>;
+                               interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&clks IMX6SLL_CLK_WDOG1>;
+                       };
+
+                       wdog2: watchdog@20c0000 {
+                               compatible = "fsl,imx6sll-wdt", "fsl,imx21-wdt";
+                               reg = <0x020c0000 0x4000>;
+                               interrupts = <GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&clks IMX6SLL_CLK_WDOG2>;
+                               status = "disabled";
+                       };
+
+                       clks: clock-controller@20c4000 {
+                               compatible = "fsl,imx6sll-ccm";
+                               reg = <0x020c4000 0x4000>;
+                               interrupts = <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>,
+                                            <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>;
+                               #clock-cells = <1>;
+                               clocks = <&ckil>, <&osc>, <&ipp_di0>, <&ipp_di1>;
+                               clock-names = "ckil", "osc", "ipp_di0", "ipp_di1";
+
+                               assigned-clocks = <&clks IMX6SLL_CLK_PERCLK_SEL>;
+                               assigned-clock-parents = <&clks IMX6SLL_CLK_OSC>;
+                       };
+
+                       anatop: anatop@20c8000 {
+                               compatible = "fsl,imx6sll-anatop",
+                                            "fsl,imx6q-anatop",
+                                            "syscon", "simple-bus";
+                               reg = <0x020c8000 0x4000>;
+                               interrupts = <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>,
+                                            <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>,
+                                            <GIC_SPI 127 IRQ_TYPE_LEVEL_HIGH>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+
+                               reg_3p0: regulator-3p0@20c8120 {
+                                       compatible = "fsl,anatop-regulator";
+                                       reg = <0x20c8120>;
+                                       regulator-name = "vdd3p0";
+                                       regulator-min-microvolt = <2625000>;
+                                       regulator-max-microvolt = <3400000>;
+                                       anatop-reg-offset = <0x120>;
+                                       anatop-vol-bit-shift = <8>;
+                                       anatop-vol-bit-width = <5>;
+                                       anatop-min-bit-val = <0>;
+                                       anatop-min-voltage = <2625000>;
+                                       anatop-max-voltage = <3400000>;
+                                       anatop-enable-bit = <0>;
+                               };
+                       };
+
+                       usbphy1: usb-phy@20c9000 {
+                               compatible = "fsl,imx6sll-usbphy", "fsl,imx6ul-usbphy",
+                                               "fsl,imx23-usbphy";
+                               reg = <0x020c9000 0x1000>;
+                               interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&clks IMX6SLL_CLK_USBPHY1>;
+                               phy-3p0-supply = <&reg_3p0>;
+                               fsl,anatop = <&anatop>;
+                       };
+
+                       usbphy2: usb-phy@20ca000 {
+                               compatible = "fsl,imx6sll-usbphy", "fsl,imx6ul-usbphy",
+                                               "fsl,imx23-usbphy";
+                               reg = <0x020ca000 0x1000>;
+                               interrupts = <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&clks IMX6SLL_CLK_USBPHY2>;
+                               phy-reg_3p0-supply = <&reg_3p0>;
+                               fsl,anatop = <&anatop>;
+                       };
+
+                       snvs: snvs@20cc000 {
+                               compatible = "fsl,sec-v4.0-mon", "syscon", "simple-mfd";
+                               reg = <0x020cc000 0x4000>;
+
+                               snvs_rtc: snvs-rtc-lp {
+                                       compatible = "fsl,sec-v4.0-mon-rtc-lp";
+                                       regmap = <&snvs>;
+                                       offset = <0x34>;
+                                       interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>,
+                                                    <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>;
+                               };
+
+                               snvs_poweroff: snvs-poweroff {
+                                       compatible = "syscon-poweroff";
+                                       regmap = <&snvs>;
+                                       offset = <0x38>;
+                                       mask = <0x61>;
+                               };
+
+                               snvs_pwrkey: snvs-powerkey {
+                                       compatible = "fsl,sec-v4.0-pwrkey";
+                                       regmap = <&snvs>;
+                                       interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>;
+                                       linux,keycode = <KEY_POWER>;
+                                       wakeup-source;
+                               };
+                       };
+
+                       src: reset-controller@20d8000 {
+                               compatible = "fsl,imx6sll-src", "fsl,imx51-src";
+                               reg = <0x020d8000 0x4000>;
+                               interrupts = <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>,
+                                            <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>;
+                               #reset-cells = <1>;
+                       };
+
+                       gpc: interrupt-controller@20dc000 {
+                               compatible = "fsl,imx6sll-gpc", "fsl,imx6q-gpc";
+                               reg = <0x020dc000 0x4000>;
+                               interrupt-controller;
+                               #interrupt-cells = <3>;
+                               interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>;
+                               interrupt-parent = <&intc>;
+                               fsl,mf-mix-wakeup-irq = <0x7c00000 0x7d00 0x0 0x1400640>;
+                       };
+
+                       iomuxc: pinctrl@20e0000 {
+                               compatible = "fsl,imx6sll-iomuxc";
+                               reg = <0x020e0000 0x4000>;
+                       };
+
+                       gpr: iomuxc-gpr@20e4000 {
+                               compatible = "fsl,imx6sll-iomuxc-gpr",
+                                            "fsl,imx6q-iomuxc-gpr", "syscon";
+                               reg = <0x020e4000 0x4000>;
+                       };
+
+                       csi: csi@20e8000 {
+                               compatible = "fsl,imx6sll-csi", "fsl,imx6s-csi";
+                               reg = <0x020e8000 0x4000>;
+                               interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&clks IMX6SLL_CLK_DUMMY>,
+                                        <&clks IMX6SLL_CLK_CSI>,
+                                        <&clks IMX6SLL_CLK_DUMMY>;
+                               clock-names = "disp-axi", "csi_mclk", "disp_dcic";
+                               status = "disabled";
+                       };
+
+                       sdma: dma-controller@20ec000 {
+                               compatible = "fsl,imx6sll-sdma", "fsl,imx35-sdma";
+                               reg = <0x020ec000 0x4000>;
+                               interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&clks IMX6SLL_CLK_SDMA>,
+                                        <&clks IMX6SLL_CLK_SDMA>;
+                               clock-names = "ipg", "ahb";
+                               #dma-cells = <3>;
+                               iram = <&ocram>;
+                               fsl,sdma-ram-script-name = "imx/sdma/sdma-imx6q.bin";
+                       };
+
+                       lcdif: lcd-controller@20f8000 {
+                               compatible = "fsl,imx6sll-lcdif", "fsl,imx28-lcdif";
+                               reg = <0x020f8000 0x4000>;
+                               interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&clks IMX6SLL_CLK_LCDIF_PIX>,
+                                        <&clks IMX6SLL_CLK_LCDIF_APB>,
+                                        <&clks IMX6SLL_CLK_DUMMY>;
+                               clock-names = "pix", "axi", "disp_axi";
+                               status = "disabled";
+                       };
+
+                       dcp: dcp@20fc000 {
+                               compatible = "fsl,imx28-dcp";
+                               reg = <0x020fc000 0x4000>;
+                               interrupts = <GIC_SPI 99 IRQ_TYPE_LEVEL_HIGH>,
+                                            <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>,
+                                            <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&clks IMX6SLL_CLK_DCP>;
+                               clock-names = "dcp";
+                       };
+               };
+
+               aips2: aips-bus@2100000 {
+                       compatible = "fsl,aips-bus", "simple-bus";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       reg = <0x02100000 0x100000>;
+                       ranges;
+
+                       usbotg1: usb@2184000 {
+                               compatible = "fsl,imx6sll-usb", "fsl,imx6ul-usb",
+                                               "fsl,imx27-usb";
+                               reg = <0x02184000 0x200>;
+                               interrupts = <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&clks IMX6SLL_CLK_USBOH3>;
+                               fsl,usbphy = <&usbphy1>;
+                               fsl,usbmisc = <&usbmisc 0>;
+                               fsl,anatop = <&anatop>;
+                               ahb-burst-config = <0x0>;
+                               tx-burst-size-dword = <0x10>;
+                               rx-burst-size-dword = <0x10>;
+                               status = "disabled";
+                       };
+
+                       usbotg2: usb@2184200 {
+                               compatible = "fsl,imx6sll-usb", "fsl,imx6ul-usb",
+                                               "fsl,imx27-usb";
+                               reg = <0x02184200 0x200>;
+                               interrupts = <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&clks IMX6SLL_CLK_USBOH3>;
+                               fsl,usbphy = <&usbphy2>;
+                               fsl,usbmisc = <&usbmisc 1>;
+                               ahb-burst-config = <0x0>;
+                               tx-burst-size-dword = <0x10>;
+                               rx-burst-size-dword = <0x10>;
+                               status = "disabled";
+                       };
+
+                       usbmisc: usbmisc@2184800 {
+                               #index-cells = <1>;
+                               compatible = "fsl,imx6sll-usbmisc", "fsl,imx6ul-usbmisc",
+                                               "fsl,imx6q-usbmisc";
+                               reg = <0x02184800 0x200>;
+                       };
+
+                       usdhc1: mmc@2190000 {
+                               compatible = "fsl,imx6sll-usdhc", "fsl,imx6sx-usdhc";
+                               reg = <0x02190000 0x4000>;
+                               interrupts = <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&clks IMX6SLL_CLK_USDHC1>,
+                                        <&clks IMX6SLL_CLK_USDHC1>,
+                                        <&clks IMX6SLL_CLK_USDHC1>;
+                               clock-names = "ipg", "ahb", "per";
+                               bus-width = <4>;
+                               fsl,tuning-step = <2>;
+                               fsl,tuning-start-tap = <20>;
+                               status = "disabled";
+                       };
+
+                       usdhc2: mmc@2194000 {
+                               compatible = "fsl,imx6sll-usdhc", "fsl,imx6sx-usdhc";
+                               reg = <0x02194000 0x4000>;
+                               interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&clks IMX6SLL_CLK_USDHC2>,
+                                        <&clks IMX6SLL_CLK_USDHC2>,
+                                        <&clks IMX6SLL_CLK_USDHC2>;
+                               clock-names = "ipg", "ahb", "per";
+                               bus-width = <4>;
+                               fsl,tuning-step = <2>;
+                               fsl,tuning-start-tap = <20>;
+                               status = "disabled";
+                       };
+
+                       usdhc3: mmc@2198000 {
+                               compatible = "fsl,imx6sll-usdhc", "fsl,imx6sx-usdhc";
+                               reg = <0x02198000 0x4000>;
+                               interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&clks IMX6SLL_CLK_USDHC3>,
+                                        <&clks IMX6SLL_CLK_USDHC3>,
+                                        <&clks IMX6SLL_CLK_USDHC3>;
+                               clock-names = "ipg", "ahb", "per";
+                               bus-width = <4>;
+                               fsl,tuning-step = <2>;
+                               fsl,tuning-start-tap = <20>;
+                               status = "disabled";
+                       };
+
+                       i2c1: i2c@21a0000 {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               compatible = "fs,imx6sll-i2c", "fsl,imx21-i2c";
+                               reg = <0x021a0000 0x4000>;
+                               interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&clks IMX6SLL_CLK_I2C1>;
+                               status = "disabled";
+                       };
+
+                       i2c2: i2c@21a4000 {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               compatible = "fsl,imx6sll-i2c", "fsl,imx21-i2c";
+                               reg = <0x021a4000 0x4000>;
+                               interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&clks IMX6SLL_CLK_I2C2>;
+                               status = "disabled";
+                       };
+
+                       i2c3: i2c@21a8000 {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               compatible = "fsl,imx6sll-i2c", "fsl,imx21-i2c";
+                               reg = <0x021a8000 0x4000>;
+                               interrupts = <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&clks IMX6SLL_CLK_I2C3>;
+                               status = "disabled";
+                       };
+
+                       mmdc: memory-controller@21b0000 {
+                               compatible = "fsl,imx6sll-mmdc", "fsl,imx6q-mmdc";
+                               reg = <0x021b0000 0x4000>;
+                       };
+
+                       ocotp: ocotp-ctrl@21bc000 {
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+                               compatible = "fsl,imx6sll-ocotp", "syscon";
+                               reg = <0x021bc000 0x4000>;
+                               clocks = <&clks IMX6SLL_CLK_OCOTP>;
+
+                               tempmon_calib: calib@38 {
+                                       reg = <0x38 4>;
+                               };
+
+                               tempmon_temp_grade: temp-grade@20 {
+                                       reg = <0x20 4>;
+                               };
+                       };
+
+                       audmux: audmux@21d8000 {
+                               compatible = "fsl,imx6sll-audmux", "fsl,imx31-audmux";
+                               reg = <0x021d8000 0x4000>;
+                               status = "disabled";
+                       };
+
+                       uart5: serial@21f4000 {
+                               compatible = "fsl,imx6sll-uart", "fsl,imx6q-uart",
+                                            "fsl,imx21-uart";
+                               reg = <0x021f4000 0x4000>;
+                               interrupts =<GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
+                               dmas = <&sdma 33 4 0>, <&sdma 34 4 0>;
+                               dma-names = "rx", "tx";
+                               clocks = <&clks IMX6SLL_CLK_UART5_IPG>,
+                                        <&clks IMX6SLL_CLK_UART5_SERIAL>;
+                               clock-names = "ipg", "per";
+                               status = "disabled";
+                       };
+               };
+       };
+};
index 59e52f5..adb5cc7 100644 (file)
@@ -1,42 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0 OR X11
 /*
  * Copyright (C) 2016 Boundary Devices, 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/;
        model = "Boundary Devices i.MX6 SoloX Nitrogen6sx Board";
        compatible = "boundary,imx6sx-nitrogen6sx", "fsl,imx6sx";
 
-       aliases {
-               fb-lcd = &lcdif1;
-               t-lcd = &t_lcd;
-       };
-
        memory@80000000 {
                reg = <0x80000000 0x40000000>;
        };
        status = "okay";
 };
 
-&lcdif1 {
-       pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_lcdif1>;
-       lcd-supply = <&reg_3p3v>;
-       display = <&display0>;
-       status = "okay";
-
-       display0: display0 {
-               bits-per-pixel = <16>;
-               bus-width = <24>;
-
-               display-timings {
-                       native-mode = <&t_lcd>;
-                       t_lcd: t_lcd_default {
-                               clock-frequency = <74160000>;
-                               hactive = <1280>;
-                               vactive = <720>;
-                               hback-porch = <220>;
-                               hfront-porch = <110>;
-                               vback-porch = <20>;
-                               vfront-porch = <5>;
-                               hsync-len = <40>;
-                               vsync-len = <5>;
-                               hsync-active = <0>;
-                               vsync-active = <0>;
-                               de-active = <1>;
-                               pixelclk-active = <0>;
-                       };
-               };
-       };
-};
-
 &pcie {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_pcie>;
                >;
        };
 
-       pinctrl_lcdif1: lcdif1grp {
-               fsl,pins = <
-                       MX6SX_PAD_LCD1_CLK__LCDIF1_CLK          0x4001b0b0
-                       MX6SX_PAD_LCD1_ENABLE__LCDIF1_ENABLE    0x4001b0b0
-                       MX6SX_PAD_LCD1_HSYNC__LCDIF1_HSYNC      0x4001b0b0
-                       MX6SX_PAD_LCD1_VSYNC__LCDIF1_VSYNC      0x4001b0b0
-                       MX6SX_PAD_LCD1_RESET__GPIO3_IO_27       0x4001b0b0
-                       MX6SX_PAD_LCD1_DATA00__LCDIF1_DATA_0    0x4001b0b0
-                       MX6SX_PAD_LCD1_DATA01__LCDIF1_DATA_1    0x4001b0b0
-                       MX6SX_PAD_LCD1_DATA02__LCDIF1_DATA_2    0x4001b0b0
-                       MX6SX_PAD_LCD1_DATA03__LCDIF1_DATA_3    0x4001b0b0
-                       MX6SX_PAD_LCD1_DATA04__LCDIF1_DATA_4    0x4001b0b0
-                       MX6SX_PAD_LCD1_DATA05__LCDIF1_DATA_5    0x4001b0b0
-                       MX6SX_PAD_LCD1_DATA06__LCDIF1_DATA_6    0x4001b0b0
-                       MX6SX_PAD_LCD1_DATA07__LCDIF1_DATA_7    0x4001b0b0
-                       MX6SX_PAD_LCD1_DATA08__LCDIF1_DATA_8    0x4001b0b0
-                       MX6SX_PAD_LCD1_DATA09__LCDIF1_DATA_9    0x4001b0b0
-                       MX6SX_PAD_LCD1_DATA10__LCDIF1_DATA_10   0x4001b0b0
-                       MX6SX_PAD_LCD1_DATA11__LCDIF1_DATA_11   0x4001b0b0
-                       MX6SX_PAD_LCD1_DATA12__LCDIF1_DATA_12   0x4001b0b0
-                       MX6SX_PAD_LCD1_DATA13__LCDIF1_DATA_13   0x4001b0b0
-                       MX6SX_PAD_LCD1_DATA14__LCDIF1_DATA_14   0x4001b0b0
-                       MX6SX_PAD_LCD1_DATA15__LCDIF1_DATA_15   0x4001b0b0
-                       MX6SX_PAD_LCD1_DATA16__LCDIF1_DATA_16   0x4001b0b0
-                       MX6SX_PAD_LCD1_DATA17__LCDIF1_DATA_17   0x4001b0b0
-                       MX6SX_PAD_LCD1_DATA18__LCDIF1_DATA_18   0x4001b0b0
-                       MX6SX_PAD_LCD1_DATA19__LCDIF1_DATA_19   0x4001b0b0
-                       MX6SX_PAD_LCD1_DATA20__LCDIF1_DATA_20   0x4001b0b0
-                       MX6SX_PAD_LCD1_DATA21__LCDIF1_DATA_21   0x4001b0b0
-                       MX6SX_PAD_LCD1_DATA22__LCDIF1_DATA_22   0x4001b0b0
-                       MX6SX_PAD_LCD1_DATA23__LCDIF1_DATA_23   0x4001b0b0
-               >;
-       };
-
        pinctrl_pcie: pciegrp {
                fsl,pins = <
                        MX6SX_PAD_NAND_DATA05__GPIO4_IO_9       0xb0b0
index e3533e7..9cc6ff2 100644 (file)
@@ -63,6 +63,7 @@
                        sw4_reg: sw4 {
                                regulator-min-microvolt = <800000>;
                                regulator-max-microvolt = <3300000>;
+                               regulator-always-on;
                        };
 
                        swbst_reg: swbst {
index 4e4a55a..844caa3 100644 (file)
@@ -79,6 +79,7 @@
                                198000      1175000
                        >;
                        clock-latency = <61036>; /* two CLK32 periods */
+                       #cooling-cells = <2>;
                        clocks = <&clks IMX6SX_CLK_ARM>,
                                 <&clks IMX6SX_CLK_PLL2_PFD2>,
                                 <&clks IMX6SX_CLK_STEP>,
                interrupt-parent = <&gpc>;
                ranges;
 
+               ocram_s: sram@8f8000 {
+                       compatible = "mmio-sram";
+                       reg = <0x008f8000 0x4000>;
+                       clocks = <&clks IMX6SX_CLK_OCRAM_S>;
+               };
+
                ocram: sram@900000 {
                        compatible = "mmio-sram";
                        reg = <0x00900000 0x20000>;
                                regulator-1p1 {
                                        compatible = "fsl,anatop-regulator";
                                        regulator-name = "vdd1p1";
-                                       regulator-min-microvolt = <800000>;
-                                       regulator-max-microvolt = <1375000>;
+                                       regulator-min-microvolt = <1000000>;
+                                       regulator-max-microvolt = <1200000>;
                                        regulator-always-on;
                                        anatop-reg-offset = <0x110>;
                                        anatop-vol-bit-shift = <8>;
                                regulator-2p5 {
                                        compatible = "fsl,anatop-regulator";
                                        regulator-name = "vdd2p5";
-                                       regulator-min-microvolt = <2100000>;
-                                       regulator-max-microvolt = <2875000>;
+                                       regulator-min-microvolt = <2250000>;
+                                       regulator-max-microvolt = <2750000>;
                                        regulator-always-on;
                                        anatop-reg-offset = <0x130>;
                                        anatop-vol-bit-shift = <8>;
 
                        crypto: caam@2100000 {
                                compatible = "fsl,sec-v4.0";
-                               fsl,sec-era = <4>;
                                #address-cells = <1>;
                                #size-cells = <1>;
                                reg = <0x2100000 0x10000>;
diff --git a/arch/arm/boot/dts/imx6ul-ccimx6ulsbcexpress.dts b/arch/arm/boot/dts/imx6ul-ccimx6ulsbcexpress.dts
new file mode 100644 (file)
index 0000000..3792679
--- /dev/null
@@ -0,0 +1,200 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Digi International's ConnectCore6UL SBC Express board device tree source
+ *
+ * Copyright 2018 Digi International, Inc.
+ *
+ */
+
+/dts-v1/;
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include "imx6ul.dtsi"
+#include "imx6ul-ccimx6ulsom.dtsi"
+
+/ {
+       model = "Digi International ConnectCore 6UL SBC Express.";
+       compatible = "digi,ccimx6ulsbcexpress", "digi,ccimx6ulsom",
+                    "fsl,imx6ul";
+};
+
+&adc1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_adc1>;
+       status = "okay";
+};
+
+&can1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_flexcan1>;
+       xceiver-supply = <&ext_3v3>;
+       status = "okay";
+};
+
+&ecspi3 {
+       cs-gpios = <&gpio1 20 GPIO_ACTIVE_LOW>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_ecspi3_master>;
+       status = "okay";
+};
+
+&fec1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_enet1>;
+       phy-mode = "rmii";
+       phy-handle = <&ethphy0>;
+       status = "okay";
+
+       mdio {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               ethphy0: ethernet-phy@0 {
+                       compatible = "ethernet-phy-ieee802.3-c22";
+                       smsc,disable-energy-detect;
+                       reg = <0>;
+               };
+       };
+};
+
+&i2c2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_i2c2>;
+       status = "okay";
+};
+
+&pwm1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_pwm1>;
+       status = "okay";
+};
+
+&uart4 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_uart4>;
+       status = "okay";
+};
+
+&uart5 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_uart5>;
+       status = "okay";
+};
+
+&usbotg1 {
+       dr_mode = "host";
+       disable-over-current;
+       status = "okay";
+};
+
+&usbotg2 {
+       dr_mode = "host";
+       disable-over-current;
+       status = "okay";
+};
+
+&usdhc2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_usdhc2>;
+       broken-cd;      /* no carrier detect line (use polling) */
+       no-1-8-v;
+       status = "okay";
+};
+
+&iomuxc {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_hog>;
+
+       pinctrl_adc1: adc1grp {
+               fsl,pins = <
+                       /* GPIO1_4/ADC1_IN4 (pin 7 of the expansion header) */
+                       MX6UL_PAD_GPIO1_IO04__GPIO1_IO04        0xb0
+               >;
+       };
+
+       pinctrl_ecspi3_master: ecspi3grp1 {
+               fsl,pins = <
+                       MX6UL_PAD_UART2_RX_DATA__ECSPI3_SCLK    0x10b0
+                       MX6UL_PAD_UART2_CTS_B__ECSPI3_MOSI      0x10b0
+                       MX6UL_PAD_UART2_RTS_B__ECSPI3_MISO      0x10b0
+                       MX6UL_PAD_UART2_TX_DATA__GPIO1_IO20     0x10b0 /* Chip Select */
+               >;
+       };
+
+       pinctrl_ecspi3_slave: ecspi3grp2 {
+               fsl,pins = <
+                       MX6UL_PAD_UART2_RX_DATA__ECSPI3_SCLK    0x10b0
+                       MX6UL_PAD_UART2_CTS_B__ECSPI3_MOSI      0x10b0
+                       MX6UL_PAD_UART2_RTS_B__ECSPI3_MISO      0x10b0
+                       MX6UL_PAD_UART2_TX_DATA__ECSPI3_SS0     0x10b0 /* Chip Select */
+               >;
+       };
+
+       pinctrl_enet1: enet1grp {
+               fsl,pins = <
+                       MX6UL_PAD_GPIO1_IO07__ENET1_MDC         0x1b0b0
+                       MX6UL_PAD_GPIO1_IO06__ENET1_MDIO        0x1b0b0
+                       MX6UL_PAD_ENET1_RX_EN__ENET1_RX_EN      0x1b0b0
+                       MX6UL_PAD_ENET1_RX_ER__ENET1_RX_ER      0x1b0b0
+                       MX6UL_PAD_ENET1_RX_DATA0__ENET1_RDATA00 0x1b0b0
+                       MX6UL_PAD_ENET1_RX_DATA1__ENET1_RDATA01 0x1b0b0
+                       MX6UL_PAD_ENET1_TX_EN__ENET1_TX_EN      0x1b0b0
+                       MX6UL_PAD_ENET1_TX_DATA0__ENET1_TDATA00 0x1b0b0
+                       MX6UL_PAD_ENET1_TX_DATA1__ENET1_TDATA01 0x1b0b0
+                       MX6UL_PAD_ENET1_TX_CLK__ENET1_REF_CLK1  0x40017051
+               >;
+       };
+
+       pinctrl_flexcan1: flexcan1grp{
+               fsl,pins = <
+                       MX6UL_PAD_LCD_DATA08__FLEXCAN1_TX       0x1b020
+                       MX6UL_PAD_LCD_DATA09__FLEXCAN1_RX       0x1b020
+               >;
+       };
+
+       pinctrl_i2c2: i2c2grp {
+               fsl,pins = <
+                       MX6UL_PAD_GPIO1_IO00__I2C2_SCL 0x4001b8b0
+                       MX6UL_PAD_GPIO1_IO01__I2C2_SDA 0x4001b8b0
+               >;
+       };
+
+       pinctrl_pwm1: pwm1grp {
+               fsl,pins = <
+                       MX6UL_PAD_LCD_DATA00__PWM1_OUT          0x10b0
+               >;
+       };
+
+       pinctrl_uart4: uart4grp {
+               fsl,pins = <
+                       MX6UL_PAD_LCD_CLK__UART4_DCE_TX         0x1b0b1
+                       MX6UL_PAD_LCD_ENABLE__UART4_DCE_RX      0x1b0b1
+               >;
+       };
+
+       pinctrl_uart5: uart5grp {
+               fsl,pins = <
+                       MX6UL_PAD_UART5_TX_DATA__UART5_DCE_TX   0x1b0b1
+                       MX6UL_PAD_UART5_RX_DATA__UART5_DCE_RX   0x1b0b1
+               >;
+       };
+
+       pinctrl_usdhc2: usdhc2grp {
+               fsl,pins = <
+                       MX6UL_PAD_CSI_HSYNC__USDHC2_CMD         0x17059
+                       MX6UL_PAD_CSI_VSYNC__USDHC2_CLK         0x10071
+                       MX6UL_PAD_CSI_DATA00__USDHC2_DATA0      0x17059
+                       MX6UL_PAD_CSI_DATA01__USDHC2_DATA1      0x17059
+                       MX6UL_PAD_CSI_DATA02__USDHC2_DATA2      0x17059
+                       MX6UL_PAD_CSI_DATA03__USDHC2_DATA3      0x17059
+               >;
+       };
+
+       /* General purpose pinctrl */
+       pinctrl_hog: hoggrp {
+               fsl,pins = <
+                       /* GPIOs BANK 3 */
+                       MX6UL_PAD_LCD_RESET__GPIO3_IO04         0xf030
+               >;
+       };
+};
diff --git a/arch/arm/boot/dts/imx6ul-ccimx6ulsom.dtsi b/arch/arm/boot/dts/imx6ul-ccimx6ulsom.dtsi
new file mode 100644 (file)
index 0000000..c71a84d
--- /dev/null
@@ -0,0 +1,201 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Digi International's ConnectCore 6UL System-On-Module device tree source
+ *
+ * Copyright 2018 Digi International, Inc.
+ *
+ */
+
+/ {
+       reserved-memory {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges;
+
+               linux,cma {
+                       compatible = "shared-dma-pool";
+                       reusable;
+                       size = <0x4000000>;
+                       linux,cma-default;
+               };
+       };
+};
+
+&adc1 {
+       vref-supply = <&vdda_adc_3v3>;
+};
+
+&gpmi {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_gpmi_nand>;
+       status = "okay";
+};
+
+&i2c1 {
+       clock-frequency = <100000>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_i2c1>;
+       status = "okay";
+
+       pfuze3000: pmic@8 {
+               compatible = "fsl,pfuze3000";
+               reg = <0x08>;
+
+               regulators {
+                       int_3v3: sw1a {
+                               regulator-min-microvolt = <700000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-ramp-delay = <6250>;
+                               regulator-boot-on;
+                               regulator-always-on;
+
+                               regulator-state-mem {
+                                       regulator-off-in-suspend;
+                               };
+                       };
+
+                       vdd_arm_soc_in: sw1b {
+                               regulator-min-microvolt = <700000>;
+                               regulator-max-microvolt = <1475000>;
+                               regulator-ramp-delay = <6250>;
+                               regulator-boot-on;
+                               regulator-always-on;
+
+                               regulator-state-mem {
+                                       regulator-on-in-suspend;
+                                       regulator-suspend-microvolt = <925000>;
+                               };
+                       };
+
+                       ext_3v3: sw2 {
+                               regulator-min-microvolt = <2500000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-ramp-delay = <6250>;
+                               regulator-always-on;
+                               regulator-boot-on;
+
+                               regulator-state-mem {
+                                       regulator-off-in-suspend;
+                               };
+                       };
+
+                       vcc_ddr3: sw3 {
+                               regulator-min-microvolt = <900000>;
+                               regulator-max-microvolt = <1650000>;
+                               regulator-always-on;
+                               regulator-boot-on;
+
+                               regulator-state-mem {
+                                       regulator-on-in-suspend;
+                                       regulator-suspend-microvolt = <1300000>;
+                               };
+                       };
+
+                       swbst_reg: swbst {
+                               regulator-min-microvolt = <5000000>;
+                               regulator-max-microvolt = <5150000>;
+                       };
+
+                       vdd_snvs_3v3: vsnvs {
+                               regulator-min-microvolt = <1000000>;
+                               regulator-max-microvolt = <3000000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+
+                       vrefddr: vrefddr {
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+
+                       vdda_adc_3v3: vldo1 {
+                               compatible = "regulator-fixed";
+                               regulator-name = "vref-adc-3v3";
+                               regulator-min-microvolt = <3300000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-always-on;
+
+                               regulator-state-mem {
+                                       regulator-off-in-suspend;
+                               };
+                       };
+
+                       ldo2_ext: vldo2 {
+                               regulator-min-microvolt = <800000>;
+                               regulator-max-microvolt = <1550000>;
+                       };
+
+                       vdda_wlan: vccsd {
+                               regulator-min-microvolt = <2850000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-always-on;
+                               regulator-boot-on;
+
+                               regulator-state-mem {
+                                       regulator-off-in-suspend;
+                               };
+                       };
+
+                       vdd_high_in: v33 {
+                               regulator-min-microvolt = <2850000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+
+                       ldo3_int: vldo3 {
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <3300000>;
+                       };
+
+                       ldo4_ext: vldo4 {
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <3300000>;
+                       };
+
+                       vcoin_chg: vcoin {
+                               regulator-min-microvolt = <2500000>;
+                               regulator-max-microvolt = <3300000>;
+                       };
+               };
+       };
+};
+
+&iomuxc {
+       pinctrl_gpmi_nand: gpmigrp {
+               fsl,pins = <
+                       MX6UL_PAD_NAND_CE0_B__RAWNAND_CE0_B     0xb0b1
+                       MX6UL_PAD_NAND_RE_B__RAWNAND_RE_B       0xb0b1
+                       MX6UL_PAD_NAND_WE_B__RAWNAND_WE_B       0xb0b1
+                       MX6UL_PAD_NAND_WP_B__RAWNAND_WP_B       0xb0b1
+                       MX6UL_PAD_NAND_ALE__RAWNAND_ALE         0xb0b1
+                       MX6UL_PAD_NAND_CLE__RAWNAND_CLE         0xb0b1
+                       MX6UL_PAD_NAND_DATA00__RAWNAND_DATA00   0xb0b1
+                       MX6UL_PAD_NAND_DATA01__RAWNAND_DATA01   0xb0b1
+                       MX6UL_PAD_NAND_DATA02__RAWNAND_DATA02   0xb0b1
+                       MX6UL_PAD_NAND_DATA03__RAWNAND_DATA03   0xb0b1
+                       MX6UL_PAD_NAND_DATA04__RAWNAND_DATA04   0xb0b1
+                       MX6UL_PAD_NAND_DATA05__RAWNAND_DATA05   0xb0b1
+                       MX6UL_PAD_NAND_DATA06__RAWNAND_DATA06   0xb0b1
+                       MX6UL_PAD_NAND_DATA07__RAWNAND_DATA07   0xb0b1
+                       MX6UL_PAD_NAND_READY_B__RAWNAND_READY_B 0xb0b1
+                       >;
+               };
+
+       pinctrl_i2c1: i2c1grp {
+               fsl,pins = <
+                       MX6UL_PAD_UART4_TX_DATA__I2C1_SCL 0x4001b8b0
+                       MX6UL_PAD_UART4_RX_DATA__I2C1_SDA 0x4001b8b0
+                       >;
+               };
+};
+
+&reg_arm {
+       vin-supply = <&vdd_arm_soc_in>;
+       regulator-allow-bypass;
+};
+
+&reg_soc {
+       vin-supply = <&vdd_arm_soc_in>;
+       regulator-allow-bypass;
+};
index 47682b8..0c09420 100644 (file)
@@ -51,8 +51,9 @@
        model = "Technexion Pico i.MX6UL Board";
        compatible = "technexion,imx6ul-pico-hobbit", "fsl,imx6ul";
 
+       /* Will be filled by the bootloader */
        memory@80000000 {
-               reg = <0x80000000 0x10000000>;
+               reg = <0x80000000 0>;
        };
 
        chosen {
index 47a3453..6dc0b56 100644 (file)
@@ -62,6 +62,7 @@
                        device_type = "cpu";
                        reg = <0>;
                        clock-latency = <61036>; /* two CLK32 periods */
+                       #cooling-cells = <2>;
                        operating-points = <
                                /* kHz  uV */
                                696000  1275000
                                reg = <0x0209c000 0x4000>;
                                interrupts = <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>,
                                             <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&clks IMX6UL_CLK_GPIO1>;
                                gpio-controller;
                                #gpio-cells = <2>;
                                interrupt-controller;
                                reg = <0x020a0000 0x4000>;
                                interrupts = <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>,
                                             <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&clks IMX6UL_CLK_GPIO2>;
                                gpio-controller;
                                #gpio-cells = <2>;
                                interrupt-controller;
                                reg = <0x020a4000 0x4000>;
                                interrupts = <GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>,
                                             <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&clks IMX6UL_CLK_GPIO3>;
                                gpio-controller;
                                #gpio-cells = <2>;
                                interrupt-controller;
                                reg = <0x020a8000 0x4000>;
                                interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>,
                                             <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&clks IMX6UL_CLK_GPIO4>;
                                gpio-controller;
                                #gpio-cells = <2>;
                                interrupt-controller;
                                reg = <0x020ac000 0x4000>;
                                interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>,
                                             <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&clks IMX6UL_CLK_GPIO5>;
                                gpio-controller;
                                #gpio-cells = <2>;
                                interrupt-controller;
index 3dffbcd..183193e 100644 (file)
 
 &cpu0 {
        clock-frequency = <792000000>;
-       operating-points = <
-               /* kHz  uV */
-               792000  1225000
-               528000  1175000
-               396000  1025000
-               198000  950000
-       >;
-       fsl,soc-operating-points = <
-               /* KHz  uV */
-               792000  1175000
-               528000  1175000
-               396000  1175000
-               198000  1175000
-       >;
 };
 
 &iomuxc {
index ebc25c9..cd1776a 100644 (file)
@@ -1,43 +1,6 @@
-/*
- * Copyright 2016 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.
- */
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+//
+// Copyright 2016 Freescale Semiconductor, Inc.
 
 #include "imx6ul.dtsi"
 #include "imx6ull-pinfunc.h"
 /* Delete CAAM node in AIPS-2 (i.MX6UL specific) */
 /delete-node/ &crypto;
 
+&cpu0 {
+       operating-points = <
+               /* kHz  uV */
+               900000  1275000
+               792000  1225000
+               528000  1175000
+               396000  1025000
+               198000  950000
+       >;
+       fsl,soc-operating-points = <
+               /* KHz  uV */
+               900000  1175000
+               792000  1175000
+               528000  1175000
+               396000  1175000
+               198000  1175000
+       >;
+};
+
 / {
        soc {
                aips3: aips-bus@2200000 {
index 70c53e5..d8aac4a 100644 (file)
@@ -1,43 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0 OR X11
 /*
  * Copyright 2016 Boundary Devices, 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 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/;
        model = "Boundary Devices i.MX7 Nitrogen7 Board";
        compatible = "boundary,imx7d-nitrogen7", "fsl,imx7d";
 
-       aliases {
-               fb-lcd = &lcdif;
-               t-lcd = &t_lcd;
-       };
-
        memory@80000000 {
                reg = <0x80000000 0x40000000>;
        };
@@ -65,7 +23,7 @@
                default-on;
        };
 
-       backlight-j20 {
+       backlight_lcd: backlight-j20 {
                compatible = "pwm-backlight";
                pwms = <&pwm1 0 5000000 0>;
                brightness-levels = <0 4 8 16 32 64 128 255>;
                status = "okay";
        };
 
+       panel-lcd {
+               compatible = "okaya,rs800480t-7x0gp";
+               backlight = <&backlight_lcd>;
+
+               port {
+                       panel_in: endpoint {
+                               remote-endpoint = <&lcdif_out>;
+                       };
+               };
+       };
+
        reg_usb_otg1_vbus: regulator-usb-otg1-vbus {
                compatible = "regulator-fixed";
                regulator-name = "usb_otg1_vbus";
 };
 
 &lcdif {
-       pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_lcdif_dat
-                    &pinctrl_lcdif_ctrl>;
-       lcd-supply = <&reg_vref_3v3>;
-       display = <&display0>;
        status = "okay";
 
-       display0: lcd-display {
-               bits-per-pixel = <16>;
-               bus-width = <18>;
-
-               display-timings {
-                       native-mode = <&t_lcd>;
-                       t_lcd: t_lcd_default {
-                               /* default to Okaya display */
-                               clock-frequency = <30000000>;
-                               hactive = <800>;
-                               vactive = <480>;
-                               hfront-porch = <40>;
-                               hback-porch = <40>;
-                               hsync-len = <48>;
-                               vback-porch = <29>;
-                               vfront-porch = <13>;
-                               vsync-len = <3>;
-                               hsync-active = <0>;
-                               vsync-active = <0>;
-                               de-active = <1>;
-                               pixelclk-active = <0>;
-                       };
+       port {
+               lcdif_out: endpoint {
+                       remote-endpoint = <&panel_in>;
                };
        };
 };
index 9408491..c9b3c60 100644 (file)
        model = "Freescale i.MX7 SabreSD Board";
        compatible = "fsl,imx7d-sdb", "fsl,imx7d";
 
+       chosen {
+               stdout-path = &uart1;
+       };
+
        memory@80000000 {
                reg = <0x80000000 0x80000000>;
        };
                enable-active-high;
        };
 
-       reg_can2_3v3: regulator-can2-3v3 {
-               compatible = "regulator-fixed";
-               regulator-name = "can2-3v3";
-               regulator-min-microvolt = <3300000>;
-               regulator-max-microvolt = <3300000>;
-               gpio = <&gpio1 7 GPIO_ACTIVE_LOW>;
-       };
-
        reg_vref_1v8: regulator-vref-1v8 {
                compatible = "regulator-fixed";
                regulator-name = "vref-1v8";
                gpio = <&gpio2 14 GPIO_ACTIVE_LOW>;
        };
 
+       backlight: backlight {
+               compatible = "pwm-backlight";
+               pwms = <&pwm1 0 5000000 0>;
+               brightness-levels = <0 4 8 16 32 64 128 255>;
+               default-brightness-level = <6>;
+               status = "okay";
+       };
+
        panel {
                compatible = "innolux,at043tn24";
-               pinctrl-0 = <&pinctrl_backlight>;
-               enable-gpios = <&gpio1 1 GPIO_ACTIVE_HIGH>;
+               backlight = <&backlight>;
                power-supply = <&reg_lcd_3v3>;
 
                port {
        };
 };
 
+&pwm1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_pwm1>;
+       status = "okay";
+};
+
 &iomuxc_lpsr {
        pinctrl_wdog: wdoggrp {
                fsl,pins = <
                >;
        };
 
-       pinctrl_backlight: backlightgrp {
+       pinctrl_pwm1: pwm1grp {
                fsl,pins = <
-                       MX7D_PAD_LPSR_GPIO1_IO01__GPIO1_IO1             0x110b0
+                       MX7D_PAD_LPSR_GPIO1_IO01__PWM1_OUT              0x30
                >;
        };
 };
index 8d3d123..7cbc2ff 100644 (file)
@@ -11,6 +11,7 @@
                cpu0: cpu@0 {
                        clock-frequency = <996000000>;
                        operating-points-v2 = <&cpu0_opp_table>;
+                       #cooling-cells = <2>;
                };
 
                cpu1: cpu@1 {
index 9ced589..a052198 100644 (file)
 
                        crypto: caam@30900000 {
                                compatible = "fsl,sec-v4.0";
-                               fsl,sec-era = <8>;
                                #address-cells = <1>;
                                #size-cells = <1>;
                                reg = <0x30900000 0x40000>;
index 66954aa..5cae74e 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Device Tree Source for the iWave-RZ/G1M/G1N Qseven carrier board
  *
  * Copyright (C) 2017 Renesas Electronics Corp.
- *
- * 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.
  */
 
 /*
index 476273b..0e99df2 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Device Tree Source for the iWave-RZ-G1M/N Daughter Board Camera Module
  *
  * Copyright (C) 2017 Renesas Electronics Corp.
- *
- * 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.
  */
 
 / {
index a17311c..1db17ec 100644 (file)
@@ -225,3 +225,23 @@ netcp: netcp@24000000 {
                };
        };
 };
+
+sa_subsys: subsys@24080000 {
+       #address-cells = <1>;
+       #size-cells = <1>;
+       compatible = "simple-bus";
+       ranges = <0 0x24080000 0x40000>;
+
+       sa_config: subsys@0 {
+               compatible = "syscon";
+               reg = <0x0 0x100>;
+       };
+
+       rng@24000 {
+               compatible = "ti,keystone-rng";
+               reg = <0x24000 0x1000>;
+               ti,syscon-sa-cfg = <&sa_config>;
+               clocks = <&clksa>;
+               clock-names = "fck";
+       };
+};
index 154fdd7..b7f10bf 100644 (file)
                regulator-max-microvolt = <3300000>;
                regulator-always-on;
        };
+
+       vcc1v8_ldo1_reg: fixedregulator-vcc1v8-ldo1 {
+               compatible = "regulator-fixed";
+               regulator-name = "ldo1";
+               regulator-min-microvolt = <1800000>;
+               regulator-max-microvolt = <1800000>;
+               regulator-always-on;
+       };
 };
 
 &k2g_pinctrl {
                        K2G_CORE_IOPAD(0x1228) (BUFFER_CLASS_B | PIN_PULLDOWN  | MUX_MODE1)     /* qspicsn3.dcan1rx */
                >;
        };
+
+       emac_pins: pinmux_emac_pins {
+               pinctrl-single,pins = <
+                       K2G_CORE_IOPAD(0x113C) (BUFFER_CLASS_D | PULL_DISABLE | MUX_MODE1)      /* MII_RXD1.RGMII_RXD1 */
+                       K2G_CORE_IOPAD(0x1138) (BUFFER_CLASS_D | PULL_DISABLE | MUX_MODE1)      /* MII_RXD2.RGMII_RXD2 */
+                       K2G_CORE_IOPAD(0x1134) (BUFFER_CLASS_D | PULL_DISABLE | MUX_MODE1)      /* MII_RXD3.RGMII_RXD3 */
+                       K2G_CORE_IOPAD(0x1140) (BUFFER_CLASS_D | PULL_DISABLE | MUX_MODE1)      /* MII_RXD0.RGMII_RXD0 */
+                       K2G_CORE_IOPAD(0x1178) (BUFFER_CLASS_D | PULL_DISABLE | MUX_MODE1)      /* MII_TXD0.RGMII_TXD0 */
+                       K2G_CORE_IOPAD(0x1174) (BUFFER_CLASS_D | PULL_DISABLE | MUX_MODE1)      /* MII_TXD1.RGMII_TXD1 */
+                       K2G_CORE_IOPAD(0x1170) (BUFFER_CLASS_D | PULL_DISABLE | MUX_MODE1)      /* MII_TXD2.RGMII_TXD2 */
+                       K2G_CORE_IOPAD(0x116C) (BUFFER_CLASS_D | PULL_DISABLE | MUX_MODE1)      /* MII_TXD3.RGMII_TXD3 */
+                       K2G_CORE_IOPAD(0x1154) (BUFFER_CLASS_D | PULL_DISABLE | MUX_MODE1)      /* MII_TXCLK.RGMII_TXC */
+                       K2G_CORE_IOPAD(0x117C) (BUFFER_CLASS_D | PULL_DISABLE | MUX_MODE1)      /* MII_TXEN.RGMII_TXCTL */
+                       K2G_CORE_IOPAD(0x1120) (BUFFER_CLASS_D | PULL_DISABLE | MUX_MODE1)      /* MII_RXCLK.RGMII_RXC */
+                       K2G_CORE_IOPAD(0x1144) (BUFFER_CLASS_D | PULL_DISABLE | MUX_MODE1)      /* MII_RXDV.RGMII_RXCTL */
+               >;
+       };
+
+       mdio_pins: pinmux_mdio_pins {
+               pinctrl-single,pins = <
+                       K2G_CORE_IOPAD(0x118C) (BUFFER_CLASS_B | PULL_DISABLE | MUX_MODE0)      /* MDIO_CLK.MDIO_CLK */
+                       K2G_CORE_IOPAD(0x1188) (BUFFER_CLASS_B | PULL_DISABLE | MUX_MODE0)      /* MDIO_DATA.MDIO_DATA */
+               >;
+       };
 };
 
 &uart0 {
        pinctrl-names = "default";
        pinctrl-0 = <&mmc0_pins>;
        vmmc-supply = <&vcc3v3_dcin_reg>;
+       vqmmc-supply = <&vcc3v3_dcin_reg>;
        cd-gpios = <&gpio1 12 GPIO_ACTIVE_LOW>;
        status = "okay";
 };
        pinctrl-names = "default";
        pinctrl-0 = <&mmc1_pins>;
        vmmc-supply = <&vcc3v3_dcin_reg>; /* VCC3V3_EMMC is connected to VCC3V3_DCIN */
+       vqmmc-supply = <&vcc1v8_ldo1_reg>;
        ti,non-removable;
        status = "okay";
 };
        pinctrl-0 = <&dcan1_pins>;
        status = "okay";
 };
+
+&qmss {
+       status = "okay";
+};
+
+&knav_dmas {
+       status = "okay";
+};
+
+&mdio {
+       pinctrl-names = "default";
+       pinctrl-0 = <&mdio_pins>;
+       status = "okay";
+       ethphy0: ethernet-phy@0 {
+               reg = <0>;
+       };
+};
+
+&gbe0 {
+       phy-handle = <&ethphy0>;
+       phy-mode = "rgmii-id";
+       status = "okay";
+};
+
+&netcp {
+       pinctrl-names = "default";
+       pinctrl-0 = <&emac_pins>;
+       status = "okay";
+};
index d820ed2..2a2d38c 100644 (file)
@@ -7,6 +7,7 @@
 /dts-v1/;
 
 #include "keystone-k2g.dtsi"
+#include <dt-bindings/net/ti-dp83867.h>
 
 / {
        compatible = "ti,k2g-ice", "ti,k2g", "ti,keystone";
                        K2G_CORE_IOPAD(0x11bc) (BUFFER_CLASS_B | PIN_PULLUP | MUX_MODE3)        /* spi2_scsn1.gpio0_102 */
                >;
        };
+
+       emac_pins: pinmux_emac_pins {
+               pinctrl-single,pins = <
+                       K2G_CORE_IOPAD(0x113C) (BUFFER_CLASS_D | PULL_DISABLE | MUX_MODE1)      /* MII_RXD1.RGMII_RXD1 */
+                       K2G_CORE_IOPAD(0x1138) (BUFFER_CLASS_D | PULL_DISABLE | MUX_MODE1)      /* MII_RXD2.RGMII_RXD2 */
+                       K2G_CORE_IOPAD(0x1134) (BUFFER_CLASS_D | PULL_DISABLE | MUX_MODE1)      /* MII_RXD3.RGMII_RXD3 */
+                       K2G_CORE_IOPAD(0x1140) (BUFFER_CLASS_D | PULL_DISABLE | MUX_MODE1)      /* MII_RXD0.RGMII_RXD0 */
+                       K2G_CORE_IOPAD(0x1178) (BUFFER_CLASS_D | PULL_DISABLE | MUX_MODE1)      /* MII_TXD0.RGMII_TXD0 */
+                       K2G_CORE_IOPAD(0x1174) (BUFFER_CLASS_D | PULL_DISABLE | MUX_MODE1)      /* MII_TXD1.RGMII_TXD1 */
+                       K2G_CORE_IOPAD(0x1170) (BUFFER_CLASS_D | PULL_DISABLE | MUX_MODE1)      /* MII_TXD2.RGMII_TXD2 */
+                       K2G_CORE_IOPAD(0x116C) (BUFFER_CLASS_D | PULL_DISABLE | MUX_MODE1)      /* MII_TXD3.RGMII_TXD3 */
+                       K2G_CORE_IOPAD(0x1154) (BUFFER_CLASS_D | PULL_DISABLE | MUX_MODE1)      /* MII_TXCLK.RGMII_TXC */
+                       K2G_CORE_IOPAD(0x117C) (BUFFER_CLASS_D | PULL_DISABLE | MUX_MODE1)      /* MII_TXEN.RGMII_TXCTL */
+                       K2G_CORE_IOPAD(0x1120) (BUFFER_CLASS_D | PULL_DISABLE | MUX_MODE1)      /* MII_RXCLK.RGMII_RXC */
+                       K2G_CORE_IOPAD(0x1144) (BUFFER_CLASS_D | PULL_DISABLE | MUX_MODE1)      /* MII_RXDV.RGMII_RXCTL */
+               >;
+       };
+
+       mdio_pins: pinmux_mdio_pins {
+               pinctrl-single,pins = <
+                       K2G_CORE_IOPAD(0x118C) (BUFFER_CLASS_B | PULL_DISABLE | MUX_MODE0)      /* MDIO_CLK.MDIO_CLK */
+                       K2G_CORE_IOPAD(0x1188) (BUFFER_CLASS_B | PULL_DISABLE | MUX_MODE0)      /* MDIO_DATA.MDIO_DATA */
+               >;
+       };
 };
 
 &uart0 {
                vcc-supply = <&vdd_3v3>;
        };
 };
+
+&qmss {
+       status = "okay";
+};
+
+&knav_dmas {
+       status = "okay";
+};
+
+&netcp {
+       pinctrl-names = "default";
+       pinctrl-0 = <&emac_pins>;
+       status = "okay";
+};
+
+&mdio {
+       pinctrl-names = "default";
+       pinctrl-0 = <&mdio_pins>;
+       status = "okay";
+       ethphy0: ethernet-phy@0 {
+               reg = <0>;
+               ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_25_NS>;
+               ti,tx-internal-delay = <DP83867_RGMIIDCTL_250_PS>;
+               ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_8_B_NIB>;
+               ti,min-output-impedance;
+               ti,dp83867-rxctrl-strap-quirk;
+       };
+};
+
+&gbe0 {
+       phy-handle = <&ethphy0>;
+       phy-mode = "rgmii-id";
+       status = "okay";
+};
diff --git a/arch/arm/boot/dts/keystone-k2g-netcp.dtsi b/arch/arm/boot/dts/keystone-k2g-netcp.dtsi
new file mode 100644 (file)
index 0000000..d0e6a9a
--- /dev/null
@@ -0,0 +1,147 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Device Tree Source for K2G Netcp driver
+ *
+ * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
+ */
+
+qmss: qmss@4020000 {
+       compatible = "ti,66ak2g-navss-qm";
+       dma-coherent;
+       #address-cells = <1>;
+       #size-cells = <1>;
+       power-domains = <&k2g_pds 0x0018>;
+       clocks = <&k2g_clks 0x0018 0>;
+       clock-names = "nss_vclk";
+       ranges;
+       queue-range = <0 0x80>;
+       linkram0 = <0x4020000 0x7ff>;
+       status = "disabled";
+
+       qmgrs {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges;
+               qmgr0 {
+                       managed-queues = <0 0x80>;
+                       reg = <0x4100000 0x800>,
+                             <0x4040000 0x100>,
+                             <0x4080000 0x800>,
+                             <0x40c0000 0x800>;
+                       reg-names = "peek", "config",
+                                   "region", "push";
+               };
+
+       };
+       queue-pools {
+               qpend {
+                       qpend-0 {
+                               qrange = <77 8>;
+                               interrupts =<0 308 0xf04 0 309 0xf04 0 310 0xf04
+                                            0 311 0xf04 0 312 0xf04 0 313 0xf04
+                                            0 314 0xf04 0 315 0xf04>;
+                               qalloc-by-id;
+                       };
+               };
+               general-purpose {
+                       gp-0 {
+                               qrange = <112 8>;
+                       };
+                       netcp-tx {
+                               qrange = <5 8>;
+                               qalloc-by-id;
+                       };
+               };
+       };
+
+       descriptor-regions {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges;
+               region-12 {
+                       id = <12>;
+                       region-spec = <1023 128>; /* num_desc desc_size */
+                       link-index = <0x400>;
+               };
+       };
+}; /* qmss */
+
+knav_dmas: knav_dmas@0 {
+       compatible = "ti,keystone-navigator-dma";
+       #address-cells = <1>;
+       #size-cells = <1>;
+       status = "disabled";
+       power-domains = <&k2g_pds 0x0018>;
+       clocks = <&k2g_clks 0x0018 0>;
+       clock-names = "nss_vclk";
+       ranges;
+       ti,navigator-cloud-address = <0x40c0000 0x40c0000 0x40c0000 0x40c0000>;
+
+       dma_gbe: dma_gbe@0 {
+               reg = <0x4010000 0x100>,
+                     <0x4011000 0x2a0>, /* 21 Tx channels */
+                     <0x4012000 0x400>, /* 32 Rx channels */
+                     <0x4010100 0x80>,
+                     <0x4013000 0x400>; /* 32 Rx flows */
+               reg-names = "global", "txchan", "rxchan",
+                           "txsched", "rxflow";
+       };
+
+};
+
+netcp: netcp@4000000 {
+       reg = <0x2620110 0x8>;
+       reg-names = "efuse";
+       compatible = "ti,netcp-1.0";
+       #address-cells = <1>;
+       #size-cells = <1>;
+       status = "disabled";
+       power-domains = <&k2g_pds 0x0018>;
+       clocks = <&k2g_clks 0x0018 3>, <&k2g_clks 0x0018 8>;
+       clock-names = "ethss_clk", "cpts";
+
+       /* NetCP address range */
+       ranges = <0 0x4000000 0x1000000>;
+
+       dma-coherent;
+
+       ti,navigator-dmas = <&dma_gbe 0>, <&dma_gbe 5>;
+       ti,navigator-dma-names = "netrx0", "nettx";
+
+       netcp-devices {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges;
+               gbe: gbe@200000 {
+                       label = "netcp-gbe";
+                       compatible = "ti,netcp-gbe-2";
+                       reg = <0x200000 0x20>, <0x220000 0x20000>;
+                       enable-ale;
+                       tx-queue = <5>;
+                       tx-channel = "nettx";
+                       cpts-rftclk-sel = <0>;
+                       cpts-ext-ts-inputs = <8>;
+
+                       interfaces {
+                               gbe0: interface-0 {
+                                       slave-port = <0>;
+                                       link-interface  = <5>;
+                               };
+                       };
+               };
+       };
+
+       netcp-interfaces {
+               interface-0 {
+                       rx-channel = "netrx0";
+                       rx-pool = <512 12>;
+                       tx-pool = <511 12>;
+                       rx-queue-depth = <128 128 0 0>;
+                       rx-buffer-size = <1518 4096 0 0>;
+                       rx-queue = <77>;
+                       tx-completion-queue = <78>;
+                       efuse-mac = <1>;
+                       netcp-gbe = <&gbe0>;
+               };
+       };
+};
index da78c00..738b44c 100644 (file)
                };
 
                mmc0: mmc@23000000 {
-                       compatible = "ti,k2g-hsmmc", "ti,omap4-hsmmc";
+                       compatible = "ti,k2g-sdhci";
                        reg = <0x23000000 0x400>;
                        interrupts = <GIC_SPI 96 IRQ_TYPE_EDGE_RISING>;
-                       dmas = <&edma1 24 0>, <&edma1 25 0>;
-                       dma-names = "tx", "rx";
                        bus-width = <4>;
-                       ti,needs-special-reset;
                        no-1-8-v;
                        max-frequency = <96000000>;
                        power-domains = <&k2g_pds 0xb>;
                };
 
                mmc1: mmc@23100000 {
-                       compatible = "ti,k2g-hsmmc", "ti,omap4-hsmmc";
+                       compatible = "ti,k2g-sdhci";
                        reg = <0x23100000 0x400>;
                        interrupts = <GIC_SPI 97 IRQ_TYPE_EDGE_RISING>;
-                       dmas = <&edma1 26 0>, <&edma1 27 0>;
-                       dma-names = "tx", "rx";
                        bus-width = <8>;
-                       ti,needs-special-reset;
+                       no-1-8-v;
+                       non-removable;
                        max-frequency = <96000000>;
                        power-domains = <&k2g_pds 0xc>;
                        clocks = <&k2g_clks 0xc 1>, <&k2g_clks 0xc 2>;
                        reg = <0x21010000 0x200>;
                        interrupts = <GIC_SPI 123 IRQ_TYPE_EDGE_RISING>;
                };
+
+               mdio: mdio@4200f00 {
+                       compatible = "ti,keystone_mdio", "ti,davinci_mdio";
+                       reg = <0x04200f00 0x100>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       clocks = <&k2g_clks 0x0018 3>;
+                       clock-names = "fck";
+                       power-domains = <&k2g_pds 0x0018>;
+                       status = "disabled";
+                       bus_freq = <2500000>;
+               };
+               #include "keystone-k2g-netcp.dtsi"
        };
 };
index b88c068..e203145 100644 (file)
@@ -228,3 +228,23 @@ netcp: netcp@2000000 {
                };
        };
 };
+
+sa_subsys: subsys@20c0000 {
+       compatible = "simple-bus";
+       #address-cells = <1>;
+       #size-cells = <1>;
+       ranges = <0 0x20c0000 0x40000>;
+
+       sa_config: subsys@0 {
+               compatible = "syscon";
+               reg = <0x0 0x100>;
+       };
+
+       rng@24000 {
+               compatible = "ti,keystone-rng";
+               reg = <0x24000 0x1000>;
+               ti,syscon-sa-cfg = <&sa_config>;
+               clocks = <&clksa>;
+               clock-names = "fck";
+       };
+};
index 9ec8422..a2e47ba 100644 (file)
@@ -208,3 +208,23 @@ netcp: netcp@26000000 {
                };
        };
 };
+
+sa_subsys: subsys@26080000 {
+       #address-cells = <1>;
+       #size-cells = <1>;
+       compatible = "simple-bus";
+       ranges = <0 0x26080000 0x40000>;
+
+       sa_config: subsys@0 {
+               compatible = "syscon";
+               reg = <0x0 0x100>;
+       };
+
+       rng@24000 {
+               compatible = "ti,keystone-rng";
+               reg = <0x24000 0x1000>;
+               ti,syscon-sa-cfg = <&sa_config>;
+               clocks = <&clksa>;
+               clock-names = "fck";
+       };
+};
index 3bb28c0..ac34333 100644 (file)
                compatible = "ti,wl1273";
                reg = <2>;
                interrupt-parent = <&gpio1>;
-               interrupts = <2 IRQ_TYPE_LEVEL_HIGH>; /* gpio 2 */
+               interrupts = <2 IRQ_TYPE_EDGE_RISING>; /* gpio 2 */
                ref-clock-frequency = <26000000>;
        };
 };
index 234afd6..9d5d53f 100644 (file)
@@ -48,7 +48,7 @@
                compatible = "ti,wl1283";
                reg = <2>;
                interrupt-parent = <&gpio5>;
-               interrupts = <24 IRQ_TYPE_LEVEL_HIGH>; /* gpio 152 */
+               interrupts = <24 IRQ_TYPE_EDGE_RISING>; /* gpio 152 */
                ref-clock-frequency = <26000000>;
                tcxo-clock-frequency = <26000000>;
        };
index c55d479..f184905 100644 (file)
@@ -84,6 +84,7 @@
                        device_type = "cpu";
                        reg = <0xf01>;
                        clocks = <&clockgen 1 0>;
+                       #cooling-cells = <2>;
                };
        };
 
index d1eb123..1cdc346 100644 (file)
@@ -92,6 +92,7 @@
                                 <&apmixedsys CLK_APMIXED_MAINPLL>;
                        clock-names = "cpu", "intermediate";
                        operating-points-v2 = <&cpu_opp_table>;
+                       #cooling-cells = <2>;
                        clock-frequency = <1300000000>;
                };
 
                                 <&apmixedsys CLK_APMIXED_MAINPLL>;
                        clock-names = "cpu", "intermediate";
                        operating-points-v2 = <&cpu_opp_table>;
+                       #cooling-cells = <2>;
                        clock-frequency = <1300000000>;
                };
 
                                 <&apmixedsys CLK_APMIXED_MAINPLL>;
                        clock-names = "cpu", "intermediate";
                        operating-points-v2 = <&cpu_opp_table>;
+                       #cooling-cells = <2>;
                        clock-frequency = <1300000000>;
                };
        };
index 531d905..2b760f9 100644 (file)
 
                blue {
                        label = "bpi-r2:pio:blue";
-                       gpios = <&pio 241 GPIO_ACTIVE_HIGH>;
+                       gpios = <&pio 240 GPIO_ACTIVE_LOW>;
                        default-state = "off";
                };
 
                green {
                        label = "bpi-r2:pio:green";
-                       gpios = <&pio 240 GPIO_ACTIVE_HIGH>;
+                       gpios = <&pio 241 GPIO_ACTIVE_LOW>;
                        default-state = "off";
                };
 
                red {
                        label = "bpi-r2:pio:red";
-                       gpios = <&pio 239 GPIO_ACTIVE_HIGH>;
+                       gpios = <&pio 239 GPIO_ACTIVE_LOW>;
                        default-state = "off";
                };
        };
diff --git a/arch/arm/boot/dts/mt7623n-rfb-nand.dts b/arch/arm/boot/dts/mt7623n-rfb-nand.dts
deleted file mode 100644 (file)
index 96ff3c9..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Copyright (c) 2017 MediaTek Inc.
- * Author: John Crispin <john@phrozen.org>
- *
- */
-
-/dts-v1/;
-#include "mt7623n-rfb.dtsi"
-
-/ {
-       model = "MediaTek MT7623N NAND reference board";
-       compatible = "mediatek,mt7623n-rfb-nand", "mediatek,mt7623";
-};
-
-&bch {
-       status = "okay";
-};
-
-&nandc {
-       status = "okay";
-       pinctrl-names = "default";
-       pinctrl-0 = <&nand_pins_default>;
-
-       nand@0 {
-               reg = <0>;
-               spare_per_sector = <64>;
-               nand-ecc-mode = "hw";
-               nand-ecc-strength = <12>;
-               nand-ecc-step-size = <1024>;
-
-               partitions {
-                       compatible = "fixed-partitions";
-                       #address-cells = <1>;
-                       #size-cells = <1>;
-
-                       partition@0 {
-                               label = "preloader";
-                               reg = <0x0 0x40000>;
-                       };
-
-                       partition@40000 {
-                               label = "uboot";
-                               reg = <0x40000 0x80000>;
-                       };
-
-                       partition@c0000 {
-                               label = "uboot-env";
-                               reg = <0xC0000 0x40000>;
-                       };
-
-                       partition@140000 {
-                               label = "bootimg";
-                               reg = <0x140000 0x2000000>;
-                       };
-
-                       partition@2140000 {
-                               label = "recovery";
-                               reg = <0x2140000 0x2000000>;
-                       };
-
-                       partition@4140000 {
-                               label = "rootfs";
-                               reg = <0x4140000 0x1000000>;
-                       };
-
-                       partition@5140000 {
-                               label = "usrdata";
-                               reg = <0x5140000 0x1000000>;
-                       };
-               };
-       };
-};
diff --git a/arch/arm/boot/dts/mt7623n-rfb.dtsi b/arch/arm/boot/dts/mt7623n-rfb.dtsi
deleted file mode 100644 (file)
index 5c5cc7d..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Copyright (c) 2017 MediaTek Inc.
- * Author: John Crispin <john@phrozen.org>
- *        Sean Wang <sean.wang@mediatek.com>
- *
- */
-
-/dts-v1/;
-#include "mt7623.dtsi"
-#include "mt6323.dtsi"
-
-/ {
-       aliases {
-               serial0 = &uart0;
-               serial1 = &uart1;
-               serial2 = &uart2;
-       };
-
-       chosen {
-               stdout-path = "serial2:115200n8";
-       };
-
-       cpus {
-               cpu0 {
-                       proc-supply = <&mt6323_vproc_reg>;
-               };
-
-               cpu1 {
-                       proc-supply = <&mt6323_vproc_reg>;
-               };
-
-               cpu2 {
-                       proc-supply = <&mt6323_vproc_reg>;
-               };
-
-               cpu3 {
-                       proc-supply = <&mt6323_vproc_reg>;
-               };
-       };
-
-       memory@80000000 {
-               device_type = "memory";
-               reg = <0 0x80000000 0 0x40000000>;
-       };
-
-       usb_p1_vbus: regulator-5v {
-               compatible = "regulator-fixed";
-               regulator-name = "usb_vbus";
-               regulator-min-microvolt = <5000000>;
-               regulator-max-microvolt = <5000000>;
-               gpio = <&pio 135 GPIO_ACTIVE_HIGH>;
-               enable-active-high;
-       };
-};
-
-&mmc0 {
-       vmmc-supply = <&mt6323_vemc3v3_reg>;
-       vqmmc-supply = <&mt6323_vio18_reg>;
-};
-
-&mmc1 {
-       vmmc-supply = <&mt6323_vmch_reg>;
-       vqmmc-supply = <&mt6323_vmc_reg>;
-};
-
-&uart0 {
-       status = "okay";
-};
-
-&uart1 {
-       status = "okay";
-};
-
-&uart2 {
-       status = "okay";
-};
-
-&usb1 {
-       vbus-supply = <&usb_p1_vbus>;
-       status = "okay";
-};
-
-&u3phy1 {
-       status = "okay";
-};
index 4994e33..632f52e 100644 (file)
                compatible = "ti,wl1271";
                reg = <2>;
                interrupt-parent = <&gpio5>;
-               interrupts = <17 IRQ_TYPE_LEVEL_HIGH>; /* gpio 145 */
+               interrupts = <17 IRQ_TYPE_EDGE_RISING>; /* gpio 145 */
                ref-clock-frequency = <38400000>;
        };
 };
index 8c63ac5..6e944df 100644 (file)
@@ -81,7 +81,7 @@
                compatible = "ti,wl1271";
                reg = <2>;
                interrupt-parent = <&gpio5>;
-               interrupts = <8 IRQ_TYPE_LEVEL_HIGH>; /* gpio 136 */
+               interrupts = <8 IRQ_TYPE_EDGE_RISING>; /* gpio 136 */
                ref-clock-frequency = <38400000>;
        };
 };
index ee64191..4c1227d 100644 (file)
                compatible = "ti,wl1271";
                reg = <2>;
                interrupt-parent = <&gpio5>;
-               interrupts = <21 IRQ_TYPE_LEVEL_HIGH>; /* gpio 149 */
+               interrupts = <21 IRQ_TYPE_EDGE_RISING>; /* gpio 149 */
                ref-clock-frequency = <38400000>;
        };
 };
index 321c2b7..285681d 100644 (file)
@@ -49,6 +49,6 @@
                compatible = "ti,wl1835";
                reg = <2>;
                interrupt-parent = <&gpio6>;
-               interrupts = <17 IRQ_TYPE_LEVEL_HIGH>; /* gpio 177 */
+               interrupts = <17 IRQ_TYPE_EDGE_RISING>; /* gpio 177 */
        };
 };
index 76dc088..1adc73b 100644 (file)
@@ -71,6 +71,6 @@
                compatible = "ti,wl1835";
                reg = <2>;
                interrupt-parent = <&gpio5>;
-               interrupts = <8 IRQ_TYPE_LEVEL_HIGH>; /* gpio 136 */
+               interrupts = <8 IRQ_TYPE_EDGE_RISING>; /* gpio 136 */
        };
 };
index 96d0301..aac27a4 100644 (file)
                compatible = "ti,wl1271";
                reg = <2>;
                interrupt-parent = <&gpio6>;
-               interrupts = <2 IRQ_TYPE_LEVEL_HIGH>; /* gpio 162 */
+               interrupts = <2 IRQ_TYPE_EDGE_RISING>; /* gpio 162 */
                ref-clock-frequency = <26000000>;
        };
 };
index e7c3c56..12d6822 100644 (file)
                        gpios = <&gpio5 26 GPIO_ACTIVE_LOW>; /* gpio154 */
                        linux,code = <KEY_VOLUMEDOWN>;
                        linux,can-disable;
+                       /* Value above 7.95ms for no GPIO hardware debounce */
+                       debounce-interval = <10>;
                };
 
                slider {
                        linux,input-type = <EV_SW>;
                        linux,code = <SW_KEYPAD_SLIDE>;
                        linux,can-disable;
-
+                       /* Value above 7.95ms for no GPIO hardware debounce */
+                       debounce-interval = <10>;
                };
        };
 
                compatible = "ti,wl1285", "ti,wl1283";
                reg = <2>;
                interrupt-parent = <&gpio4>;
-               interrupts = <4 IRQ_TYPE_LEVEL_HIGH>; /* gpio100 */
+               interrupts = <4 IRQ_TYPE_EDGE_RISING>; /* gpio100 */
                ref-clock-frequency = <26000000>;
                tcxo-clock-frequency = <26000000>;
        };
index a9a584b..cfcac0d 100644 (file)
@@ -36,6 +36,8 @@
                        label = "button0";
                        linux,code = <BTN_0>;
                        gpios = <&gpio4 25 GPIO_ACTIVE_LOW>;    /* gpio_121 */
+                       /* Value above 7.95ms for no GPIO hardware debounce */
+                       debounce-interval = <10>;
                        wakeup-source;
                };
        };
        ethernet@gpmc {
                reg = <5 0 0xff>;
                interrupt-parent = <&gpio2>;
-               interrupts = <12 IRQ_TYPE_LEVEL_LOW>;           /* gpio_44 */
+               interrupts = <12 IRQ_TYPE_EDGE_FALLING>;        /* gpio_44 */
 
                phy-mode = "mii";
 
index eb123b2..5e81691 100644 (file)
        ti,bus-width = <4>;
        ti,non-removable;
        cap-power-off-card;
+       keep-power-in-suspend;
 };
 
 &twl_usb_comparator {
diff --git a/arch/arm/boot/dts/omap4-l4.dtsi b/arch/arm/boot/dts/omap4-l4.dtsi
new file mode 100644 (file)
index 0000000..6eb26b8
--- /dev/null
@@ -0,0 +1,2444 @@
+// SPDX-License-Identifier: GPL-2.0
+&l4_cfg {                                              /* 0x4a000000 */
+       compatible = "ti,omap4-l4-cfg", "simple-bus";
+       reg = <0x4a000000 0x800>,
+             <0x4a000800 0x800>,
+             <0x4a001000 0x1000>;
+       reg-names = "ap", "la", "ia0";
+       #address-cells = <1>;
+       #size-cells = <1>;
+       ranges = <0x00000000 0x4a000000 0x080000>,      /* segment 0 */
+                <0x00080000 0x4a080000 0x080000>,      /* segment 1 */
+                <0x00100000 0x4a100000 0x080000>,      /* segment 2 */
+                <0x00180000 0x4a180000 0x080000>,      /* segment 3 */
+                <0x00200000 0x4a200000 0x080000>,      /* segment 4 */
+                <0x00280000 0x4a280000 0x080000>,      /* segment 5 */
+                <0x00300000 0x4a300000 0x080000>;      /* segment 6 */
+
+       segment@0 {                                     /* 0x4a000000 */
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges = <0x00000000 0x00000000 0x000800>,      /* ap 0 */
+                        <0x00001000 0x00001000 0x001000>,      /* ap 1 */
+                        <0x00000800 0x00000800 0x000800>,      /* ap 2 */
+                        <0x00002000 0x00002000 0x001000>,      /* ap 3 */
+                        <0x00003000 0x00003000 0x001000>,      /* ap 4 */
+                        <0x00004000 0x00004000 0x001000>,      /* ap 5 */
+                        <0x00005000 0x00005000 0x001000>,      /* ap 6 */
+                        <0x00056000 0x00056000 0x001000>,      /* ap 7 */
+                        <0x00057000 0x00057000 0x001000>,      /* ap 8 */
+                        <0x0005c000 0x0005c000 0x001000>,      /* ap 9 */
+                        <0x00058000 0x00058000 0x004000>,      /* ap 10 */
+                        <0x00062000 0x00062000 0x001000>,      /* ap 11 */
+                        <0x00063000 0x00063000 0x001000>,      /* ap 12 */
+                        <0x00008000 0x00008000 0x002000>,      /* ap 23 */
+                        <0x0000a000 0x0000a000 0x001000>,      /* ap 24 */
+                        <0x00066000 0x00066000 0x001000>,      /* ap 25 */
+                        <0x00067000 0x00067000 0x001000>,      /* ap 26 */
+                        <0x0005e000 0x0005e000 0x002000>,      /* ap 80 */
+                        <0x00060000 0x00060000 0x001000>,      /* ap 81 */
+                        <0x00064000 0x00064000 0x001000>,      /* ap 86 */
+                        <0x00065000 0x00065000 0x001000>;      /* ap 87 */
+
+               target-module@2000 {                    /* 0x4a002000, ap 3 06.0 */
+                       compatible = "ti,sysc-omap4", "ti,sysc";
+                       ti,hwmods = "ctrl_module_core";
+                       reg = <0x2000 0x4>,
+                             <0x2010 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): core, core_pwrdm, l4_cfg_clkdm */
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x2000 0x1000>;
+
+                       omap4_scm_core: scm@0 {
+                               compatible = "ti,omap4-scm-core", "simple-bus";
+                               reg = <0x0 0x1000>;
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+                               ranges = <0 0 0x1000>;
+
+                               scm_conf: scm_conf@0 {
+                                       compatible = "syscon";
+                                       reg = <0x0 0x800>;
+                                       #address-cells = <1>;
+                                       #size-cells = <1>;
+                               };
+
+                               omap_control_usb2phy: control-phy@300 {
+                                       compatible = "ti,control-phy-usb2";
+                                       reg = <0x300 0x4>;
+                                       reg-names = "power";
+                               };
+
+                               omap_control_usbotg: control-phy@33c {
+                                       compatible = "ti,control-phy-otghs";
+                                       reg = <0x33c 0x4>;
+                                       reg-names = "otghs_control";
+                               };
+                       };
+               };
+
+               target-module@4000 {                    /* 0x4a004000, ap 5 02.0 */
+                       compatible = "ti,sysc-omap4", "ti,sysc";
+                       reg = <0x4000 0x4>;
+                       reg-names = "rev";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x4000 0x1000>;
+
+                       cm1: cm1@0 {
+                               compatible = "ti,omap4-cm1", "simple-bus";
+                               reg = <0x0 0x2000>;
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+                               ranges = <0 0 0x2000>;
+
+                               cm1_clocks: clocks {
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                               };
+
+                               cm1_clockdomains: clockdomains {
+                               };
+                       };
+               };
+
+               target-module@8000 {                    /* 0x4a008000, ap 23 32.0 */
+                       compatible = "ti,sysc-omap4", "ti,sysc";
+                       reg = <0x8000 0x4>;
+                       reg-names = "rev";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x8000 0x2000>;
+
+                       cm2: cm2@0 {
+                               compatible = "ti,omap4-cm2", "simple-bus";
+                               reg = <0x0 0x2000>;
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+                               ranges = <0 0 0x2000>;
+
+                               cm2_clocks: clocks {
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                               };
+
+                               cm2_clockdomains: clockdomains {
+                               };
+                       };
+               };
+
+               target-module@56000 {                   /* 0x4a056000, ap 7 0a.0 */
+                       compatible = "ti,sysc-omap2", "ti,sysc";
+                       ti,hwmods = "dma_system";
+                       reg = <0x56000 0x4>,
+                             <0x5602c 0x4>,
+                             <0x56028 0x4>;
+                       reg-names = "rev", "sysc", "syss";
+                       ti,sysc-mask = <(SYSC_OMAP2_CLOCKACTIVITY |
+                                        SYSC_OMAP2_EMUFREE |
+                                        SYSC_OMAP2_SOFTRESET |
+                                        SYSC_OMAP2_AUTOIDLE)>;
+                       ti,sysc-midle = <SYSC_IDLE_FORCE>,
+                                       <SYSC_IDLE_NO>,
+                                       <SYSC_IDLE_SMART>;
+                       ti,sysc-sidle = <SYSC_IDLE_FORCE>,
+                                       <SYSC_IDLE_NO>,
+                                       <SYSC_IDLE_SMART>;
+                       ti,syss-mask = <1>;
+                       /* Domains (V, P, C): core, core_pwrdm, l3_dma_clkdm */
+                       clocks = <&l3_dma_clkctrl OMAP4_DMA_SYSTEM_CLKCTRL 0>;
+                       clock-names = "fck";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x56000 0x1000>;
+
+                       sdma: dma-controller@0 {
+                               compatible = "ti,omap4430-sdma";
+                               reg = <0x0 0x1000>;
+                               interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>,
+                                            <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>,
+                                            <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>,
+                                            <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
+                               #dma-cells = <1>;
+                               dma-channels = <32>;
+                               dma-requests = <127>;
+                       };
+               };
+
+               target-module@58000 {                   /* 0x4a058000, ap 10 0e.0 */
+                       compatible = "ti,sysc-omap2", "ti,sysc";
+                       ti,hwmods = "hsi";
+                       reg = <0x58000 0x4>,
+                             <0x58010 0x4>,
+                             <0x58014 0x4>;
+                       reg-names = "rev", "sysc", "syss";
+                       ti,sysc-mask = <(SYSC_OMAP2_EMUFREE |
+                                        SYSC_OMAP2_SOFTRESET |
+                                        SYSC_OMAP2_AUTOIDLE)>;
+                       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>,
+                                       <SYSC_IDLE_SMART_WKUP>;
+                       ti,syss-mask = <1>;
+                       /* Domains (V, P, C): core, l3init_pwrdm, l3_init_clkdm */
+                       clocks = <&l3_init_clkctrl OMAP4_HSI_CLKCTRL 0>;
+                       clock-names = "fck";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x58000 0x4000>;
+
+                       hsi: hsi@0 {
+                               compatible = "ti,omap4-hsi";
+                               reg = <0x0 0x4000>,
+                                     <0x4a05c000 0x1000>;
+                               reg-names = "sys", "gdd";
+
+                               clocks = <&l3_init_clkctrl OMAP4_HSI_CLKCTRL 0>;
+                               clock-names = "hsi_fck";
+
+                               interrupts = <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
+                               interrupt-names = "gdd_mpu";
+
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+                               ranges = <0 0 0x4000>;
+
+                               hsi_port1: hsi-port@2000 {
+                                       compatible = "ti,omap4-hsi-port";
+                                       reg = <0x2000 0x800>,
+                                             <0x2800 0x800>;
+                                       reg-names = "tx", "rx";
+                                       interrupts = <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>;
+                               };
+
+                               hsi_port2: hsi-port@3000 {
+                                       compatible = "ti,omap4-hsi-port";
+                                       reg = <0x3000 0x800>,
+                                             <0x3800 0x800>;
+                                       reg-names = "tx", "rx";
+                                       interrupts = <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>;
+                               };
+                       };
+               };
+
+               target-module@5e000 {                   /* 0x4a05e000, ap 80 68.0 */
+                       compatible = "ti,sysc";
+                       status = "disabled";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x5e000 0x2000>;
+               };
+
+               target-module@62000 {                   /* 0x4a062000, ap 11 16.0 */
+                       compatible = "ti,sysc-omap2", "ti,sysc";
+                       ti,hwmods = "usb_tll_hs";
+                       reg = <0x62000 0x4>,
+                             <0x62010 0x4>,
+                             <0x62014 0x4>;
+                       reg-names = "rev", "sysc", "syss";
+                       ti,sysc-mask = <(SYSC_OMAP2_CLOCKACTIVITY |
+                                        SYSC_OMAP2_ENAWAKEUP |
+                                        SYSC_OMAP2_SOFTRESET |
+                                        SYSC_OMAP2_AUTOIDLE)>;
+                       ti,sysc-sidle = <SYSC_IDLE_FORCE>,
+                                       <SYSC_IDLE_NO>,
+                                       <SYSC_IDLE_SMART>;
+                       /* Domains (V, P, C): core, l3init_pwrdm, l3_init_clkdm */
+                       clocks = <&l3_init_clkctrl OMAP4_USB_TLL_HS_CLKCTRL 0>;
+                       clock-names = "fck";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x62000 0x1000>;
+
+                       usbhstll: usbhstll@0 {
+                               compatible = "ti,usbhs-tll";
+                               reg = <0x0 0x1000>;
+                               interrupts = <GIC_SPI 78 IRQ_TYPE_LEVEL_HIGH>;
+                       };
+               };
+
+               target-module@64000 {                   /* 0x4a064000, ap 86 1e.0 */
+                       compatible = "ti,sysc-omap4", "ti,sysc";
+                       ti,hwmods = "usb_host_hs";
+                       reg = <0x64000 0x4>,
+                             <0x64010 0x4>,
+                             <0x64014 0x4>;
+                       reg-names = "rev", "sysc", "syss";
+                       ti,sysc-mask = <SYSC_OMAP4_SOFTRESET>;
+                       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>,
+                                       <SYSC_IDLE_SMART_WKUP>;
+                       /* Domains (V, P, C): core, l3init_pwrdm, l3_init_clkdm */
+                       clocks = <&l3_init_clkctrl OMAP4_USB_HOST_HS_CLKCTRL 0>;
+                       clock-names = "fck";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x64000 0x1000>;
+
+                       usbhshost: usbhshost@0 {
+                               compatible = "ti,usbhs-host";
+                               reg = <0x0 0x800>;
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+                               ranges = <0 0 0x1000>;
+                               clocks = <&init_60m_fclk>,
+                                        <&xclk60mhsp1_ck>,
+                                        <&xclk60mhsp2_ck>;
+                               clock-names = "refclk_60m_int",
+                                             "refclk_60m_ext_p1",
+                                             "refclk_60m_ext_p2";
+
+                               usbhsohci: ohci@800 {
+                                       compatible = "ti,ohci-omap3";
+                                       reg = <0x800 0x400>;
+                                       interrupts = <GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>;
+                                       remote-wakeup-connected;
+                               };
+
+                               usbhsehci: ehci@c00 {
+                                       compatible = "ti,ehci-omap";
+                                       reg = <0xc00 0x400>;
+                                       interrupts = <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>;
+                               };
+                       };
+               };
+
+               target-module@66000 {                   /* 0x4a066000, ap 25 26.0 */
+                       compatible = "ti,sysc-omap2", "ti,sysc";
+                       ti,hwmods = "mmu_dsp";
+                       reg = <0x66000 0x4>,
+                             <0x66010 0x4>,
+                             <0x66014 0x4>;
+                       reg-names = "rev", "sysc", "syss";
+                       ti,sysc-mask = <(SYSC_OMAP2_CLOCKACTIVITY |
+                                        SYSC_OMAP2_SOFTRESET |
+                                        SYSC_OMAP2_AUTOIDLE)>;
+                       ti,sysc-sidle = <SYSC_IDLE_FORCE>,
+                                       <SYSC_IDLE_NO>,
+                                       <SYSC_IDLE_SMART>;
+                       /* Domains (V, P, C): iva, tesla_pwrdm, tesla_clkdm */
+                       clocks = <&tesla_clkctrl OMAP4_DSP_CLKCTRL 0>;
+                       clock-names = "fck";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x66000 0x1000>;
+
+                       /* mmu_dsp cannot be moved before reset driver */
+                       status = "disabled";
+               };
+       };
+
+       segment@80000 {                                 /* 0x4a080000 */
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges = <0x00059000 0x000d9000 0x001000>,      /* ap 13 */
+                        <0x0005a000 0x000da000 0x001000>,      /* ap 14 */
+                        <0x0005b000 0x000db000 0x001000>,      /* ap 15 */
+                        <0x0005c000 0x000dc000 0x001000>,      /* ap 16 */
+                        <0x0005d000 0x000dd000 0x001000>,      /* ap 17 */
+                        <0x0005e000 0x000de000 0x001000>,      /* ap 18 */
+                        <0x00060000 0x000e0000 0x001000>,      /* ap 19 */
+                        <0x00061000 0x000e1000 0x001000>,      /* ap 20 */
+                        <0x00074000 0x000f4000 0x001000>,      /* ap 27 */
+                        <0x00075000 0x000f5000 0x001000>,      /* ap 28 */
+                        <0x00076000 0x000f6000 0x001000>,      /* ap 29 */
+                        <0x00077000 0x000f7000 0x001000>,      /* ap 30 */
+                        <0x00036000 0x000b6000 0x001000>,      /* ap 69 */
+                        <0x00037000 0x000b7000 0x001000>,      /* ap 70 */
+                        <0x0004d000 0x000cd000 0x001000>,      /* ap 78 */
+                        <0x0004e000 0x000ce000 0x001000>,      /* ap 79 */
+                        <0x00029000 0x000a9000 0x001000>,      /* ap 82 */
+                        <0x0002a000 0x000aa000 0x001000>,      /* ap 83 */
+                        <0x0002b000 0x000ab000 0x001000>,      /* ap 84 */
+                        <0x0002c000 0x000ac000 0x001000>,      /* ap 85 */
+                        <0x0002d000 0x000ad000 0x001000>,      /* ap 88 */
+                        <0x0002e000 0x000ae000 0x001000>;      /* ap 89 */
+
+               target-module@29000 {                   /* 0x4a0a9000, ap 82 04.0 */
+                       compatible = "ti,sysc";
+                       status = "disabled";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x29000 0x1000>;
+               };
+
+               target-module@2b000 {                   /* 0x4a0ab000, ap 84 12.0 */
+                       compatible = "ti,sysc-omap2", "ti,sysc";
+                       ti,hwmods = "usb_otg_hs";
+                       reg = <0x2b400 0x4>,
+                             <0x2b404 0x4>,
+                             <0x2b408 0x4>;
+                       reg-names = "rev", "sysc", "syss";
+                       ti,sysc-mask = <(SYSC_OMAP2_ENAWAKEUP |
+                                        SYSC_OMAP2_SOFTRESET |
+                                        SYSC_OMAP2_AUTOIDLE)>;
+                       ti,sysc-midle = <SYSC_IDLE_FORCE>,
+                                       <SYSC_IDLE_NO>,
+                                       <SYSC_IDLE_SMART>;
+                       ti,sysc-sidle = <SYSC_IDLE_FORCE>,
+                                       <SYSC_IDLE_NO>,
+                                       <SYSC_IDLE_SMART>,
+                                       <SYSC_IDLE_SMART_WKUP>;
+                       ti,syss-mask = <1>;
+                       /* Domains (V, P, C): core, l3init_pwrdm, l3_init_clkdm */
+                       clocks = <&l3_init_clkctrl OMAP4_USB_OTG_HS_CLKCTRL 0>;
+                       clock-names = "fck";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x2b000 0x1000>;
+
+                       usb_otg_hs: usb_otg_hs@0 {
+                               compatible = "ti,omap4-musb";
+                               reg = <0x0 0x7ff>;
+                               interrupts = <GIC_SPI 92 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 93 IRQ_TYPE_LEVEL_HIGH>;
+                               interrupt-names = "mc", "dma";
+                               usb-phy = <&usb2_phy>;
+                               phys = <&usb2_phy>;
+                               phy-names = "usb2-phy";
+                               multipoint = <1>;
+                               num-eps = <16>;
+                               ram-bits = <12>;
+                               ctrl-module = <&omap_control_usbotg>;
+                       };
+               };
+
+               target-module@2d000 {                   /* 0x4a0ad000, ap 88 0c.0 */
+                       compatible = "ti,sysc-omap2", "ti,sysc";
+                       ti,hwmods = "ocp2scp_usb_phy";
+                       reg = <0x2d000 0x4>,
+                             <0x2d010 0x4>,
+                             <0x2d014 0x4>;
+                       reg-names = "rev", "sysc", "syss";
+                       ti,sysc-mask = <(SYSC_OMAP2_SOFTRESET |
+                                        SYSC_OMAP2_AUTOIDLE)>;
+                       ti,sysc-sidle = <SYSC_IDLE_FORCE>,
+                                       <SYSC_IDLE_NO>,
+                                       <SYSC_IDLE_SMART>;
+                       ti,syss-mask = <1>;
+                       /* Domains (V, P, C): core, l3init_pwrdm, l3_init_clkdm */
+                       clocks = <&l3_init_clkctrl OMAP4_OCP2SCP_USB_PHY_CLKCTRL 0>;
+                       clock-names = "fck";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x2d000 0x1000>;
+
+                       ocp2scp@0 {
+                               compatible = "ti,omap-ocp2scp";
+                               reg = <0x0 0x1f>;
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+                               ranges = <0 0 0x1000>;
+                               usb2_phy: usb2phy@80 {
+                                       compatible = "ti,omap-usb2";
+                                       reg = <0x80 0x58>;
+                                       ctrl-module = <&omap_control_usb2phy>;
+                                       clocks = <&usb_phy_cm_clk32k>;
+                                       clock-names = "wkupclk";
+                                       #phy-cells = <0>;
+                               };
+                       };
+               };
+
+               target-module@36000 {                   /* 0x4a0b6000, ap 69 60.0 */
+                       compatible = "ti,sysc";
+                       status = "disabled";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x36000 0x1000>;
+               };
+
+               target-module@4d000 {                   /* 0x4a0cd000, ap 78 58.0 */
+                       compatible = "ti,sysc";
+                       status = "disabled";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x4d000 0x1000>;
+               };
+
+               target-module@59000 {                   /* 0x4a0d9000, ap 13 1a.0 */
+                       compatible = "ti,sysc-omap4-sr", "ti,sysc";
+                       ti,hwmods = "smartreflex_mpu";
+                       reg = <0x59038 0x4>;
+                       reg-names = "sysc";
+                       ti,sysc-mask = <SYSC_OMAP3_SR_ENAWAKEUP>;
+                       ti,sysc-sidle = <SYSC_IDLE_FORCE>,
+                                       <SYSC_IDLE_NO>,
+                                       <SYSC_IDLE_SMART>,
+                                       <SYSC_IDLE_SMART_WKUP>;
+                       /* Domains (V, P, C): core, always_on_core_pwrdm, l4_ao_clkdm */
+                       clocks = <&l4_ao_clkctrl OMAP4_SMARTREFLEX_MPU_CLKCTRL 0>;
+                       clock-names = "fck";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x59000 0x1000>;
+
+                       smartreflex_mpu: smartreflex@0 {
+                               compatible = "ti,omap4-smartreflex-mpu";
+                               reg = <0x0 0x80>;
+                               interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>;
+                       };
+               };
+
+               target-module@5b000 {                   /* 0x4a0db000, ap 15 08.0 */
+                       compatible = "ti,sysc-omap4-sr", "ti,sysc";
+                       ti,hwmods = "smartreflex_iva";
+                       reg = <0x5b038 0x4>;
+                       reg-names = "sysc";
+                       ti,sysc-mask = <SYSC_OMAP3_SR_ENAWAKEUP>;
+                       ti,sysc-sidle = <SYSC_IDLE_FORCE>,
+                                       <SYSC_IDLE_NO>,
+                                       <SYSC_IDLE_SMART>,
+                                       <SYSC_IDLE_SMART_WKUP>;
+                       /* Domains (V, P, C): core, always_on_core_pwrdm, l4_ao_clkdm */
+                       clocks = <&l4_ao_clkctrl OMAP4_SMARTREFLEX_IVA_CLKCTRL 0>;
+                       clock-names = "fck";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x5b000 0x1000>;
+
+                       smartreflex_iva: smartreflex@0 {
+                               compatible = "ti,omap4-smartreflex-iva";
+                               reg = <0x0 0x80>;
+                               interrupts = <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>;
+                       };
+               };
+
+               target-module@5d000 {                   /* 0x4a0dd000, ap 17 22.0 */
+                       compatible = "ti,sysc-omap4-sr", "ti,sysc";
+                       ti,hwmods = "smartreflex_core";
+                       reg = <0x5d038 0x4>;
+                       reg-names = "sysc";
+                       ti,sysc-mask = <SYSC_OMAP3_SR_ENAWAKEUP>;
+                       ti,sysc-sidle = <SYSC_IDLE_FORCE>,
+                                       <SYSC_IDLE_NO>,
+                                       <SYSC_IDLE_SMART>,
+                                       <SYSC_IDLE_SMART_WKUP>;
+                       /* Domains (V, P, C): core, always_on_core_pwrdm, l4_ao_clkdm */
+                       clocks = <&l4_ao_clkctrl OMAP4_SMARTREFLEX_CORE_CLKCTRL 0>;
+                       clock-names = "fck";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x5d000 0x1000>;
+
+                       smartreflex_core: smartreflex@0 {
+                               compatible = "ti,omap4-smartreflex-core";
+                               reg = <0x0 0x80>;
+                               interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
+                       };
+               };
+
+               target-module@60000 {                   /* 0x4a0e0000, ap 19 1c.0 */
+                       compatible = "ti,sysc";
+                       status = "disabled";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x60000 0x1000>;
+               };
+
+               target-module@74000 {                   /* 0x4a0f4000, ap 27 24.0 */
+                       compatible = "ti,sysc-omap4", "ti,sysc";
+                       ti,hwmods = "mailbox";
+                       reg = <0x74000 0x4>,
+                             <0x74010 0x4>;
+                       reg-names = "rev", "sysc";
+                       ti,sysc-mask = <SYSC_OMAP4_SOFTRESET>;
+                       ti,sysc-sidle = <SYSC_IDLE_FORCE>,
+                                       <SYSC_IDLE_NO>,
+                                       <SYSC_IDLE_SMART>;
+                       /* Domains (V, P, C): core, core_pwrdm, l4_cfg_clkdm */
+                       clocks = <&l4_cfg_clkctrl OMAP4_MAILBOX_CLKCTRL 0>;
+                       clock-names = "fck";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x74000 0x1000>;
+
+                       mailbox: mailbox@0 {
+                               compatible = "ti,omap4-mailbox";
+                               reg = <0x0 0x200>;
+                               interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
+                               #mbox-cells = <1>;
+                               ti,mbox-num-users = <3>;
+                               ti,mbox-num-fifos = <8>;
+                               mbox_ipu: mbox_ipu {
+                                       ti,mbox-tx = <0 0 0>;
+                                       ti,mbox-rx = <1 0 0>;
+                               };
+                               mbox_dsp: mbox_dsp {
+                                       ti,mbox-tx = <3 0 0>;
+                                       ti,mbox-rx = <2 0 0>;
+                               };
+                       };
+               };
+
+               target-module@76000 {                   /* 0x4a0f6000, ap 29 3a.0 */
+                       compatible = "ti,sysc-omap2", "ti,sysc";
+                       ti,hwmods = "spinlock";
+                       reg = <0x76000 0x4>,
+                             <0x76010 0x4>,
+                             <0x76014 0x4>;
+                       reg-names = "rev", "sysc", "syss";
+                       ti,sysc-mask = <(SYSC_OMAP2_CLOCKACTIVITY |
+                                        SYSC_OMAP2_ENAWAKEUP |
+                                        SYSC_OMAP2_SOFTRESET |
+                                        SYSC_OMAP2_AUTOIDLE)>;
+                       ti,sysc-sidle = <SYSC_IDLE_FORCE>,
+                                       <SYSC_IDLE_NO>,
+                                       <SYSC_IDLE_SMART>;
+                       ti,syss-mask = <1>;
+                       /* Domains (V, P, C): core, core_pwrdm, l4_cfg_clkdm */
+                       clocks = <&l4_cfg_clkctrl OMAP4_SPINLOCK_CLKCTRL 0>;
+                       clock-names = "fck";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x76000 0x1000>;
+
+                       hwspinlock: spinlock@0 {
+                               compatible = "ti,omap4-hwspinlock";
+                               reg = <0x0 0x1000>;
+                               #hwlock-cells = <1>;
+                       };
+               };
+       };
+
+       segment@100000 {                                        /* 0x4a100000 */
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges = <0x00000000 0x00100000 0x001000>,      /* ap 21 */
+                        <0x00001000 0x00101000 0x001000>,      /* ap 22 */
+                        <0x00002000 0x00102000 0x001000>,      /* ap 61 */
+                        <0x00003000 0x00103000 0x001000>,      /* ap 62 */
+                        <0x00008000 0x00108000 0x001000>,      /* ap 63 */
+                        <0x00009000 0x00109000 0x001000>,      /* ap 64 */
+                        <0x0000a000 0x0010a000 0x001000>,      /* ap 65 */
+                        <0x0000b000 0x0010b000 0x001000>;      /* ap 66 */
+
+               target-module@0 {                       /* 0x4a100000, ap 21 2a.0 */
+                       compatible = "ti,sysc-omap4", "ti,sysc";
+                       ti,hwmods = "ctrl_module_pad_core";
+                       reg = <0x0 0x4>,
+                             <0x10 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): core, core_pwrdm, l4_cfg_clkdm */
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x0 0x1000>;
+
+                       omap4_pmx_core: pinmux@40 {
+                               compatible = "ti,omap4-padconf",
+                                            "pinctrl-single";
+                               reg = <0x40 0x0196>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               #pinctrl-cells = <1>;
+                               #interrupt-cells = <1>;
+                               interrupt-controller;
+                               pinctrl-single,register-width = <16>;
+                               pinctrl-single,function-mask = <0x7fff>;
+                       };
+
+                       omap4_padconf_global: omap4_padconf_global@5a0 {
+                               compatible = "syscon",
+                                            "simple-bus";
+                               reg = <0x5a0 0x170>;
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+                               ranges = <0 0x5a0 0x170>;
+
+                               pbias_regulator: pbias_regulator@60 {
+                                       compatible = "ti,pbias-omap4", "ti,pbias-omap";
+                                       reg = <0x60 0x4>;
+                                       syscon = <&omap4_padconf_global>;
+                                       pbias_mmc_reg: pbias_mmc_omap4 {
+                                               regulator-name = "pbias_mmc_omap4";
+                                               regulator-min-microvolt = <1800000>;
+                                               regulator-max-microvolt = <3000000>;
+                                       };
+                               };
+                       };
+               };
+
+               target-module@2000 {                    /* 0x4a102000, ap 61 3c.0 */
+                       compatible = "ti,sysc";
+                       status = "disabled";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x2000 0x1000>;
+               };
+
+               target-module@8000 {                    /* 0x4a108000, ap 63 62.0 */
+                       compatible = "ti,sysc";
+                       status = "disabled";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x8000 0x1000>;
+               };
+
+               target-module@a000 {                    /* 0x4a10a000, ap 65 50.0 */
+                       compatible = "ti,sysc-omap4", "ti,sysc";
+                       ti,hwmods = "fdif";
+                       reg = <0xa000 0x4>,
+                             <0xa010 0x4>;
+                       reg-names = "rev", "sysc";
+                       ti,sysc-mask = <SYSC_OMAP4_SOFTRESET>;
+                       ti,sysc-midle = <SYSC_IDLE_FORCE>,
+                                       <SYSC_IDLE_NO>,
+                                       <SYSC_IDLE_SMART>;
+                       ti,sysc-sidle = <SYSC_IDLE_FORCE>,
+                                       <SYSC_IDLE_NO>,
+                                       <SYSC_IDLE_SMART>;
+                       ti,sysc-delay-us = <2>;
+                       /* Domains (V, P, C): core, cam_pwrdm, iss_clkdm */
+                       clocks = <&iss_clkctrl OMAP4_FDIF_CLKCTRL 0>;
+                       clock-names = "fck";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0xa000 0x1000>;
+
+                       /* No child device binding or driver in mainline */
+               };
+       };
+
+       segment@180000 {                                        /* 0x4a180000 */
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <1>;
+       };
+
+       segment@200000 {                                        /* 0x4a200000 */
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges = <0x0001e000 0x0021e000 0x001000>,      /* ap 31 */
+                        <0x0001f000 0x0021f000 0x001000>,      /* ap 32 */
+                        <0x0000a000 0x0020a000 0x001000>,      /* ap 33 */
+                        <0x0000b000 0x0020b000 0x001000>,      /* ap 34 */
+                        <0x00004000 0x00204000 0x001000>,      /* ap 35 */
+                        <0x00005000 0x00205000 0x001000>,      /* ap 36 */
+                        <0x00006000 0x00206000 0x001000>,      /* ap 37 */
+                        <0x00007000 0x00207000 0x001000>,      /* ap 38 */
+                        <0x00012000 0x00212000 0x001000>,      /* ap 39 */
+                        <0x00013000 0x00213000 0x001000>,      /* ap 40 */
+                        <0x0000c000 0x0020c000 0x001000>,      /* ap 41 */
+                        <0x0000d000 0x0020d000 0x001000>,      /* ap 42 */
+                        <0x00010000 0x00210000 0x001000>,      /* ap 43 */
+                        <0x00011000 0x00211000 0x001000>,      /* ap 44 */
+                        <0x00016000 0x00216000 0x001000>,      /* ap 45 */
+                        <0x00017000 0x00217000 0x001000>,      /* ap 46 */
+                        <0x00014000 0x00214000 0x001000>,      /* ap 47 */
+                        <0x00015000 0x00215000 0x001000>,      /* ap 48 */
+                        <0x00018000 0x00218000 0x001000>,      /* ap 49 */
+                        <0x00019000 0x00219000 0x001000>,      /* ap 50 */
+                        <0x00020000 0x00220000 0x001000>,      /* ap 51 */
+                        <0x00021000 0x00221000 0x001000>,      /* ap 52 */
+                        <0x00026000 0x00226000 0x001000>,      /* ap 53 */
+                        <0x00027000 0x00227000 0x001000>,      /* ap 54 */
+                        <0x00028000 0x00228000 0x001000>,      /* ap 55 */
+                        <0x00029000 0x00229000 0x001000>,      /* ap 56 */
+                        <0x0002a000 0x0022a000 0x001000>,      /* ap 57 */
+                        <0x0002b000 0x0022b000 0x001000>,      /* ap 58 */
+                        <0x0001c000 0x0021c000 0x001000>,      /* ap 59 */
+                        <0x0001d000 0x0021d000 0x001000>;      /* ap 60 */
+
+               target-module@4000 {                    /* 0x4a204000, ap 35 42.0 */
+                       compatible = "ti,sysc";
+                       status = "disabled";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x4000 0x1000>;
+               };
+
+               target-module@6000 {                    /* 0x4a206000, ap 37 4a.0 */
+                       compatible = "ti,sysc";
+                       status = "disabled";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x6000 0x1000>;
+               };
+
+               target-module@a000 {                    /* 0x4a20a000, ap 33 2c.0 */
+                       compatible = "ti,sysc";
+                       status = "disabled";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0xa000 0x1000>;
+               };
+
+               target-module@c000 {                    /* 0x4a20c000, ap 41 20.0 */
+                       compatible = "ti,sysc";
+                       status = "disabled";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0xc000 0x1000>;
+               };
+
+               target-module@10000 {                   /* 0x4a210000, ap 43 52.0 */
+                       compatible = "ti,sysc";
+                       status = "disabled";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x10000 0x1000>;
+               };
+
+               target-module@12000 {                   /* 0x4a212000, ap 39 18.0 */
+                       compatible = "ti,sysc";
+                       status = "disabled";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x12000 0x1000>;
+               };
+
+               target-module@14000 {                   /* 0x4a214000, ap 47 30.0 */
+                       compatible = "ti,sysc";
+                       status = "disabled";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x14000 0x1000>;
+               };
+
+               target-module@16000 {                   /* 0x4a216000, ap 45 28.0 */
+                       compatible = "ti,sysc";
+                       status = "disabled";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x16000 0x1000>;
+               };
+
+               target-module@18000 {                   /* 0x4a218000, ap 49 38.0 */
+                       compatible = "ti,sysc";
+                       status = "disabled";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x18000 0x1000>;
+               };
+
+               target-module@1c000 {                   /* 0x4a21c000, ap 59 5a.0 */
+                       compatible = "ti,sysc";
+                       status = "disabled";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x1c000 0x1000>;
+               };
+
+               target-module@1e000 {                   /* 0x4a21e000, ap 31 10.0 */
+                       compatible = "ti,sysc";
+                       status = "disabled";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x1e000 0x1000>;
+               };
+
+               target-module@20000 {                   /* 0x4a220000, ap 51 40.0 */
+                       compatible = "ti,sysc";
+                       status = "disabled";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x20000 0x1000>;
+               };
+
+               target-module@26000 {                   /* 0x4a226000, ap 53 34.0 */
+                       compatible = "ti,sysc";
+                       status = "disabled";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x26000 0x1000>;
+               };
+
+               target-module@28000 {                   /* 0x4a228000, ap 55 2e.0 */
+                       compatible = "ti,sysc";
+                       status = "disabled";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x28000 0x1000>;
+               };
+
+               target-module@2a000 {                   /* 0x4a22a000, ap 57 48.0 */
+                       compatible = "ti,sysc";
+                       status = "disabled";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x2a000 0x1000>;
+               };
+       };
+
+       segment@280000 {                                        /* 0x4a280000 */
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <1>;
+       };
+
+       l4_cfg_segment_300000: segment@300000 {                 /* 0x4a300000 */
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges = <0x00000000 0x00300000 0x020000>,      /* ap 67 */
+                        <0x00040000 0x00340000 0x001000>,      /* ap 68 */
+                        <0x00020000 0x00320000 0x004000>,      /* ap 71 */
+                        <0x00024000 0x00324000 0x002000>,      /* ap 72 */
+                        <0x00026000 0x00326000 0x001000>,      /* ap 73 */
+                        <0x00027000 0x00327000 0x001000>,      /* ap 74 */
+                        <0x00028000 0x00328000 0x001000>,      /* ap 75 */
+                        <0x00029000 0x00329000 0x001000>,      /* ap 76 */
+                        <0x00030000 0x00330000 0x010000>,      /* ap 77 */
+                        <0x0002a000 0x0032a000 0x002000>,      /* ap 90 */
+                        <0x0002c000 0x0032c000 0x004000>;      /* ap 91 */
+
+               l4_cfg_target_0: target-module@0 {      /* 0x4a300000, ap 67 14.0 */
+                       compatible = "ti,sysc";
+                       status = "disabled";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x00000000 0x00000000 0x00020000>,
+                                <0x00020000 0x00020000 0x00004000>,
+                                <0x00024000 0x00024000 0x00002000>,
+                                <0x00026000 0x00026000 0x00001000>,
+                                <0x00027000 0x00027000 0x00001000>,
+                                <0x00028000 0x00028000 0x00001000>,
+                                <0x00029000 0x00029000 0x00001000>,
+                                <0x0002a000 0x0002a000 0x00002000>,
+                                <0x0002c000 0x0002c000 0x00004000>,
+                                <0x00030000 0x00030000 0x00010000>;
+               };
+       };
+};
+
+&l4_wkup {                                             /* 0x4a300000 */
+       compatible = "ti,omap4-l4-wkup", "simple-bus";
+       reg = <0x4a300000 0x800>,
+             <0x4a300800 0x800>,
+             <0x4a301000 0x1000>;
+       reg-names = "ap", "la", "ia0";
+       #address-cells = <1>;
+       #size-cells = <1>;
+       ranges = <0x00000000 0x4a300000 0x010000>,      /* segment 0 */
+                <0x00010000 0x4a310000 0x010000>,      /* segment 1 */
+                <0x00020000 0x4a320000 0x010000>;      /* segment 2 */
+
+       segment@0 {                                     /* 0x4a300000 */
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges = <0x00000000 0x00000000 0x000800>,      /* ap 0 */
+                        <0x00001000 0x00001000 0x001000>,      /* ap 1 */
+                        <0x00000800 0x00000800 0x000800>,      /* ap 2 */
+                        <0x00006000 0x00006000 0x002000>,      /* ap 3 */
+                        <0x00008000 0x00008000 0x001000>,      /* ap 4 */
+                        <0x0000a000 0x0000a000 0x001000>,      /* ap 15 */
+                        <0x0000b000 0x0000b000 0x001000>,      /* ap 16 */
+                        <0x00004000 0x00004000 0x001000>,      /* ap 17 */
+                        <0x00005000 0x00005000 0x001000>,      /* ap 18 */
+                        <0x0000c000 0x0000c000 0x001000>,      /* ap 19 */
+                        <0x0000d000 0x0000d000 0x001000>;      /* ap 20 */
+
+               target-module@4000 {                    /* 0x4a304000, ap 17 24.0 */
+                       compatible = "ti,sysc-omap2", "ti,sysc";
+                       ti,hwmods = "counter_32k";
+                       reg = <0x4000 0x4>,
+                             <0x4004 0x4>;
+                       reg-names = "rev", "sysc";
+                       ti,sysc-sidle = <SYSC_IDLE_FORCE>,
+                                       <SYSC_IDLE_NO>;
+                       /* Domains (V, P, C): wakeup, wkup_pwrdm, l4_wkup_clkdm */
+                       clocks = <&l4_wkup_clkctrl OMAP4_COUNTER_32K_CLKCTRL 0>;
+                       clock-names = "fck";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x4000 0x1000>;
+
+                       counter32k: counter@0 {
+                               compatible = "ti,omap-counter32k";
+                               reg = <0x0 0x20>;
+                       };
+               };
+
+               target-module@6000 {                    /* 0x4a306000, ap 3 08.0 */
+                       compatible = "ti,sysc-omap4", "ti,sysc";
+                       reg = <0x6000 0x4>;
+                       reg-names = "rev";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x6000 0x2000>;
+
+                       prm: prm@0 {
+                               compatible = "ti,omap4-prm";
+                               reg = <0x0 0x2000>;
+                               interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>;
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+                               ranges = <0 0 0x2000>;
+
+                               prm_clocks: clocks {
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                               };
+
+                               prm_clockdomains: clockdomains {
+                               };
+                       };
+               };
+
+               target-module@a000 {                    /* 0x4a30a000, ap 15 34.0 */
+                       compatible = "ti,sysc-omap4", "ti,sysc";
+                       reg = <0xa000 0x4>;
+                       reg-names = "rev";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0xa000 0x1000>;
+
+                       scrm: scrm@0 {
+                               compatible = "ti,omap4-scrm";
+                               reg = <0x0 0x2000>;
+
+                               scrm_clocks: clocks {
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                               };
+
+                               scrm_clockdomains: clockdomains {
+                               };
+                       };
+               };
+
+               target-module@c000 {                    /* 0x4a30c000, ap 19 2c.0 */
+                       compatible = "ti,sysc-omap4", "ti,sysc";
+                       ti,hwmods = "ctrl_module_wkup";
+                       reg = <0xc000 0x4>,
+                             <0xc010 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): wakeup, wkup_pwrdm, l4_wkup_clkdm */
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0xc000 0x1000>;
+
+                       omap4_scm_wkup: scm@c000 {
+                               compatible = "ti,omap4-scm-wkup";
+                               reg = <0xc000 0x1000>;
+                       };
+               };
+       };
+
+       segment@10000 {                                 /* 0x4a310000 */
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges = <0x00000000 0x00010000 0x001000>,      /* ap 5 */
+                        <0x00001000 0x00011000 0x001000>,      /* ap 6 */
+                        <0x00004000 0x00014000 0x001000>,      /* ap 7 */
+                        <0x00005000 0x00015000 0x001000>,      /* ap 8 */
+                        <0x00008000 0x00018000 0x001000>,      /* ap 9 */
+                        <0x00009000 0x00019000 0x001000>,      /* ap 10 */
+                        <0x0000c000 0x0001c000 0x001000>,      /* ap 11 */
+                        <0x0000d000 0x0001d000 0x001000>,      /* ap 12 */
+                        <0x0000e000 0x0001e000 0x001000>,      /* ap 21 */
+                        <0x0000f000 0x0001f000 0x001000>;      /* ap 22 */
+
+               gpio1_target: target-module@0 {                 /* 0x4a310000, ap 5 14.0 */
+                       compatible = "ti,sysc-omap2", "ti,sysc";
+                       ti,hwmods = "gpio1";
+                       reg = <0x0 0x4>,
+                             <0x10 0x4>,
+                             <0x114 0x4>;
+                       reg-names = "rev", "sysc", "syss";
+                       ti,sysc-mask = <(SYSC_OMAP2_ENAWAKEUP |
+                                        SYSC_OMAP2_SOFTRESET |
+                                        SYSC_OMAP2_AUTOIDLE)>;
+                       ti,sysc-sidle = <SYSC_IDLE_FORCE>,
+                                       <SYSC_IDLE_NO>,
+                                       <SYSC_IDLE_SMART>,
+                                       <SYSC_IDLE_SMART_WKUP>;
+                       ti,syss-mask = <1>;
+                       /* Domains (V, P, C): wakeup, wkup_pwrdm, l4_wkup_clkdm */
+                       clocks = <&l4_wkup_clkctrl OMAP4_GPIO1_CLKCTRL 0>,
+                                <&l4_wkup_clkctrl OMAP4_GPIO1_CLKCTRL 8>;
+                       clock-names = "fck", "dbclk";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x0 0x1000>;
+
+                       gpio1: gpio@0 {
+                               compatible = "ti,omap4-gpio";
+                               reg = <0x0 0x200>;
+                               interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
+                               ti,gpio-always-on;
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               interrupt-controller;
+                               #interrupt-cells = <2>;
+                       };
+               };
+
+               target-module@4000 {                    /* 0x4a314000, ap 7 18.0 */
+                       compatible = "ti,sysc-omap2", "ti,sysc";
+                       ti,hwmods = "wd_timer2";
+                       reg = <0x4000 0x4>,
+                             <0x4010 0x4>,
+                             <0x4014 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): wakeup, wkup_pwrdm, l4_wkup_clkdm */
+                       clocks = <&l4_wkup_clkctrl OMAP4_WD_TIMER2_CLKCTRL 0>;
+                       clock-names = "fck";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x4000 0x1000>;
+
+                       wdt2: wdt@0 {
+                               compatible = "ti,omap4-wdt", "ti,omap3-wdt";
+                               reg = <0x0 0x80>;
+                               interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>;
+                       };
+               };
+
+               target-module@8000 {                    /* 0x4a318000, ap 9 1c.0 */
+                       compatible = "ti,sysc-omap2-timer", "ti,sysc";
+                       ti,hwmods = "timer1";
+                       reg = <0x8000 0x4>,
+                             <0x8010 0x4>,
+                             <0x8014 0x4>;
+                       reg-names = "rev", "sysc", "syss";
+                       ti,sysc-mask = <(SYSC_OMAP2_CLOCKACTIVITY |
+                                        SYSC_OMAP2_EMUFREE |
+                                        SYSC_OMAP2_ENAWAKEUP |
+                                        SYSC_OMAP2_SOFTRESET |
+                                        SYSC_OMAP2_AUTOIDLE)>;
+                       ti,sysc-sidle = <SYSC_IDLE_FORCE>,
+                                       <SYSC_IDLE_NO>,
+                                       <SYSC_IDLE_SMART>;
+                       ti,syss-mask = <1>;
+                       /* Domains (V, P, C): wakeup, wkup_pwrdm, l4_wkup_clkdm */
+                       clocks = <&l4_wkup_clkctrl OMAP4_TIMER1_CLKCTRL 0>;
+                       clock-names = "fck";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x8000 0x1000>;
+
+                       timer1: timer@0 {
+                               compatible = "ti,omap3430-timer";
+                               reg = <0x0 0x80>;
+                               clocks = <&l4_wkup_clkctrl OMAP4_TIMER1_CLKCTRL 24>;
+                               clock-names = "fck";
+                               interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
+                               ti,timer-alwon;
+                       };
+               };
+
+               target-module@c000 {                    /* 0x4a31c000, ap 11 20.0 */
+                       compatible = "ti,sysc-omap2", "ti,sysc";
+                       ti,hwmods = "kbd";
+                       reg = <0xc000 0x4>,
+                             <0xc010 0x4>,
+                             <0xc014 0x4>;
+                       reg-names = "rev", "sysc", "syss";
+                       ti,sysc-mask = <(SYSC_OMAP2_CLOCKACTIVITY |
+                                        SYSC_OMAP2_EMUFREE |
+                                        SYSC_OMAP2_ENAWAKEUP |
+                                        SYSC_OMAP2_SOFTRESET |
+                                        SYSC_OMAP2_AUTOIDLE)>;
+                       ti,sysc-sidle = <SYSC_IDLE_FORCE>,
+                                       <SYSC_IDLE_NO>,
+                                       <SYSC_IDLE_SMART>;
+                       ti,syss-mask = <1>;
+                       /* Domains (V, P, C): wakeup, wkup_pwrdm, l4_wkup_clkdm */
+                       clocks = <&l4_wkup_clkctrl OMAP4_KBD_CLKCTRL 0>;
+                       clock-names = "fck";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0xc000 0x1000>;
+
+                       keypad: keypad@0 {
+                               compatible = "ti,omap4-keypad";
+                               reg = <0x0 0x80>;
+                               interrupts = <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>;
+                               reg-names = "mpu";
+                       };
+               };
+
+               target-module@e000 {                    /* 0x4a31e000, ap 21 30.0 */
+                       compatible = "ti,sysc-omap4", "ti,sysc";
+                       ti,hwmods = "ctrl_module_pad_wkup";
+                       reg = <0xe000 0x4>,
+                             <0xe010 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): wakeup, wkup_pwrdm, l4_wkup_clkdm */
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0xe000 0x1000>;
+
+                       omap4_pmx_wkup: pinmux@40 {
+                               compatible = "ti,omap4-padconf",
+                                            "pinctrl-single";
+                               reg = <0x40 0x0038>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               #pinctrl-cells = <1>;
+                               #interrupt-cells = <1>;
+                               interrupt-controller;
+                               pinctrl-single,register-width = <16>;
+                               pinctrl-single,function-mask = <0x7fff>;
+                       };
+               };
+       };
+
+       segment@20000 {                                 /* 0x4a320000 */
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges = <0x00006000 0x00026000 0x001000>,      /* ap 13 */
+                        <0x0000a000 0x0002a000 0x001000>,      /* ap 14 */
+                        <0x00000000 0x00020000 0x001000>,      /* ap 23 */
+                        <0x00001000 0x00021000 0x001000>,      /* ap 24 */
+                        <0x00002000 0x00022000 0x001000>,      /* ap 25 */
+                        <0x00003000 0x00023000 0x001000>,      /* ap 26 */
+                        <0x00004000 0x00024000 0x001000>,      /* ap 27 */
+                        <0x00005000 0x00025000 0x001000>,      /* ap 28 */
+                        <0x00007000 0x00027000 0x000400>,      /* ap 29 */
+                        <0x00008000 0x00028000 0x000800>,      /* ap 30 */
+                        <0x00009000 0x00029000 0x000400>;      /* ap 31 */
+
+               target-module@0 {                       /* 0x4a320000, ap 23 04.0 */
+                       compatible = "ti,sysc";
+                       status = "disabled";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x0 0x1000>;
+               };
+
+               target-module@2000 {                    /* 0x4a322000, ap 25 0c.0 */
+                       compatible = "ti,sysc";
+                       status = "disabled";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x2000 0x1000>;
+               };
+
+               target-module@4000 {                    /* 0x4a324000, ap 27 10.0 */
+                       compatible = "ti,sysc";
+                       status = "disabled";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x4000 0x1000>;
+               };
+
+               target-module@6000 {                    /* 0x4a326000, ap 13 28.0 */
+                       compatible = "ti,sysc";
+                       status = "disabled";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x00000000 0x00006000 0x00001000>,
+                                <0x00001000 0x00007000 0x00000400>,
+                                <0x00002000 0x00008000 0x00000800>,
+                                <0x00003000 0x00009000 0x00000400>;
+               };
+       };
+};
+
+&l4_per {                                              /* 0x48000000 */
+       compatible = "ti,omap4-l4-per", "simple-bus";
+       reg = <0x48000000 0x800>,
+             <0x48000800 0x800>,
+             <0x48001000 0x400>,
+             <0x48001400 0x400>,
+             <0x48001800 0x400>,
+             <0x48001c00 0x400>;
+       reg-names = "ap", "la", "ia0", "ia1", "ia2", "ia3";
+       #address-cells = <1>;
+       #size-cells = <1>;
+       ranges = <0x00000000 0x48000000 0x200000>,      /* segment 0 */
+                <0x00200000 0x48200000 0x200000>;      /* segment 1 */
+
+       segment@0 {                                     /* 0x48000000 */
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges = <0x00000000 0x00000000 0x000800>,      /* ap 0 */
+                        <0x00001000 0x00001000 0x000400>,      /* ap 1 */
+                        <0x00000800 0x00000800 0x000800>,      /* ap 2 */
+                        <0x00020000 0x00020000 0x001000>,      /* ap 3 */
+                        <0x00021000 0x00021000 0x001000>,      /* ap 4 */
+                        <0x00032000 0x00032000 0x001000>,      /* ap 5 */
+                        <0x00033000 0x00033000 0x001000>,      /* ap 6 */
+                        <0x00034000 0x00034000 0x001000>,      /* ap 7 */
+                        <0x00035000 0x00035000 0x001000>,      /* ap 8 */
+                        <0x00036000 0x00036000 0x001000>,      /* ap 9 */
+                        <0x00037000 0x00037000 0x001000>,      /* ap 10 */
+                        <0x0003e000 0x0003e000 0x001000>,      /* ap 11 */
+                        <0x0003f000 0x0003f000 0x001000>,      /* ap 12 */
+                        <0x00040000 0x00040000 0x010000>,      /* ap 13 */
+                        <0x00050000 0x00050000 0x001000>,      /* ap 14 */
+                        <0x00055000 0x00055000 0x001000>,      /* ap 15 */
+                        <0x00056000 0x00056000 0x001000>,      /* ap 16 */
+                        <0x00057000 0x00057000 0x001000>,      /* ap 17 */
+                        <0x00058000 0x00058000 0x001000>,      /* ap 18 */
+                        <0x00059000 0x00059000 0x001000>,      /* ap 19 */
+                        <0x0005a000 0x0005a000 0x001000>,      /* ap 20 */
+                        <0x0005b000 0x0005b000 0x001000>,      /* ap 21 */
+                        <0x0005c000 0x0005c000 0x001000>,      /* ap 22 */
+                        <0x0005d000 0x0005d000 0x001000>,      /* ap 23 */
+                        <0x0005e000 0x0005e000 0x001000>,      /* ap 24 */
+                        <0x00060000 0x00060000 0x001000>,      /* ap 25 */
+                        <0x0006a000 0x0006a000 0x001000>,      /* ap 26 */
+                        <0x0006b000 0x0006b000 0x001000>,      /* ap 27 */
+                        <0x0006c000 0x0006c000 0x001000>,      /* ap 28 */
+                        <0x0006d000 0x0006d000 0x001000>,      /* ap 29 */
+                        <0x0006e000 0x0006e000 0x001000>,      /* ap 30 */
+                        <0x0006f000 0x0006f000 0x001000>,      /* ap 31 */
+                        <0x00070000 0x00070000 0x001000>,      /* ap 32 */
+                        <0x00071000 0x00071000 0x001000>,      /* ap 33 */
+                        <0x00072000 0x00072000 0x001000>,      /* ap 34 */
+                        <0x00073000 0x00073000 0x001000>,      /* ap 35 */
+                        <0x00061000 0x00061000 0x001000>,      /* ap 36 */
+                        <0x00096000 0x00096000 0x001000>,      /* ap 37 */
+                        <0x00097000 0x00097000 0x001000>,      /* ap 38 */
+                        <0x00076000 0x00076000 0x001000>,      /* ap 39 */
+                        <0x00077000 0x00077000 0x001000>,      /* ap 40 */
+                        <0x00078000 0x00078000 0x001000>,      /* ap 41 */
+                        <0x00079000 0x00079000 0x001000>,      /* ap 42 */
+                        <0x00086000 0x00086000 0x001000>,      /* ap 43 */
+                        <0x00087000 0x00087000 0x001000>,      /* ap 44 */
+                        <0x00088000 0x00088000 0x001000>,      /* ap 45 */
+                        <0x00089000 0x00089000 0x001000>,      /* ap 46 */
+                        <0x000b0000 0x000b0000 0x001000>,      /* ap 47 */
+                        <0x000b1000 0x000b1000 0x001000>,      /* ap 48 */
+                        <0x00098000 0x00098000 0x001000>,      /* ap 49 */
+                        <0x00099000 0x00099000 0x001000>,      /* ap 50 */
+                        <0x0009a000 0x0009a000 0x001000>,      /* ap 51 */
+                        <0x0009b000 0x0009b000 0x001000>,      /* ap 52 */
+                        <0x0009c000 0x0009c000 0x001000>,      /* ap 53 */
+                        <0x0009d000 0x0009d000 0x001000>,      /* ap 54 */
+                        <0x0009e000 0x0009e000 0x001000>,      /* ap 55 */
+                        <0x0009f000 0x0009f000 0x001000>,      /* ap 56 */
+                        <0x00090000 0x00090000 0x002000>,      /* ap 57 */
+                        <0x00092000 0x00092000 0x001000>,      /* ap 58 */
+                        <0x000a4000 0x000a4000 0x001000>,      /* ap 59 */
+                        <0x000a6000 0x000a6000 0x001000>,      /* ap 60 */
+                        <0x000a8000 0x000a8000 0x004000>,      /* ap 61 */
+                        <0x000ac000 0x000ac000 0x001000>,      /* ap 62 */
+                        <0x000ad000 0x000ad000 0x001000>,      /* ap 63 */
+                        <0x000ae000 0x000ae000 0x001000>,      /* ap 64 */
+                        <0x000b2000 0x000b2000 0x001000>,      /* ap 65 */
+                        <0x000b3000 0x000b3000 0x001000>,      /* ap 66 */
+                        <0x000b4000 0x000b4000 0x001000>,      /* ap 67 */
+                        <0x000b5000 0x000b5000 0x001000>,      /* ap 68 */
+                        <0x000b8000 0x000b8000 0x001000>,      /* ap 69 */
+                        <0x000b9000 0x000b9000 0x001000>,      /* ap 70 */
+                        <0x000ba000 0x000ba000 0x001000>,      /* ap 71 */
+                        <0x000bb000 0x000bb000 0x001000>,      /* ap 72 */
+                        <0x000d1000 0x000d1000 0x001000>,      /* ap 73 */
+                        <0x000d2000 0x000d2000 0x001000>,      /* ap 74 */
+                        <0x000d5000 0x000d5000 0x001000>,      /* ap 75 */
+                        <0x000d6000 0x000d6000 0x001000>,      /* ap 76 */
+                        <0x000a2000 0x000a2000 0x001000>,      /* ap 79 */
+                        <0x000a3000 0x000a3000 0x001000>,      /* ap 80 */
+                        <0x00001400 0x00001400 0x000400>,      /* ap 81 */
+                        <0x00001800 0x00001800 0x000400>,      /* ap 82 */
+                        <0x00001c00 0x00001c00 0x000400>,      /* ap 83 */
+                        <0x000a5000 0x000a5000 0x001000>;      /* ap 84 */
+
+               target-module@20000 {                   /* 0x48020000, ap 3 06.0 */
+                       compatible = "ti,sysc-omap2", "ti,sysc";
+                       ti,hwmods = "uart3";
+                       reg = <0x20050 0x4>,
+                             <0x20054 0x4>,
+                             <0x20058 0x4>;
+                       reg-names = "rev", "sysc", "syss";
+                       ti,sysc-mask = <(SYSC_OMAP2_ENAWAKEUP |
+                                        SYSC_OMAP2_SOFTRESET |
+                                        SYSC_OMAP2_AUTOIDLE)>;
+                       ti,sysc-sidle = <SYSC_IDLE_FORCE>,
+                                       <SYSC_IDLE_NO>,
+                                       <SYSC_IDLE_SMART>,
+                                       <SYSC_IDLE_SMART_WKUP>;
+                       ti,syss-mask = <1>;
+                       /* Domains (V, P, C): core, l4per_pwrdm, l4_per_clkdm */
+                       clocks = <&l4_per_clkctrl OMAP4_UART3_CLKCTRL 0>;
+                       clock-names = "fck";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x20000 0x1000>;
+
+                       uart3: serial@0 {
+                               compatible = "ti,omap4-uart";
+                               reg = <0x0 0x100>;
+                               interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
+                               clock-frequency = <48000000>;
+                       };
+               };
+
+               target-module@32000 {                   /* 0x48032000, ap 5 02.0 */
+                       compatible = "ti,sysc-omap2-timer", "ti,sysc";
+                       ti,hwmods = "timer2";
+                       reg = <0x32000 0x4>,
+                             <0x32010 0x4>,
+                             <0x32014 0x4>;
+                       reg-names = "rev", "sysc", "syss";
+                       ti,sysc-mask = <(SYSC_OMAP2_CLOCKACTIVITY |
+                                        SYSC_OMAP2_EMUFREE |
+                                        SYSC_OMAP2_ENAWAKEUP |
+                                        SYSC_OMAP2_SOFTRESET |
+                                        SYSC_OMAP2_AUTOIDLE)>;
+                       ti,sysc-sidle = <SYSC_IDLE_FORCE>,
+                                       <SYSC_IDLE_NO>,
+                                       <SYSC_IDLE_SMART>;
+                       ti,syss-mask = <1>;
+                       /* Domains (V, P, C): core, l4per_pwrdm, l4_per_clkdm */
+                       clocks = <&l4_per_clkctrl OMAP4_TIMER2_CLKCTRL 0>;
+                       clock-names = "fck";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x32000 0x1000>;
+
+                       timer2: timer@0 {
+                               compatible = "ti,omap3430-timer";
+                               reg = <0x0 0x80>;
+                               clocks = <&l4_per_clkctrl OMAP4_TIMER2_CLKCTRL 24>;
+                               clock-names = "fck";
+                               interrupts = <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>;
+                       };
+               };
+
+               target-module@34000 {                   /* 0x48034000, ap 7 04.0 */
+                       compatible = "ti,sysc-omap4-timer", "ti,sysc";
+                       ti,hwmods = "timer3";
+                       reg = <0x34000 0x4>,
+                             <0x34010 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, l4per_pwrdm, l4_per_clkdm */
+                       clocks = <&l4_per_clkctrl OMAP4_TIMER3_CLKCTRL 0>;
+                       clock-names = "fck";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x34000 0x1000>;
+
+                       timer3: timer@0 {
+                               compatible = "ti,omap4430-timer";
+                               reg = <0x0 0x80>;
+                               clocks = <&l4_per_clkctrl OMAP4_TIMER3_CLKCTRL 24>;
+                               clock-names = "fck";
+                               interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>;
+                       };
+               };
+
+               target-module@36000 {                   /* 0x48036000, ap 9 0e.0 */
+                       compatible = "ti,sysc-omap4-timer", "ti,sysc";
+                       ti,hwmods = "timer4";
+                       reg = <0x36000 0x4>,
+                             <0x36010 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, l4per_pwrdm, l4_per_clkdm */
+                       clocks = <&l4_per_clkctrl OMAP4_TIMER4_CLKCTRL 0>;
+                       clock-names = "fck";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x36000 0x1000>;
+
+                       timer4: timer@0 {
+                               compatible = "ti,omap4430-timer";
+                               reg = <0x0 0x80>;
+                               clocks = <&l4_per_clkctrl OMAP4_TIMER4_CLKCTRL 24>;
+                               clock-names = "fck";
+                               interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
+                       };
+               };
+
+               target-module@3e000 {                   /* 0x4803e000, ap 11 08.0 */
+                       compatible = "ti,sysc-omap4-timer", "ti,sysc";
+                       ti,hwmods = "timer9";
+                       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, l4per_pwrdm, l4_per_clkdm */
+                       clocks = <&l4_per_clkctrl OMAP4_TIMER9_CLKCTRL 0>;
+                       clock-names = "fck";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x3e000 0x1000>;
+
+                       timer9: timer@0 {
+                               compatible = "ti,omap4430-timer";
+                               reg = <0x0 0x80>;
+                               clocks = <&l4_per_clkctrl OMAP4_TIMER9_CLKCTRL 24>;
+                               clock-names = "fck";
+                               interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
+                               ti,timer-pwm;
+                       };
+               };
+
+               target-module@40000 {                   /* 0x48040000, ap 13 0a.0 */
+                       compatible = "ti,sysc";
+                       status = "disabled";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x40000 0x10000>;
+               };
+
+               target-module@55000 {                   /* 0x48055000, ap 15 0c.0 */
+                       compatible = "ti,sysc-omap2", "ti,sysc";
+                       ti,hwmods = "gpio2";
+                       reg = <0x55000 0x4>,
+                             <0x55010 0x4>,
+                             <0x55114 0x4>;
+                       reg-names = "rev", "sysc", "syss";
+                       ti,sysc-mask = <(SYSC_OMAP2_ENAWAKEUP |
+                                        SYSC_OMAP2_SOFTRESET |
+                                        SYSC_OMAP2_AUTOIDLE)>;
+                       ti,sysc-sidle = <SYSC_IDLE_FORCE>,
+                                       <SYSC_IDLE_NO>,
+                                       <SYSC_IDLE_SMART>,
+                                       <SYSC_IDLE_SMART_WKUP>;
+                       ti,syss-mask = <1>;
+                       /* Domains (V, P, C): core, l4per_pwrdm, l4_per_clkdm */
+                       clocks = <&l4_per_clkctrl OMAP4_GPIO2_CLKCTRL 0>,
+                                <&l4_per_clkctrl OMAP4_GPIO2_CLKCTRL 8>;
+                       clock-names = "fck", "dbclk";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x55000 0x1000>;
+
+                       gpio2: gpio@0 {
+                               compatible = "ti,omap4-gpio";
+                               reg = <0x0 0x200>;
+                               interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               interrupt-controller;
+                               #interrupt-cells = <2>;
+                       };
+               };
+
+               target-module@57000 {                   /* 0x48057000, ap 17 16.0 */
+                       compatible = "ti,sysc-omap2", "ti,sysc";
+                       ti,hwmods = "gpio3";
+                       reg = <0x57000 0x4>,
+                             <0x57010 0x4>,
+                             <0x57114 0x4>;
+                       reg-names = "rev", "sysc", "syss";
+                       ti,sysc-mask = <(SYSC_OMAP2_ENAWAKEUP |
+                                        SYSC_OMAP2_SOFTRESET |
+                                        SYSC_OMAP2_AUTOIDLE)>;
+                       ti,sysc-sidle = <SYSC_IDLE_FORCE>,
+                                       <SYSC_IDLE_NO>,
+                                       <SYSC_IDLE_SMART>,
+                                       <SYSC_IDLE_SMART_WKUP>;
+                       ti,syss-mask = <1>;
+                       /* Domains (V, P, C): core, l4per_pwrdm, l4_per_clkdm */
+                       clocks = <&l4_per_clkctrl OMAP4_GPIO3_CLKCTRL 0>,
+                                <&l4_per_clkctrl OMAP4_GPIO3_CLKCTRL 8>;
+                       clock-names = "fck", "dbclk";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x57000 0x1000>;
+
+                       gpio3: gpio@0 {
+                               compatible = "ti,omap4-gpio";
+                               reg = <0x0 0x200>;
+                               interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               interrupt-controller;
+                               #interrupt-cells = <2>;
+                       };
+               };
+
+               target-module@59000 {                   /* 0x48059000, ap 19 10.0 */
+                       compatible = "ti,sysc-omap2", "ti,sysc";
+                       ti,hwmods = "gpio4";
+                       reg = <0x59000 0x4>,
+                             <0x59010 0x4>,
+                             <0x59114 0x4>;
+                       reg-names = "rev", "sysc", "syss";
+                       ti,sysc-mask = <(SYSC_OMAP2_ENAWAKEUP |
+                                        SYSC_OMAP2_SOFTRESET |
+                                        SYSC_OMAP2_AUTOIDLE)>;
+                       ti,sysc-sidle = <SYSC_IDLE_FORCE>,
+                                       <SYSC_IDLE_NO>,
+                                       <SYSC_IDLE_SMART>,
+                                       <SYSC_IDLE_SMART_WKUP>;
+                       ti,syss-mask = <1>;
+                       /* Domains (V, P, C): core, l4per_pwrdm, l4_per_clkdm */
+                       clocks = <&l4_per_clkctrl OMAP4_GPIO4_CLKCTRL 0>,
+                                <&l4_per_clkctrl OMAP4_GPIO4_CLKCTRL 8>;
+                       clock-names = "fck", "dbclk";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x59000 0x1000>;
+
+                       gpio4: gpio@0 {
+                               compatible = "ti,omap4-gpio";
+                               reg = <0x0 0x200>;
+                               interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               interrupt-controller;
+                               #interrupt-cells = <2>;
+                       };
+               };
+
+               target-module@5b000 {                   /* 0x4805b000, ap 21 12.0 */
+                       compatible = "ti,sysc-omap2", "ti,sysc";
+                       ti,hwmods = "gpio5";
+                       reg = <0x5b000 0x4>,
+                             <0x5b010 0x4>,
+                             <0x5b114 0x4>;
+                       reg-names = "rev", "sysc", "syss";
+                       ti,sysc-mask = <(SYSC_OMAP2_ENAWAKEUP |
+                                        SYSC_OMAP2_SOFTRESET |
+                                        SYSC_OMAP2_AUTOIDLE)>;
+                       ti,sysc-sidle = <SYSC_IDLE_FORCE>,
+                                       <SYSC_IDLE_NO>,
+                                       <SYSC_IDLE_SMART>,
+                                       <SYSC_IDLE_SMART_WKUP>;
+                       ti,syss-mask = <1>;
+                       /* Domains (V, P, C): core, l4per_pwrdm, l4_per_clkdm */
+                       clocks = <&l4_per_clkctrl OMAP4_GPIO5_CLKCTRL 0>,
+                                <&l4_per_clkctrl OMAP4_GPIO5_CLKCTRL 8>;
+                       clock-names = "fck", "dbclk";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x5b000 0x1000>;
+
+                       gpio5: gpio@0 {
+                               compatible = "ti,omap4-gpio";
+                               reg = <0x0 0x200>;
+                               interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               interrupt-controller;
+                               #interrupt-cells = <2>;
+                       };
+               };
+
+               target-module@5d000 {                   /* 0x4805d000, ap 23 14.0 */
+                       compatible = "ti,sysc-omap2", "ti,sysc";
+                       ti,hwmods = "gpio6";
+                       reg = <0x5d000 0x4>,
+                             <0x5d010 0x4>,
+                             <0x5d114 0x4>;
+                       reg-names = "rev", "sysc", "syss";
+                       ti,sysc-mask = <(SYSC_OMAP2_ENAWAKEUP |
+                                        SYSC_OMAP2_SOFTRESET |
+                                        SYSC_OMAP2_AUTOIDLE)>;
+                       ti,sysc-sidle = <SYSC_IDLE_FORCE>,
+                                       <SYSC_IDLE_NO>,
+                                       <SYSC_IDLE_SMART>,
+                                       <SYSC_IDLE_SMART_WKUP>;
+                       ti,syss-mask = <1>;
+                       /* Domains (V, P, C): core, l4per_pwrdm, l4_per_clkdm */
+                       clocks = <&l4_per_clkctrl OMAP4_GPIO6_CLKCTRL 0>,
+                                <&l4_per_clkctrl OMAP4_GPIO6_CLKCTRL 8>;
+                       clock-names = "fck", "dbclk";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x5d000 0x1000>;
+
+                       gpio6: gpio@0 {
+                               compatible = "ti,omap4-gpio";
+                               reg = <0x0 0x200>;
+                               interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               interrupt-controller;
+                               #interrupt-cells = <2>;
+                       };
+               };
+
+               target-module@60000 {                   /* 0x48060000, ap 25 1e.0 */
+                       compatible = "ti,sysc-omap2", "ti,sysc";
+                       ti,hwmods = "i2c3";
+                       reg = <0x60000 0x8>,
+                             <0x60010 0x8>,
+                             <0x60090 0x8>;
+                       reg-names = "rev", "sysc", "syss";
+                       ti,sysc-mask = <(SYSC_OMAP2_CLOCKACTIVITY |
+                                        SYSC_OMAP2_ENAWAKEUP |
+                                        SYSC_OMAP2_SOFTRESET |
+                                        SYSC_OMAP2_AUTOIDLE)>;
+                       ti,sysc-sidle = <SYSC_IDLE_FORCE>,
+                                       <SYSC_IDLE_NO>,
+                                       <SYSC_IDLE_SMART>,
+                                       <SYSC_IDLE_SMART_WKUP>;
+                       ti,syss-mask = <1>;
+                       /* Domains (V, P, C): core, l4per_pwrdm, l4_per_clkdm */
+                       clocks = <&l4_per_clkctrl OMAP4_I2C3_CLKCTRL 0>;
+                       clock-names = "fck";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x60000 0x1000>;
+
+                       i2c3: i2c@0 {
+                               compatible = "ti,omap4-i2c";
+                               reg = <0x0 0x100>;
+                               interrupts = <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                       };
+               };
+
+               target-module@6a000 {                   /* 0x4806a000, ap 26 18.0 */
+                       compatible = "ti,sysc-omap2", "ti,sysc";
+                       ti,hwmods = "uart1";
+                       reg = <0x6a050 0x4>,
+                             <0x6a054 0x4>,
+                             <0x6a058 0x4>;
+                       reg-names = "rev", "sysc", "syss";
+                       ti,sysc-mask = <(SYSC_OMAP2_ENAWAKEUP |
+                                        SYSC_OMAP2_SOFTRESET |
+                                        SYSC_OMAP2_AUTOIDLE)>;
+                       ti,sysc-sidle = <SYSC_IDLE_FORCE>,
+                                       <SYSC_IDLE_NO>,
+                                       <SYSC_IDLE_SMART>,
+                                       <SYSC_IDLE_SMART_WKUP>;
+                       ti,syss-mask = <1>;
+                       /* Domains (V, P, C): core, l4per_pwrdm, l4_per_clkdm */
+                       clocks = <&l4_per_clkctrl OMAP4_UART1_CLKCTRL 0>;
+                       clock-names = "fck";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x6a000 0x1000>;
+
+                       uart1: serial@0 {
+                               compatible = "ti,omap4-uart";
+                               reg = <0x0 0x100>;
+                               interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>;
+                               clock-frequency = <48000000>;
+                       };
+               };
+
+               target-module@6c000 {                   /* 0x4806c000, ap 28 20.0 */
+                       compatible = "ti,sysc-omap2", "ti,sysc";
+                       ti,hwmods = "uart2";
+                       reg = <0x6c050 0x4>,
+                             <0x6c054 0x4>,
+                             <0x6c058 0x4>;
+                       reg-names = "rev", "sysc", "syss";
+                       ti,sysc-mask = <(SYSC_OMAP2_ENAWAKEUP |
+                                        SYSC_OMAP2_SOFTRESET |
+                                        SYSC_OMAP2_AUTOIDLE)>;
+                       ti,sysc-sidle = <SYSC_IDLE_FORCE>,
+                                       <SYSC_IDLE_NO>,
+                                       <SYSC_IDLE_SMART>,
+                                       <SYSC_IDLE_SMART_WKUP>;
+                       ti,syss-mask = <1>;
+                       /* Domains (V, P, C): core, l4per_pwrdm, l4_per_clkdm */
+                       clocks = <&l4_per_clkctrl OMAP4_UART2_CLKCTRL 0>;
+                       clock-names = "fck";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x6c000 0x1000>;
+
+                       uart2: serial@0 {
+                               compatible = "ti,omap4-uart";
+                               reg = <0x0 0x100>;
+                               interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
+                               clock-frequency = <48000000>;
+                       };
+               };
+
+               target-module@6e000 {                   /* 0x4806e000, ap 30 1c.1 */
+                       compatible = "ti,sysc-omap2", "ti,sysc";
+                       ti,hwmods = "uart4";
+                       reg = <0x6e050 0x4>,
+                             <0x6e054 0x4>,
+                             <0x6e058 0x4>;
+                       reg-names = "rev", "sysc", "syss";
+                       ti,sysc-mask = <(SYSC_OMAP2_ENAWAKEUP |
+                                        SYSC_OMAP2_SOFTRESET |
+                                        SYSC_OMAP2_AUTOIDLE)>;
+                       ti,sysc-sidle = <SYSC_IDLE_FORCE>,
+                                       <SYSC_IDLE_NO>,
+                                       <SYSC_IDLE_SMART>,
+                                       <SYSC_IDLE_SMART_WKUP>;
+                       ti,syss-mask = <1>;
+                       /* Domains (V, P, C): core, l4per_pwrdm, l4_per_clkdm */
+                       clocks = <&l4_per_clkctrl OMAP4_UART4_CLKCTRL 0>;
+                       clock-names = "fck";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x6e000 0x1000>;
+
+                       uart4: serial@0 {
+                               compatible = "ti,omap4-uart";
+                               reg = <0x0 0x100>;
+                               interrupts = <GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
+                               clock-frequency = <48000000>;
+                       };
+               };
+
+               target-module@70000 {                   /* 0x48070000, ap 32 28.0 */
+                       compatible = "ti,sysc-omap2", "ti,sysc";
+                       ti,hwmods = "i2c1";
+                       reg = <0x70000 0x8>,
+                             <0x70010 0x8>,
+                             <0x70090 0x8>;
+                       reg-names = "rev", "sysc", "syss";
+                       ti,sysc-mask = <(SYSC_OMAP2_CLOCKACTIVITY |
+                                        SYSC_OMAP2_ENAWAKEUP |
+                                        SYSC_OMAP2_SOFTRESET |
+                                        SYSC_OMAP2_AUTOIDLE)>;
+                       ti,sysc-sidle = <SYSC_IDLE_FORCE>,
+                                       <SYSC_IDLE_NO>,
+                                       <SYSC_IDLE_SMART>,
+                                       <SYSC_IDLE_SMART_WKUP>;
+                       ti,syss-mask = <1>;
+                       /* Domains (V, P, C): core, l4per_pwrdm, l4_per_clkdm */
+                       clocks = <&l4_per_clkctrl OMAP4_I2C1_CLKCTRL 0>;
+                       clock-names = "fck";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x70000 0x1000>;
+
+                       i2c1: i2c@0 {
+                               compatible = "ti,omap4-i2c";
+                               reg = <0x0 0x100>;
+                               interrupts = <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                       };
+               };
+
+               target-module@72000 {                   /* 0x48072000, ap 34 30.0 */
+                       compatible = "ti,sysc-omap2", "ti,sysc";
+                       ti,hwmods = "i2c2";
+                       reg = <0x72000 0x8>,
+                             <0x72010 0x8>,
+                             <0x72090 0x8>;
+                       reg-names = "rev", "sysc", "syss";
+                       ti,sysc-mask = <(SYSC_OMAP2_CLOCKACTIVITY |
+                                        SYSC_OMAP2_ENAWAKEUP |
+                                        SYSC_OMAP2_SOFTRESET |
+                                        SYSC_OMAP2_AUTOIDLE)>;
+                       ti,sysc-sidle = <SYSC_IDLE_FORCE>,
+                                       <SYSC_IDLE_NO>,
+                                       <SYSC_IDLE_SMART>,
+                                       <SYSC_IDLE_SMART_WKUP>;
+                       ti,syss-mask = <1>;
+                       /* Domains (V, P, C): core, l4per_pwrdm, l4_per_clkdm */
+                       clocks = <&l4_per_clkctrl OMAP4_I2C2_CLKCTRL 0>;
+                       clock-names = "fck";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x72000 0x1000>;
+
+                       i2c2: i2c@0 {
+                               compatible = "ti,omap4-i2c";
+                               reg = <0x0 0x100>;
+                               interrupts = <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                       };
+               };
+
+               target-module@76000 {                   /* 0x48076000, ap 39 38.0 */
+                       compatible = "ti,sysc-omap4", "ti,sysc";
+                       ti,hwmods = "slimbus2";
+                       reg = <0x76000 0x4>,
+                             <0x76010 0x4>;
+                       reg-names = "rev", "sysc";
+                       ti,sysc-mask = <SYSC_OMAP4_SOFTRESET>;
+                       ti,sysc-sidle = <SYSC_IDLE_FORCE>,
+                                       <SYSC_IDLE_NO>,
+                                       <SYSC_IDLE_SMART>,
+                                       <SYSC_IDLE_SMART_WKUP>;
+                       /* Domains (V, P, C): core, l4per_pwrdm, l4_per_clkdm */
+                       clocks = <&l4_per_clkctrl OMAP4_SLIMBUS2_CLKCTRL 0>;
+                       clock-names = "fck";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x76000 0x1000>;
+
+                       /* No child device binding or driver in mainline */
+               };
+
+               target-module@78000 {                   /* 0x48078000, ap 41 1a.0 */
+                       compatible = "ti,sysc-omap2", "ti,sysc";
+                       ti,hwmods = "elm";
+                       reg = <0x78000 0x4>,
+                             <0x78010 0x4>,
+                             <0x78014 0x4>;
+                       reg-names = "rev", "sysc", "syss";
+                       ti,sysc-mask = <(SYSC_OMAP2_CLOCKACTIVITY |
+                                        SYSC_OMAP2_SOFTRESET |
+                                        SYSC_OMAP2_AUTOIDLE)>;
+                       ti,sysc-sidle = <SYSC_IDLE_FORCE>,
+                                       <SYSC_IDLE_NO>,
+                                       <SYSC_IDLE_SMART>;
+                       ti,syss-mask = <1>;
+                       /* Domains (V, P, C): core, l4per_pwrdm, l4_per_clkdm */
+                       clocks = <&l4_per_clkctrl OMAP4_ELM_CLKCTRL 0>;
+                       clock-names = "fck";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x78000 0x1000>;
+
+                       elm: elm@0 {
+                               compatible = "ti,am3352-elm";
+                               reg = <0x0 0x2000>;
+                               interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>;
+                               status = "disabled";
+                       };
+               };
+
+               target-module@86000 {                   /* 0x48086000, ap 43 24.0 */
+                       compatible = "ti,sysc-omap2-timer", "ti,sysc";
+                       ti,hwmods = "timer10";
+                       reg = <0x86000 0x4>,
+                             <0x86010 0x4>,
+                             <0x86014 0x4>;
+                       reg-names = "rev", "sysc", "syss";
+                       ti,sysc-mask = <(SYSC_OMAP2_CLOCKACTIVITY |
+                                        SYSC_OMAP2_EMUFREE |
+                                        SYSC_OMAP2_ENAWAKEUP |
+                                        SYSC_OMAP2_SOFTRESET |
+                                        SYSC_OMAP2_AUTOIDLE)>;
+                       ti,sysc-sidle = <SYSC_IDLE_FORCE>,
+                                       <SYSC_IDLE_NO>,
+                                       <SYSC_IDLE_SMART>;
+                       ti,syss-mask = <1>;
+                       /* Domains (V, P, C): core, l4per_pwrdm, l4_per_clkdm */
+                       clocks = <&l4_per_clkctrl OMAP4_TIMER10_CLKCTRL 0>;
+                       clock-names = "fck";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x86000 0x1000>;
+
+                       timer10: timer@0 {
+                               compatible = "ti,omap3430-timer";
+                               reg = <0x0 0x80>;
+                               clocks = <&l4_per_clkctrl OMAP4_TIMER10_CLKCTRL 24>;
+                               clock-names = "fck";
+                               interrupts = <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>;
+                               ti,timer-pwm;
+                       };
+               };
+
+               target-module@88000 {                   /* 0x48088000, ap 45 2e.0 */
+                       compatible = "ti,sysc-omap4-timer", "ti,sysc";
+                       ti,hwmods = "timer11";
+                       reg = <0x88000 0x4>,
+                             <0x88010 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, l4per_pwrdm, l4_per_clkdm */
+                       clocks = <&l4_per_clkctrl OMAP4_TIMER11_CLKCTRL 0>;
+                       clock-names = "fck";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x88000 0x1000>;
+
+                       timer11: timer@0 {
+                               compatible = "ti,omap4430-timer";
+                               reg = <0x0 0x80>;
+                               clocks = <&l4_per_clkctrl OMAP4_TIMER11_CLKCTRL 24>;
+                               clock-names = "fck";
+                               interrupts = <GIC_SPI 47 IRQ_TYPE_LEVEL_HIGH>;
+                               ti,timer-pwm;
+                       };
+               };
+
+               target-module@90000 {                   /* 0x48090000, ap 57 2a.0 */
+                       compatible = "ti,sysc";
+                       status = "disabled";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x90000 0x2000>;
+               };
+
+               target-module@96000 {                   /* 0x48096000, ap 37 26.0 */
+                       compatible = "ti,sysc-omap2", "ti,sysc";
+                       ti,hwmods = "mcbsp4";
+                       reg = <0x9608c 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, l4per_pwrdm, l4_per_clkdm */
+                       clocks = <&l4_per_clkctrl OMAP4_MCBSP4_CLKCTRL 0>;
+                       clock-names = "fck";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x96000 0x1000>;
+
+                       mcbsp4: mcbsp@0 {
+                               compatible = "ti,omap4-mcbsp";
+                               reg = <0x0 0xff>; /* L4 Interconnect */
+                               reg-names = "mpu";
+                               interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>;
+                               interrupt-names = "common";
+                               ti,buffer-size = <128>;
+                               dmas = <&sdma 31>,
+                                      <&sdma 32>;
+                               dma-names = "tx", "rx";
+                               status = "disabled";
+                       };
+               };
+
+               target-module@98000 {                   /* 0x48098000, ap 49 22.0 */
+                       compatible = "ti,sysc-omap4", "ti,sysc";
+                       ti,hwmods = "mcspi1";
+                       reg = <0x98000 0x4>,
+                             <0x98010 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, l4per_pwrdm, l4_per_clkdm */
+                       clocks = <&l4_per_clkctrl OMAP4_MCSPI1_CLKCTRL 0>;
+                       clock-names = "fck";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x98000 0x1000>;
+
+                       mcspi1: spi@0 {
+                               compatible = "ti,omap4-mcspi";
+                               reg = <0x0 0x200>;
+                               interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               ti,spi-num-cs = <4>;
+                               dmas = <&sdma 35>,
+                                      <&sdma 36>,
+                                      <&sdma 37>,
+                                      <&sdma 38>,
+                                      <&sdma 39>,
+                                      <&sdma 40>,
+                                      <&sdma 41>,
+                                      <&sdma 42>;
+                               dma-names = "tx0", "rx0", "tx1", "rx1",
+                                           "tx2", "rx2", "tx3", "rx3";
+                       };
+               };
+
+               target-module@9a000 {                   /* 0x4809a000, ap 51 2c.0 */
+                       compatible = "ti,sysc-omap4", "ti,sysc";
+                       ti,hwmods = "mcspi2";
+                       reg = <0x9a000 0x4>,
+                             <0x9a010 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, l4per_pwrdm, l4_per_clkdm */
+                       clocks = <&l4_per_clkctrl OMAP4_MCSPI2_CLKCTRL 0>;
+                       clock-names = "fck";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x9a000 0x1000>;
+
+                       mcspi2: spi@0 {
+                               compatible = "ti,omap4-mcspi";
+                               reg = <0x0 0x200>;
+                               interrupts = <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               ti,spi-num-cs = <2>;
+                               dmas = <&sdma 43>,
+                                      <&sdma 44>,
+                                      <&sdma 45>,
+                                      <&sdma 46>;
+                               dma-names = "tx0", "rx0", "tx1", "rx1";
+                       };
+               };
+
+               target-module@9c000 {                   /* 0x4809c000, ap 53 36.0 */
+                       compatible = "ti,sysc-omap4", "ti,sysc";
+                       ti,hwmods = "mmc1";
+                       reg = <0x9c000 0x4>,
+                             <0x9c010 0x4>;
+                       reg-names = "rev", "sysc";
+                       ti,sysc-mask = <(SYSC_OMAP4_FREEEMU |
+                                        SYSC_OMAP4_SOFTRESET)>;
+                       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>,
+                                       <SYSC_IDLE_SMART_WKUP>;
+                       /* Domains (V, P, C): core, l3init_pwrdm, l3_init_clkdm */
+                       clocks = <&l3_init_clkctrl OMAP4_MMC1_CLKCTRL 0>;
+                       clock-names = "fck";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x9c000 0x1000>;
+
+                       mmc1: mmc@0 {
+                               compatible = "ti,omap4-hsmmc";
+                               reg = <0x0 0x400>;
+                               interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
+                               ti,dual-volt;
+                               ti,needs-special-reset;
+                               dmas = <&sdma 61>, <&sdma 62>;
+                               dma-names = "tx", "rx";
+                               pbias-supply = <&pbias_mmc_reg>;
+                       };
+               };
+
+               target-module@9e000 {                   /* 0x4809e000, ap 55 48.0 */
+                       compatible = "ti,sysc";
+                       status = "disabled";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x9e000 0x1000>;
+               };
+
+               target-module@a2000 {                   /* 0x480a2000, ap 79 3a.0 */
+                       compatible = "ti,sysc";
+                       status = "disabled";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0xa2000 0x1000>;
+               };
+
+               target-module@a4000 {                   /* 0x480a4000, ap 59 34.0 */
+                       compatible = "ti,sysc";
+                       status = "disabled";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x00000000 0x000a4000 0x00001000>,
+                                <0x00001000 0x000a5000 0x00001000>;
+               };
+
+               target-module@a8000 {                   /* 0x480a8000, ap 61 3e.0 */
+                       compatible = "ti,sysc";
+                       status = "disabled";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0xa8000 0x4000>;
+               };
+
+               target-module@ad000 {                   /* 0x480ad000, ap 63 50.0 */
+                       compatible = "ti,sysc-omap4", "ti,sysc";
+                       ti,hwmods = "mmc3";
+                       reg = <0xad000 0x4>,
+                             <0xad010 0x4>;
+                       reg-names = "rev", "sysc";
+                       ti,sysc-mask = <(SYSC_OMAP4_FREEEMU |
+                                        SYSC_OMAP4_SOFTRESET)>;
+                       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>,
+                                       <SYSC_IDLE_SMART_WKUP>;
+                       /* Domains (V, P, C): core, l4per_pwrdm, l4_per_clkdm */
+                       clocks = <&l4_per_clkctrl OMAP4_MMC3_CLKCTRL 0>;
+                       clock-names = "fck";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0xad000 0x1000>;
+
+                       mmc3: mmc@0 {
+                               compatible = "ti,omap4-hsmmc";
+                               reg = <0x0 0x400>;
+                               interrupts = <GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH>;
+                               ti,needs-special-reset;
+                               dmas = <&sdma 77>, <&sdma 78>;
+                               dma-names = "tx", "rx";
+                       };
+               };
+
+               target-module@b0000 {                   /* 0x480b0000, ap 47 40.0 */
+                       compatible = "ti,sysc";
+                       status = "disabled";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0xb0000 0x1000>;
+               };
+
+               target-module@b2000 {                   /* 0x480b2000, ap 65 3c.0 */
+                       compatible = "ti,sysc-omap2", "ti,sysc";
+                       ti,hwmods = "hdq1w";
+                       reg = <0xb2000 0x4>,
+                             <0xb2014 0x4>,
+                             <0xb2018 0x4>;
+                       reg-names = "rev", "sysc", "syss";
+                       ti,sysc-mask = <(SYSC_OMAP2_SOFTRESET |
+                                        SYSC_OMAP2_AUTOIDLE)>;
+                       ti,syss-mask = <1>;
+                       ti,no-reset-on-init;
+                       /* Domains (V, P, C): core, l4per_pwrdm, l4_per_clkdm */
+                       clocks = <&l4_per_clkctrl OMAP4_HDQ1W_CLKCTRL 0>;
+                       clock-names = "fck";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0xb2000 0x1000>;
+
+                       hdqw1w: 1w@0 {
+                               compatible = "ti,omap3-1w";
+                               reg = <0x0 0x1000>;
+                               interrupts = <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>;
+                       };
+               };
+
+               target-module@b4000 {                   /* 0x480b4000, ap 67 46.0 */
+                       compatible = "ti,sysc-omap4", "ti,sysc";
+                       ti,hwmods = "mmc2";
+                       reg = <0xb4000 0x4>,
+                             <0xb4010 0x4>;
+                       reg-names = "rev", "sysc";
+                       ti,sysc-mask = <(SYSC_OMAP4_FREEEMU |
+                                        SYSC_OMAP4_SOFTRESET)>;
+                       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>,
+                                       <SYSC_IDLE_SMART_WKUP>;
+                       /* Domains (V, P, C): core, l3init_pwrdm, l3_init_clkdm */
+                       clocks = <&l3_init_clkctrl OMAP4_MMC2_CLKCTRL 0>;
+                       clock-names = "fck";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0xb4000 0x1000>;
+
+                       mmc2: mmc@0 {
+                               compatible = "ti,omap4-hsmmc";
+                               reg = <0x0 0x400>;
+                               interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
+                               ti,needs-special-reset;
+                               dmas = <&sdma 47>, <&sdma 48>;
+                               dma-names = "tx", "rx";
+                       };
+               };
+
+               target-module@b8000 {                   /* 0x480b8000, ap 69 58.0 */
+                       compatible = "ti,sysc-omap4", "ti,sysc";
+                       ti,hwmods = "mcspi3";
+                       reg = <0xb8000 0x4>,
+                             <0xb8010 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, l4per_pwrdm, l4_per_clkdm */
+                       clocks = <&l4_per_clkctrl OMAP4_MCSPI3_CLKCTRL 0>;
+                       clock-names = "fck";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0xb8000 0x1000>;
+
+                       mcspi3: spi@0 {
+                               compatible = "ti,omap4-mcspi";
+                               reg = <0x0 0x200>;
+                               interrupts = <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               ti,spi-num-cs = <2>;
+                               dmas = <&sdma 15>, <&sdma 16>;
+                               dma-names = "tx0", "rx0";
+                       };
+               };
+
+               target-module@ba000 {                   /* 0x480ba000, ap 71 32.0 */
+                       compatible = "ti,sysc-omap4", "ti,sysc";
+                       ti,hwmods = "mcspi4";
+                       reg = <0xba000 0x4>,
+                             <0xba010 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, l4per_pwrdm, l4_per_clkdm */
+                       clocks = <&l4_per_clkctrl OMAP4_MCSPI4_CLKCTRL 0>;
+                       clock-names = "fck";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0xba000 0x1000>;
+
+                       mcspi4: spi@0 {
+                               compatible = "ti,omap4-mcspi";
+                               reg = <0x0 0x200>;
+                               interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               ti,spi-num-cs = <1>;
+                               dmas = <&sdma 70>, <&sdma 71>;
+                               dma-names = "tx0", "rx0";
+                       };
+               };
+
+               target-module@d1000 {                   /* 0x480d1000, ap 73 44.0 */
+                       compatible = "ti,sysc-omap4", "ti,sysc";
+                       ti,hwmods = "mmc4";
+                       reg = <0xd1000 0x4>,
+                             <0xd1010 0x4>;
+                       reg-names = "rev", "sysc";
+                       ti,sysc-mask = <(SYSC_OMAP4_FREEEMU |
+                                        SYSC_OMAP4_SOFTRESET)>;
+                       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>,
+                                       <SYSC_IDLE_SMART_WKUP>;
+                       /* Domains (V, P, C): core, l4per_pwrdm, l4_per_clkdm */
+                       clocks = <&l4_per_clkctrl OMAP4_MMC4_CLKCTRL 0>;
+                       clock-names = "fck";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0xd1000 0x1000>;
+
+                       mmc4: mmc@0 {
+                               compatible = "ti,omap4-hsmmc";
+                               reg = <0x0 0x400>;
+                               interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>;
+                               ti,needs-special-reset;
+                               dmas = <&sdma 57>, <&sdma 58>;
+                               dma-names = "tx", "rx";
+                       };
+               };
+
+               target-module@d5000 {                   /* 0x480d5000, ap 75 4e.0 */
+                       compatible = "ti,sysc-omap4", "ti,sysc";
+                       ti,hwmods = "mmc5";
+                       reg = <0xd5000 0x4>,
+                             <0xd5010 0x4>;
+                       reg-names = "rev", "sysc";
+                       ti,sysc-mask = <(SYSC_OMAP4_FREEEMU |
+                                        SYSC_OMAP4_SOFTRESET)>;
+                       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>,
+                                       <SYSC_IDLE_SMART_WKUP>;
+                       /* Domains (V, P, C): core, l4per_pwrdm, l4_per_clkdm */
+                       clocks = <&l4_per_clkctrl OMAP4_MMC5_CLKCTRL 0>;
+                       clock-names = "fck";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0xd5000 0x1000>;
+
+                       mmc5: mmc@0 {
+                               compatible = "ti,omap4-hsmmc";
+                               reg = <0x0 0x400>;
+                               interrupts = <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>;
+                               ti,needs-special-reset;
+                               dmas = <&sdma 59>, <&sdma 60>;
+                               dma-names = "tx", "rx";
+                       };
+               };
+       };
+
+       segment@200000 {                                        /* 0x48200000 */
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges = <0x00150000 0x00350000 0x001000>,      /* ap 77 */
+                        <0x00151000 0x00351000 0x001000>;      /* ap 78 */
+
+               target-module@150000 {                  /* 0x48350000, ap 77 4c.0 */
+                       compatible = "ti,sysc-omap2", "ti,sysc";
+                       ti,hwmods = "i2c4";
+                       reg = <0x150000 0x8>,
+                             <0x150010 0x8>,
+                             <0x150090 0x8>;
+                       reg-names = "rev", "sysc", "syss";
+                       ti,sysc-mask = <(SYSC_OMAP2_CLOCKACTIVITY |
+                                        SYSC_OMAP2_ENAWAKEUP |
+                                        SYSC_OMAP2_SOFTRESET |
+                                        SYSC_OMAP2_AUTOIDLE)>;
+                       ti,sysc-sidle = <SYSC_IDLE_FORCE>,
+                                       <SYSC_IDLE_NO>,
+                                       <SYSC_IDLE_SMART>,
+                                       <SYSC_IDLE_SMART_WKUP>;
+                       ti,syss-mask = <1>;
+                       /* Domains (V, P, C): core, l4per_pwrdm, l4_per_clkdm */
+                       clocks = <&l4_per_clkctrl OMAP4_I2C4_CLKCTRL 0>;
+                       clock-names = "fck";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x150000 0x1000>;
+
+                       i2c4: i2c@0 {
+                               compatible = "ti,omap4-i2c";
+                               reg = <0x0 0x100>;
+                               interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                       };
+               };
+       };
+};
+
index 5501d1b..27895c1 100644 (file)
@@ -5,6 +5,7 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
+#include <dt-bindings/input/input.h>
 #include "elpida_ecb240abacn.dtsi"
 
 / {
                };
        };
 
+       gpio_keys: gpio_keys {
+               compatible = "gpio-keys";
+               pinctrl-names = "default";
+               pinctrl-0 = <
+                       &button_pins
+               >;
+
+               buttonS2 {
+                       label = "button S2";
+                       gpios = <&gpio4 25 GPIO_ACTIVE_LOW>;    /* gpio_121 */
+                       linux,code = <BTN_0>;
+                       wakeup-source;
+               };
+       };
+
        sound: sound {
                compatible = "ti,abe-twl6040";
                ti,model = "PandaBoard";
                        OMAP4_IOPAD(0x152, PIN_INPUT_PULLUP | MUX_MODE0)        /* sdmmc5_dat3.sdmmc5_dat3 */
                >;
        };
+
+       button_pins: pinmux_button_pins {
+               pinctrl-single,pins = <
+                       OMAP4_IOPAD(0x114, PIN_INPUT_PULLUP | MUX_MODE3)        /* gpio_121 */
+               >;
+       };
 };
 
 &omap4_pmx_wkup {
                compatible = "ti,wl1271";
                reg = <2>;
                interrupt-parent = <&gpio2>;
-               interrupts = <21 IRQ_TYPE_LEVEL_HIGH>; /* gpio 53 */
+               interrupts = <21 IRQ_TYPE_EDGE_RISING>; /* gpio 53 */
                ref-clock-frequency = <38400000>;
        };
 };
index 940fe4f..19d02df 100644 (file)
                        OMAP4_IOPAD(0x0f6, PIN_OUTPUT | MUX_MODE3)      /* gpio_110 */
                >;
        };
+
+       button_pins: pinmux_button_pins {
+               pinctrl-single,pins = <
+                       OMAP4_IOPAD(0x11b, PIN_INPUT_PULLUP | MUX_MODE3) /* gpio_113 */
+               >;
+       };
 };
 
 &led_wkgpio_pins {
        };
 };
 
-&gpio1 {
+&gpio_keys {
+       buttonS2 {
+               gpios = <&gpio4 17 GPIO_ACTIVE_LOW>; /* gpio_113 */
+       };
+};
+
+&gpio1_target {
         ti,no-reset-on-init;
 };
index 280d92d..490726b 100644 (file)
                compatible = "ti,wl1281";
                reg = <2>;
                interrupt-parent = <&gpio1>;
-               interrupts = <21 IRQ_TYPE_LEVEL_HIGH>; /* gpio 53 */
+               interrupts = <21 IRQ_TYPE_EDGE_RISING>; /* gpio 53 */
                ref-clock-frequency = <26000000>;
                tcxo-clock-frequency = <26000000>;
        };
index 1c5f6f3..8789234 100644 (file)
@@ -72,7 +72,7 @@
                compatible = "ti,wl1271";
                reg = <2>;
                interrupt-parent = <&gpio2>;
-               interrupts = <9 IRQ_TYPE_LEVEL_HIGH>; /* gpio 41 */
+               interrupts = <9 IRQ_TYPE_EDGE_RISING>; /* gpio 41 */
                ref-clock-frequency = <38400000>;
        };
 };
index e554b6e..1a96d43 100644 (file)
                interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>,
                             <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>;
 
-               l4_cfg: l4@4a000000 {
-                       compatible = "ti,omap4-l4-cfg", "simple-bus";
-                       #address-cells = <1>;
-                       #size-cells = <1>;
-                       ranges = <0 0x4a000000 0x1000000>;
-
-                       cm1: cm1@4000 {
-                               compatible = "ti,omap4-cm1", "simple-bus";
-                               reg = <0x4000 0x2000>;
-                               #address-cells = <1>;
-                               #size-cells = <1>;
-                               ranges = <0 0x4000 0x2000>;
-
-                               cm1_clocks: clocks {
-                                       #address-cells = <1>;
-                                       #size-cells = <0>;
-                               };
-
-                               cm1_clockdomains: clockdomains {
-                               };
-                       };
-
-                       cm2: cm2@8000 {
-                               compatible = "ti,omap4-cm2", "simple-bus";
-                               reg = <0x8000 0x2000>;
-                               #address-cells = <1>;
-                               #size-cells = <1>;
-                               ranges = <0 0x8000 0x2000>;
-
-                               cm2_clocks: clocks {
-                                       #address-cells = <1>;
-                                       #size-cells = <0>;
-                               };
-
-                               cm2_clockdomains: clockdomains {
-                               };
-                       };
-
-                       omap4_scm_core: scm@2000 {
-                               compatible = "ti,omap4-scm-core", "simple-bus";
-                               reg = <0x2000 0x1000>;
-                               #address-cells = <1>;
-                               #size-cells = <1>;
-                               ranges = <0 0x2000 0x1000>;
-                               ti,hwmods = "ctrl_module_core";
-
-                               scm_conf: scm_conf@0 {
-                                       compatible = "syscon";
-                                       reg = <0x0 0x800>;
-                                       #address-cells = <1>;
-                                       #size-cells = <1>;
-                               };
-                       };
-
-                       omap4_padconf_core: scm@100000 {
-                               compatible = "ti,omap4-scm-padconf-core",
-                                            "simple-bus";
-                               reg = <0x100000 0x1000>;
-                               #address-cells = <1>;
-                               #size-cells = <1>;
-                               ranges = <0 0x100000 0x1000>;
-                               ti,hwmods = "ctrl_module_pad_core";
-
-                               omap4_pmx_core: pinmux@40 {
-                                       compatible = "ti,omap4-padconf",
-                                                    "pinctrl-single";
-                                       reg = <0x40 0x0196>;
-                                       #address-cells = <1>;
-                                       #size-cells = <0>;
-                                       #pinctrl-cells = <1>;
-                                       #interrupt-cells = <1>;
-                                       interrupt-controller;
-                                       pinctrl-single,register-width = <16>;
-                                       pinctrl-single,function-mask = <0x7fff>;
-                               };
-
-                               omap4_padconf_global: omap4_padconf_global@5a0 {
-                                       compatible = "syscon",
-                                                    "simple-bus";
-                                       reg = <0x5a0 0x170>;
-                                       #address-cells = <1>;
-                                       #size-cells = <1>;
-                                       ranges = <0 0x5a0 0x170>;
-
-                                       pbias_regulator: pbias_regulator@60 {
-                                               compatible = "ti,pbias-omap4", "ti,pbias-omap";
-                                               reg = <0x60 0x4>;
-                                               syscon = <&omap4_padconf_global>;
-                                               pbias_mmc_reg: pbias_mmc_omap4 {
-                                                       regulator-name = "pbias_mmc_omap4";
-                                                       regulator-min-microvolt = <1800000>;
-                                                       regulator-max-microvolt = <3000000>;
-                                               };
-                                       };
-                               };
-                       };
-
-                       l4_wkup: l4@300000 {
-                               compatible = "ti,omap4-l4-wkup", "simple-bus";
-                               #address-cells = <1>;
-                               #size-cells = <1>;
-                               ranges = <0 0x300000 0x40000>;
-
-                               counter32k: counter@4000 {
-                                       compatible = "ti,omap-counter32k";
-                                       reg = <0x4000 0x20>;
-                                       ti,hwmods = "counter_32k";
-                               };
-
-                               prm: prm@6000 {
-                                       compatible = "ti,omap4-prm";
-                                       reg = <0x6000 0x2000>;
-                                       interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>;
-                                       #address-cells = <1>;
-                                       #size-cells = <1>;
-                                       ranges = <0 0x6000 0x2000>;
-
-                                       prm_clocks: clocks {
-                                               #address-cells = <1>;
-                                               #size-cells = <0>;
-                                       };
-
-                                       prm_clockdomains: clockdomains {
-                                       };
-                               };
-
-                               scrm: scrm@a000 {
-                                       compatible = "ti,omap4-scrm";
-                                       reg = <0xa000 0x2000>;
-
-                                       scrm_clocks: clocks {
-                                               #address-cells = <1>;
-                                               #size-cells = <0>;
-                                       };
-
-                                       scrm_clockdomains: clockdomains {
-                                       };
-                               };
-
-                               omap4_scm_wkup: scm@c000 {
-                                       compatible = "ti,omap4-scm-wkup";
-                                       reg = <0xc000 0x1000>;
-                                       ti,hwmods = "ctrl_module_wkup";
-                               };
+               l4_wkup: interconnect@4a300000 {
+               };
 
-                               omap4_padconf_wkup: padconf@1e000 {
-                                       compatible = "ti,omap4-scm-padconf-wkup",
-                                                    "simple-bus";
-                                       reg = <0x1e000 0x1000>;
-                                       #address-cells = <1>;
-                                       #size-cells = <1>;
-                                       ranges = <0 0x1e000 0x1000>;
-                                       ti,hwmods = "ctrl_module_pad_wkup";
+               l4_cfg: interconnect@4a000000 {
+               };
 
-                                       omap4_pmx_wkup: pinmux@40 {
-                                               compatible = "ti,omap4-padconf",
-                                                            "pinctrl-single";
-                                               reg = <0x40 0x0038>;
-                                               #address-cells = <1>;
-                                               #size-cells = <0>;
-                                               #pinctrl-cells = <1>;
-                                               #interrupt-cells = <1>;
-                                               interrupt-controller;
-                                               pinctrl-single,register-width = <16>;
-                                               pinctrl-single,function-mask = <0x7fff>;
-                                       };
-                               };
-                       };
+               l4_per: interconnect@48000000 {
                };
 
                ocmcram: ocmcram@40304000 {
                        reg = <0x40304000 0xa000>; /* 40k */
                };
 
-               sdma: dma-controller@4a056000 {
-                       compatible = "ti,omap4430-sdma";
-                       reg = <0x4a056000 0x1000>;
-                       interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>,
-                                    <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>,
-                                    <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>,
-                                    <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
-                       #dma-cells = <1>;
-                       dma-channels = <32>;
-                       dma-requests = <127>;
-                       ti,hwmods = "dma_system";
-               };
-
-               gpio1: gpio@4a310000 {
-                       compatible = "ti,omap4-gpio";
-                       reg = <0x4a310000 0x200>;
-                       interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
-                       ti,hwmods = "gpio1";
-                       ti,gpio-always-on;
-                       gpio-controller;
-                       #gpio-cells = <2>;
-                       interrupt-controller;
-                       #interrupt-cells = <2>;
-               };
-
-               gpio2: gpio@48055000 {
-                       compatible = "ti,omap4-gpio";
-                       reg = <0x48055000 0x200>;
-                       interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
-                       ti,hwmods = "gpio2";
-                       gpio-controller;
-                       #gpio-cells = <2>;
-                       interrupt-controller;
-                       #interrupt-cells = <2>;
-               };
-
-               gpio3: gpio@48057000 {
-                       compatible = "ti,omap4-gpio";
-                       reg = <0x48057000 0x200>;
-                       interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
-                       ti,hwmods = "gpio3";
-                       gpio-controller;
-                       #gpio-cells = <2>;
-                       interrupt-controller;
-                       #interrupt-cells = <2>;
-               };
-
-               gpio4: gpio@48059000 {
-                       compatible = "ti,omap4-gpio";
-                       reg = <0x48059000 0x200>;
-                       interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
-                       ti,hwmods = "gpio4";
-                       gpio-controller;
-                       #gpio-cells = <2>;
-                       interrupt-controller;
-                       #interrupt-cells = <2>;
-               };
-
-               gpio5: gpio@4805b000 {
-                       compatible = "ti,omap4-gpio";
-                       reg = <0x4805b000 0x200>;
-                       interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
-                       ti,hwmods = "gpio5";
-                       gpio-controller;
-                       #gpio-cells = <2>;
-                       interrupt-controller;
-                       #interrupt-cells = <2>;
-               };
-
-               gpio6: gpio@4805d000 {
-                       compatible = "ti,omap4-gpio";
-                       reg = <0x4805d000 0x200>;
-                       interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
-                       ti,hwmods = "gpio6";
-                       gpio-controller;
-                       #gpio-cells = <2>;
-                       interrupt-controller;
-                       #interrupt-cells = <2>;
-               };
-
-               target-module@48076000 {
-                       compatible = "ti,sysc-omap4", "ti,sysc";
-                       ti,hwmods = "slimbus2";
-                       reg = <0x48076000 0x4>,
-                             <0x48076010 0x4>;
-                       reg-names = "rev", "sysc";
-                       ti,sysc-mask = <SYSC_OMAP4_SOFTRESET>;
-                       ti,sysc-sidle = <SYSC_IDLE_FORCE>,
-                                       <SYSC_IDLE_NO>,
-                                       <SYSC_IDLE_SMART>,
-                                       <SYSC_IDLE_SMART_WKUP>;
-                       clocks = <&l4_per_clkctrl OMAP4_SLIMBUS2_CLKCTRL 0>;
-                       clock-names = "fck";
-                       #address-cells = <1>;
-                       #size-cells = <1>;
-                       ranges = <0 0x48076000 0x001000>;
-
-                       /* No child device binding or driver in mainline */
-               };
-
-               elm: elm@48078000 {
-                       compatible = "ti,am3352-elm";
-                       reg = <0x48078000 0x2000>;
-                       interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>;
-                       ti,hwmods = "elm";
-                       status = "disabled";
-               };
-
                gpmc: gpmc@50000000 {
                        compatible = "ti,omap4430-gpmc";
                        reg = <0x50000000 0x1000>;
                        #gpio-cells = <2>;
                };
 
-               uart1: serial@4806a000 {
-                       compatible = "ti,omap4-uart";
-                       reg = <0x4806a000 0x100>;
-                       interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>;
-                       ti,hwmods = "uart1";
-                       clock-frequency = <48000000>;
-               };
-
-               uart2: serial@4806c000 {
-                       compatible = "ti,omap4-uart";
-                       reg = <0x4806c000 0x100>;
-                       interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
-                       ti,hwmods = "uart2";
-                       clock-frequency = <48000000>;
-               };
-
-               uart3: serial@48020000 {
-                       compatible = "ti,omap4-uart";
-                       reg = <0x48020000 0x100>;
-                       interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
-                       ti,hwmods = "uart3";
-                       clock-frequency = <48000000>;
-               };
-
-               uart4: serial@4806e000 {
-                       compatible = "ti,omap4-uart";
-                       reg = <0x4806e000 0x100>;
-                       interrupts = <GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
-                       ti,hwmods = "uart4";
-                       clock-frequency = <48000000>;
-               };
-
-               target-module@4a0db000 {
-                       compatible = "ti,sysc-omap4-sr", "ti,sysc";
-                       ti,hwmods = "smartreflex_iva";
-                       reg = <0x4a0db038 0x4>;
-                       reg-names = "sysc";
-                       ti,sysc-mask = <SYSC_OMAP3_SR_ENAWAKEUP>;
-                       ti,sysc-sidle = <SYSC_IDLE_FORCE>,
-                                       <SYSC_IDLE_NO>,
-                                       <SYSC_IDLE_SMART>,
-                                       <SYSC_IDLE_SMART_WKUP>;
-                       clocks = <&l4_ao_clkctrl OMAP4_SMARTREFLEX_IVA_CLKCTRL 0>;
-                       clock-names = "fck";
-                       #address-cells = <1>;
-                       #size-cells = <1>;
-                       ranges = <0 0x4a0db000 0x001000>;
-
-                       smartreflex_iva: smartreflex@0 {
-                               compatible = "ti,omap4-smartreflex-iva";
-                               reg = <0 0x80>;
-                               interrupts = <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>;
-                       };
-               };
-
-               target-module@4a0dd000 {
-                       compatible = "ti,sysc-omap4-sr", "ti,sysc";
-                       ti,hwmods = "smartreflex_core";
-                       reg = <0x4a0dd038 0x4>;
-                       reg-names = "sysc";
-                       ti,sysc-mask = <SYSC_OMAP3_SR_ENAWAKEUP>;
-                       ti,sysc-sidle = <SYSC_IDLE_FORCE>,
-                                       <SYSC_IDLE_NO>,
-                                       <SYSC_IDLE_SMART>,
-                                       <SYSC_IDLE_SMART_WKUP>;
-                       clocks = <&l4_ao_clkctrl OMAP4_SMARTREFLEX_CORE_CLKCTRL 0>;
-                       clock-names = "fck";
-                       #address-cells = <1>;
-                       #size-cells = <1>;
-                       ranges = <0 0x4a0dd000 0x001000>;
-
-                       smartreflex_core: smartreflex@0 {
-                               compatible = "ti,omap4-smartreflex-core";
-                               reg = <0 0x80>;
-                               interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
-                       };
-               };
-
-               target-module@4a0d9000 {
-                       compatible = "ti,sysc-omap4-sr", "ti,sysc";
-                       ti,hwmods = "smartreflex_mpu";
-                       reg = <0x4a0d9038 0x4>;
-                       reg-names = "sysc";
-                       ti,sysc-mask = <SYSC_OMAP3_SR_ENAWAKEUP>;
-                       ti,sysc-sidle = <SYSC_IDLE_FORCE>,
-                                       <SYSC_IDLE_NO>,
-                                       <SYSC_IDLE_SMART>,
-                                       <SYSC_IDLE_SMART_WKUP>;
-                       clocks = <&l4_ao_clkctrl OMAP4_SMARTREFLEX_MPU_CLKCTRL 0>;
-                       clock-names = "fck";
-                       #address-cells = <1>;
-                       #size-cells = <1>;
-                       ranges = <0 0x4a0d9000 0x001000>;
-
-                       smartreflex_mpu: smartreflex@0 {
-                               compatible = "ti,omap4-smartreflex-mpu";
-                               reg = <0 0x80>;
-                               interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>;
-                       };
-               };
-
-               hwspinlock: spinlock@4a0f6000 {
-                       compatible = "ti,omap4-hwspinlock";
-                       reg = <0x4a0f6000 0x1000>;
-                       ti,hwmods = "spinlock";
-                       #hwlock-cells = <1>;
-               };
-
-               i2c1: i2c@48070000 {
-                       compatible = "ti,omap4-i2c";
-                       reg = <0x48070000 0x100>;
-                       interrupts = <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>;
-                       #address-cells = <1>;
-                       #size-cells = <0>;
-                       ti,hwmods = "i2c1";
-               };
-
-               i2c2: i2c@48072000 {
-                       compatible = "ti,omap4-i2c";
-                       reg = <0x48072000 0x100>;
-                       interrupts = <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>;
-                       #address-cells = <1>;
-                       #size-cells = <0>;
-                       ti,hwmods = "i2c2";
-               };
-
-               i2c3: i2c@48060000 {
-                       compatible = "ti,omap4-i2c";
-                       reg = <0x48060000 0x100>;
-                       interrupts = <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>;
-                       #address-cells = <1>;
-                       #size-cells = <0>;
-                       ti,hwmods = "i2c3";
-               };
-
-               i2c4: i2c@48350000 {
-                       compatible = "ti,omap4-i2c";
-                       reg = <0x48350000 0x100>;
-                       interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>;
-                       #address-cells = <1>;
-                       #size-cells = <0>;
-                       ti,hwmods = "i2c4";
-               };
-
-               mcspi1: spi@48098000 {
-                       compatible = "ti,omap4-mcspi";
-                       reg = <0x48098000 0x200>;
-                       interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>;
-                       #address-cells = <1>;
-                       #size-cells = <0>;
-                       ti,hwmods = "mcspi1";
-                       ti,spi-num-cs = <4>;
-                       dmas = <&sdma 35>,
-                              <&sdma 36>,
-                              <&sdma 37>,
-                              <&sdma 38>,
-                              <&sdma 39>,
-                              <&sdma 40>,
-                              <&sdma 41>,
-                              <&sdma 42>;
-                       dma-names = "tx0", "rx0", "tx1", "rx1",
-                                   "tx2", "rx2", "tx3", "rx3";
-               };
-
-               mcspi2: spi@4809a000 {
-                       compatible = "ti,omap4-mcspi";
-                       reg = <0x4809a000 0x200>;
-                       interrupts = <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>;
-                       #address-cells = <1>;
-                       #size-cells = <0>;
-                       ti,hwmods = "mcspi2";
-                       ti,spi-num-cs = <2>;
-                       dmas = <&sdma 43>,
-                              <&sdma 44>,
-                              <&sdma 45>,
-                              <&sdma 46>;
-                       dma-names = "tx0", "rx0", "tx1", "rx1";
-               };
-
-               hdqw1w: 1w@480b2000 {
-                       compatible = "ti,omap3-1w";
-                       reg = <0x480b2000 0x1000>;
-                       interrupts = <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>;
-                       ti,hwmods = "hdq1w";
-               };
-
-               mcspi3: spi@480b8000 {
-                       compatible = "ti,omap4-mcspi";
-                       reg = <0x480b8000 0x200>;
-                       interrupts = <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>;
-                       #address-cells = <1>;
-                       #size-cells = <0>;
-                       ti,hwmods = "mcspi3";
-                       ti,spi-num-cs = <2>;
-                       dmas = <&sdma 15>, <&sdma 16>;
-                       dma-names = "tx0", "rx0";
-               };
-
-               mcspi4: spi@480ba000 {
-                       compatible = "ti,omap4-mcspi";
-                       reg = <0x480ba000 0x200>;
-                       interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
-                       #address-cells = <1>;
-                       #size-cells = <0>;
-                       ti,hwmods = "mcspi4";
-                       ti,spi-num-cs = <1>;
-                       dmas = <&sdma 70>, <&sdma 71>;
-                       dma-names = "tx0", "rx0";
-               };
-
-               mmc1: mmc@4809c000 {
-                       compatible = "ti,omap4-hsmmc";
-                       reg = <0x4809c000 0x400>;
-                       interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
-                       ti,hwmods = "mmc1";
-                       ti,dual-volt;
-                       ti,needs-special-reset;
-                       dmas = <&sdma 61>, <&sdma 62>;
-                       dma-names = "tx", "rx";
-                       pbias-supply = <&pbias_mmc_reg>;
-               };
-
-               mmc2: mmc@480b4000 {
-                       compatible = "ti,omap4-hsmmc";
-                       reg = <0x480b4000 0x400>;
-                       interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
-                       ti,hwmods = "mmc2";
-                       ti,needs-special-reset;
-                       dmas = <&sdma 47>, <&sdma 48>;
-                       dma-names = "tx", "rx";
-               };
-
-               mmc3: mmc@480ad000 {
-                       compatible = "ti,omap4-hsmmc";
-                       reg = <0x480ad000 0x400>;
-                       interrupts = <GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH>;
-                       ti,hwmods = "mmc3";
-                       ti,needs-special-reset;
-                       dmas = <&sdma 77>, <&sdma 78>;
-                       dma-names = "tx", "rx";
-               };
-
-               mmc4: mmc@480d1000 {
-                       compatible = "ti,omap4-hsmmc";
-                       reg = <0x480d1000 0x400>;
-                       interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>;
-                       ti,hwmods = "mmc4";
-                       ti,needs-special-reset;
-                       dmas = <&sdma 57>, <&sdma 58>;
-                       dma-names = "tx", "rx";
-               };
-
-               mmc5: mmc@480d5000 {
-                       compatible = "ti,omap4-hsmmc";
-                       reg = <0x480d5000 0x400>;
-                       interrupts = <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>;
-                       ti,hwmods = "mmc5";
-                       ti,needs-special-reset;
-                       dmas = <&sdma 59>, <&sdma 60>;
-                       dma-names = "tx", "rx";
-               };
-
-               hsi: hsi@4a058000 {
-                       compatible = "ti,omap4-hsi";
-                       reg = <0x4a058000 0x4000>,
-                             <0x4a05c000 0x1000>;
-                       reg-names = "sys", "gdd";
-                       ti,hwmods = "hsi";
-
-                       clocks = <&l3_init_clkctrl OMAP4_HSI_CLKCTRL 0>;
-                       clock-names = "hsi_fck";
-
-                       interrupts = <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
-                       interrupt-names = "gdd_mpu";
-
-                       #address-cells = <1>;
-                       #size-cells = <1>;
-                       ranges = <0 0x4a058000 0x4000>;
-
-                       hsi_port1: hsi-port@2000 {
-                               compatible = "ti,omap4-hsi-port";
-                               reg = <0x2000 0x800>,
-                                     <0x2800 0x800>;
-                               reg-names = "tx", "rx";
-                               interrupts = <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>;
-                       };
-
-                       hsi_port2: hsi-port@3000 {
-                               compatible = "ti,omap4-hsi-port";
-                               reg = <0x3000 0x800>,
-                                     <0x3800 0x800>;
-                               reg-names = "tx", "rx";
-                               interrupts = <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>;
-                       };
-               };
-
                mmu_dsp: mmu@4a066000 {
                        compatible = "ti,omap4-iommu";
                        reg = <0x4a066000 0x100>;
                        #iommu-cells = <0>;
                        ti,iommu-bus-err-back;
                };
-
-               wdt2: wdt@4a314000 {
-                       compatible = "ti,omap4-wdt", "ti,omap3-wdt";
-                       reg = <0x4a314000 0x80>;
-                       interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>;
-                       ti,hwmods = "wd_timer2";
-               };
-
-               wdt3: wdt@40130000 {
-                       compatible = "ti,omap4-wdt", "ti,omap3-wdt";
-                       reg = <0x40130000 0x80>, /* MPU private access */
-                             <0x49030000 0x80>; /* L3 Interconnect */
-                       interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
+               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 {
                         */
                };
 
-               mcbsp4: mcbsp@48096000 {
-                       compatible = "ti,omap4-mcbsp";
-                       reg = <0x48096000 0xff>; /* L4 Interconnect */
-                       reg-names = "mpu";
-                       interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>;
-                       interrupt-names = "common";
-                       ti,buffer-size = <128>;
-                       ti,hwmods = "mcbsp4";
-                       dmas = <&sdma 31>,
-                              <&sdma 32>;
-                       dma-names = "tx", "rx";
-                       status = "disabled";
-               };
-
-               keypad: keypad@4a31c000 {
-                       compatible = "ti,omap4-keypad";
-                       reg = <0x4a31c000 0x80>;
-                       interrupts = <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>;
-                       reg-names = "mpu";
-                       ti,hwmods = "kbd";
-               };
-
                dmm@4e000000 {
                        compatible = "ti,omap4-dmm";
                        reg = <0x4e000000 0x800>;
                        hw-caps-temp-alert;
                };
 
-               ocp2scp@4a0ad000 {
-                       compatible = "ti,omap-ocp2scp";
-                       reg = <0x4a0ad000 0x1f>;
-                       #address-cells = <1>;
-                       #size-cells = <1>;
-                       ranges;
-                       ti,hwmods = "ocp2scp_usb_phy";
-                       usb2_phy: usb2phy@4a0ad080 {
-                               compatible = "ti,omap-usb2";
-                               reg = <0x4a0ad080 0x58>;
-                               ctrl-module = <&omap_control_usb2phy>;
-                               clocks = <&usb_phy_cm_clk32k>;
-                               clock-names = "wkupclk";
-                               #phy-cells = <0>;
-                       };
-               };
-
-               mailbox: mailbox@4a0f4000 {
-                       compatible = "ti,omap4-mailbox";
-                       reg = <0x4a0f4000 0x200>;
-                       interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
-                       ti,hwmods = "mailbox";
-                       #mbox-cells = <1>;
-                       ti,mbox-num-users = <3>;
-                       ti,mbox-num-fifos = <8>;
-                       mbox_ipu: mbox_ipu {
-                               ti,mbox-tx = <0 0 0>;
-                               ti,mbox-rx = <1 0 0>;
-                       };
-                       mbox_dsp: mbox_dsp {
-                               ti,mbox-tx = <3 0 0>;
-                               ti,mbox-rx = <2 0 0>;
-                       };
-               };
-
-               target-module@4a10a000 {
-                       compatible = "ti,sysc-omap4", "ti,sysc";
-                       ti,hwmods = "fdif";
-                       reg = <0x4a10a000 0x4>,
-                             <0x4a10a010 0x4>;
-                       reg-names = "rev", "sysc";
-                       ti,sysc-mask = <SYSC_OMAP4_SOFTRESET>;
-                       ti,sysc-midle = <SYSC_IDLE_FORCE>,
-                                       <SYSC_IDLE_NO>,
-                                       <SYSC_IDLE_SMART>;
-                       ti,sysc-sidle = <SYSC_IDLE_FORCE>,
-                                       <SYSC_IDLE_NO>,
-                                       <SYSC_IDLE_SMART>;
-                       ti,sysc-delay-us = <2>;
-                       clocks = <&iss_clkctrl OMAP4_FDIF_CLKCTRL 0>;
-                       clock-names = "fck";
-                       #address-cells = <1>;
-                       #size-cells = <1>;
-                       ranges = <0 0x4a10a000 0x1000>;
-
-                       /* No child device binding or driver in mainline */
-               };
-
-               timer1: timer@4a318000 {
-                       compatible = "ti,omap3430-timer";
-                       reg = <0x4a318000 0x80>;
-                       interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
-                       ti,hwmods = "timer1";
-                       ti,timer-alwon;
-                       clocks = <&l4_wkup_clkctrl OMAP4_TIMER1_CLKCTRL 24>;
-                       clock-names = "fck";
-               };
-
-               timer2: timer@48032000 {
-                       compatible = "ti,omap3430-timer";
-                       reg = <0x48032000 0x80>;
-                       interrupts = <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>;
-                       ti,hwmods = "timer2";
-               };
-
-               timer3: timer@48034000 {
-                       compatible = "ti,omap4430-timer";
-                       reg = <0x48034000 0x80>;
-                       interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>;
-                       ti,hwmods = "timer3";
-               };
-
-               timer4: timer@48036000 {
-                       compatible = "ti,omap4430-timer";
-                       reg = <0x48036000 0x80>;
-                       interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
-                       ti,hwmods = "timer4";
-               };
-
                timer5: timer@40138000 {
                        compatible = "ti,omap4430-timer";
                        reg = <0x40138000 0x80>,
                        ti,timer-dsp;
                };
 
-               timer9: timer@4803e000 {
-                       compatible = "ti,omap4430-timer";
-                       reg = <0x4803e000 0x80>;
-                       interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
-                       ti,hwmods = "timer9";
-                       ti,timer-pwm;
-               };
-
-               timer10: timer@48086000 {
-                       compatible = "ti,omap3430-timer";
-                       reg = <0x48086000 0x80>;
-                       interrupts = <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>;
-                       ti,hwmods = "timer10";
-                       ti,timer-pwm;
-               };
-
-               timer11: timer@48088000 {
-                       compatible = "ti,omap4430-timer";
-                       reg = <0x48088000 0x80>;
-                       interrupts = <GIC_SPI 47 IRQ_TYPE_LEVEL_HIGH>;
-                       ti,hwmods = "timer11";
-                       ti,timer-pwm;
-               };
-
-               usbhstll: usbhstll@4a062000 {
-                       compatible = "ti,usbhs-tll";
-                       reg = <0x4a062000 0x1000>;
-                       interrupts = <GIC_SPI 78 IRQ_TYPE_LEVEL_HIGH>;
-                       ti,hwmods = "usb_tll_hs";
-               };
-
-               usbhshost: usbhshost@4a064000 {
-                       compatible = "ti,usbhs-host";
-                       reg = <0x4a064000 0x800>;
-                       ti,hwmods = "usb_host_hs";
-                       #address-cells = <1>;
-                       #size-cells = <1>;
-                       ranges;
-                       clocks = <&init_60m_fclk>,
-                                <&xclk60mhsp1_ck>,
-                                <&xclk60mhsp2_ck>;
-                       clock-names = "refclk_60m_int",
-                                     "refclk_60m_ext_p1",
-                                     "refclk_60m_ext_p2";
-
-                       usbhsohci: ohci@4a064800 {
-                               compatible = "ti,ohci-omap3";
-                               reg = <0x4a064800 0x400>;
-                               interrupts = <GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>;
-                               remote-wakeup-connected;
-                       };
-
-                       usbhsehci: ehci@4a064c00 {
-                               compatible = "ti,ehci-omap";
-                               reg = <0x4a064c00 0x400>;
-                               interrupts = <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>;
-                       };
-               };
-
-               omap_control_usb2phy: control-phy@4a002300 {
-                       compatible = "ti,control-phy-usb2";
-                       reg = <0x4a002300 0x4>;
-                       reg-names = "power";
-               };
-
-               omap_control_usbotg: control-phy@4a00233c {
-                       compatible = "ti,control-phy-otghs";
-                       reg = <0x4a00233c 0x4>;
-                       reg-names = "otghs_control";
-               };
-
-               usb_otg_hs: usb_otg_hs@4a0ab000 {
-                       compatible = "ti,omap4-musb";
-                       reg = <0x4a0ab000 0x7ff>;
-                       interrupts = <GIC_SPI 92 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 93 IRQ_TYPE_LEVEL_HIGH>;
-                       interrupt-names = "mc", "dma";
-                       ti,hwmods = "usb_otg_hs";
-                       usb-phy = <&usb2_phy>;
-                       phys = <&usb2_phy>;
-                       phy-names = "usb2-phy";
-                       multipoint = <1>;
-                       num-eps = <16>;
-                       ram-bits = <12>;
-                       ctrl-module = <&omap_control_usbotg>;
-               };
-
                aes1: aes@4b501000 {
                        compatible = "ti,omap4-aes";
                        ti,hwmods = "aes1";
        };
 };
 
+#include "omap4-l4.dtsi"
 #include "omap44xx-clocks.dtsi"
index ad97493..2223dc0 100644 (file)
        coefficients = <348 (-9301)>;
 };
 
+/* Only some L4 CFG interconnect ranges are different on 4460 */
+&l4_cfg_segment_300000 {
+       ranges = <0x00000000 0x00300000 0x020000>,      /* ap 67 */
+                <0x00040000 0x00340000 0x001000>,      /* ap 68 */
+                <0x00020000 0x00320000 0x004000>,      /* ap 71 */
+                <0x00024000 0x00324000 0x002000>,      /* ap 72 */
+                <0x00026000 0x00326000 0x001000>,      /* ap 73 */
+                <0x00027000 0x00327000 0x001000>,      /* ap 74 */
+                <0x00028000 0x00328000 0x001000>,      /* ap 75 */
+                <0x00029000 0x00329000 0x001000>,      /* ap 76 */
+                <0x00030000 0x00330000 0x010000>,      /* ap 77 */
+                <0x0002a000 0x0032a000 0x002000>,      /* ap 90 */
+                <0x0002c000 0x0032c000 0x004000>,      /* ap 91 */
+                <0x00010000 0x00310000 0x008000>,      /* ap 92 */
+                <0x00018000 0x00318000 0x004000>,      /* ap 93 */
+                <0x0001c000 0x0031c000 0x002000>,      /* ap 94 */
+                <0x0001e000 0x0031e000 0x002000>;      /* ap 95 */
+};
+
+&l4_cfg_target_0 {
+       ranges = <0x00000000 0x00000000 0x00010000>,
+                <0x00010000 0x00010000 0x00008000>,
+                <0x00018000 0x00018000 0x00004000>,
+                <0x0001c000 0x0001c000 0x00002000>,
+                <0x0001e000 0x0001e000 0x00002000>,
+                <0x00020000 0x00020000 0x00004000>,
+                <0x00024000 0x00024000 0x00002000>,
+                <0x00026000 0x00026000 0x00001000>,
+                <0x00027000 0x00027000 0x00001000>,
+                <0x00028000 0x00028000 0x00001000>,
+                <0x00029000 0x00029000 0x00001000>,
+                <0x0002a000 0x0002a000 0x00002000>,
+                <0x0002c000 0x0002c000 0x00004000>,
+                <0x00030000 0x00030000 0x00010000>;
+};
+
 /include/ "omap446x-clocks.dtsi"
index 3b22445..ab6f640 100644 (file)
                pinctrl-names = "default";
                pinctrl-0 = <&wlcore_irq_pin>;
                interrupt-parent = <&gpio1>;
-               interrupts = <14 IRQ_TYPE_LEVEL_HIGH>;  /* gpio 14 */
+               interrupts = <14 IRQ_TYPE_EDGE_RISING>; /* gpio 14 */
                ref-clock-frequency = <26000000>;
        };
 };
index 732b61a..574ac11 100644 (file)
                        device_type = "cpu";
                        compatible = "arm,cortex-a15";
                        reg = <0x1>;
+
+                       operating-points = <
+                               /* kHz    uV */
+                               1000000 1060000
+                               1500000 1250000
+                       >;
+
+                       clocks = <&dpll_mpu_ck>;
+                       clock-names = "cpu";
+
+                       clock-latency = <300000>; /* From omap-cpufreq driver */
+
+                       /* cooling options */
+                       #cooling-cells = <2>; /* min followed by max */
                };
        };
 
index e4ebcde..a520b4c 100644 (file)
                        interrupts = <30 31>;
                };
 
-               lcd-controller@40500000 {
+               lcdc: lcd-controller@40500000 {
                        compatible = "marvell,pxa2xx-lcdc";
                        reg = <0x44000000 0x10000>;
                        interrupts = <17>;
index 132a3b8..3a8f0ed 100644 (file)
                        reg = <0x43100000 90>;
                        interrupts = <45>;
                        clocks = <&clks CLK_NAND>;
+                       clock-names = "core";
                        dmas = <&pdma 97 3>;
                        dma-names = "data";
                        #address-cells = <1>;
                        clocks = <&clks CLK_PWM1>;
                        status = "disabled";
                };
+
+               ssp1: ssp@41000000 {
+                       compatible = "mrvl,pxa3xx-ssp";
+                       reg = <0x41000000 0x40>;
+                       interrupts = <24>;
+                       clocks = <&clks CLK_SSP1>;
+                       status = "disabled";
+               };
+
+               ssp2: ssp@41700000 {
+                       compatible = "mrvl,pxa3xx-ssp";
+                       reg = <0x41700000 0x40>;
+                       interrupts = <16>;
+                       clocks = <&clks CLK_SSP2>;
+                       status = "disabled";
+               };
+
+               ssp3: ssp@41900000 {
+                       compatible = "mrvl,pxa3xx-ssp";
+                       reg = <0x41900000 0x40>;
+                       interrupts = <0>;
+                       clocks = <&clks CLK_SSP3>;
+                       status = "disabled";
+               };
+
+               ssp4: ssp@41a00000 {
+                       compatible = "mrvl,pxa3xx-ssp";
+                       reg = <0x41a00000 0x40>;
+                       interrupts = <13>;
+                       clocks = <&clks CLK_SSP4>;
+                       status = "disabled";
+               };
        };
 
        clocks {
index 7bcd763..78db673 100644 (file)
                        reg = <0x1>;
                        clocks = <&gcc GCC_APPS_CLK_SRC>;
                        clock-frequency = <0>;
+                       operating-points = <
+                               /* kHz  uV (fixed) */
+                               48000   1100000
+                               200000  1100000
+                               500000  1100000
+                               666000  1100000
+                       >;
+                       clock-latency = <256000>;
                };
 
                cpu@2 {
                        reg = <0x2>;
                        clocks = <&gcc GCC_APPS_CLK_SRC>;
                        clock-frequency = <0>;
+                       operating-points = <
+                               /* kHz  uV (fixed) */
+                               48000   1100000
+                               200000  1100000
+                               500000  1100000
+                               666000  1100000
+                       >;
+                       clock-latency = <256000>;
                };
 
                cpu@3 {
                        reg = <0x3>;
                        clocks = <&gcc GCC_APPS_CLK_SRC>;
                        clock-frequency = <0>;
+                       operating-points = <
+                               /* kHz  uV (fixed) */
+                               48000   1100000
+                               200000  1100000
+                               500000  1100000
+                               666000  1100000
+                       >;
+                       clock-latency = <256000>;
                };
        };
 
index 1e0a3b4..70790ac 100644 (file)
@@ -5,6 +5,7 @@
 #include <dt-bindings/clock/qcom,gcc-ipq806x.h>
 #include <dt-bindings/clock/qcom,lcc-ipq806x.h>
 #include <dt-bindings/soc/qcom,gsbi.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
 
 / {
        model = "Qualcomm IPQ8064";
@@ -43,7 +44,8 @@
 
        cpu-pmu {
                compatible = "qcom,krait-pmu";
-               interrupts = <1 10 0x304>;
+               interrupts = <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(2) |
+                                         IRQ_TYPE_LEVEL_HIGH)>;
        };
 
        reserved-memory {
@@ -97,7 +99,7 @@
                        clock-names = "ahbix-clk",
                                        "mi2s-osr-clk",
                                        "mi2s-bit-clk";
-                       interrupts = <0 85 1>;
+                       interrupts = <GIC_SPI 85 IRQ_TYPE_EDGE_RISING>;
                        interrupt-names = "lpass-irq-lpaif";
                        reg = <0x28100000 0x10000>;
                        reg-names = "lpass-lpaif";
                        #gpio-cells = <2>;
                        interrupt-controller;
                        #interrupt-cells = <2>;
-                       interrupts = <0 16 0x4>;
+                       interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>;
                };
 
                intc: interrupt-controller@2000000 {
                timer@200a000 {
                        compatible = "qcom,kpss-timer",
                                     "qcom,kpss-wdt-ipq8064", "qcom,msm-timer";
-                       interrupts = <1 1 0x301>,
-                                    <1 2 0x301>,
-                                    <1 3 0x301>,
-                                    <1 4 0x301>,
-                                    <1 5 0x301>;
+                       interrupts = <GIC_PPI 1 (GIC_CPU_MASK_SIMPLE(2) |
+                                                IRQ_TYPE_EDGE_RISING)>,
+                                    <GIC_PPI 2 (GIC_CPU_MASK_SIMPLE(2) |
+                                                IRQ_TYPE_EDGE_RISING)>,
+                                    <GIC_PPI 3 (GIC_CPU_MASK_SIMPLE(2) |
+                                                IRQ_TYPE_EDGE_RISING)>,
+                                    <GIC_PPI 4 (GIC_CPU_MASK_SIMPLE(2) |
+                                                IRQ_TYPE_EDGE_RISING)>,
+                                    <GIC_PPI 5 (GIC_CPU_MASK_SIMPLE(2) |
+                                                IRQ_TYPE_EDGE_RISING)>;
                        reg = <0x0200a000 0x100>;
                        clock-frequency = <25000000>,
                                          <32768>;
                                compatible = "qcom,msm-uartdm-v1.3", "qcom,msm-uartdm";
                                reg = <0x12490000 0x1000>,
                                      <0x12480000 0x1000>;
-                               interrupts = <0 195 0x0>;
+                               interrupts = <GIC_SPI 195 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&gcc GSBI2_UART_CLK>, <&gcc GSBI2_H_CLK>;
                                clock-names = "core", "iface";
                                status = "disabled";
                        i2c@124a0000 {
                                compatible = "qcom,i2c-qup-v1.1.1";
                                reg = <0x124a0000 0x1000>;
-                               interrupts = <0 196 0>;
+                               interrupts = <GIC_SPI 196 IRQ_TYPE_LEVEL_HIGH>;
 
                                clocks = <&gcc GSBI2_QUP_CLK>, <&gcc GSBI2_H_CLK>;
                                clock-names = "core", "iface";
                                compatible = "qcom,msm-uartdm-v1.3", "qcom,msm-uartdm";
                                reg = <0x16340000 0x1000>,
                                      <0x16300000 0x1000>;
-                               interrupts = <0 152 0x0>;
+                               interrupts = <GIC_SPI 152 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&gcc GSBI4_UART_CLK>, <&gcc GSBI4_H_CLK>;
                                clock-names = "core", "iface";
                                status = "disabled";
                        i2c@16380000 {
                                compatible = "qcom,i2c-qup-v1.1.1";
                                reg = <0x16380000 0x1000>;
-                               interrupts = <0 153 0>;
+                               interrupts = <GIC_SPI 153 IRQ_TYPE_LEVEL_HIGH>;
 
                                clocks = <&gcc GSBI4_QUP_CLK>, <&gcc GSBI4_H_CLK>;
                                clock-names = "core", "iface";
                                compatible = "qcom,msm-uartdm-v1.3", "qcom,msm-uartdm";
                                reg = <0x1a240000 0x1000>,
                                      <0x1a200000 0x1000>;
-                               interrupts = <0 154 0x0>;
+                               interrupts = <GIC_SPI 154 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&gcc GSBI5_UART_CLK>, <&gcc GSBI5_H_CLK>;
                                clock-names = "core", "iface";
                                status = "disabled";
                        i2c@1a280000 {
                                compatible = "qcom,i2c-qup-v1.1.1";
                                reg = <0x1a280000 0x1000>;
-                               interrupts = <0 155 0>;
+                               interrupts = <GIC_SPI 155 IRQ_TYPE_LEVEL_HIGH>;
 
                                clocks = <&gcc GSBI5_QUP_CLK>, <&gcc GSBI5_H_CLK>;
                                clock-names = "core", "iface";
                        spi@1a280000 {
                                compatible = "qcom,spi-qup-v1.1.1";
                                reg = <0x1a280000 0x1000>;
-                               interrupts = <0 155 0>;
+                               interrupts = <GIC_SPI 155 IRQ_TYPE_LEVEL_HIGH>;
 
                                clocks = <&gcc GSBI5_QUP_CLK>, <&gcc GSBI5_H_CLK>;
                                clock-names = "core", "iface";
                                compatible = "qcom,msm-uartdm-v1.3", "qcom,msm-uartdm";
                                reg = <0x16640000 0x1000>,
                                      <0x16600000 0x1000>;
-                               interrupts = <0 158 0x0>;
+                               interrupts = <GIC_SPI 158 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&gcc GSBI7_UART_CLK>, <&gcc GSBI7_H_CLK>;
                                clock-names = "core", "iface";
                                status = "disabled";
                        compatible = "qcom,ipq806x-ahci", "generic-ahci";
                        reg = <0x29000000 0x180>;
 
-                       interrupts = <0 209 0x0>;
+                       interrupts = <GIC_SPI 209 IRQ_TYPE_LEVEL_HIGH>;
 
                        clocks = <&gcc SFAB_SATA_S_H_CLK>,
                                 <&gcc SATA_H_CLK>,
index 4dc0b34..c2dc9d0 100644 (file)
                                                regulator-max-microvolt = <2950000>;
 
                                                regulator-boot-on;
+                                               regulator-system-load = <200000>;
+                                               regulator-allow-set-load;
                                        };
 
                                        l21 {
index 5af2a01..474baa0 100644 (file)
@@ -1,12 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Device Tree Source for the Genmai board
  *
  * Copyright (C) 2013-14 Renesas Solutions Corp.
  * Copyright (C) 2014 Wolfram Sang, Sang Engineering <wsa@sang-engineering.com>
- *
- * This file is licensed under the terms of the GNU General Public License
- * version 2.  This program is licensed "as is" without any warranty of any
- * kind, whether express or implied.
  */
 
 /dts-v1/;
index 779f724..fe1a4aa 100644 (file)
@@ -1,12 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Device Tree Source for the GR-Peach board
  *
  * Copyright (C) 2017 Jacopo Mondi <jacopo+renesas@jmondi.org>
  * Copyright (C) 2016 Renesas Electronics
- *
- * 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.
  */
 
 /dts-v1/;
index 5dcaaf1..8ee44a1 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Device Tree Source for the RZ/A1H RSK board
  *
  * Copyright (C) 2016 Renesas Electronics
- *
- * 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.
  */
 
 /dts-v1/;
index a54822e..2211f88 100644 (file)
@@ -1,12 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Device Tree Source for the r7s72100 SoC
  *
  * Copyright (C) 2013-14 Renesas Solutions Corp.
  * Copyright (C) 2014 Wolfram Sang, Sang Engineering <wsa@sang-engineering.com>
- *
- * This file is licensed under the terms of the GNU General Public License
- * version 2.  This program is licensed "as is" without any warranty of any
- * kind, whether express or implied.
  */
 
 #include <dt-bindings/clock/r7s72100-clock.h>
index 125c39c..d530f45 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Device Tree Source for the APE6EVM board
  *
  * Copyright (C) 2013 Renesas Solutions Corp.
- *
- * 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.
  */
 
 /dts-v1/;
index 080d037..dd865f3 100644 (file)
@@ -1,12 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Device Tree Source for the r8a73a4 SoC
  *
  * Copyright (C) 2013 Renesas Solutions Corp.
  * Copyright (C) 2013 Magnus Damm
- *
- * 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 <dt-bindings/clock/r8a73a4-clock.h>
index 03b00d8..32757ca 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Device Tree Source for the armadillo 800 eva board
  *
  * Copyright (C) 2012 Renesas Solutions Corp.
- *
- * 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.
  */
 
 /dts-v1/;
index eb9a911..383cba6 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Device Tree Source for the r8a7740 SoC
  *
  * Copyright (C) 2012 Renesas Solutions Corp.
- *
- * 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 <dt-bindings/clock/r8a7740-clock.h>
index d90eb84..3275451 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Device Tree Source for the iWave-RZ/G1M Qseven board + camera daughter board
  *
  * Copyright (C) 2017 Renesas Electronics Corp.
- *
- * 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.
  */
 
 /dts-v1/;
index 6aa6b74..b683db4 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Device Tree Source for the iWave-RZ/G1M Qseven board
  *
  * Copyright (C) 2017 Renesas Electronics Corp.
- *
- * 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.
  */
 
 /dts-v1/;
index d364685..0e2e033 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Device Tree Source for the iWave-RZG1M-20M Qseven SOM
  *
  * Copyright (C) 2017 Renesas Electronics Corp.
- *
- * 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 "r8a7743.dtsi"
index 3d918d1..ca0e0fc 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Device Tree Source for the SK-RZG1M board
  *
  * Copyright (C) 2016-2017 Cogent Embedded, Inc.
- *
- * This file is licensed under the terms of the GNU General Public License
- * version 2. This program is licensed "as is" without any warranty of any
- * kind, whether express or implied.
  */
 
 /dts-v1/;
index 142949d..24715f7 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Device Tree Source for the r8a7743 SoC
  *
  * Copyright (C) 2016-2017 Cogent Embedded Inc.
- *
- * This file is licensed under the terms of the GNU General Public License
- * version 2. This program is licensed "as is" without any warranty of any
- * kind, whether express or implied.
  */
 
 #include <dt-bindings/interrupt-controller/irq.h>
                        reg = <1>;
                        clock-frequency = <1500000000>;
                        clocks = <&cpg CPG_CORE R8A7743_CLK_Z>;
+                       clock-latency = <300000>; /* 300 us */
                        power-domains = <&sysc R8A7743_PD_CA15_CPU1>;
                        next-level-cache = <&L2_CA15>;
+
+                       /* kHz - uV - OPPs unknown yet */
+                       operating-points = <1500000 1000000>,
+                                          <1312500 1000000>,
+                                          <1125000 1000000>,
+                                          < 937500 1000000>,
+                                          < 750000 1000000>,
+                                          < 375000 1000000>;
                };
 
                L2_CA15: cache-controller-0 {
index d34de82..2aeebfc 100644 (file)
@@ -1,12 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Device Tree Source for the iWave-RZG1E SODIMM carrier board + HDMI daughter
  * board
  *
  * Copyright (C) 2017 Renesas Electronics Corp.
- *
- * 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 "r8a7745-iwg22d-sodimm.dts"
index a4058f4..1db220c 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Device Tree Source for the iWave-RZG1E SODIMM carrier board
  *
  * Copyright (C) 2017 Renesas Electronics Corp.
- *
- * 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.
  */
 
 /*
index 29b6e10..41f111b 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Device Tree Source for the iWave-RZG1E-G22M SODIMM SOM
  *
  * Copyright (C) 2017 Renesas Electronics Corp.
- *
- * 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 "r8a7745.dtsi"
index b4d679b..655b10b 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Device Tree Source for the SK-RZG1E board
  *
  * Copyright (C) 2016-2017 Cogent Embedded, Inc.
- *
- * This file is licensed under the terms of the GNU General Public License
- * version 2. This program is licensed "as is" without any warranty of any
- * kind, whether express or implied.
  */
 
 /dts-v1/;
index 1cb7a7a..c53f7ff 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Device Tree Source for the r8a7745 SoC
  *
  * Copyright (C) 2016-2017 Cogent Embedded Inc.
- *
- * This file is licensed under the terms of the GNU General Public License
- * version 2. This program is licensed "as is" without any warranty of any
- * kind, whether express or implied.
  */
 
 #include <dt-bindings/interrupt-controller/irq.h>
index c85032f..87d32d3 100644 (file)
@@ -7,7 +7,7 @@
 
 #include <dt-bindings/interrupt-controller/irq.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
-#include <dt-bindings/clock/renesas-cpg-mssr.h>
+#include <dt-bindings/clock/r8a77470-cpg-mssr.h>
 / {
        compatible = "renesas,r8a77470";
        #address-cells = <2>;
@@ -22,7 +22,7 @@
                        compatible = "arm,cortex-a7";
                        reg = <0>;
                        clock-frequency = <1000000000>;
-                       clocks = <&cpg CPG_CORE 0>;
+                       clocks = <&cpg CPG_CORE R8A77470_CLK_Z2>;
                        power-domains = <&sysc 5>;
                        next-level-cache = <&L2_CA7>;
                };
                        reg = <0 0xe6e60000 0 0x40>;
                        interrupts = <GIC_SPI 152 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&cpg CPG_MOD 721>,
-                                <&cpg CPG_CORE 5>, <&scif_clk>;
+                                <&cpg CPG_CORE R8A77470_CLK_ZS>, <&scif_clk>;
                        clock-names = "fck", "brg_int", "scif_clk";
                        dmas = <&dmac0 0x29>, <&dmac0 0x2a>,
                               <&dmac1 0x29>, <&dmac1 0x2a>;
                        reg = <0 0xe6e68000 0 0x40>;
                        interrupts = <GIC_SPI 153 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&cpg CPG_MOD 720>,
-                                <&cpg CPG_CORE 5>, <&scif_clk>;
+                                <&cpg CPG_CORE R8A77470_CLK_ZS>, <&scif_clk>;
                        clock-names = "fck", "brg_int", "scif_clk";
                        dmas = <&dmac0 0x2d>, <&dmac0 0x2e>,
                               <&dmac1 0x2d>, <&dmac1 0x2e>;
                        reg = <0 0xe6e58000 0 0x40>;
                        interrupts = <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&cpg CPG_MOD 719>,
-                                <&cpg CPG_CORE 5>, <&scif_clk>;
+                                <&cpg CPG_CORE R8A77470_CLK_ZS>, <&scif_clk>;
                        clock-names = "fck", "brg_int", "scif_clk";
                        dmas = <&dmac0 0x2b>, <&dmac0 0x2c>,
                               <&dmac1 0x2b>, <&dmac1 0x2c>;
                        reg = <0 0xe6ea8000 0 0x40>;
                        interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&cpg CPG_MOD 718>,
-                                <&cpg CPG_CORE 5>, <&scif_clk>;
+                                <&cpg CPG_CORE R8A77470_CLK_ZS>, <&scif_clk>;
                        clock-names = "fck", "brg_int", "scif_clk";
                        dmas = <&dmac0 0x2f>, <&dmac0 0x30>,
                               <&dmac1 0x2f>, <&dmac1 0x30>;
                        reg = <0 0xe6ee0000 0 0x40>;
                        interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&cpg CPG_MOD 715>,
-                                <&cpg CPG_CORE 5>, <&scif_clk>;
+                                <&cpg CPG_CORE R8A77470_CLK_ZS>, <&scif_clk>;
                        clock-names = "fck", "brg_int", "scif_clk";
                        dmas = <&dmac0 0xfb>, <&dmac0 0xfc>,
                               <&dmac1 0xfb>, <&dmac1 0xfc>;
                        reg = <0 0xe6ee8000 0 0x40>;
                        interrupts = <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&cpg CPG_MOD 714>,
-                                <&cpg CPG_CORE 5>, <&scif_clk>;
+                                <&cpg CPG_CORE R8A77470_CLK_ZS>, <&scif_clk>;
                        clock-names = "fck", "brg_int", "scif_clk";
                        dmas = <&dmac0 0xfd>, <&dmac0 0xfe>,
                               <&dmac1 0xfd>, <&dmac1 0xfe>;
index c79d55e..de808d2 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Reference Device Tree Source for the Bock-W board
  *
@@ -8,10 +9,6 @@
  *
  * Copyright (C) 2013 Renesas Solutions Corp.
  * Copyright (C) 2013 Simon Horman
- *
- * 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.
  */
 
 /dts-v1/;
index 3b49f9e..1bce16c 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Device Tree Source for Renesas r8a7778
  *
@@ -8,10 +9,6 @@
  *
  * Copyright (C) 2013 Renesas Solutions Corp.
  * Copyright (C) 2013 Simon Horman
- *
- * 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 <dt-bindings/clock/r8a7778-clock.h>
index 4b9006b..a4d0038 100644 (file)
@@ -1,12 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Device Tree Source for the Marzen board
  *
  * Copyright (C) 2013 Renesas Solutions Corp.
  * Copyright (C) 2013 Simon Horman
- *
- * 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.
  */
 
 /dts-v1/;
index e79ae30..6b997bc 100644 (file)
@@ -1,12 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Device Tree Source for Renesas r8a7779
  *
  * Copyright (C) 2013 Renesas Solutions Corp.
  * Copyright (C) 2013 Simon Horman
- *
- * 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 <dt-bindings/clock/r8a7779-clock.h>
index 092610e..50312e7 100644 (file)
@@ -1,13 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Device Tree Source for the Lager board
  *
  * Copyright (C) 2013-2014 Renesas Solutions Corp.
  * Copyright (C) 2014 Cogent Embedded, Inc.
  * Copyright (C) 2015-2016 Renesas Electronics Corporation
- *
- * 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.
  */
 
 /*
index 4d06b15..0925bdc 100644 (file)
@@ -1,13 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Device Tree Source for the r8a7790 SoC
  *
  * Copyright (C) 2015 Renesas Electronics Corporation
  * Copyright (C) 2013-2014 Renesas Solutions Corp.
  * Copyright (C) 2014 Cogent Embedded Inc.
- *
- * This file is licensed under the terms of the GNU General Public License
- * version 2.  This program is licensed "as is" without any warranty of any
- * kind, whether express or implied.
  */
 
 #include <dt-bindings/clock/r8a7790-cpg-mssr.h>
                        compatible = "arm,cortex-a15";
                        reg = <0>;
                        clock-frequency = <1300000000>;
-                       voltage-tolerance = <1>; /* 1% */
                        clocks = <&cpg CPG_CORE R8A7790_CLK_Z>;
-                       clock-latency = <300000>; /* 300 us */
                        power-domains = <&sysc R8A7790_PD_CA15_CPU0>;
                        next-level-cache = <&L2_CA15>;
                        capacity-dmips-mhz = <1024>;
+                       voltage-tolerance = <1>; /* 1% */
+                       clock-latency = <300000>; /* 300 us */
 
                        /* kHz - uV - OPPs unknown yet */
                        operating-points = <1400000 1000000>,
                        power-domains = <&sysc R8A7790_PD_CA15_CPU1>;
                        next-level-cache = <&L2_CA15>;
                        capacity-dmips-mhz = <1024>;
+                       voltage-tolerance = <1>; /* 1% */
+                       clock-latency = <300000>; /* 300 us */
+
+                       /* kHz - uV - OPPs unknown yet */
+                       operating-points = <1400000 1000000>,
+                                          <1225000 1000000>,
+                                          <1050000 1000000>,
+                                          < 875000 1000000>,
+                                          < 700000 1000000>,
+                                          < 350000 1000000>;
                };
 
                cpu2: cpu@2 {
                        power-domains = <&sysc R8A7790_PD_CA15_CPU2>;
                        next-level-cache = <&L2_CA15>;
                        capacity-dmips-mhz = <1024>;
+                       voltage-tolerance = <1>; /* 1% */
+                       clock-latency = <300000>; /* 300 us */
+
+                       /* kHz - uV - OPPs unknown yet */
+                       operating-points = <1400000 1000000>,
+                                          <1225000 1000000>,
+                                          <1050000 1000000>,
+                                          < 875000 1000000>,
+                                          < 700000 1000000>,
+                                          < 350000 1000000>;
                };
 
                cpu3: cpu@3 {
                        power-domains = <&sysc R8A7790_PD_CA15_CPU3>;
                        next-level-cache = <&L2_CA15>;
                        capacity-dmips-mhz = <1024>;
+                       voltage-tolerance = <1>; /* 1% */
+                       clock-latency = <300000>; /* 300 us */
+
+                       /* kHz - uV - OPPs unknown yet */
+                       operating-points = <1400000 1000000>,
+                                          <1225000 1000000>,
+                                          <1050000 1000000>,
+                                          < 875000 1000000>,
+                                          < 700000 1000000>,
+                                          < 350000 1000000>;
                };
 
                cpu4: cpu@100 {
index 8ab793d..ce22db0 100644 (file)
@@ -1,13 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Device Tree Source for the Koelsch board
  *
  * Copyright (C) 2013 Renesas Electronics Corporation
  * Copyright (C) 2013-2014 Renesas Solutions Corp.
  * Copyright (C) 2014 Cogent Embedded, Inc.
- *
- * This file is licensed under the terms of the GNU General Public License
- * version 2.  This program is licensed "as is" without any warranty of any
- * kind, whether express or implied.
  */
 
 /*
index a01101b..f02036e 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Device Tree Source for the Porter board
  *
  * Copyright (C) 2015 Cogent Embedded, Inc.
- *
- * This file is licensed under the terms of the GNU General Public License
- * version 2.  This program is licensed "as is" without any warranty of any
- * kind, whether express or implied.
  */
 
 /*
        clock-frequency = <400000>;
 };
 
+&i2c6 {
+       status = "okay";
+       clock-frequency = <100000>;
+
+       pmic@5a {
+               compatible = "dlg,da9063l";
+               reg = <0x5a>;
+               interrupt-parent = <&irqc0>;
+               interrupts = <2 IRQ_TYPE_LEVEL_LOW>;
+               interrupt-controller;
+
+               wdt {
+                       compatible = "dlg,da9063-watchdog";
+               };
+       };
+
+       vdd_dvfs: regulator@68 {
+               compatible = "dlg,da9210";
+               reg = <0x68>;
+               interrupt-parent = <&irqc0>;
+               interrupts = <2 IRQ_TYPE_LEVEL_LOW>;
+
+               regulator-min-microvolt = <1000000>;
+               regulator-max-microvolt = <1000000>;
+               regulator-boot-on;
+               regulator-always-on;
+       };
+};
+
 &sata0 {
        status = "okay";
 };
 
+&cpu0 {
+       cpu0-supply = <&vdd_dvfs>;
+};
+
 /* composite video input */
 &vin0 {
        status = "okay";
index 6e1dd7a..991ac6f 100644 (file)
@@ -1,13 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Device Tree Source for the r8a7791 SoC
  *
  * Copyright (C) 2013-2015 Renesas Electronics Corporation
  * Copyright (C) 2013-2014 Renesas Solutions Corp.
  * Copyright (C) 2014 Cogent Embedded Inc.
- *
- * This file is licensed under the terms of the GNU General Public License
- * version 2.  This program is licensed "as is" without any warranty of any
- * kind, whether express or implied.
  */
 
 #include <dt-bindings/clock/r8a7791-cpg-mssr.h>
                        compatible = "arm,cortex-a15";
                        reg = <0>;
                        clock-frequency = <1500000000>;
-                       voltage-tolerance = <1>; /* 1% */
                        clocks = <&cpg CPG_CORE R8A7791_CLK_Z>;
-                       clock-latency = <300000>; /* 300 us */
                        power-domains = <&sysc R8A7791_PD_CA15_CPU0>;
                        next-level-cache = <&L2_CA15>;
+                       voltage-tolerance = <1>; /* 1% */
+                       clock-latency = <300000>; /* 300 us */
 
                        /* kHz - uV - OPPs unknown yet */
                        operating-points = <1500000 1000000>,
                        clocks = <&cpg CPG_CORE R8A7791_CLK_Z>;
                        power-domains = <&sysc R8A7791_PD_CA15_CPU1>;
                        next-level-cache = <&L2_CA15>;
+                       voltage-tolerance = <1>; /* 1% */
+                       clock-latency = <300000>; /* 300 us */
+
+                       /* kHz - uV - OPPs unknown yet */
+                       operating-points = <1500000 1000000>,
+                                          <1312500 1000000>,
+                                          <1125000 1000000>,
+                                          < 937500 1000000>,
+                                          < 750000 1000000>,
+                                          < 375000 1000000>;
                };
 
                L2_CA15: cache-controller-0 {
index 04fb709..f923012 100644 (file)
@@ -1,12 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Device Tree Source for the Blanche board
  *
  * Copyright (C) 2014 Renesas Electronics Corporation
  * Copyright (C) 2016 Cogent  Embedded, Inc.
- *
- * This file is licensed under the terms of the GNU General Public License
- * version 2.  This program is licensed "as is" without any warranty of any
- * kind, whether express or implied.
  */
 
 /dts-v1/;
index db01de7..f46f456 100644 (file)
@@ -1,12 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Device Tree Source for the Wheat board
  *
  * Copyright (C) 2016 Renesas Electronics Corporation
  * Copyright (C) 2016 Cogent  Embedded, Inc.
- *
- * This file is licensed under the terms of the GNU General Public License
- * version 2.  This program is licensed "as is" without any warranty of any
- * kind, whether express or implied.
  */
 
 /dts-v1/;
index f44257d..63a978e 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Device Tree Source for the r8a7792 SoC
  *
  * Copyright (C) 2016 Cogent Embedded Inc.
- *
- * This file is licensed under the terms of the GNU General Public License
- * version 2.  This program is licensed "as is" without any warranty of any
- * kind, whether express or implied.
  */
 
 #include <dt-bindings/clock/r8a7792-cpg-mssr.h>
index aa209f6..6b2f3a4 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Device Tree Source for the Gose board
  *
  * Copyright (C) 2014-2015 Renesas Electronics Corporation
- *
- * 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.
  */
 
 /*
index 4abecfc..620a570 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Device Tree Source for the r8a7793 SoC
  *
  * Copyright (C) 2014-2015 Renesas Electronics Corporation
- *
- * 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 <dt-bindings/clock/r8a7793-cpg-mssr.h>
                        compatible = "arm,cortex-a15";
                        reg = <0>;
                        clock-frequency = <1500000000>;
-                       voltage-tolerance = <1>; /* 1% */
                        clocks = <&cpg CPG_CORE R8A7793_CLK_Z>;
-                       clock-latency = <300000>; /* 300 us */
                        power-domains = <&sysc R8A7793_PD_CA15_CPU0>;
+                       voltage-tolerance = <1>; /* 1% */
+                       clock-latency = <300000>; /* 300 us */
 
                        /* kHz - uV - OPPs unknown yet */
                        operating-points = <1500000 1000000>,
                        clock-frequency = <1500000000>;
                        clocks = <&cpg CPG_CORE R8A7793_CLK_Z>;
                        power-domains = <&sysc R8A7793_PD_CA15_CPU1>;
+                       voltage-tolerance = <1>; /* 1% */
+                       clock-latency = <300000>; /* 300 us */
+
+                       /* kHz - uV - OPPs unknown yet */
+                       operating-points = <1500000 1000000>,
+                                          <1312500 1000000>,
+                                          <1125000 1000000>,
+                                          < 937500 1000000>,
+                                          < 750000 1000000>,
+                                          < 375000 1000000>;
+                       next-level-cache = <&L2_CA15>;
                };
 
                L2_CA15: cache-controller-0 {
index e170275..ef7e2a8 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Device Tree Source for the Alt board
  *
  * Copyright (C) 2014 Renesas Electronics Corporation
- *
- * 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.
  */
 
 /dts-v1/;
index 7808aae..daec965 100644 (file)
@@ -1,13 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Device Tree Source for the SILK board
  *
  * Copyright (C) 2014 Renesas Electronics Corporation
  * Copyright (C) 2014-2015 Renesas Solutions Corp.
  * Copyright (C) 2014-2015 Cogent Embedded, Inc.
- *
- * This file is licensed under the terms of the GNU General Public License
- * version 2.  This program is licensed "as is" without any warranty of any
- * kind, whether express or implied.
  */
 
 /*
index 7361969..ea2ca4b 100644 (file)
@@ -1,12 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Device Tree Source for the r8a7794 SoC
  *
  * Copyright (C) 2014 Renesas Electronics Corporation
  * Copyright (C) 2014 Ulrich Hecht
- *
- * 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 <dt-bindings/clock/r8a7794-cpg-mssr.h>
index 238d14b..79fce67 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Common file for the AA104XD12 panel connected to Renesas R-Car boards
  *
  * Copyright (C) 2014 Renesas Electronics Corp.
- *
- * 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.
  */
 
 / {
index 04aafd4..6e7589e 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Common file for the AA121TD01 panel connected to Renesas R-Car boards
  *
  * Copyright (C) 2015 Renesas Electronics Corp.
- *
- * 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.
  */
 
 / {
diff --git a/arch/arm/boot/dts/r9a06g032-rzn1d400-db.dts b/arch/arm/boot/dts/r9a06g032-rzn1d400-db.dts
new file mode 100644 (file)
index 0000000..4e57ae2
--- /dev/null
@@ -0,0 +1,28 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Device Tree Source for the RZN1D-DB Board
+ *
+ * Copyright (C) 2018 Renesas Electronics Europe Limited
+ *
+ */
+
+/dts-v1/;
+
+#include "r9a06g032.dtsi"
+
+/ {
+       model = "RZN1D-DB Board";
+       compatible = "renesas,rzn1d400-db", "renesas,r9a06g032";
+
+       chosen {
+               stdout-path = "serial0:115200n8";
+       };
+
+       aliases {
+               serial0 = &uart0;
+       };
+};
+
+&uart0 {
+       status = "okay";
+};
diff --git a/arch/arm/boot/dts/r9a06g032.dtsi b/arch/arm/boot/dts/r9a06g032.dtsi
new file mode 100644 (file)
index 0000000..afe29c9
--- /dev/null
@@ -0,0 +1,115 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Base Device Tree Source for the Renesas RZ/N1D (R9A06G032)
+ *
+ * Copyright (C) 2018 Renesas Electronics Europe Limited
+ *
+ */
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+/ {
+       compatible = "renesas,r9a06g032";
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       cpus {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               cpu@0 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a7";
+                       reg = <0>;
+                       clocks = <&sysctrl 84>;
+               };
+
+               cpu@1 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a7";
+                       reg = <1>;
+                       clocks = <&sysctrl 84>;
+                       enable-method = "renesas,r9a06g032-smp";
+                       cpu-release-addr = <0 0x4000c204>;
+               };
+       };
+
+       ext_jtag_clk: extjtagclk {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <0>;
+       };
+
+       ext_mclk: extmclk {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <40000000>;
+       };
+
+       ext_rgmii_ref: extrgmiiref {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <0>;
+       };
+
+       ext_rtc_clk: extrtcclk {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <0>;
+       };
+
+       soc {
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <1>;
+               interrupt-parent = <&gic>;
+               ranges;
+
+               sysctrl: system-controller@4000c000 {
+                       compatible = "renesas,r9a06g032-sysctrl";
+                       reg = <0x4000c000 0x1000>;
+                       status = "okay";
+                       #clock-cells = <1>;
+
+                       clocks = <&ext_mclk>, <&ext_rtc_clk>,
+                                       <&ext_jtag_clk>, <&ext_rgmii_ref>;
+                       clock-names = "mclk", "rtc", "jtag", "rgmii_ref_ext";
+               };
+
+               uart0: serial@40060000 {
+                       compatible = "snps,dw-apb-uart";
+                       reg = <0x40060000 0x400>;
+                       interrupts = <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>;
+                       reg-shift = <2>;
+                       reg-io-width = <4>;
+                       clocks = <&sysctrl 146>;
+                       clock-names = "baudclk";
+                       status = "disabled";
+               };
+
+               gic: gic@44101000 {
+                       compatible = "arm,cortex-a7-gic", "arm,gic-400";
+                       interrupt-controller;
+                       #interrupt-cells = <3>;
+                       reg = <0x44101000 0x1000>, /* Distributer */
+                             <0x44102000 0x2000>, /* CPU interface */
+                             <0x44104000 0x2000>, /* Virt interface control */
+                             <0x44106000 0x2000>; /* Virt CPU interface */
+                       interrupts =
+                               <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>;
+               };
+       };
+
+       timer {
+               compatible = "arm,cortex-a7-timer",
+                            "arm,armv7-timer";
+               interrupt-parent = <&gic>;
+               arm,cpu-registers-not-fw-configured;
+               always-on;
+               interrupts =
+                       <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
+                       <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
+                       <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
+                       <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>;
+       };
+};
index c095341..2a7e662 100644 (file)
@@ -1,42 +1,4 @@
-/*
- * 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.
- */
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 
 /dts-v1/;
 
index e2a0f57..0fd19f9 100644 (file)
@@ -1,42 +1,4 @@
-/*
- * 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.
- */
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 
 /dts-v1/;
 
index 567a6a7..67f5720 100644 (file)
@@ -1,42 +1,4 @@
-/*
- * 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.
- */
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/interrupt-controller/irq.h>
index ef1eabf..1c925f2 100644 (file)
@@ -1,44 +1,7 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * Copyright (c) 2013 MundoReader S.L.
  * Author: Heiko Stuebner <heiko@sntech.de>
- *
- * 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/;
index d23ee6d..ce525b9 100644 (file)
@@ -1,43 +1,6 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * Copyright (c) 2014 Romain Perier <romain.perier@gmail.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/;
index 13e285c..b6a8a82 100644 (file)
@@ -1,43 +1,6 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * Copyright (c) 2016 Paweł Jarosz <paweljarosz3691@gmail.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/;
index 4d7057a..cd126b9 100644 (file)
@@ -1,43 +1,6 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * Copyright (c) 2014, 2015 FUKAUMI Naoki <naobsd@gmail.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/;
index 06523ca..2ab3c4b 100644 (file)
@@ -1,44 +1,7 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * Copyright (c) 2013 MundoReader S.L.
  * Author: Heiko Stuebner <heiko@sntech.de>
- *
- * 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/gpio/gpio.h>
index 8ba9e06..375129b 100644 (file)
@@ -1,43 +1,6 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * Copyright (c) 2016 Andy Yan <andy.yan@rock-chips.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/;
index 00e05a6..45fd2b3 100644 (file)
@@ -1,43 +1,6 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * Copyright (c) 2013 Heiko Stuebner <heiko@sntech.de>
- *
- * 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/;
index aa10caa..aa123f9 100644 (file)
@@ -1,44 +1,7 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * Copyright (c) 2013 MundoReader S.L.
  * Author: Heiko Stuebner <heiko@sntech.de>
- *
- * 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/gpio/gpio.h>
index 1be9daa..5670b33 100644 (file)
@@ -1,42 +1,4 @@
-/*
- * 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.
- */
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 
 /dts-v1/;
 
index 73e3845..4df7acc 100644 (file)
@@ -1,42 +1,4 @@
-/*
- * 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.
- */
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 
 /dts-v1/;
 
index 6fe6c15..cb7d3fa 100644 (file)
@@ -1,43 +1,6 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * Copyright (c) 2017 Fuzhou Rockchip Electronics Co., Ltd
- *
- * This file is dual-licensed: you can use it either under the terms
- * of the GPL or the X11 license, at your option. Note that this dual
- * licensing only applies to this file, and not this project as a
- * whole.
- *
- *  a) This library is free software; 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 library is distributed in the hope that it will be useful,
- *     but WITHOUT 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 "rk322x.dtsi"
index be80e9a..cd8f2a3 100644 (file)
@@ -1,42 +1,4 @@
-/*
- * 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.
- */
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/interrupt-controller/irq.h>
@@ -80,6 +42,7 @@
                        reg = <0xf01>;
                        resets = <&cru SRST_CORE1>;
                        operating-points-v2 = <&cpu0_opp_table>;
+                       #cooling-cells = <2>; /* min followed by max */
                        enable-method = "psci";
                };
 
@@ -89,6 +52,7 @@
                        reg = <0xf02>;
                        resets = <&cru SRST_CORE2>;
                        operating-points-v2 = <&cpu0_opp_table>;
+                       #cooling-cells = <2>; /* min followed by max */
                        enable-method = "psci";
                };
 
@@ -98,6 +62,7 @@
                        reg = <0xf03>;
                        resets = <&cru SRST_CORE3>;
                        operating-points-v2 = <&cpu0_opp_table>;
+                       #cooling-cells = <2>; /* min followed by max */
                        enable-method = "psci";
                };
        };
index b9418d1..6592c80 100644 (file)
@@ -1,42 +1,4 @@
-/*
- * 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.
- */
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 
 /dts-v1/;
 #include "rk3288-evb.dtsi"
index 56c266d..1678820 100644 (file)
@@ -1,42 +1,4 @@
-/*
- * 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.
- */
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 
 /dts-v1/;
 #include "rk3288-evb.dtsi"
index 39b61dc..97e4d55 100644 (file)
@@ -1,42 +1,4 @@
-/*
- * 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.
- */
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 
 #include <dt-bindings/input/input.h>
 #include <dt-bindings/pwm/pwm.h>
                        #address-cells = <1>;
                        #size-cells = <0>;
 
-                       edp_out_panel: endpoint {
+                       edp_out_panel: endpoint@0 {
                                reg = <0>;
                                remote-endpoint = <&panel_in_edp>;
                        };
index 4140597..b1b56df 100644 (file)
@@ -1,42 +1,4 @@
-/*
- * 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.
- */
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 
 /dts-v1/;
 
index 0195d97..0f3c29d 100644 (file)
@@ -1,43 +1,6 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * Copyright (c) 2014, 2015 FUKAUMI Naoki <naobsd@gmail.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/;
index 5f1e336..f57f286 100644 (file)
@@ -1,44 +1,7 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * Device tree file for Firefly Rockchip RK3288 Core board
  * Copyright (c) 2016 Randy Li <ayaka@soulik.info>
- *
- * 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/input/input.h>
index eab176e..58ea8be 100644 (file)
@@ -1,44 +1,7 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * Device tree file for Firefly Rockchip RK3288 Core board
  * Copyright (c) 2016 Randy Li <ayaka@soulik.info>
- *
- * 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/;
index 14271be..556ab42 100644 (file)
@@ -1,43 +1,6 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * Copyright (c) 2014, 2015 FUKAUMI Naoki <naobsd@gmail.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/;
index b9e6f3a..a6ff7ea 100644 (file)
@@ -1,43 +1,6 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * Copyright (c) 2014, 2015 FUKAUMI Naoki <naobsd@gmail.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/input/input.h>
index 4d923aa..504ab11 100644 (file)
@@ -1,43 +1,6 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * Copyright (c) 2016 Heiko Stuebner <heiko@sntech.de>
- *
- * 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/;
index 985743f..7077c34 100644 (file)
@@ -1,45 +1,8 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * Device tree file for Phytec PCM-947 carrier board
  * Copyright (C) 2017 PHYTEC Messtechnik GmbH
  * Author: Wadim Egorov <w.egorov@phytec.de>
- *
- * 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/;
index aaab2d1..c218dd5 100644 (file)
@@ -1,45 +1,8 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * Device tree file for Phytec phyCORE-RK3288 SoM
  * Copyright (C) 2017 PHYTEC Messtechnik GmbH
  * Author: Wadim Egorov <w.egorov@phytec.de>
- *
- * 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/net/ti-dp83867.h>
index c06d0f4..596435e 100644 (file)
@@ -1,43 +1,6 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * Copyright (c) 2014, 2015 Andy Yan <andy.yan@rock-chips.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/;
index e95215c..28972fb 100644 (file)
@@ -1,43 +1,6 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * Copyright (c) 2015 Heiko Stuebner <heiko@sntech.de>
- *
- * 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/;
index 51f36a1..5032548 100644 (file)
@@ -1,42 +1,4 @@
-/*
- * 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.
- */
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 
 #include <dt-bindings/pwm/pwm.h>
 #include "rk3288.dtsi"
index 8ccc89d..6a30cad 100644 (file)
@@ -1,42 +1,4 @@
-/*
- * 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.
- */
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 
 /dts-v1/;
 #include <dt-bindings/input/input.h>
index 127488f..ceade59 100644 (file)
@@ -1,43 +1,6 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * Copyright (c) 2017 Fuzhou Rockchip Electronics Co., Ltd.
- *
- * This file is dual-licensed: you can use it either under the terms
- * of the GPL or the X11 license, at your option. Note that this dual
- * licensing only applies to this file, and not this project as a
- * whole.
- *
- *  a) This file is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License 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/;
index 280acea..eaf9216 100644 (file)
@@ -1,12 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Google Veyron (and derivatives) fragment for the  max98090 audio
  * codec and analog headphone jack.
  *
  * Copyright 2016 Google, 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.
  */
 
 / {
index ed42552..5c94a33 100644 (file)
@@ -1,45 +1,8 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * Google Veyron Brain Rev 0 board device tree source
  *
  * Copyright 2014 Google, 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 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/;
index b16d570..b54746d 100644 (file)
@@ -1,46 +1,9 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * Google Veyron (and derivatives) board device tree source
  * Chromebook specific parts
  *
  * Copyright 2015 Google, 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 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/rockchip,rk808.h>
                        reg = <1>;
                        #address-cells = <1>;
                        #size-cells = <0>;
-                       edp_out_panel: endpoint {
+                       edp_out_panel: endpoint@0 {
                                reg = <0>;
                                remote-endpoint = <&panel_in_edp>;
                        };
index d33f576..9d6814c 100644 (file)
@@ -1,45 +1,8 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * Google Veyron Jaq Rev 1+ board device tree source
  *
  * Copyright 2015 Google, 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 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/;
index cdea751..2ba8989 100644 (file)
@@ -1,45 +1,8 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * Google Veyron Jerry Rev 3+ board device tree source
  *
  * Copyright 2015 Google, 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 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/;
index f0994f0..1e0158a 100644 (file)
@@ -1,45 +1,8 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * Google Veyron Mickey Rev 0 board device tree source
  *
  * Copyright 2015 Google, 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 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/;
index 4c5307e..f95d0c5 100644 (file)
@@ -1,45 +1,8 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * Google Veyron Minnie Rev 0+ board device tree source
  *
  * Copyright 2015 Google, 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 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/;
index 995cff4..2950aad 100644 (file)
@@ -1,45 +1,8 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * Google Veyron Pinky Rev 2 board device tree source
  *
  * Copyright 2015 Google, 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 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/;
index 95e9bee..a457044 100644 (file)
@@ -1,45 +1,8 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * Google Veyron (and derivatives) fragment for sdmmc cards
  *
  * Copyright 2015 Google, 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 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.
  */
 
 &io_domains {
index cc0b78c..e16421d 100644 (file)
@@ -1,45 +1,8 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * Google Veyron Speedy Rev 1+ board device tree source
  *
  * Copyright 2015 Google, 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 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/;
index 6e5bd89..2075120 100644 (file)
@@ -1,45 +1,8 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * Google Veyron (and derivatives) board device tree source
  *
  * Copyright 2015 Google, 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 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/rockchip,rk808.h>
 
 &cpu0 {
        cpu0-supply = <&vdd_cpu>;
-       operating-points = <
-               /* KHz    uV */
-               1800000 1400000
-               1704000 1350000
-               1608000 1300000
-               1512000 1250000
-               1416000 1200000
-               1200000 1100000
-               1008000 1050000
-                816000 1000000
-                696000  950000
-                600000  900000
-                408000  900000
-                216000  900000
-                126000  900000
-       >;
+};
+
+/* rk3288-c used in Veyron Chrome-devices has slightly changed OPPs */
+&cpu_opp_table {
+       /delete-node/ opp-312000000;
+
+       opp-1512000000 {
+               opp-microvolt = <1250000>;
+       };
+       opp-1608000000 {
+               opp-microvolt = <1300000>;
+       };
+       opp-1704000000 {
+               opp-hz = /bits/ 64 <1704000000>;
+               opp-microvolt = <1350000>;
+       };
+       opp-1800000000 {
+               opp-hz = /bits/ 64 <1800000000>;
+               opp-microvolt = <1400000>;
+       };
 };
 
 &emmc {
index 14c896b..4856a9f 100644 (file)
@@ -1,43 +1,6 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * Copyright (C) 2017 Jagan Teki <jagan@amarulasolutions.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/;
index d7e49d2..0840ffb 100644 (file)
@@ -1,42 +1,4 @@
-/*
- * 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.
- */
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/interrupt-controller/irq.h>
                        compatible = "arm,cortex-a12";
                        reg = <0x500>;
                        resets = <&cru SRST_CORE0>;
-                       operating-points = <
-                               /* KHz    uV */
-                               1608000 1350000
-                               1512000 1300000
-                               1416000 1200000
-                               1200000 1100000
-                               1008000 1050000
-                                816000 1000000
-                                696000  950000
-                                600000  900000
-                                408000  900000
-                                312000  900000
-                                216000  900000
-                                126000  900000
-                       >;
+                       operating-points-v2 = <&cpu_opp_table>;
                        #cooling-cells = <2>; /* min followed by max */
                        clock-latency = <40000>;
                        clocks = <&cru ARMCLK>;
                        compatible = "arm,cortex-a12";
                        reg = <0x501>;
                        resets = <&cru SRST_CORE1>;
+                       operating-points = <&cpu_opp_table>;
+                       #cooling-cells = <2>; /* min followed by max */
+                       clock-latency = <40000>;
+                       clocks = <&cru ARMCLK>;
                };
                cpu2: cpu@502 {
                        device_type = "cpu";
                        compatible = "arm,cortex-a12";
                        reg = <0x502>;
                        resets = <&cru SRST_CORE2>;
+                       operating-points = <&cpu_opp_table>;
+                       #cooling-cells = <2>; /* min followed by max */
+                       clock-latency = <40000>;
+                       clocks = <&cru ARMCLK>;
                };
                cpu3: cpu@503 {
                        device_type = "cpu";
                        compatible = "arm,cortex-a12";
                        reg = <0x503>;
                        resets = <&cru SRST_CORE3>;
+                       operating-points = <&cpu_opp_table>;
+                       #cooling-cells = <2>; /* min followed by max */
+                       clock-latency = <40000>;
+                       clocks = <&cru ARMCLK>;
+               };
+       };
+
+       cpu_opp_table: cpu-opp-table {
+               compatible = "operating-points-v2";
+               opp-shared;
+
+               opp-126000000 {
+                       opp-hz = /bits/ 64 <126000000>;
+                       opp-microvolt = <900000>;
+               };
+               opp-216000000 {
+                       opp-hz = /bits/ 64 <216000000>;
+                       opp-microvolt = <900000>;
+               };
+               opp-312000000 {
+                       opp-hz = /bits/ 64 <312000000>;
+                       opp-microvolt = <900000>;
+               };
+               opp-408000000 {
+                       opp-hz = /bits/ 64 <408000000>;
+                       opp-microvolt = <900000>;
+               };
+               opp-600000000 {
+                       opp-hz = /bits/ 64 <600000000>;
+                       opp-microvolt = <900000>;
+               };
+               opp-696000000 {
+                       opp-hz = /bits/ 64 <696000000>;
+                       opp-microvolt = <950000>;
+               };
+               opp-816000000 {
+                       opp-hz = /bits/ 64 <816000000>;
+                       opp-microvolt = <1000000>;
+               };
+               opp-1008000000 {
+                       opp-hz = /bits/ 64 <1008000000>;
+                       opp-microvolt = <1050000>;
+               };
+               opp-1200000000 {
+                       opp-hz = /bits/ 64 <1200000000>;
+                       opp-microvolt = <1100000>;
+               };
+               opp-1416000000 {
+                       opp-hz = /bits/ 64 <1416000000>;
+                       opp-microvolt = <1200000>;
+               };
+               opp-1512000000 {
+                       opp-hz = /bits/ 64 <1512000000>;
+                       opp-microvolt = <1300000>;
+               };
+               opp-1608000000 {
+                       opp-hz = /bits/ 64 <1608000000>;
+                       opp-microvolt = <1350000>;
                };
        };
 
index 49584b6..d752dc6 100644 (file)
@@ -1,44 +1,7 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * Copyright (c) 2013 MundoReader S.L.
  * Author: Heiko Stuebner <heiko@sntech.de>
- *
- * 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/interrupt-controller/irq.h>
index 70f0106..203d83e 100644 (file)
@@ -1,42 +1,4 @@
-/*
- * 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.
- */
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 
 /dts-v1/;
 
index 76ea246..ed8f6ca 100644 (file)
@@ -1,42 +1,4 @@
-/*
- * 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.
- */
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/interrupt-controller/irq.h>
diff --git a/arch/arm/boot/dts/s5pv210-aries.dtsi b/arch/arm/boot/dts/s5pv210-aries.dtsi
new file mode 100644 (file)
index 0000000..575094e
--- /dev/null
@@ -0,0 +1,419 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Samsung's S5PV210 based Galaxy Aries board device tree source
+ */
+
+/dts-v1/;
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include "s5pv210.dtsi"
+
+/ {
+       compatible = "samsung,aries", "samsung,s5pv210";
+
+       aliases {
+               i2c6 = &i2c_pmic;
+               i2c9 = &i2c_fuel;
+       };
+
+       memory@30000000 {
+               device_type = "memory";
+               reg = <0x30000000 0x05000000
+                       0x40000000 0x10000000
+                       0x50000000 0x08000000>;
+       };
+
+       wifi_pwrseq: wifi-pwrseq {
+               compatible = "mmc-pwrseq-simple";
+               reset-gpios = <&gpg1 2 GPIO_ACTIVE_LOW>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&wlan_gpio_rst>;
+               post-power-on-delay-ms = <500>;
+               power-off-delay-us = <500>;
+       };
+
+       i2c_pmic: i2c-gpio-0 {
+               compatible = "i2c-gpio";
+               sda-gpios = <&gpj4 0 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+               scl-gpios = <&gpj4 3 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+               i2c-gpio,delay-us = <2>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               pmic@66 {
+                       compatible = "maxim,max8998";
+                       reg = <0x66>;
+                       interrupt-parent = <&gph0>;
+                       interrupts = <7 IRQ_TYPE_EDGE_FALLING>;
+
+                       max8998,pmic-buck1-default-dvs-idx = <1>;
+                       max8998,pmic-buck1-dvs-gpios = <&gph0 3 GPIO_ACTIVE_HIGH>,
+                                                       <&gph0 4 GPIO_ACTIVE_HIGH>;
+                       max8998,pmic-buck1-dvs-voltage = <1275000>, <1200000>,
+                                                       <1050000>, <950000>;
+
+                       max8998,pmic-buck2-default-dvs-idx = <0>;
+                       max8998,pmic-buck2-dvs-gpio = <&gph0 5 GPIO_ACTIVE_HIGH>;
+                       max8998,pmic-buck2-dvs-voltage = <1100000>, <1000000>;
+
+                       regulators {
+                               ldo2_reg: LDO2 {
+                                       regulator-name = "VALIVE_1.2V";
+                                       regulator-min-microvolt = <1200000>;
+                                       regulator-max-microvolt = <1200000>;
+                                       regulator-always-on;
+
+                                       regulator-state-mem {
+                                               regulator-on-in-suspend;
+                                       };
+                               };
+
+                               ldo3_reg: LDO3 {
+                                       regulator-name = "VUSB_1.1V";
+                                       regulator-min-microvolt = <1100000>;
+                                       regulator-max-microvolt = <1100000>;
+
+                                       regulator-state-mem {
+                                               regulator-off-in-suspend;
+                                       };
+                               };
+
+                               ldo4_reg: LDO4 {
+                                       regulator-name = "VADC_3.3V";
+                                       regulator-min-microvolt = <3300000>;
+                                       regulator-max-microvolt = <3300000>;
+                                       regulator-always-on;
+
+                                       regulator-state-mem {
+                                               regulator-off-in-suspend;
+                                       };
+                               };
+
+                               ldo5_reg: LDO5 {
+                                       regulator-name = "VTF_2.8V";
+                                       regulator-min-microvolt = <2800000>;
+                                       regulator-max-microvolt = <2800000>;
+
+                                       regulator-state-mem {
+                                               regulator-off-in-suspend;
+                                       };
+                               };
+
+                               ldo6_reg: LDO6 {
+                                       regulator-name = "LDO6";
+                                       regulator-min-microvolt = <1600000>;
+                                       regulator-max-microvolt = <3600000>;
+                               };
+
+                               ldo7_reg: LDO7 {
+                                       regulator-name = "VLCD_1.8V";
+                                       regulator-min-microvolt = <1800000>;
+                                       regulator-max-microvolt = <1800000>;
+                                       /* Till we get panel driver */
+                                       regulator-always-on;
+
+                                       regulator-state-mem {
+                                               regulator-off-in-suspend;
+                                       };
+                               };
+
+                               ldo8_reg: LDO8 {
+                                       regulator-name = "VUSB_3.3V";
+                                       regulator-min-microvolt = <3300000>;
+                                       regulator-max-microvolt = <3300000>;
+
+                                       regulator-state-mem {
+                                               regulator-off-in-suspend;
+                                       };
+                               };
+
+                               ldo9_reg: LDO9 {
+                                       regulator-name = "VCC_2.8V_PDA";
+                                       regulator-min-microvolt = <2800000>;
+                                       regulator-max-microvolt = <2800000>;
+                                       regulator-always-on;
+                               };
+
+                               ldo10_reg: LDO10 {
+                                       regulator-name = "VPLL_1.2V";
+                                       regulator-min-microvolt = <1200000>;
+                                       regulator-max-microvolt = <1200000>;
+                                       regulator-always-on;
+
+                                       regulator-state-mem {
+                                               regulator-on-in-suspend;
+                                       };
+                               };
+
+                               ldo11_reg: LDO11 {
+                                       regulator-name = "CAM_AF_3.0V";
+                                       regulator-min-microvolt = <3000000>;
+                                       regulator-max-microvolt = <3000000>;
+
+                                       regulator-state-mem {
+                                               regulator-off-in-suspend;
+                                       };
+                               };
+
+                               ldo12_reg: LDO12 {
+                                       regulator-name = "CAM_SENSOR_CORE_1.2V";
+                                       regulator-min-microvolt = <1200000>;
+                                       regulator-max-microvolt = <1200000>;
+
+                                       regulator-state-mem {
+                                               regulator-off-in-suspend;
+                                       };
+                               };
+
+                               ldo13_reg: LDO13 {
+                                       regulator-name = "VGA_VDDIO_2.8V";
+                                       regulator-min-microvolt = <2800000>;
+                                       regulator-max-microvolt = <2800000>;
+
+                                       regulator-state-mem {
+                                               regulator-off-in-suspend;
+                                       };
+                               };
+
+                               ldo14_reg: LDO14 {
+                                       regulator-name = "VGA_DVDD_1.8V";
+                                       regulator-min-microvolt = <1800000>;
+                                       regulator-max-microvolt = <1800000>;
+
+                                       regulator-state-mem {
+                                               regulator-off-in-suspend;
+                                       };
+                               };
+
+                               ldo15_reg: LDO15 {
+                                       regulator-name = "CAM_ISP_HOST_2.8V";
+                                       regulator-min-microvolt = <2800000>;
+                                       regulator-max-microvolt = <2800000>;
+
+                                       regulator-state-mem {
+                                               regulator-off-in-suspend;
+                                       };
+                               };
+
+                               ldo16_reg: LDO16 {
+                                       regulator-name = "VGA_AVDD_2.8V";
+                                       regulator-min-microvolt = <2800000>;
+                                       regulator-max-microvolt = <2800000>;
+
+                                       regulator-state-mem {
+                                               regulator-off-in-suspend;
+                                       };
+                               };
+
+                               ldo17_reg: LDO17 {
+                                       regulator-name = "VCC_3.0V_LCD";
+                                       regulator-min-microvolt = <3000000>;
+                                       regulator-max-microvolt = <3000000>;
+                                       /* Till we get panel driver */
+                                       regulator-always-on;
+
+                                       regulator-state-mem {
+                                               regulator-off-in-suspend;
+                                       };
+                               };
+
+                               buck1_reg: BUCK1 {
+                                       regulator-name = "vddarm";
+                                       regulator-min-microvolt = <750000>;
+                                       regulator-max-microvolt = <1500000>;
+
+                                       regulator-state-mem {
+                                               regulator-off-in-suspend;
+                                               regulator-suspend-microvolt = <1250000>;
+                                       };
+                               };
+
+                               buck2_reg: BUCK2 {
+                                       regulator-name = "vddint";
+                                       regulator-min-microvolt = <750000>;
+                                       regulator-max-microvolt = <1500000>;
+
+                                       regulator-state-mem {
+                                               regulator-off-in-suspend;
+                                               regulator-suspend-microvolt = <1100000>;
+                                       };
+                               };
+
+                               buck3_reg: BUCK3 {
+                                       regulator-name = "VCC_1.8V";
+                                       regulator-min-microvolt = <1800000>;
+                                       regulator-max-microvolt = <1800000>;
+                                       regulator-always-on;
+                               };
+
+                               buck4_reg: BUCK4 {
+                                       regulator-name = "CAM_ISP_CORE_1.2V";
+                                       regulator-min-microvolt = <1200000>;
+                                       regulator-max-microvolt = <1200000>;
+
+                                       regulator-state-mem {
+                                               regulator-off-in-suspend;
+                                       };
+                               };
+
+                               ap32khz_reg: EN32KHz-AP {
+                                       regulator-name = "32KHz AP";
+                                       regulator-always-on;
+                               };
+
+                               cp32khz_reg: EN32KHz-CP {
+                                       regulator-name = "32KHz CP";
+                               };
+
+                               vichg_reg: ENVICHG {
+                                       regulator-name = "VICHG";
+                                       regulator-always-on;
+                               };
+
+                               safe1_sreg: ESAFEOUT1 {
+                                       regulator-name = "SAFEOUT1";
+                               };
+
+                               safe2_sreg: ESAFEOUT2 {
+                                       regulator-name = "SAFEOUT2";
+                               };
+                       };
+               };
+       };
+
+       i2c_fuel: i2c-gpio-1 {
+               compatible = "i2c-gpio";
+               sda-gpios = <&mp05 1 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+               scl-gpios = <&mp05 0 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+               i2c-gpio,delay-us = <2>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               fuelgauge@36 {
+                       compatible = "maxim,max17040";
+                       interrupt-parent = <&vic0>;
+                       interrupts = <7>;
+                       reg = <0x36>;
+               };
+       };
+};
+
+&fimd {
+       pinctrl-names = "default";
+       pinctrl-0 = <&lcd_clk &lcd_data24>;
+       status = "okay";
+
+       samsung,invert-vden;
+       samsung,invert-vclk;
+
+       display-timings {
+               timing-0 {
+                       /* 480x800@60Hz */
+                       clock-frequency = <25628040>;
+                       hactive = <480>;
+                       vactive = <800>;
+                       hfront-porch = <16>;
+                       hback-porch = <16>;
+                       hsync-len = <2>;
+                       vfront-porch = <28>;
+                       vback-porch = <1>;
+                       vsync-len = <2>;
+               };
+       };
+};
+
+&hsotg {
+       vusb_a-supply = <&ldo8_reg>;
+       vusb_d-supply = <&ldo3_reg>;
+       dr_mode = "peripheral";
+       status = "okay";
+};
+
+&pinctrl0 {
+       wlan_bt_en: wlan-bt-en {
+               samsung,pins = "gpb-5";
+               samsung,pin-function = <EXYNOS_PIN_FUNC_OUTPUT>;
+               samsung,pin-pud = <S3C64XX_PIN_PULL_NONE>;
+               samsung,pin-val = <1>;
+       };
+
+       wlan_gpio_rst: wlan-gpio-rst {
+               samsung,pins = "gpg1-2";
+               samsung,pin-function = <EXYNOS_PIN_FUNC_OUTPUT>;
+               samsung,pin-pud = <S3C64XX_PIN_PULL_NONE>;
+       };
+
+       wifi_host_wake: wifi-host-wake {
+               samsung,pins = "gph2-4";
+               samsung,pin-function = <EXYNOS_PIN_FUNC_INPUT>;
+               samsung,pin-pud = <S3C64XX_PIN_PULL_DOWN>;
+               samsung,pin-drv = <EXYNOS4_PIN_DRV_LV1>;
+       };
+
+       tf_detect: tf-detect {
+               samsung,pins = "gph3-4";
+               samsung,pin-function = <EXYNOS_PIN_FUNC_INPUT>;
+               samsung,pin-pud = <S3C64XX_PIN_PULL_DOWN>;
+               samsung,pin-drv = <EXYNOS4_PIN_DRV_LV1>;
+       };
+
+       wifi_wake: wifi-wake {
+               samsung,pins = "gph3-5";
+               samsung,pin-function = <EXYNOS_PIN_FUNC_OUTPUT>;
+               samsung,pin-pud = <S3C64XX_PIN_PULL_NONE>;
+       };
+};
+
+&sdhci1 {
+       #address-cells = <1>;
+       #size-cells = <0>;
+
+       bus-width = <4>;
+       max-frequency = <38400000>;
+       pinctrl-0 = <&sd1_clk &sd1_cmd &sd1_bus4 &wifi_wake &wifi_host_wake &wlan_bt_en>;
+       pinctrl-names = "default";
+       cap-sd-highspeed;
+       cap-mmc-highspeed;
+
+       mmc-pwrseq = <&wifi_pwrseq>;
+       non-removable;
+       status = "okay";
+
+       wlan@1 {
+               reg = <1>;
+               compatible = "brcm,bcm4329-fmac";
+               interrupt-parent = <&gph2>;
+               interrupts = <4 IRQ_TYPE_LEVEL_HIGH>;
+               interrupt-names = "host-wake";
+       };
+};
+
+&sdhci2 {
+       bus-width = <4>;
+       cd-gpios = <&gph3 4 GPIO_ACTIVE_LOW>;
+       vmmc-supply = <&ldo5_reg>;
+       pinctrl-0 = <&sd2_clk &sd2_cmd &sd2_bus4 &tf_detect>;
+       pinctrl-names = "default";
+       status = "okay";
+};
+
+&uart0 {
+       status = "okay";
+};
+
+&uart1 {
+       status = "okay";
+};
+
+&uart2 {
+       status = "okay";
+};
+
+&usbphy {
+       status = "okay";
+       vbus-supply = <&safe1_sreg>;
+};
+
+&xusbxti {
+       clock-frequency = <24000000>;
+};
diff --git a/arch/arm/boot/dts/s5pv210-fascinate4g.dts b/arch/arm/boot/dts/s5pv210-fascinate4g.dts
new file mode 100644 (file)
index 0000000..ccf761b
--- /dev/null
@@ -0,0 +1,45 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/dts-v1/;
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include "s5pv210-aries.dtsi"
+
+/ {
+       model = "Samsung Galaxy S Fascinate 4G (SGH-T959P) based on S5PV210";
+       compatible = "samsung,fascinate4g", "samsung,aries", "samsung,s5pv210";
+
+       chosen {
+               stdout-path = &uart2;
+               /*
+                * It's hard to change those parameters in stock bootloader,
+                * since it requires special hardware/cable.
+                * Let's hardocde bootargs for now, till u-boot port is finished,
+                * with which it should be easier.
+                */
+               bootargs = "root=/dev/mmcblk1p1 rw rootwait ignore_loglevel earlyprintk";
+       };
+
+       gpio-keys {
+               compatible = "gpio-keys";
+
+               power {
+                       label = "power";
+                       gpios = <&gph2 6 GPIO_ACTIVE_LOW>;
+                       linux,code = <KEY_POWER>;
+                       wakeup-source;
+               };
+
+               vol-down {
+                       label = "volume_down";
+                       gpios = <&gph3 2 GPIO_ACTIVE_LOW>;
+                       linux,code = <KEY_VOLUMEDOWN>;
+               };
+
+               vol-up {
+                       label = "volume_up";
+                       gpios = <&gph3 1 GPIO_ACTIVE_LOW>;
+                       linux,code = <KEY_VOLUMEUP>;
+               };
+       };
+};
diff --git a/arch/arm/boot/dts/s5pv210-galaxys.dts b/arch/arm/boot/dts/s5pv210-galaxys.dts
new file mode 100644 (file)
index 0000000..8422767
--- /dev/null
@@ -0,0 +1,77 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/dts-v1/;
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include "s5pv210-aries.dtsi"
+
+/ {
+       model = "Samsung Galaxy S1 (GT-I9000) based on S5PV210";
+       compatible = "samsung,galaxys", "samsung,aries", "samsung,s5pv210";
+
+       chosen {
+               stdout-path = &uart2;
+               /*
+                * It's hard to change those parameters in stock bootloader,
+                * since it requires special hardware/cable.
+                * Let's hardocde bootargs for now, till u-boot port is finished,
+                * with which it should be easier.
+                */
+               bootargs = "root=/dev/mmcblk2p1 rw rootwait ignore_loglevel earlyprintk";
+       };
+
+       nand_pwrseq: nand-pwrseq {
+               compatible = "mmc-pwrseq-simple";
+               reset-gpios = <&gpj2 7 GPIO_ACTIVE_LOW>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&massmemory_en>;
+       };
+
+       gpio-keys {
+               compatible = "gpio-keys";
+
+               power {
+                       label = "power";
+                       gpios = <&gph2 6 GPIO_ACTIVE_LOW>;
+                       linux,code = <KEY_POWER>;
+                       wakeup-source;
+               };
+
+               vol-down {
+                       label = "volume_down";
+                       gpios = <&gph3 1 GPIO_ACTIVE_LOW>;
+                       linux,code = <KEY_VOLUMEDOWN>;
+               };
+
+               vol-up {
+                       label = "volume_up";
+                       gpios = <&gph3 2 GPIO_ACTIVE_LOW>;
+                       linux,code = <KEY_VOLUMEUP>;
+               };
+
+               home {
+                       label = "home";
+                       gpios = <&gph3 5 GPIO_ACTIVE_LOW>;
+                       linux,code = <KEY_HOME>;
+                       wakeup-source;
+               };
+       };
+};
+
+&pinctrl0 {
+       massmemory_en: massmemory-en {
+               samsung,pins = "gpj2-7";
+               samsung,pin-function = <EXYNOS_PIN_FUNC_OUTPUT>;
+               samsung,pin-pud = <S3C64XX_PIN_PULL_NONE>;
+               samsung,pin-drv = <EXYNOS4_PIN_DRV_LV1>;
+       };
+};
+
+&sdhci0 {
+       bus-width = <4>;
+       non-removable;
+       mmc-pwrseq = <&nand_pwrseq>;
+       pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4>;
+       pinctrl-names = "default";
+       status = "okay";
+};
index 3a79fea..7f0c9d4 100644 (file)
        gph2: gph2 {
                gpio-controller;
                #gpio-cells = <2>;
+
+               interrupt-controller;
                #interrupt-cells = <2>;
        };
 
index e57191f..1c01a6f 100644 (file)
 #define PIN_PB22__GPIO                 PINMUX_PIN(PIN_PB22, 0, 0)
 #define PIN_PB22__LCDDAT11             PINMUX_PIN(PIN_PB22, 1, 1)
 #define PIN_PB22__A11                  PINMUX_PIN(PIN_PB22, 2, 1)
-#define PIN_PB22__TDO                  PINMUX_PIN(PIN_PB22, 3, 1)
+#define PIN_PB22__TD0                  PINMUX_PIN(PIN_PB22, 3, 1)
 #define PIN_PB22__TIOA2                        PINMUX_PIN(PIN_PB22, 4, 2)
 #define PIN_PB22__FLEXCOM3_IO1         PINMUX_PIN(PIN_PB22, 5, 3)
 #define PIN_PB22__GMDC                 PINMUX_PIN(PIN_PB22, 6, 3)
 #define PIN_PC14__LCDDAT6              PINMUX_PIN(PIN_PC14, 1, 2)
 #define PIN_PC14__GRX0                 PINMUX_PIN(PIN_PC14, 2, 1)
 #define PIN_PC14__ISC_D5               PINMUX_PIN(PIN_PC14, 3, 1)
-#define PIN_PC14__TDO                  PINMUX_PIN(PIN_PC14, 5, 2)
+#define PIN_PC14__TD0                  PINMUX_PIN(PIN_PC14, 5, 2)
 #define PIN_PC14__A3                   PINMUX_PIN(PIN_PC14, 6, 2)
 #define PIN_PC15                       79
 #define PIN_PC15__GPIO                 PINMUX_PIN(PIN_PC15, 0, 0)
index eae5e1e..1408fa4 100644 (file)
                                atmel,external-irqs = <47>;
                        };
 
-                       pinctrl@fffff200 {
+                       pinctrl: pinctrl@fffff200 {
                                #address-cells = <1>;
                                #size-cells = <1>;
                                compatible = "atmel,sama5d3-pinctrl", "atmel,at91sam9x5-pinctrl", "simple-bus";
                                };
                        };
 
-                       rstc@fffffe00 {
+                       reset_controller: rstc@fffffe00 {
                                compatible = "atmel,sama5d3-rstc", "atmel,at91sam9g45-rstc";
                                reg = <0xfffffe00 0x10>;
                                clocks = <&clk32k>;
                        };
 
-                       shutdown-controller@fffffe10 {
+                       shutdown_controller: shutdown-controller@fffffe10 {
                                compatible = "atmel,at91sam9x5-shdwc";
                                reg = <0xfffffe10 0x10>;
                                clocks = <&clk32k>;
                                clocks = <&mck>;
                        };
 
-                       watchdog@fffffe40 {
+                       watchdog: watchdog@fffffe40 {
                                compatible = "atmel,at91sam9260-wdt";
                                reg = <0xfffffe40 0x10>;
                                interrupts = <4 IRQ_TYPE_LEVEL_HIGH 7>;
index 0cf9bed..92a35a1 100644 (file)
                        };
 
                        pmc: pmc@f0018000 {
-                               compatible = "atmel,sama5d3-pmc", "syscon";
+                               compatible = "atmel,sama5d4-pmc", "syscon";
                                reg = <0xf0018000 0x120>;
                                interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>;
                                interrupt-controller;
index 3d65f1f..daac0c6 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Device Tree Source for the KZM-A9-GT board
  *
@@ -5,10 +6,6 @@
  *
  * Based on sh73a0-kzm9g.dts
  * Copyright (C) 2012 Renesas Solutions Corp.
- *
- * 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.
  */
 
 /dts-v1/;
index c953648..e8f0a07 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Device Tree Source for the SH73A0 SoC
  *
  * Copyright (C) 2012 Renesas Solutions Corp.
- *
- * 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 <dt-bindings/clock/sh73a0-clock.h>
index 791ca15..a4dcb68 100644 (file)
                        status = "disabled";
                };
 
+               spi0: spi@ffda4000 {
+                       compatible = "snps,dw-apb-ssi";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       reg = <0xffda4000 0x100>;
+                       interrupts = <0 101 4>;
+                       num-cs = <4>;
+                       /*32bit_access;*/
+                       clocks = <&spi_m_clk>;
+                       status = "disabled";
+               };
+
                spi1: spi@ffda5000 {
                        compatible = "snps,dw-apb-ssi";
                        #address-cells = <1>;
index 733678b..fca76a6 100644 (file)
                reg-names = "fsmc_regs", "nand_data", "nand_addr", "nand_cmd";
                clocks = <&hclksmc>;
                status = "okay";
-               timings = /bits/ 8 <0 0 0 0x10 0x0a 0>;
 
                partition@0 {
                label = "X-Loader(NAND)";
index ede77e0..e35d782 100644 (file)
                        interrupt-parent = <&exti>;
                        interrupts = <17 1>;
                        interrupt-names = "alarm";
-                       st,syscfg = <&pwrcfg>;
+                       st,syscfg = <&pwrcfg 0x00 0x100>;
                        status = "disabled";
                };
 
                        compatible = "st,stm32-iwdg";
                        reg = <0x40003000 0x400>;
                        clocks = <&clk_lsi>;
+                       clock-names = "lsi";
                        status = "disabled";
                };
 
index 1479e3e..f48d06a 100644 (file)
                        interrupt-parent = <&exti>;
                        interrupts = <17 1>;
                        interrupt-names = "alarm";
-                       st,syscfg = <&pwrcfg>;
+                       st,syscfg = <&pwrcfg 0x00 0x100>;
                        status = "disabled";
                };
 
index 4839db1..c485127 100644 (file)
                                };
                        };
 
+                       ethernet0_rgmii_pins_a: rgmii-0 {
+                               pins1 {
+                                       pinmux = <STM32_PINMUX('G', 5, AF11)>, /* ETH_RGMII_CLK125 */
+                                                <STM32_PINMUX('G', 4, AF11)>, /* ETH_RGMII_GTX_CLK */
+                                                <STM32_PINMUX('G', 13, AF11)>, /* ETH_RGMII_TXD0 */
+                                                <STM32_PINMUX('G', 14, AF11)>, /* ETH_RGMII_TXD1 */
+                                                <STM32_PINMUX('C', 2, AF11)>, /* ETH_RGMII_TXD2 */
+                                                <STM32_PINMUX('E', 2, AF11)>, /* ETH_RGMII_TXD3 */
+                                                <STM32_PINMUX('B', 11, AF11)>, /* ETH_RGMII_TX_CTL */
+                                                <STM32_PINMUX('A', 2, AF11)>, /* ETH_MDIO */
+                                                <STM32_PINMUX('C', 1, AF11)>; /* ETH_MDC */
+                                       bias-disable;
+                                       drive-push-pull;
+                                       slew-rate = <3>;
+                               };
+                               pins2 {
+                                       pinmux = <STM32_PINMUX('C', 4, AF11)>, /* ETH_RGMII_RXD0 */
+                                                <STM32_PINMUX('C', 5, AF11)>, /* ETH_RGMII_RXD1 */
+                                                <STM32_PINMUX('B', 0, AF11)>, /* ETH_RGMII_RXD2 */
+                                                <STM32_PINMUX('B', 1, AF11)>, /* ETH_RGMII_RXD3 */
+                                                <STM32_PINMUX('A', 1, AF11)>, /* ETH_RGMII_RX_CLK */
+                                                <STM32_PINMUX('A', 7, AF11)>; /* ETH_RGMII_RX_CTL */
+                                       bias-disable;
+                               };
+                       };
+
+                       ethernet0_rgmii_pins_sleep_a: rgmii-sleep-0 {
+                               pins1 {
+                                       pinmux = <STM32_PINMUX('G', 5, ANALOG)>, /* ETH_RGMII_CLK125 */
+                                                <STM32_PINMUX('G', 4, ANALOG)>, /* ETH_RGMII_GTX_CLK */
+                                                <STM32_PINMUX('G', 13, ANALOG)>, /* ETH_RGMII_TXD0 */
+                                                <STM32_PINMUX('G', 14, ANALOG)>, /* ETH_RGMII_TXD1 */
+                                                <STM32_PINMUX('C', 2, ANALOG)>, /* ETH_RGMII_TXD2 */
+                                                <STM32_PINMUX('E', 2, ANALOG)>, /* ETH_RGMII_TXD3 */
+                                                <STM32_PINMUX('B', 11, ANALOG)>, /* ETH_RGMII_TX_CTL */
+                                                <STM32_PINMUX('A', 2, ANALOG)>, /* ETH_MDIO */
+                                                <STM32_PINMUX('C', 1, ANALOG)>, /* ETH_MDC */
+                                                <STM32_PINMUX('C', 4, ANALOG)>, /* ETH_RGMII_RXD0 */
+                                                <STM32_PINMUX('C', 5, ANALOG)>, /* ETH_RGMII_RXD1 */
+                                                <STM32_PINMUX('B', 0, ANALOG)>, /* ETH_RGMII_RXD2 */
+                                                <STM32_PINMUX('B', 1, ANALOG)>, /* ETH_RGMII_RXD3 */
+                                                <STM32_PINMUX('A', 1, ANALOG)>, /* ETH_RGMII_RX_CLK */
+                                                <STM32_PINMUX('A', 7, ANALOG)>; /* ETH_RGMII_RX_CTL */
+                               };
+                       };
+
                        i2c1_pins_a: i2c1-0 {
                                pins {
                                        pinmux = <STM32_PINMUX('D', 12, AF5)>, /* I2C1_SCL */
                                };
                        };
 
+                       m_can1_pins_a: m-can1-0 {
+                               pins1 {
+                                       pinmux = <STM32_PINMUX('H', 13, AF9)>; /* CAN1_TX */
+                                       slew-rate = <1>;
+                                       drive-push-pull;
+                                       bias-disable;
+                               };
+                               pins2 {
+                                       pinmux = <STM32_PINMUX('I', 9, AF9)>; /* CAN1_RX */
+                                       bias-disable;
+                               };
+                       };
+
                        pwm2_pins_a: pwm2-0 {
                                pins {
                                        pinmux = <STM32_PINMUX('A', 3, AF1)>; /* TIM2_CH4 */
                        pins-are-numbered;
                        interrupt-parent = <&exti>;
                        st,syscfg = <&exti 0x60 0xff>;
-                       status = "disabled";
 
                        gpioz: gpio@54004000 {
                                gpio-controller;
                                        slew-rate = <0>;
                                };
                        };
+
+                       spi1_pins_a: spi1-0 {
+                               pins1 {
+                                       pinmux = <STM32_PINMUX('Z', 0, AF5)>, /* SPI1_SCK */
+                                                <STM32_PINMUX('Z', 2, AF5)>; /* SPI1_MOSI */
+                                       bias-disable;
+                                       drive-push-pull;
+                                       slew-rate = <1>;
+                               };
+
+                               pins2 {
+                                       pinmux = <STM32_PINMUX('Z', 1, AF5)>; /* SPI1_MISO */
+                                       bias-disable;
+                               };
+                       };
                };
        };
 };
index ae33653..f77bea4 100644 (file)
        };
 };
 
+&i2c4 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&i2c4_pins_a>;
+       i2c-scl-rising-time-ns = <185>;
+       i2c-scl-falling-time-ns = <20>;
+       status = "okay";
+};
+
+&iwdg2 {
+       timeout-sec = <32>;
+       status = "okay";
+};
+
 &rng1 {
        status = "okay";
 };
 
+&rtc {
+       status = "okay";
+};
+
 &timers6 {
        status = "okay";
        timer@5 {
        };
 };
 
-&i2c4 {
-       pinctrl-names = "default";
-       pinctrl-0 = <&i2c4_pins_a>;
-       i2c-scl-rising-time-ns = <185>;
-       i2c-scl-falling-time-ns = <20>;
-       status = "okay";
-};
-
 &uart4 {
        pinctrl-names = "default";
        pinctrl-0 = <&uart4_pins_a>;
index 9382d80..372bc2e 100644 (file)
 
        aliases {
                serial0 = &uart4;
+               ethernet0 = &ethernet0;
+       };
+};
+
+&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>;
+               };
        };
 };
 
        status = "okay";
 };
 
+&m_can1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&m_can1_pins_a>;
+       status = "okay";
+};
+
 &qspi {
        pinctrl-names = "default";
        pinctrl-0 = <&qspi_clk_pins_a &qspi_bk1_pins_a &qspi_bk2_pins_a>;
        };
 };
 
+&spi1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&spi1_pins_a>;
+       status = "disabled";
+};
+
 &timers2 {
        status = "disabled";
        pwm {
        };
 };
 
+&usbh_ehci {
+       phys = <&usbphyc_port0>;
+       phy-names = "usb";
+       status = "okay";
+};
+
+&usbotg_hs {
+       dr_mode = "peripheral";
+       phys = <&usbphyc_port1 0>;
+       phy-names = "usb2-phy";
+       status = "okay";
+};
+
 &usbphyc {
        status = "okay";
 };
index 7d17538..661be94 100644 (file)
                cpu_on = <0x84000003>;
        };
 
-       aliases {
-               gpio0 = &gpioa;
-               gpio1 = &gpiob;
-               gpio2 = &gpioc;
-               gpio3 = &gpiod;
-               gpio4 = &gpioe;
-               gpio5 = &gpiof;
-               gpio6 = &gpiog;
-               gpio7 = &gpioh;
-               gpio8 = &gpioi;
-               gpio9 = &gpioj;
-               gpio10 = &gpiok;
-       };
-
        intc: interrupt-controller@a0021000 {
                compatible = "arm,cortex-a7-gic";
                #interrupt-cells = <3>;
                        };
                };
 
+               spi2: spi@4000b000 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       compatible = "st,stm32h7-spi";
+                       reg = <0x4000b000 0x400>;
+                       interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&rcc SPI2_K>;
+                       resets = <&rcc SPI2_R>;
+                       dmas = <&dmamux1 39 0x400 0x05>,
+                              <&dmamux1 40 0x400 0x05>;
+                       dma-names = "rx", "tx";
+                       status = "disabled";
+               };
+
+               spi3: spi@4000c000 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       compatible = "st,stm32h7-spi";
+                       reg = <0x4000c000 0x400>;
+                       interrupts = <GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&rcc SPI3_K>;
+                       resets = <&rcc SPI3_R>;
+                       dmas = <&dmamux1 61 0x400 0x05>,
+                              <&dmamux1 62 0x400 0x05>;
+                       dma-names = "rx", "tx";
+                       status = "disabled";
+               };
+
                usart2: serial@4000e000 {
                        compatible = "st,stm32h7-uart";
                        reg = <0x4000e000 0x400>;
                        status = "disabled";
                };
 
+               spi1: spi@44004000 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       compatible = "st,stm32h7-spi";
+                       reg = <0x44004000 0x400>;
+                       interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&rcc SPI1_K>;
+                       resets = <&rcc SPI1_R>;
+                       dmas = <&dmamux1 37 0x400 0x05>,
+                              <&dmamux1 38 0x400 0x05>;
+                       dma-names = "rx", "tx";
+                       status = "disabled";
+               };
+
+               spi4: spi@44005000 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       compatible = "st,stm32h7-spi";
+                       reg = <0x44005000 0x400>;
+                       interrupts = <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&rcc SPI4_K>;
+                       resets = <&rcc SPI4_R>;
+                       dmas = <&dmamux1 83 0x400 0x05>,
+                              <&dmamux1 84 0x400 0x05>;
+                       dma-names = "rx", "tx";
+                       status = "disabled";
+               };
+
                timers15: timer@44006000 {
                        #address-cells = <1>;
                        #size-cells = <0>;
                        };
                };
 
+               spi5: spi@44009000 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       compatible = "st,stm32h7-spi";
+                       reg = <0x44009000 0x400>;
+                       interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&rcc SPI5_K>;
+                       resets = <&rcc SPI5_R>;
+                       dmas = <&dmamux1 85 0x400 0x05>,
+                              <&dmamux1 86 0x400 0x05>;
+                       dma-names = "rx", "tx";
+                       status = "disabled";
+               };
+
+               dfsdm: dfsdm@4400d000 {
+                       compatible = "st,stm32mp1-dfsdm";
+                       reg = <0x4400d000 0x800>;
+                       clocks = <&rcc DFSDM_K>;
+                       clock-names = "dfsdm";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       status = "disabled";
+
+                       dfsdm0: filter@0 {
+                               compatible = "st,stm32-dfsdm-adc";
+                               #io-channel-cells = <1>;
+                               reg = <0>;
+                               interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>;
+                               dmas = <&dmamux1 101 0x400 0x01>;
+                               dma-names = "rx";
+                               status = "disabled";
+                       };
+
+                       dfsdm1: filter@1 {
+                               compatible = "st,stm32-dfsdm-adc";
+                               #io-channel-cells = <1>;
+                               reg = <1>;
+                               interrupts = <GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>;
+                               dmas = <&dmamux1 102 0x400 0x01>;
+                               dma-names = "rx";
+                               status = "disabled";
+                       };
+
+                       dfsdm2: filter@2 {
+                               compatible = "st,stm32-dfsdm-adc";
+                               #io-channel-cells = <1>;
+                               reg = <2>;
+                               interrupts = <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>;
+                               dmas = <&dmamux1 103 0x400 0x01>;
+                               dma-names = "rx";
+                               status = "disabled";
+                       };
+
+                       dfsdm3: filter@3 {
+                               compatible = "st,stm32-dfsdm-adc";
+                               #io-channel-cells = <1>;
+                               reg = <3>;
+                               interrupts = <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>;
+                               dmas = <&dmamux1 104 0x400 0x01>;
+                               dma-names = "rx";
+                               status = "disabled";
+                       };
+
+                       dfsdm4: filter@4 {
+                               compatible = "st,stm32-dfsdm-adc";
+                               #io-channel-cells = <1>;
+                               reg = <4>;
+                               interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>;
+                               dmas = <&dmamux1 91 0x400 0x01>;
+                               dma-names = "rx";
+                               status = "disabled";
+                       };
+
+                       dfsdm5: filter@5 {
+                               compatible = "st,stm32-dfsdm-adc";
+                               #io-channel-cells = <1>;
+                               reg = <5>;
+                               interrupts = <GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>;
+                               dmas = <&dmamux1 92 0x400 0x01>;
+                               dma-names = "rx";
+                               status = "disabled";
+                       };
+               };
+
+               m_can1: can@4400e000 {
+                       compatible = "bosch,m_can";
+                       reg = <0x4400e000 0x400>, <0x44011000 0x2800>;
+                       reg-names = "m_can", "message_ram";
+                       interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
+                       interrupt-names = "int0", "int1";
+                       clocks = <&rcc CK_HSE>, <&rcc FDCAN_K>;
+                       clock-names = "hclk", "cclk";
+                       bosch,mram-cfg = <0x0 0 0 32 0 0 2 2>;
+                       status = "disabled";
+               };
+
+               m_can2: can@4400f000 {
+                       compatible = "bosch,m_can";
+                       reg = <0x4400f000 0x400>, <0x44011000 0x2800>;
+                       reg-names = "m_can", "message_ram";
+                       interrupts = <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>;
+                       interrupt-names = "int0", "int1";
+                       clocks = <&rcc CK_HSE>, <&rcc FDCAN_K>;
+                       clock-names = "hclk", "cclk";
+                       bosch,mram-cfg = <0x0 0 0 32 0 0 2 2>;
+                       status = "disabled";
+               };
+
                dma1: dma@48000000 {
                        compatible = "st,stm32-dma";
                        reg = <0x48000000 0x400>;
                        clocks = <&rcc DMAMUX>;
                };
 
+               adc: adc@48003000 {
+                       compatible = "st,stm32mp1-adc-core";
+                       reg = <0x48003000 0x400>;
+                       interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&rcc ADC12>, <&rcc ADC12_K>;
+                       clock-names = "bus", "adc";
+                       interrupt-controller;
+                       #interrupt-cells = <1>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       status = "disabled";
+
+                       adc1: adc@0 {
+                               compatible = "st,stm32mp1-adc";
+                               #io-channel-cells = <1>;
+                               reg = <0x0>;
+                               interrupt-parent = <&adc>;
+                               interrupts = <0>;
+                               dmas = <&dmamux1 9 0x400 0x01>;
+                               dma-names = "rx";
+                               status = "disabled";
+                       };
+
+                       adc2: adc@100 {
+                               compatible = "st,stm32mp1-adc";
+                               #io-channel-cells = <1>;
+                               reg = <0x100>;
+                               interrupt-parent = <&adc>;
+                               interrupts = <1>;
+                               dmas = <&dmamux1 10 0x400 0x01>;
+                               dma-names = "rx";
+                               status = "disabled";
+                       };
+               };
+
+               usbotg_hs: usb-otg@49000000 {
+                       compatible = "snps,dwc2";
+                       reg = <0x49000000 0x10000>;
+                       clocks = <&rcc USBO_K>;
+                       clock-names = "otg";
+                       resets = <&rcc USBO_R>;
+                       reset-names = "dwc2";
+                       interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>;
+                       g-rx-fifo-size = <256>;
+                       g-np-tx-fifo-size = <32>;
+                       g-tx-fifo-size = <128 128 64 64 64 64 32 32>;
+                       dr_mode = "otg";
+                       status = "disabled";
+               };
+
                rcc: rcc@50000000 {
                        compatible = "st,stm32mp1-rcc", "syscon";
                        reg = <0x50000000 0x1000>;
                        reg = <0x5000d000 0x400>;
                };
 
+               syscfg: syscon@50020000 {
+                       compatible = "st,stm32mp157-syscfg", "syscon";
+                       reg = <0x50020000 0x400>;
+               };
+
                lptimer2: timer@50021000 {
                        #address-cells = <1>;
                        #size-cells = <0>;
                        status = "disabled";
                };
 
+               hash1: hash@54002000 {
+                       compatible = "st,stm32f756-hash";
+                       reg = <0x54002000 0x400>;
+                       interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&rcc HASH1>;
+                       resets = <&rcc HASH1_R>;
+                       dmas = <&mdma1 31 0x10 0x1000A02 0x0 0x0 0x0>;
+                       dma-names = "in";
+                       dma-maxburst = <2>;
+                       status = "disabled";
+               };
+
                rng1: rng@54003000 {
                        compatible = "st,stm32-rng";
                        reg = <0x54003000 0x400>;
                        status = "disabled";
                };
 
+               stmmac_axi_config_0: stmmac-axi-config {
+                       snps,wr_osr_lmt = <0x7>;
+                       snps,rd_osr_lmt = <0x7>;
+                       snps,blen = <0 0 0 0 16 8 4>;
+               };
+
+               ethernet0: ethernet@5800a000 {
+                       compatible = "st,stm32mp1-dwmac", "snps,dwmac-4.20a";
+                       reg = <0x5800a000 0x2000>;
+                       reg-names = "stmmaceth";
+                       interrupts-extended = <&intc GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>;
+                       interrupt-names = "macirq";
+                       clock-names = "stmmaceth",
+                                     "mac-clk-tx",
+                                     "mac-clk-rx",
+                                     "ethstp",
+                                     "syscfg-clk";
+                       clocks = <&rcc ETHMAC>,
+                                <&rcc ETHTX>,
+                                <&rcc ETHRX>,
+                                <&rcc ETHSTP>,
+                                <&rcc SYSCFG>;
+                       st,syscon = <&syscfg 0x4>;
+                       snps,mixed-burst;
+                       snps,pbl = <2>;
+                       snps,axi-config = <&stmmac_axi_config_0>;
+                       snps,tso;
+                       status = "disabled";
+               };
+
                usbh_ohci: usbh-ohci@5800c000 {
                        compatible = "generic-ohci";
                        reg = <0x5800c000 0x1000>;
                        status = "disabled";
                };
 
+               iwdg2: watchdog@5a002000 {
+                       compatible = "st,stm32mp1-iwdg";
+                       reg = <0x5a002000 0x400>;
+                       clocks = <&rcc IWDG2>, <&rcc CK_LSI>;
+                       clock-names = "pclk", "lsi";
+                       status = "disabled";
+               };
+
                usbphyc: usbphyc@5a006000 {
                        #address-cells = <1>;
                        #size-cells = <0>;
                        status = "disabled";
                };
 
+               spi6: spi@5c001000 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       compatible = "st,stm32h7-spi";
+                       reg = <0x5c001000 0x400>;
+                       interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&rcc SPI6_K>;
+                       resets = <&rcc SPI6_R>;
+                       dmas = <&mdma1 34 0x0 0x40008 0x0 0x0 0>,
+                              <&mdma1 35 0x0 0x40002 0x0 0x0 0>;
+                       dma-names = "rx", "tx";
+                       status = "disabled";
+               };
+
                i2c4: i2c@5c002000 {
                        compatible = "st,stm32f7-i2c";
                        reg = <0x5c002000 0x400>;
                        status = "disabled";
                };
 
+               rtc: rtc@5c004000 {
+                       compatible = "st,stm32mp1-rtc";
+                       reg = <0x5c004000 0x400>;
+                       clocks = <&rcc RTCAPB>, <&rcc RTC>;
+                       clock-names = "pclk", "rtc_ck";
+                       interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>;
+                       status = "disabled";
+               };
+
                i2c6: i2c@5c009000 {
                        compatible = "st,stm32f7-i2c";
                        reg = <0x5c009000 0x400>;
index 5d09652..71c27ea 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright 2014 Open Source Support GmbH
  *
- * David Lanzendörfer <david.lanzendoerfer@o2s.ch>
+ * David Lanzendörfer <david.lanzendoerfer@o2s.ch>
  *
  * 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
index 3a1c6b4..3d62a89 100644 (file)
                #size-cells = <1>;
                ranges;
 
-               sram-controller@1c00000 {
-                       compatible = "allwinner,sun4i-a10-sram-controller";
+               system-control@1c00000 {
+                       compatible = "allwinner,sun4i-a10-system-control";
                        reg = <0x01c00000 0x30>;
                        #address-cells = <1>;
                        #size-cells = <1>;
                        status = "disabled";
                };
 
+               mali: gpu@1c40000 {
+                       compatible = "allwinner,sun4i-a10-mali", "arm,mali-400";
+                       reg = <0x01c40000 0x10000>;
+                       interrupts = <69>,
+                                    <70>,
+                                    <71>,
+                                    <72>,
+                                    <73>;
+                       interrupt-names = "gp",
+                                         "gpmmu",
+                                         "pp0",
+                                         "ppmmu0",
+                                         "pmu";
+                       clocks = <&ccu CLK_AHB_GPU>, <&ccu CLK_GPU>;
+                       clock-names = "bus", "core";
+                       resets = <&ccu RST_GPU>;
+
+                       assigned-clocks = <&ccu CLK_GPU>;
+                       assigned-clock-rates = <384000000>;
+               };
+
                fe0: display-frontend@1e00000 {
                        compatible = "allwinner,sun4i-a10-display-frontend";
                        reg = <0x01e00000 0x20000>;
index 07f2248..8bfb366 100644 (file)
                #size-cells = <1>;
                ranges;
 
-               sram-controller@1c00000 {
-                       compatible = "allwinner,sun4i-a10-sram-controller";
+               system-control@1c00000 {
+                       compatible = "allwinner,sun5i-a13-system-control";
                        reg = <0x01c00000 0x30>;
                        #address-cells = <1>;
                        #size-cells = <1>;
                                #address-cells = <1>;
                                #size-cells = <1>;
                                ranges = <0 0x00000000 0xc000>;
-                       };
 
-                       emac_sram: sram-section@8000 {
-                               compatible = "allwinner,sun4i-a10-sram-a3-a4";
-                               reg = <0x8000 0x4000>;
-                               status = "disabled";
+                               emac_sram: sram-section@8000 {
+                                       compatible = "allwinner,sun5i-a13-sram-a3-a4",
+                                                    "allwinner,sun4i-a10-sram-a3-a4";
+                                       reg = <0x8000 0x4000>;
+                                       status = "disabled";
+                               };
                        };
 
                        sram_d: sram@10000 {
                                ranges = <0 0x00010000 0x1000>;
 
                                otg_sram: sram-section@0 {
-                                       compatible = "allwinner,sun4i-a10-sram-d";
+                                       compatible = "allwinner,sun5i-a13-sram-d",
+                                                    "allwinner,sun4i-a10-sram-d";
                                        reg = <0x0000 0x1000>;
                                        status = "disabled";
                                };
                        };
+
+                       sram_c: sram@1d00000 {
+                               compatible = "mmio-sram";
+                               reg = <0x01d00000 0xd0000>;
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+                               ranges = <0 0x01d00000 0xd0000>;
+
+                               ve_sram: sram-section@0 {
+                                       compatible = "allwinner,sun5i-a13-sram-c1",
+                                                    "allwinner,sun4i-a10-sram-c1";
+                                       reg = <0x000000 0x80000>;
+                               };
+                       };
                };
 
                dma: dma-controller@1c02000 {
index c729925..debc0bf 100644 (file)
                        compatible = "arm,cortex-a7";
                        device_type = "cpu";
                        reg = <1>;
+                       clocks = <&ccu CLK_CPU>;
+                       clock-latency = <244144>; /* 8 32k periods */
+                       operating-points = <
+                               /* kHz    uV */
+                               1008000 1200000
+                               864000  1200000
+                               720000  1100000
+                               480000  1000000
+                               >;
+                       #cooling-cells = <2>;
                };
 
                cpu@2 {
                        compatible = "arm,cortex-a7";
                        device_type = "cpu";
                        reg = <2>;
+                       clocks = <&ccu CLK_CPU>;
+                       clock-latency = <244144>; /* 8 32k periods */
+                       operating-points = <
+                               /* kHz    uV */
+                               1008000 1200000
+                               864000  1200000
+                               720000  1100000
+                               480000  1000000
+                               >;
+                       #cooling-cells = <2>;
                };
 
                cpu@3 {
                        compatible = "arm,cortex-a7";
                        device_type = "cpu";
                        reg = <3>;
+                       clocks = <&ccu CLK_CPU>;
+                       clock-latency = <244144>; /* 8 32k periods */
+                       operating-points = <
+                               /* kHz    uV */
+                               1008000 1200000
+                               864000  1200000
+                               720000  1100000
+                               480000  1000000
+                               >;
+                       #cooling-cells = <2>;
                };
        };
 
index e529e4f..9c52712 100644 (file)
                        compatible = "arm,cortex-a7";
                        device_type = "cpu";
                        reg = <1>;
+                       clocks = <&ccu CLK_CPU>;
+                       clock-latency = <244144>; /* 8 32k periods */
+                       operating-points = <
+                               /* kHz    uV */
+                               960000  1400000
+                               912000  1400000
+                               864000  1300000
+                               720000  1200000
+                               528000  1100000
+                               312000  1000000
+                               144000  1000000
+                               >;
+                       #cooling-cells = <2>;
                };
        };
 
                #size-cells = <1>;
                ranges;
 
-               sram-controller@1c00000 {
-                       compatible = "allwinner,sun4i-a10-sram-controller";
+               system-control@1c00000 {
+                       compatible = "allwinner,sun7i-a20-system-control",
+                                    "allwinner,sun4i-a10-system-control";
                        reg = <0x01c00000 0x30>;
                        #address-cells = <1>;
                        #size-cells = <1>;
                                ranges = <0 0x00000000 0xc000>;
 
                                emac_sram: sram-section@8000 {
-                                       compatible = "allwinner,sun4i-a10-sram-a3-a4";
+                                       compatible = "allwinner,sun7i-a20-sram-a3-a4",
+                                                    "allwinner,sun4i-a10-sram-a3-a4";
                                        reg = <0x8000 0x4000>;
                                        status = "disabled";
                                };
                                ranges = <0 0x00010000 0x1000>;
 
                                otg_sram: sram-section@0 {
-                                       compatible = "allwinner,sun4i-a10-sram-d";
+                                       compatible = "allwinner,sun7i-a20-sram-d",
+                                                    "allwinner,sun4i-a10-sram-d";
                                        reg = <0x0000 0x1000>;
                                        status = "disabled";
                                };
                        };
+
+                       sram_c: sram@1d00000 {
+                               compatible = "mmio-sram";
+                               reg = <0x01d00000 0xd0000>;
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+                               ranges = <0 0x01d00000 0xd0000>;
+
+                               ve_sram: sram-section@0 {
+                                       compatible = "allwinner,sun7i-a20-sram-c1",
+                                                    "allwinner,sun4i-a10-sram-c1";
+                                       reg = <0x000000 0x80000>;
+                               };
+                       };
                };
 
                nmi_intc: interrupt-controller@1c00030 {
index 44f3cad..c16ffcc 100644 (file)
                #size-cells = <1>;
                ranges;
 
+               system-control@1c00000 {
+                       compatible = "allwinner,sun8i-a23-system-control";
+                       reg = <0x01c00000 0x30>;
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges;
+
+                       sram_c: sram@1d00000 {
+                               compatible = "mmio-sram";
+                               reg = <0x01d00000 0x80000>;
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+                               ranges = <0 0x01d00000 0x80000>;
+
+                               ve_sram: sram-section@0 {
+                                       compatible = "allwinner,sun8i-a23-sram-c1",
+                                                    "allwinner,sun4i-a10-sram-c1";
+                                       reg = <0x000000 0x80000>;
+                               };
+                       };
+               };
+
                dma: dma-controller@1c02000 {
                        compatible = "allwinner,sun8i-a23-dma";
                        reg = <0x01c02000 0x1000>;
index 8d278ee..4e92741 100644 (file)
                };
 
                cpu@1 {
+                       clocks = <&ccu CLK_CPUX>;
+                       clock-names = "cpu";
                        operating-points-v2 = <&cpu0_opp_table>;
+                       #cooling-cells = <2>;
                };
 
                cpu@2 {
                        compatible = "arm,cortex-a7";
                        device_type = "cpu";
                        reg = <2>;
+                       clocks = <&ccu CLK_CPUX>;
+                       clock-names = "cpu";
                        operating-points-v2 = <&cpu0_opp_table>;
+                       #cooling-cells = <2>;
                };
 
                cpu@3 {
                        compatible = "arm,cortex-a7";
                        device_type = "cpu";
                        reg = <3>;
+                       clocks = <&ccu CLK_CPUX>;
+                       clock-names = "cpu";
                        operating-points-v2 = <&cpu0_opp_table>;
+                       #cooling-cells = <2>;
                };
        };
 
index 36eceba..1c012a4 100644 (file)
        };
 };
 
+&cpu0 {
+       cpu-supply = <&reg_dcdc2>;
+};
+
+&cpu100 {
+       cpu-supply = <&reg_dcdc3>;
+};
+
 &ehci0 {
        status = "okay";
 };
index 3b579d7..c7ce415 100644 (file)
        };
 };
 
+&cpu0 {
+       cpu-supply = <&reg_dcdc2>;
+};
+
+&cpu100 {
+       cpu-supply = <&reg_dcdc3>;
+};
+
 &de {
        status = "okay";
 };
index 88decb0..e5f0645 100644 (file)
        };
 };
 
+&cpu0 {
+       cpu-supply = <&reg_dcdc2>;
+};
+
+&cpu100 {
+       cpu-supply = <&reg_dcdc3>;
+};
+
 &ehci0 {
        /* GL830 USB-to-SATA bridge here */
        status = "okay";
index 2be23d6..00a02b0 100644 (file)
                        reset-names = "stmmaceth";
                        clocks = <&ccu 27>;
                        clock-names = "stmmaceth";
-                       #address-cells = <1>;
-                       #size-cells = <0>;
                        status = "disabled";
 
                        mdio: mdio {
index 7d01f93..1db2541 100644 (file)
                };
        };
 
+       reg_vdd_cpux: vdd-cpux-regulator {
+               compatible = "regulator-gpio";
+               regulator-name = "vdd-cpux";
+               regulator-type = "voltage";
+               regulator-boot-on;
+               regulator-always-on;
+               regulator-min-microvolt = <1100000>;
+               regulator-max-microvolt = <1300000>;
+               regulator-ramp-delay = <50>; /* 4ms */
+
+               gpios = <&r_pio 0 1 GPIO_ACTIVE_HIGH>; /* PL1 */
+               enable-active-high;
+               gpios-states = <0x1>;
+               states = <1100000 0x0
+                         1300000 0x1>;
+       };
+
        wifi_pwrseq: wifi_pwrseq {
                compatible = "mmc-pwrseq-simple";
                pinctrl-names = "default";
        };
 };
 
+&cpu0 {
+       cpu-supply = <&reg_vdd_cpux>;
+};
+
 &ehci0 {
        status = "okay";
 };
index cf1f970..5d23667 100644 (file)
        status = "okay";
 };
 
+&emac {
+       phy-handle = <&int_mii_phy>;
+       phy-mode = "mii";
+       allwinner,leds-active-low;
+       status = "okay";
+};
+
 &hdmi {
        status = "okay";
 };
index 41d57c7..f009607 100644 (file)
                        compatible = "arm,cortex-a7";
                        device_type = "cpu";
                        reg = <1>;
+                       clocks = <&ccu CLK_CPUX>;
+                       clock-names = "cpu";
                        operating-points-v2 = <&cpu0_opp_table>;
+                       #cooling-cells = <2>;
                };
 
                cpu@2 {
                        compatible = "arm,cortex-a7";
                        device_type = "cpu";
                        reg = <2>;
+                       clocks = <&ccu CLK_CPUX>;
+                       clock-names = "cpu";
                        operating-points-v2 = <&cpu0_opp_table>;
+                       #cooling-cells = <2>;
                };
 
                cpu@3 {
                        compatible = "arm,cortex-a7";
                        device_type = "cpu";
                        reg = <3>;
+                       clocks = <&ccu CLK_CPUX>;
+                       clock-names = "cpu";
                        operating-points-v2 = <&cpu0_opp_table>;
+                       #cooling-cells = <2>;
                };
        };
 
        };
 
        soc {
+               system-control@1c00000 {
+                       compatible = "allwinner,sun8i-h3-system-control";
+                       reg = <0x01c00000 0x30>;
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges;
+
+                       sram_c: sram@1d00000 {
+                               compatible = "mmio-sram";
+                               reg = <0x01d00000 0x80000>;
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+                               ranges = <0 0x01d00000 0x80000>;
+
+                               ve_sram: sram-section@0 {
+                                       compatible = "allwinner,sun8i-h3-sram-c1",
+                                                    "allwinner,sun4i-a10-sram-c1";
+                                       reg = <0x000000 0x80000>;
+                               };
+                       };
+               };
+
                mali: gpu@1c40000 {
                        compatible = "allwinner,sun8i-h3-mali", "arm,mali-400";
                        reg = <0x01c40000 0x10000>;
index 25fb048..c39b916 100644 (file)
                stdout-path = "serial0:115200n8";
        };
 
+       connector {
+               compatible = "hdmi-connector";
+               type = "a";
+
+               port {
+                       hdmi_con_in: endpoint {
+                               remote-endpoint = <&hdmi_out_con>;
+                       };
+               };
+       };
+
        leds {
                compatible = "gpio-leds";
 
        };
 };
 
+&de {
+       status = "okay";
+};
+
 &ehci1 {
        status = "okay";
 };
        };
 };
 
+&hdmi {
+       status = "okay";
+};
+
+&hdmi_out {
+       hdmi_out_con: endpoint {
+               remote-endpoint = <&hdmi_con_in>;
+       };
+};
+
 &i2c0 {
        status = "okay";
 
        regulator-name = "vcc-wifi";
 };
 
+&tcon_tv0 {
+       status = "okay";
+};
+
 &uart0 {
        pinctrl-names = "default";
        pinctrl-0 = <&uart0_pb_pins>;
index bd97ca3..ffd9f00 100644 (file)
  */
 
 #include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/clock/sun8i-de2.h>
 #include <dt-bindings/clock/sun8i-r40-ccu.h>
 #include <dt-bindings/reset/sun8i-r40-ccu.h>
+#include <dt-bindings/reset/sun8i-de2.h>
 
 / {
        #address-cells = <1>;
                };
        };
 
+       de: display-engine {
+               compatible = "allwinner,sun8i-r40-display-engine";
+               allwinner,pipelines = <&mixer0>, <&mixer1>;
+               status = "disabled";
+       };
+
        soc {
                compatible = "simple-bus";
                #address-cells = <1>;
                #size-cells = <1>;
                ranges;
 
+               display_clocks: clock@1000000 {
+                       compatible = "allwinner,sun8i-r40-de2-clk",
+                                    "allwinner,sun8i-h3-de2-clk";
+                       reg = <0x01000000 0x100000>;
+                       clocks = <&ccu CLK_DE>,
+                                <&ccu CLK_BUS_DE>;
+                       clock-names = "mod",
+                                     "bus";
+                       resets = <&ccu RST_BUS_DE>;
+                       #clock-cells = <1>;
+                       #reset-cells = <1>;
+               };
+
+               mixer0: mixer@1100000 {
+                       compatible = "allwinner,sun8i-r40-de2-mixer-0";
+                       reg = <0x01100000 0x100000>;
+                       clocks = <&display_clocks CLK_BUS_MIXER0>,
+                                <&display_clocks CLK_MIXER0>;
+                       clock-names = "bus",
+                                     "mod";
+                       resets = <&display_clocks RST_MIXER0>;
+
+                       ports {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+
+                               mixer0_out: port@1 {
+                                       reg = <1>;
+                                       mixer0_out_tcon_top: endpoint {
+                                               remote-endpoint = <&tcon_top_mixer0_in_mixer0>;
+                                       };
+                               };
+                       };
+               };
+
+               mixer1: mixer@1200000 {
+                       compatible = "allwinner,sun8i-r40-de2-mixer-1";
+                       reg = <0x01200000 0x100000>;
+                       clocks = <&display_clocks CLK_BUS_MIXER1>,
+                                <&display_clocks CLK_MIXER1>;
+                       clock-names = "bus",
+                                     "mod";
+                       resets = <&display_clocks RST_WB>;
+
+                       ports {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+
+                               mixer1_out: port@1 {
+                                       reg = <1>;
+                                       mixer1_out_tcon_top: endpoint {
+                                               remote-endpoint = <&tcon_top_mixer1_in_mixer1>;
+                                       };
+                               };
+                       };
+               };
+
                nmi_intc: interrupt-controller@1c00030 {
                        compatible = "allwinner,sun7i-a20-sc-nmi";
                        interrupt-controller;
                        reset-names = "stmmaceth";
                        clocks = <&ccu CLK_BUS_GMAC>;
                        clock-names = "stmmaceth";
-                       #address-cells = <1>;
-                       #size-cells = <0>;
                        status = "disabled";
 
                        gmac_mdio: mdio {
                        };
                };
 
+               tcon_top: tcon-top@1c70000 {
+                       compatible = "allwinner,sun8i-r40-tcon-top";
+                       reg = <0x01c70000 0x1000>;
+                       clocks = <&ccu CLK_BUS_TCON_TOP>,
+                                <&ccu CLK_TCON_TV0>,
+                                <&ccu CLK_TVE0>,
+                                <&ccu CLK_TCON_TV1>,
+                                <&ccu CLK_TVE1>,
+                                <&ccu CLK_DSI_DPHY>;
+                       clock-names = "bus",
+                                     "tcon-tv0",
+                                     "tve0",
+                                     "tcon-tv1",
+                                     "tve1",
+                                     "dsi";
+                       clock-output-names = "tcon-top-tv0",
+                                            "tcon-top-tv1",
+                                            "tcon-top-dsi";
+                       resets = <&ccu RST_BUS_TCON_TOP>;
+                       #clock-cells = <1>;
+
+                       ports {
+                               #address-cells = <1>;
+                               #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>;
+                                               remote-endpoint = <&mixer0_out_tcon_top>;
+                                       };
+                               };
+
+                               tcon_top_mixer0_out: port@1 {
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                                       reg = <1>;
+
+                                       tcon_top_mixer0_out_tcon_lcd0: endpoint@0 {
+                                               reg = <0>;
+                                       };
+
+                                       tcon_top_mixer0_out_tcon_lcd1: endpoint@1 {
+                                               reg = <1>;
+                                       };
+
+                                       tcon_top_mixer0_out_tcon_tv0: endpoint@2 {
+                                               reg = <2>;
+                                               remote-endpoint = <&tcon_tv0_in_tcon_top_mixer0>;
+                                       };
+
+                                       tcon_top_mixer0_out_tcon_tv1: endpoint@3 {
+                                               reg = <3>;
+                                               remote-endpoint = <&tcon_tv1_in_tcon_top_mixer0>;
+                                       };
+                               };
+
+                               tcon_top_mixer1_in: port@2 {
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                                       reg = <2>;
+
+                                       tcon_top_mixer1_in_mixer1: endpoint@1 {
+                                               reg = <1>;
+                                               remote-endpoint = <&mixer1_out_tcon_top>;
+                                       };
+                               };
+
+                               tcon_top_mixer1_out: port@3 {
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                                       reg = <3>;
+
+                                       tcon_top_mixer1_out_tcon_lcd0: endpoint@0 {
+                                               reg = <0>;
+                                       };
+
+                                       tcon_top_mixer1_out_tcon_lcd1: endpoint@1 {
+                                               reg = <1>;
+                                       };
+
+                                       tcon_top_mixer1_out_tcon_tv0: endpoint@2 {
+                                               reg = <2>;
+                                               remote-endpoint = <&tcon_tv0_in_tcon_top_mixer1>;
+                                       };
+
+                                       tcon_top_mixer1_out_tcon_tv1: endpoint@3 {
+                                               reg = <3>;
+                                               remote-endpoint = <&tcon_tv1_in_tcon_top_mixer1>;
+                                       };
+                               };
+
+                               tcon_top_hdmi_in: port@4 {
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                                       reg = <4>;
+
+                                       tcon_top_hdmi_in_tcon_tv0: endpoint@0 {
+                                               reg = <0>;
+                                               remote-endpoint = <&tcon_tv0_out_tcon_top>;
+                                       };
+
+                                       tcon_top_hdmi_in_tcon_tv1: endpoint@1 {
+                                               reg = <1>;
+                                               remote-endpoint = <&tcon_tv1_out_tcon_top>;
+                                       };
+                               };
+
+                               tcon_top_hdmi_out: port@5 {
+                                       reg = <5>;
+
+                                       tcon_top_hdmi_out_hdmi: endpoint {
+                                               remote-endpoint = <&hdmi_in_tcon_top>;
+                                       };
+                               };
+                       };
+               };
+
+               tcon_tv0: lcd-controller@1c73000 {
+                       compatible = "allwinner,sun8i-r40-tcon-tv";
+                       reg = <0x01c73000 0x1000>;
+                       interrupts = <GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&ccu CLK_BUS_TCON_TV0>, <&tcon_top 0>;
+                       clock-names = "ahb", "tcon-ch1";
+                       resets = <&ccu RST_BUS_TCON_TV0>;
+                       reset-names = "lcd";
+                       status = "disabled";
+
+                       ports {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+
+                               tcon_tv0_in: port@0 {
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                                       reg = <0>;
+
+                                       tcon_tv0_in_tcon_top_mixer0: endpoint@0 {
+                                               reg = <0>;
+                                               remote-endpoint = <&tcon_top_mixer0_out_tcon_tv0>;
+                                       };
+
+                                       tcon_tv0_in_tcon_top_mixer1: endpoint@1 {
+                                               reg = <1>;
+                                               remote-endpoint = <&tcon_top_mixer1_out_tcon_tv0>;
+                                       };
+                               };
+
+                               tcon_tv0_out: port@1 {
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                                       reg = <1>;
+
+                                       tcon_tv0_out_tcon_top: endpoint@1 {
+                                               reg = <1>;
+                                               remote-endpoint = <&tcon_top_hdmi_in_tcon_tv0>;
+                                       };
+                               };
+                       };
+               };
+
+               tcon_tv1: lcd-controller@1c74000 {
+                       compatible = "allwinner,sun8i-r40-tcon-tv";
+                       reg = <0x01c74000 0x1000>;
+                       interrupts = <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&ccu CLK_BUS_TCON_TV1>, <&tcon_top 1>;
+                       clock-names = "ahb", "tcon-ch1";
+                       resets = <&ccu RST_BUS_TCON_TV1>;
+                       reset-names = "lcd";
+                       status = "disabled";
+
+                       ports {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+
+                               tcon_tv1_in: port@0 {
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                                       reg = <0>;
+
+                                       tcon_tv1_in_tcon_top_mixer0: endpoint@0 {
+                                               reg = <0>;
+                                               remote-endpoint = <&tcon_top_mixer0_out_tcon_tv1>;
+                                       };
+
+                                       tcon_tv1_in_tcon_top_mixer1: endpoint@1 {
+                                               reg = <1>;
+                                               remote-endpoint = <&tcon_top_mixer1_out_tcon_tv1>;
+                                       };
+                               };
+
+                               tcon_tv1_out: port@1 {
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                                       reg = <1>;
+
+                                       tcon_tv1_out_tcon_top: endpoint@1 {
+                                               reg = <1>;
+                                               remote-endpoint = <&tcon_top_hdmi_in_tcon_tv1>;
+                                       };
+                               };
+                       };
+               };
+
                gic: interrupt-controller@1c81000 {
                        compatible = "arm,gic-400";
                        reg = <0x01c81000 0x1000>,
                        #interrupt-cells = <3>;
                        interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
                };
+
+               hdmi: hdmi@1ee0000 {
+                       compatible = "allwinner,sun8i-r40-dw-hdmi",
+                                    "allwinner,sun8i-a83t-dw-hdmi";
+                       reg = <0x01ee0000 0x10000>;
+                       reg-io-width = <1>;
+                       interrupts = <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&ccu CLK_BUS_HDMI0>, <&ccu CLK_HDMI_SLOW>,
+                                <&ccu CLK_HDMI>;
+                       clock-names = "iahb", "isfr", "tmds";
+                       resets = <&ccu RST_BUS_HDMI1>;
+                       reset-names = "ctrl";
+                       phys = <&hdmi_phy>;
+                       phy-names = "hdmi-phy";
+                       status = "disabled";
+
+                       ports {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+
+                               hdmi_in: port@0 {
+                                       reg = <0>;
+
+                                       hdmi_in_tcon_top: endpoint {
+                                               remote-endpoint = <&tcon_top_hdmi_out_hdmi>;
+                                       };
+                               };
+
+                               hdmi_out: port@1 {
+                                       reg = <1>;
+                               };
+                       };
+               };
+
+               hdmi_phy: hdmi-phy@1ef0000 {
+                       compatible = "allwinner,sun8i-r40-hdmi-phy",
+                                    "allwinner,sun50i-a64-hdmi-phy";
+                       reg = <0x01ef0000 0x10000>;
+                       clocks = <&ccu CLK_BUS_HDMI1>, <&ccu CLK_HDMI_SLOW>,
+                                <&ccu 7>, <&ccu 16>;
+                       clock-names = "bus", "mod", "pll-0", "pll-1";
+                       resets = <&ccu RST_BUS_HDMI0>;
+                       reset-names = "phy";
+                       #phy-cells = <0>;
+               };
        };
 
        timer {
index c3bff11..fc61313 100644 (file)
                        reset-names = "stmmaceth";
                        clocks = <&ccu CLK_BUS_EMAC>;
                        clock-names = "stmmaceth";
-                       #address-cells = <1>;
-                       #size-cells = <0>;
                        status = "disabled";
 
                        mdio: mdio {
index f7ffdd6..1eadc13 100644 (file)
        status = "okay";
 };
 
+&mmc2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&mmc2_8bit_pins>;
+       vmmc-supply = <&reg_vcc_io>;
+       bus-width = <8>;
+       non-removable;
+       status = "okay";
+};
+
 &ohci0 {
        status = "okay";
 };
index eafff16..1788556 100644 (file)
@@ -23,7 +23,7 @@
                stdout-path = "serial0:115200n8";
        };
 
-       memory {
+       memory@80000000 {
                reg = <0x80000000 0x40000000>;
        };
 
index 7ed7370..3d38355 100644 (file)
@@ -28,7 +28,7 @@
                };
        };
 
-       memory {
+       memory@80000000 {
                /* memory >= 0x79600000 is reserved for firmware usage */
                reg = <0x80000000 0x79600000>;
        };
index 7fc4a8b..bfdd1bf 100644 (file)
@@ -28,7 +28,7 @@
                };
        };
 
-       memory {
+       memory@80000000 {
                /* memory >= 0x37e00000 is reserved for firmware usage */
                reg = <0x80000000 0x37e00000>;
        };
index 84c4358..0d7a632 100644 (file)
@@ -5,11 +5,16 @@
 #include <dt-bindings/pinctrl/pinctrl-tegra.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 
-#include "skeleton.dtsi"
-
 / {
        compatible = "nvidia,tegra114";
        interrupt-parent = <&lic>;
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       memory@80000000 {
+               device_type = "memory";
+               reg = <0x80000000 0x0>;
+       };
 
        host1x@50000000 {
                compatible = "nvidia,tegra114-host1x", "simple-bus";
index 3455822..573aaa5 100644 (file)
@@ -15,7 +15,7 @@
        compatible = "toradex,apalis-tk1-v1.2", "toradex,apalis-tk1",
                     "nvidia,tegra124";
 
-       memory {
+       memory@80000000 {
                reg = <0x0 0x80000000 0x0 0x80000000>;
        };
 
index 9f960c8..0f0d4a4 100644 (file)
@@ -50,7 +50,7 @@
        model = "Toradex Apalis TK1";
        compatible = "toradex,apalis-tk1", "nvidia,tegra124";
 
-       memory {
+       memory@80000000 {
                reg = <0x0 0x80000000 0x0 0x80000000>;
        };
 
index 6dbcf84..9151b3e 100644 (file)
@@ -24,7 +24,7 @@
                stdout-path = "serial0:115200n8";
        };
 
-       memory {
+       memory@80000000 {
                reg = <0x0 0x80000000 0x0 0x80000000>;
        };
 
index 3609367..d5f11d6 100644 (file)
@@ -13,7 +13,7 @@
                stdout-path = "serial0:115200n8";
        };
 
-       memory {
+       memory@80000000 {
                reg = <0x0 0x80000000 0x0 0x80000000>;
        };
 
index 89bcc17..82d1396 100644 (file)
@@ -18,7 +18,7 @@
                stdout-path = "serial0:115200n8";
        };
 
-       memory {
+       memory@80000000 {
                reg = <0x0 0x80000000 0x0 0x80000000>;
        };
 
index 174092b..183c5ac 100644 (file)
@@ -7,14 +7,17 @@
 #include <dt-bindings/reset/tegra124-car.h>
 #include <dt-bindings/thermal/tegra124-soctherm.h>
 
-#include "skeleton.dtsi"
-
 / {
        compatible = "nvidia,tegra124";
        interrupt-parent = <&lic>;
        #address-cells = <2>;
        #size-cells = <2>;
 
+       memory@80000000 {
+               device_type = "memory";
+               reg = <0x0 0x80000000 0x0 0x0>;
+       };
+
        pcie@1003000 {
                compatible = "nvidia,tegra124-pcie";
                device_type = "pci";
similarity index 95%
rename from arch/arm/boot/dts/tegra20-iris-512.dts
rename to arch/arm/boot/dts/tegra20-colibri-iris.dts
index 4012638..57f16c0 100644 (file)
@@ -1,10 +1,10 @@
 // SPDX-License-Identifier: GPL-2.0
 /dts-v1/;
 
-#include "tegra20-colibri-512.dtsi"
+#include "tegra20-colibri.dtsi"
 
 / {
-       model = "Toradex Colibri T20 512MB on Iris";
+       model = "Toradex Colibri T20 256/512 MB on Iris";
        compatible = "toradex,iris", "toradex,colibri_t20-512", "nvidia,tegra20";
 
        aliases {
similarity index 96%
rename from arch/arm/boot/dts/tegra20-colibri-512.dtsi
rename to arch/arm/boot/dts/tegra20-colibri.dtsi
index 5c202b3..e7b9ab0 100644 (file)
@@ -2,7 +2,7 @@
 #include "tegra20.dtsi"
 
 / {
-       model = "Toradex Colibri T20 512MB";
+       model = "Toradex Colibri T20 256/512 MB";
        compatible = "toradex,colibri_t20-512", "nvidia,tegra20";
 
        aliases {
                rtc1 = "/rtc@7000e000";
        };
 
-       memory {
-               reg = <0x00000000 0x20000000>;
+       memory@0 {
+               /*
+                * Set memory to 256 MB to be safe as this could be used on
+                * 256 or 512 MB module. It is expected from bootloader
+                * to fix this up for 512 MB version.
+                */
+               reg = <0x00000000 0x10000000>;
        };
 
        host1x@50000000 {
                        GPIO_ACTIVE_HIGH>;
        };
 
+       nand-controller@70008000 {
+               status = "okay";
+
+               nand@0 {
+                       reg = <0>;
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       nand-bus-width = <8>;
+                       nand-on-flash-bbt;
+                       nand-ecc-algo = "bch";
+                       nand-is-boot-medium;
+                       nand-ecc-maximize;
+                       wp-gpios = <&gpio TEGRA_GPIO(S, 0) GPIO_ACTIVE_LOW>;
+               };
+       };
+
        /*
         * GEN1_I2C: I2C_SDA/SCL on SODIMM pin 194/196 (e.g. RTC on carrier
         * board)
index 628a55a..1d96d92 100644 (file)
@@ -18,7 +18,7 @@
                stdout-path = "serial0:115200n8";
        };
 
-       memory {
+       memory@0 {
                reg = <0x00000000 0x40000000>;
        };
 
index 3043696..ef24529 100644 (file)
@@ -19,7 +19,7 @@
                stdout-path = "serial0:115200n8";
        };
 
-       memory {
+       memory@0 {
                reg = <0x00000000 0x20000000>;
        };
 
index 284aae3..f914416 100644 (file)
@@ -18,7 +18,7 @@
                stdout-path = "serial0:115200n8";
        };
 
-       memory {
+       memory@0 {
                reg = <0x00000000 0x40000000>;
        };
 
index 872046d..20137fc 100644 (file)
@@ -15,7 +15,7 @@
                stdout-path = "serial0:115200n8";
        };
 
-       memory {
+       memory@0 {
                reg = <0x00000000 0x20000000>;
        };
 
index d55c6b2..9eb26dc 100644 (file)
@@ -18,7 +18,7 @@
                stdout-path = "serial0:115200n8";
        };
 
-       memory {
+       memory@0 {
                reg = <0x00000000 0x40000000>;
        };
 
index ee3fbf9..f44551e 100644 (file)
@@ -18,7 +18,7 @@
                stdout-path = "serial0:115200n8";
        };
 
-       memory {
+       memory@0 {
                reg = <0x00000000 0x40000000>;
        };
 
index 983dd5c..15b73bd 100644 (file)
@@ -1,14 +1,20 @@
 // SPDX-License-Identifier: GPL-2.0
 #include <dt-bindings/clock/tegra20-car.h>
 #include <dt-bindings/gpio/tegra-gpio.h>
+#include <dt-bindings/memory/tegra20-mc.h>
 #include <dt-bindings/pinctrl/pinctrl-tegra.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 
-#include "skeleton.dtsi"
-
 / {
        compatible = "nvidia,tegra20";
        interrupt-parent = <&lic>;
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       memory@0 {
+               device_type = "memory";
+               reg = <0 0>;
+       };
 
        iram@40000000 {
                compatible = "mmio-sram";
                             <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>; /* SXE interrupt */
                interrupt-names = "sync-token", "bsev", "sxe";
                clocks = <&tegra_car TEGRA20_CLK_VDE>;
-               resets = <&tegra_car 61>;
+               reset-names = "vde", "mc";
+               resets = <&tegra_car 61>, <&mc TEGRA20_MC_RESET_VDE>;
        };
 
        apbmisc@70000800 {
                status = "disabled";
        };
 
+       nand-controller@70008000 {
+               compatible = "nvidia,tegra20-nand";
+               reg = <0x70008000 0x100>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+               interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&tegra_car TEGRA20_CLK_NDFLASH>;
+               clock-names = "nand";
+               resets = <&tegra_car 13>;
+               reset-names = "nand";
+               assigned-clocks = <&tegra_car TEGRA20_CLK_NDFLASH>;
+               assigned-clock-rates = <150000000>;
+               status = "disabled";
+       };
+
        pwm: pwm@7000a000 {
                compatible = "nvidia,tegra20-pwm";
                reg = <0x7000a000 0x100>;
                clock-names = "pclk", "clk32k_in";
        };
 
-       memory-controller@7000f000 {
+       mc: memory-controller@7000f000 {
                compatible = "nvidia,tegra20-mc";
                reg = <0x7000f000 0x024
                       0x7000f03c 0x3c4>;
                interrupts = <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>;
+               #reset-cells = <1>;
        };
 
        iommu@7000f024 {
index d1d21ec..2f807d4 100644 (file)
        model = "Toradex Apalis T30";
        compatible = "toradex,apalis_t30", "nvidia,tegra30";
 
+       memory@80000000 {
+               reg = <0x80000000 0x40000000>;
+       };
+
        pcie@3000 {
                avdd-pexa-supply = <&vdd2_reg>;
                vdd-pexa-supply = <&vdd2_reg>;
                                nvidia,function = "spi4";
                                nvidia,pull = <TEGRA_PIN_PULL_NONE>;
                                nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                               nvidia,enable-input = <TEGRA_PIN_ENABLE>;
                        };
                        /* CAN_INT2 */
                        spi2_cs2_n_pw3 {
                /* STMPE811 touch screen controller */
                stmpe811@41 {
                        compatible = "st,stmpe811";
-                       #address-cells = <1>;
-                       #size-cells = <0>;
                        reg = <0x41>;
                        interrupts = <TEGRA_GPIO(V, 0) IRQ_TYPE_LEVEL_LOW>;
                        interrupt-parent = <&gpio>;
                        blocks = <0x5>;
                        irq-trigger = <0x1>;
 
-                       stmpe_touchscreen@0 {
+                       stmpe_touchscreen {
                                compatible = "st,stmpe-ts";
                                /* 3.25 MHz ADC clock speed */
                                st,adc-freq = <1>;
index ae52a50..b0d40ac 100644 (file)
@@ -17,7 +17,7 @@
                stdout-path = "serial0:115200n8";
        };
 
-       memory {
+       memory@80000000 {
                reg = <0x80000000 0x7ff00000>;
        };
 
                        vccio-supply = <&vdd_5v_in_reg>;
 
                        regulators {
-                               #address-cells = <1>;
-                               #size-cells = <0>;
-
                                vdd1_reg: vdd1 {
                                        regulator-name = "vddio_ddr_1v2";
                                        regulator-min-microvolt = <1200000>;
index 92a9740..fb9222b 100644 (file)
@@ -40,7 +40,7 @@
                stdout-path = "serial0:115200n8";
        };
 
-       memory {
+       memory@80000000 {
                reg = <0x80000000 0x40000000>;
        };
 
                        #address-cells = <1>;
                        #size-cells = <0>;
                        reg = <0x70>;
+                       reset-gpio = <&gpio TEGRA_GPIO(BB, 0) GPIO_ACTIVE_LOW>;
                };
        };
 
index c44d8c4..526ed71 100644 (file)
@@ -10,7 +10,7 @@
        model = "Toradex Colibri T30";
        compatible = "toradex,colibri_t30", "nvidia,tegra30";
 
-       memory {
+       memory@80000000 {
                reg = <0x80000000 0x40000000>;
        };
 
                /* STMPE811 touch screen controller */
                stmpe811@41 {
                        compatible = "st,stmpe811";
-                       #address-cells = <1>;
-                       #size-cells = <0>;
                        reg = <0x41>;
                        interrupts = <TEGRA_GPIO(V, 0) IRQ_TYPE_LEVEL_LOW>;
                        interrupt-parent = <&gpio>;
index 09087b9..a6781f6 100644 (file)
@@ -5,11 +5,16 @@
 #include <dt-bindings/pinctrl/pinctrl-tegra.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 
-#include "skeleton.dtsi"
-
 / {
        compatible = "nvidia,tegra30";
        interrupt-parent = <&lic>;
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       memory@80000000 {
+               device_type = "memory";
+               reg = <0x80000000 0x0>;
+       };
 
        pcie@3000 {
                compatible = "nvidia,tegra30-pcie";
                             <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>; /* SXE interrupt */
                interrupt-names = "sync-token", "bsev", "sxe";
                clocks = <&tegra_car TEGRA30_CLK_VDE>;
-               resets = <&tegra_car 61>;
+               reset-names = "vde", "mc";
+               resets = <&tegra_car 61>, <&mc TEGRA30_MC_RESET_VDE>;
        };
 
        apbmisc@70000800 {
                interrupts = <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>;
 
                #iommu-cells = <1>;
+               #reset-cells = <1>;
        };
 
        fuse@7000f800 {
index 641d961..e2d1a22 100644 (file)
@@ -36,6 +36,7 @@
                        enable-method = "psci";
                        next-level-cache = <&l2>;
                        operating-points-v2 = <&cpu_opp>;
+                       #cooling-cells = <2>;
                };
 
                cpu2: cpu@2 {
@@ -46,6 +47,7 @@
                        enable-method = "psci";
                        next-level-cache = <&l2>;
                        operating-points-v2 = <&cpu_opp>;
+                       #cooling-cells = <2>;
                };
 
                cpu3: cpu@3 {
@@ -56,6 +58,7 @@
                        enable-method = "psci";
                        next-level-cache = <&l2>;
                        operating-points-v2 = <&cpu_opp>;
+                       #cooling-cells = <2>;
                };
        };
 
diff --git a/arch/arm/boot/dts/vf610-zii-cfu1.dts b/arch/arm/boot/dts/vf610-zii-cfu1.dts
new file mode 100644 (file)
index 0000000..37777cf
--- /dev/null
@@ -0,0 +1,305 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+
+/*
+ * Copyright (C) 2018 Zodiac Inflight Innovations
+ */
+
+/dts-v1/;
+#include "vf610.dtsi"
+
+/ {
+       model = "ZII VF610 CFU1 Board";
+       compatible = "zii,vf610cfu1", "zii,vf610dev", "fsl,vf610";
+
+       chosen {
+               stdout-path = &uart0;
+       };
+
+       memory@80000000 {
+               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";
+                       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>;
+               };
+       };
+
+       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";
+
+       m25p128@0 {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "m25p128", "jedec,spi-nor";
+               reg = <0>;
+               spi-max-frequency = <50000000>;
+
+               partition@0 {
+                       label = "m25p128-0";
+                       reg = <0x0 0x01000000>;
+               };
+       };
+};
+
+&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;
+       status = "okay";
+};
+
+&esdhc1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_esdhc1>;
+       bus-width = <4>;
+       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,mv88e6085";
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&pinctrl_switch>;
+                       reg = <0>;
+                       eeprom-length = <512>;
+                       interrupt-parent = <&gpio3>;
+                       interrupts = <2 IRQ_TYPE_LEVEL_LOW>;
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+                       reset-gpios = <&gpio3 11 GPIO_ACTIVE_LOW>;
+
+                       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 = "eth_cu_1000_3";
+                               };
+
+                               port@6 {
+                                       reg = <6>;
+                                       label = "cpu";
+                                       ethernet = <&fec1>;
+
+                                       fixed-link {
+                                               speed = <100>;
+                                               full-duplex;
+                                       };
+                               };
+                       };
+               };
+       };
+};
+
+&i2c0 {
+       clock-frequency = <100000>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_i2c0>;
+       status = "okay";
+
+       pca9554@22 {
+               compatible = "nxp,pca9554";
+               reg = <0x22>;
+               gpio-controller;
+       };
+
+       lm75@48 {
+               compatible = "national,lm75";
+               reg = <0x48>;
+       };
+
+       at24c04@52 {
+               compatible = "atmel,24c04";
+               reg = <0x52>;
+               label = "nvm";
+       };
+
+       at24c04@54 {
+               compatible = "atmel,24c04";
+               reg = <0x54>;
+               label = "nameplate";
+       };
+};
+
+&uart0 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_uart0>;
+       status = "okay";
+};
+
+&iomuxc {
+       pinctrl_dspi1: dspi1grp {
+               fsl,pins = <
+                       VF610_PAD_PTD5__DSPI1_CS0               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          0x30fe
+                       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_i2c0: i2c0grp {
+               fsl,pins = <
+                       VF610_PAD_PTB14__I2C0_SCL               0x37ff
+                       VF610_PAD_PTB15__I2C0_SDA               0x37ff
+               >;
+       };
+
+       pinctrl_leds_debug: pinctrl-leds-debug {
+               fsl,pins = <
+                       VF610_PAD_PTD3__GPIO_82                 0x31c2
+                       VF610_PAD_PTE3__GPIO_108                0x31c2
+                       VF610_PAD_PTE4__GPIO_109                0x31c2
+                       VF610_PAD_PTE5__GPIO_110                0x31c2
+                       VF610_PAD_PTE6__GPIO_111                0x31c2
+               >;
+       };
+
+       pinctrl_switch: switch-grp {
+               fsl,pins = <
+                       VF610_PAD_PTB28__GPIO_98                0x3061
+                       VF610_PAD_PTE2__GPIO_107                0x1042
+               >;
+       };
+
+       pinctrl_uart0: uart0grp {
+               fsl,pins = <
+                       VF610_PAD_PTB10__UART0_TX               0x21a2
+                       VF610_PAD_PTB11__UART0_RX               0x21a1
+               >;
+       };
+};
diff --git a/arch/arm/boot/dts/vf610-zii-ssmb-spu3.dts b/arch/arm/boot/dts/vf610-zii-ssmb-spu3.dts
new file mode 100644 (file)
index 0000000..fe35766
--- /dev/null
@@ -0,0 +1,341 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+
+/*
+ * Device tree file for ZII's SSMB SPU3 board
+ *
+ * SSMB - SPU3 Switch Management Board
+ * SPU - Seat Power Unit
+ *
+ * Copyright (C) 2015, 2016 Zodiac Inflight Innovations
+ *
+ * Based on an original 'vf610-twr.dts' which is Copyright 2015,
+ * Freescale Semiconductor, Inc.
+ */
+
+/dts-v1/;
+#include "vf610.dtsi"
+
+/ {
+       model = "ZII VF610 SSMB SPU3 Board";
+       compatible = "zii,vf610spu3", "zii,vf610dev", "fsl,vf610";
+
+       chosen {
+               stdout-path = &uart0;
+       };
+
+       memory@80000000 {
+               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";
+                       max-brightness = <1>;
+               };
+       };
+
+       reg_vcc_3v3_mcu: regulator {
+               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>;
+       /*
+        * Some SPU3s 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";
+
+       m25p128@0 {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "m25p128", "jedec,spi-nor";
+               reg = <0>;
+               spi-max-frequency = <50000000>;
+
+               partition@0 {
+                       label = "m25p128-0";
+                       reg = <0x0 0x01000000>;
+               };
+       };
+};
+
+&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;
+       status = "okay";
+};
+
+&esdhc1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_esdhc1>;
+       bus-width = <4>;
+       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";
+
+       gpio6: pca9505@22 {
+               compatible = "nxp,pca9554";
+               reg = <0x22>;
+               gpio-controller;
+               #gpio-cells = <2>;
+       };
+
+       lm75@48 {
+               compatible = "national,lm75";
+               reg = <0x48>;
+       };
+
+       at24c04@50 {
+               compatible = "atmel,24c04";
+               reg = <0x50>;
+               label = "nameplate";
+       };
+
+       at24c04@52 {
+               compatible = "atmel,24c04";
+               reg = <0x52>;
+       };
+};
+
+&uart0 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_uart0>;
+       status = "okay";
+};
+
+&uart1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_uart1>;
+       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";
+               };
+       };
+};
+
+&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
+               >;
+       };
+};
index 1a0f631..8b9ab9b 100644 (file)
@@ -12,8 +12,8 @@
 /include/ "zynq-7000.dtsi"
 
 / {
+       model = "Xilinx CC108 board";
        compatible = "xlnx,zynq-cc108", "xlnx,zynq-7000";
-       model = "Xilinx Zynq";
 
        aliases {
                ethernet0 = &gem0;
index aa4a0b6..6ed84fb 100644 (file)
@@ -7,8 +7,8 @@
 /include/ "zynq-7000.dtsi"
 
 / {
-       model = "Zynq MicroZED Development Board";
-       compatible = "xlnx,zynq-microzed", "xlnx,zynq-7000";
+       model = "Avnet MicroZed board";
+       compatible = "avnet,zynq-microzed", "xlnx,zynq-microzed", "xlnx,zynq-7000";
 
        aliases {
                ethernet0 = &gem0;
index c05f4b6..54592ae 100644 (file)
@@ -12,7 +12,7 @@
 /include/ "zynq-7000.dtsi"
 
 / {
-       model = "Adapteva Parallella Board";
+       model = "Adapteva Parallella board";
        compatible = "adapteva,parallella", "xlnx,zynq-7000";
 
        aliases {
index f2330b0..cc5a3dc 100644 (file)
@@ -7,13 +7,14 @@
 #include "zynq-7000.dtsi"
 
 / {
-       model = "Zynq ZC702 Development Board";
+       model = "Xilinx ZC702 board";
        compatible = "xlnx,zynq-zc702", "xlnx,zynq-7000";
 
        aliases {
                ethernet0 = &gem0;
                i2c0 = &i2c0;
                serial0 = &uart1;
+               mmc0 = &sdhci0;
        };
 
        memory@0 {
@@ -28,8 +29,6 @@
 
        gpio-keys {
                compatible = "gpio-keys";
-               #address-cells = <1>;
-               #size-cells = <0>;
                autorepeat;
                sw14 {
                        label = "sw14";
index 3ad1260..77943c1 100644 (file)
@@ -7,13 +7,14 @@
 #include "zynq-7000.dtsi"
 
 / {
-       model = "Zynq ZC706 Development Board";
+       model = "Xilinx ZC706 board";
        compatible = "xlnx,zynq-zc706", "xlnx,zynq-7000";
 
        aliases {
                ethernet0 = &gem0;
                i2c0 = &i2c0;
                serial0 = &uart1;
+               mmc0 = &sdhci0;
        };
 
        memory@0 {
index 6884f1a..0e1bfdd 100644 (file)
@@ -8,8 +8,8 @@
 #include "zynq-7000.dtsi"
 
 / {
+       model = "Xilinx ZC770 XM010 board";
        compatible = "xlnx,zynq-zc770-xm010", "xlnx,zynq-7000";
-       model = "Xilinx Zynq";
 
        aliases {
                ethernet0 = &gem0;
index b78883c..b7f6586 100644 (file)
@@ -8,8 +8,8 @@
 #include "zynq-7000.dtsi"
 
 / {
+       model = "Xilinx ZC770 XM011 board";
        compatible = "xlnx,zynq-zc770-xm011", "xlnx,zynq-7000";
-       model = "Xilinx Zynq";
 
        aliases {
                i2c0 = &i2c1;
index c3169d6..d2359b7 100644 (file)
@@ -8,8 +8,8 @@
 #include "zynq-7000.dtsi"
 
 / {
+       model = "Xilinx ZC770 XM012 board";
        compatible = "xlnx,zynq-zc770-xm012", "xlnx,zynq-7000";
-       model = "Xilinx Zynq";
 
        aliases {
                i2c0 = &i2c0;
index 8bb6685..651913f 100644 (file)
@@ -8,8 +8,8 @@
 #include "zynq-7000.dtsi"
 
 / {
+       model = "Xilinx ZC770 XM013 board";
        compatible = "xlnx,zynq-zc770-xm013", "xlnx,zynq-7000";
-       model = "Xilinx Zynq";
 
        aliases {
                ethernet0 = &gem1;
index 53c6883..6a5a93a 100644 (file)
@@ -7,12 +7,13 @@
 #include "zynq-7000.dtsi"
 
 / {
-       model = "Zynq Zed Development Board";
-       compatible = "xlnx,zynq-zed", "xlnx,zynq-7000";
+       model = "Avnet ZedBoard board";
+       compatible = "avnet,zynq-zed", "xlnx,zynq-zed", "xlnx,zynq-7000";
 
        aliases {
                ethernet0 = &gem0;
                serial0 = &uart1;
+               mmc0 = &sdhci0;
        };
 
        memory@0 {
diff --git a/arch/arm/boot/dts/zynq-zturn.dts b/arch/arm/boot/dts/zynq-zturn.dts
new file mode 100644 (file)
index 0000000..b387046
--- /dev/null
@@ -0,0 +1,114 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ *  Copyright (C) 2015 Andrea Merello <adnrea.merello@gmail.com>
+ *  Copyright (C) 2017 Alexander Graf <agraf@suse.de>
+ *
+ *  Based on zynq-zed.dts which is:
+ *  Copyright (C) 2011 - 2014 Xilinx
+ *  Copyright (C) 2012 National Instruments Corp.
+ *
+ */
+
+/dts-v1/;
+/include/ "zynq-7000.dtsi"
+
+/ {
+       model = "Zynq Z-Turn MYIR Board";
+       compatible = "myir,zynq-zturn", "xlnx,zynq-7000";
+
+       aliases {
+               ethernet0 = &gem0;
+               serial0 = &uart1;
+               serial1 = &uart0;
+               mmc0 = &sdhci0;
+       };
+
+       memory@0 {
+               device_type = "memory";
+               reg = <0x0 0x40000000>;
+       };
+
+       chosen {
+               stdout-path = "serial0:115200n8";
+       };
+
+       gpio-leds {
+               compatible = "gpio-leds";
+               usr-led1 {
+                       label = "usr-led1";
+                       gpios = <&gpio0 0x0 0x1>;
+                       default-state = "off";
+               };
+
+               usr-led2 {
+                       label = "usr-led2";
+                       gpios = <&gpio0 0x9 0x1>;
+                       default-state = "off";
+               };
+       };
+
+       gpio-keys {
+               compatible = "gpio-keys";
+               autorepeat;
+               K1 {
+                       label = "K1";
+                       gpios = <&gpio0 0x32 0x1>;
+                       linux,code = <0x66>;
+                       gpio-key,wakeup;
+                       autorepeat;
+               };
+       };
+};
+
+&clkc {
+       ps-clk-frequency = <33333333>;
+};
+
+&gem0 {
+       status = "okay";
+       phy-mode = "rgmii-id";
+       phy-handle = <&ethernet_phy>;
+
+       ethernet_phy: ethernet-phy@0 {
+               reg = <0x0>;
+       };
+};
+
+&sdhci0 {
+       status = "okay";
+};
+
+&uart0 {
+       status = "okay";
+};
+
+&uart1 {
+       status = "okay";
+};
+
+&usb0 {
+       status = "okay";
+       dr_mode = "host";
+};
+
+&can0 {
+       status = "okay";
+};
+
+&i2c0 {
+       status = "okay";
+       clock-frequency = <400000>;
+
+       stlm75@49 {
+               status = "okay";
+               compatible = "lm75";
+               reg = <0x49>;
+       };
+
+       accelerometer@53 {
+               compatible = "adi,adxl345", "adxl345", "adi,adxl34x", "adxl34x";
+               reg = <0x53>;
+               interrupt-parent = <&intc>;
+               interrupts = <0x0 0x1e 0x4>;
+       };
+};
index 1e713dc..357b78a 100644 (file)
@@ -1,9 +1,10 @@
 // SPDX-License-Identifier: GPL-2.0+
 /dts-v1/;
 #include "zynq-7000.dtsi"
+#include <dt-bindings/gpio/gpio.h>
 
 / {
-       model = "Zynq ZYBO Z7 Development Board";
+       model = "Digilent Zybo Z7 board";
        compatible = "digilent,zynq-zybo-z7", "xlnx,zynq-7000";
 
        aliases {
@@ -13,7 +14,7 @@
 
        memory@0 {
                device_type = "memory";
-               reg = <0x0 0x20000000>;
+               reg = <0x0 0x40000000>;
        };
 
        chosen {
                stdout-path = "serial0:115200n8";
        };
 
+       gpio-leds {
+               compatible = "gpio-leds";
+
+               ld4 {
+                       label = "zynq-zybo-z7:green:ld4";
+                       gpios = <&gpio0 7 GPIO_ACTIVE_HIGH>;
+               };
+       };
+
        usb_phy0: phy0 {
                #phy-cells = <0>;
                compatible = "usb-nop-xceiv";
-               reset-gpios = <&gpio0 46 1>;
+               reset-gpios = <&gpio0 46 GPIO_ACTIVE_LOW>;
        };
 };
 
index a6c00e7..755f6f1 100644 (file)
@@ -7,12 +7,13 @@
 #include "zynq-7000.dtsi"
 
 / {
-       model = "Zynq ZYBO Development Board";
+       model = "Digilent Zybo board";
        compatible = "digilent,zynq-zybo", "xlnx,zynq-7000";
 
        aliases {
                ethernet0 = &gem0;
                serial0 = &uart1;
+               mmc0 = &sdhci0;
        };
 
        memory@0 {
index 95946de..1446262 100644 (file)
@@ -3,30 +3,39 @@ CONFIG_KERNEL_XZ=y
 CONFIG_SYSVIPC=y
 CONFIG_NO_HZ_IDLE=y
 CONFIG_HIGH_RES_TIMERS=y
-CONFIG_LOG_BUF_SHIFT=14
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=16
 CONFIG_CGROUPS=y
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_RD_BZIP2 is not set
 # CONFIG_RD_LZO is not set
 # CONFIG_RD_LZ4 is not set
-CONFIG_KALLSYMS_ALL=y
-CONFIG_BPF_SYSCALL=y
+# CONFIG_UID16 is not set
+# CONFIG_SYSFS_SYSCALL is not set
 # CONFIG_AIO is not set
+CONFIG_BPF_SYSCALL=y
 CONFIG_EMBEDDED=y
+CONFIG_PERF_EVENTS=y
 # CONFIG_COMPAT_BRK is not set
 CONFIG_SLAB=y
+CONFIG_SLAB_FREELIST_RANDOM=y
 CONFIG_JUMP_LABEL=y
+CONFIG_STRICT_KERNEL_RWX=y
 CONFIG_GCC_PLUGINS=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
 # CONFIG_LBDAF is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEBUG_FS is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_MQ_IOSCHED_DEADLINE is not set
+# CONFIG_MQ_IOSCHED_KYBER is not set
 # CONFIG_ARCH_MULTI_V7 is not set
 CONFIG_ARCH_ASPEED=y
 CONFIG_MACH_ASPEED_G4=y
 CONFIG_VMSPLIT_2G=y
 CONFIG_AEABI=y
-# CONFIG_CPU_SW_DOMAIN_PAN is not set
 # CONFIG_COMPACTION is not set
+CONFIG_UACCESS_WITH_MEMCPY=y
 CONFIG_SECCOMP=y
 # CONFIG_ATAGS is not set
 CONFIG_ZBOOT_ROM_TEXT=0x0
@@ -47,8 +56,14 @@ CONFIG_SYN_COOKIES=y
 # CONFIG_INET_XFRM_MODE_TUNNEL is not set
 # CONFIG_INET_XFRM_MODE_BEET is not set
 # CONFIG_INET_DIAG is not set
-# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET6_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET6_XFRM_MODE_BEET is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_ADVANCED is not set
+CONFIG_VLAN_8021Q=y
 CONFIG_NET_NCSI=y
+CONFIG_BPF_STREAM_PARSER=y
 # CONFIG_WIRELESS is not set
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_DEVTMPFS=y
@@ -58,11 +73,12 @@ CONFIG_MTD=y
 CONFIG_MTD_BLOCK=y
 CONFIG_MTD_PARTITIONED_MASTER=y
 CONFIG_MTD_SPI_NOR=y
+# CONFIG_MTD_SPI_NOR_USE_4K_SECTORS is not set
 CONFIG_SPI_ASPEED_SMC=y
 CONFIG_MTD_UBI=y
 CONFIG_MTD_UBI_FASTMAP=y
 CONFIG_MTD_UBI_BLOCK=y
-CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_LOOP=y
 CONFIG_ASPEED_LPC_CTRL=y
 CONFIG_ASPEED_LPC_SNOOP=y
 CONFIG_EEPROM_AT24=y
@@ -70,18 +86,26 @@ CONFIG_NETDEVICES=y
 CONFIG_NETCONSOLE=y
 # CONFIG_NET_VENDOR_ALACRITECH is not set
 # CONFIG_NET_VENDOR_AMAZON is not set
+# CONFIG_NET_VENDOR_AQUANTIA is not set
 # CONFIG_NET_VENDOR_ARC is not set
-# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_AURORA is not set
 # CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_CADENCE is not set
+# CONFIG_NET_VENDOR_CAVIUM is not set
 # CONFIG_NET_VENDOR_CIRRUS is not set
+# CONFIG_NET_VENDOR_CORTINA is not set
 # CONFIG_NET_VENDOR_EZCHIP is not set
 CONFIG_FTGMAC100=y
 # CONFIG_NET_VENDOR_HISILICON is not set
+# CONFIG_NET_VENDOR_HUAWEI is not set
 # CONFIG_NET_VENDOR_INTEL is not set
 # CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MELLANOX is not set
 # CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_MICROSEMI is not set
 # CONFIG_NET_VENDOR_NATSEMI is not set
 # CONFIG_NET_VENDOR_NETRONOME is not set
+# CONFIG_NET_VENDOR_NI is not set
 # CONFIG_NET_VENDOR_QUALCOMM is not set
 # CONFIG_NET_VENDOR_RENESAS is not set
 # CONFIG_NET_VENDOR_ROCKER is not set
@@ -89,13 +113,20 @@ CONFIG_FTGMAC100=y
 # CONFIG_NET_VENDOR_SEEQ is not set
 # CONFIG_NET_VENDOR_SOLARFLARE is not set
 # CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_SOCIONEXT is not set
 # CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_SYNOPSYS is not set
 # CONFIG_NET_VENDOR_VIA is not set
 # CONFIG_NET_VENDOR_WIZNET is not set
 CONFIG_BROADCOM_PHY=y
 CONFIG_REALTEK_PHY=y
+# CONFIG_USB_NET_DRIVERS is not set
 # CONFIG_WLAN is not set
-# CONFIG_INPUT is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_KEYBOARD_ATKBD is not set
+CONFIG_KEYBOARD_GPIO=y
+CONFIG_KEYBOARD_GPIO_POLLED=y
+# CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
 # CONFIG_VT is not set
 # CONFIG_LEGACY_PTYS is not set
@@ -108,15 +139,16 @@ CONFIG_SERIAL_8250_EXTENDED=y
 CONFIG_SERIAL_8250_ASPEED_VUART=y
 CONFIG_SERIAL_8250_SHARE_IRQ=y
 CONFIG_SERIAL_OF_PLATFORM=y
+CONFIG_ASPEED_KCS_IPMI_BMC=y
 CONFIG_ASPEED_BT_IPMI_BMC=y
-# CONFIG_HW_RANDOM is not set
-CONFIG_I2C=y
+CONFIG_HW_RANDOM_TIMERIOMEM=y
 # CONFIG_I2C_COMPAT is not set
 CONFIG_I2C_CHARDEV=y
 CONFIG_I2C_MUX=y
 CONFIG_I2C_MUX_PCA9541=y
 CONFIG_I2C_MUX_PCA954x=y
 CONFIG_I2C_ASPEED=y
+CONFIG_I2C_FSI=y
 CONFIG_GPIOLIB=y
 CONFIG_GPIO_SYSFS=y
 CONFIG_GPIO_ASPEED=y
@@ -129,19 +161,45 @@ CONFIG_SENSORS_LM75=y
 CONFIG_SENSORS_NCT7904=y
 CONFIG_PMBUS=y
 CONFIG_SENSORS_ADM1275=y
+CONFIG_SENSORS_IBM_CFFPS=y
+CONFIG_SENSORS_IR35221=y
 CONFIG_SENSORS_LM25066=y
+CONFIG_SENSORS_MAX31785=y
 CONFIG_SENSORS_UCD9000=y
+CONFIG_SENSORS_UCD9200=y
 CONFIG_SENSORS_TMP421=y
+CONFIG_SENSORS_W83773G=y
+CONFIG_WATCHDOG_SYSFS=y
+CONFIG_DRM=y
 CONFIG_USB=y
 CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
 CONFIG_USB_DYNAMIC_MINORS=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_EHCI_ROOT_HUB_TT=y
 CONFIG_USB_EHCI_HCD_PLATFORM=y
+CONFIG_USB_GADGET=y
+CONFIG_U_SERIAL_CONSOLE=y
+CONFIG_USB_ASPEED_VHUB=y
+CONFIG_USB_CONFIGFS=y
+CONFIG_USB_CONFIGFS_SERIAL=y
+CONFIG_USB_CONFIGFS_ACM=y
+CONFIG_USB_CONFIGFS_OBEX=y
+CONFIG_USB_CONFIGFS_NCM=y
+CONFIG_USB_CONFIGFS_ECM=y
+CONFIG_USB_CONFIGFS_ECM_SUBSET=y
+CONFIG_USB_CONFIGFS_RNDIS=y
+CONFIG_USB_CONFIGFS_EEM=y
+CONFIG_USB_CONFIGFS_MASS_STORAGE=y
+CONFIG_USB_CONFIGFS_F_LB_SS=y
+CONFIG_USB_CONFIGFS_F_FS=y
+CONFIG_USB_CONFIGFS_F_HID=y
+CONFIG_USB_CONFIGFS_F_PRINTER=y
 CONFIG_NEW_LEDS=y
 CONFIG_LEDS_CLASS=y
 CONFIG_LEDS_CLASS_FLASH=y
 CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_PCA955X=y
+CONFIG_LEDS_PCA955X_GPIO=y
 CONFIG_LEDS_TRIGGERS=y
 CONFIG_LEDS_TRIGGER_TIMER=y
 CONFIG_LEDS_TRIGGER_HEARTBEAT=y
@@ -150,33 +208,56 @@ CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_DS1307=y
 CONFIG_RTC_DRV_PCF8523=y
 CONFIG_RTC_DRV_RV8803=y
-CONFIG_MAILBOX=y
+# CONFIG_VIRTIO_MENU is not set
 # CONFIG_IOMMU_SUPPORT is not set
 CONFIG_IIO=y
 CONFIG_ASPEED_ADC=y
+CONFIG_MAX1363=y
 CONFIG_BMP280=y
+CONFIG_FSI=y
+CONFIG_FSI_MASTER_GPIO=y
+CONFIG_FSI_MASTER_HUB=y
+CONFIG_FSI_MASTER_AST_CF=y
+CONFIG_FSI_SCOM=y
+CONFIG_FSI_SBEFIFO=y
 CONFIG_FIRMWARE_MEMMAP=y
 CONFIG_FANOTIFY=y
 CONFIG_OVERLAY_FS=y
 CONFIG_TMPFS=y
 CONFIG_JFFS2_FS=y
+# CONFIG_JFFS2_FS_WRITEBUFFER is not set
 CONFIG_JFFS2_SUMMARY=y
 CONFIG_JFFS2_FS_XATTR=y
 CONFIG_UBIFS_FS=y
 CONFIG_SQUASHFS=y
 CONFIG_SQUASHFS_XZ=y
+CONFIG_SQUASHFS_ZSTD=y
+# CONFIG_NETWORK_FILESYSTEMS is not set
 CONFIG_PRINTK_TIME=y
 CONFIG_DYNAMIC_DEBUG=y
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_INFO_REDUCED=y
+CONFIG_DEBUG_INFO_DWARF4=y
+CONFIG_GDB_SCRIPTS=y
 CONFIG_STRIP_ASM_SYMS=y
-CONFIG_DEBUG_FS=y
+CONFIG_SOFTLOCKUP_DETECTOR=y
+# CONFIG_DETECT_HUNG_TASK is not set
 CONFIG_WQ_WATCHDOG=y
+CONFIG_PANIC_ON_OOPS=y
 CONFIG_PANIC_TIMEOUT=-1
 # CONFIG_SCHED_DEBUG is not set
 CONFIG_SCHED_STACK_END_CHECK=y
-CONFIG_STACKTRACE=y
-# CONFIG_FTRACE is not set
+CONFIG_FUNCTION_TRACER=y
+# CONFIG_TRACING_EVENTS_GPIO is not set
+# CONFIG_RUNTIME_TESTING_MENU is not set
+CONFIG_DEBUG_WX=y
 CONFIG_DEBUG_USER=y
+CONFIG_HARDENED_USERCOPY=y
+CONFIG_FORTIFY_SOURCE=y
 # CONFIG_CRYPTO_ECHAINIV is not set
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_SHA256=y
+CONFIG_CRYPTO_USER_API_HASH=y
 # CONFIG_CRYPTO_HW is not set
 # CONFIG_XZ_DEC_X86 is not set
 # CONFIG_XZ_DEC_POWERPC is not set
index 8c7ea03..02fa3a4 100644 (file)
@@ -3,40 +3,47 @@ CONFIG_KERNEL_XZ=y
 CONFIG_SYSVIPC=y
 CONFIG_NO_HZ_IDLE=y
 CONFIG_HIGH_RES_TIMERS=y
-CONFIG_LOG_BUF_SHIFT=14
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=16
 CONFIG_CGROUPS=y
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_RD_BZIP2 is not set
 # CONFIG_RD_LZO is not set
 # CONFIG_RD_LZ4 is not set
-CONFIG_KALLSYMS_ALL=y
-CONFIG_BPF_SYSCALL=y
+# CONFIG_UID16 is not set
+# CONFIG_SYSFS_SYSCALL is not set
 # CONFIG_AIO is not set
+CONFIG_BPF_SYSCALL=y
 CONFIG_EMBEDDED=y
+CONFIG_PERF_EVENTS=y
 # CONFIG_COMPAT_BRK is not set
 CONFIG_SLAB=y
+CONFIG_SLAB_FREELIST_RANDOM=y
 CONFIG_JUMP_LABEL=y
+CONFIG_STRICT_KERNEL_RWX=y
 CONFIG_GCC_PLUGINS=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
 # CONFIG_LBDAF is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEBUG_FS is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_MQ_IOSCHED_DEADLINE is not set
+# CONFIG_MQ_IOSCHED_KYBER is not set
 CONFIG_ARCH_MULTI_V6=y
 # CONFIG_ARCH_MULTI_V7 is not set
 CONFIG_ARCH_ASPEED=y
 CONFIG_MACH_ASPEED_G5=y
 # CONFIG_CACHE_L2X0 is not set
 CONFIG_VMSPLIT_2G=y
-CONFIG_AEABI=y
-# CONFIG_CPU_SW_DOMAIN_PAN is not set
 # CONFIG_COMPACTION is not set
+CONFIG_UACCESS_WITH_MEMCPY=y
 CONFIG_SECCOMP=y
 # CONFIG_ATAGS is not set
 CONFIG_ZBOOT_ROM_TEXT=0x0
 CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_ARM_APPENDED_DTB=y
-CONFIG_ARM_ATAG_DTB_COMPAT=y
 CONFIG_KEXEC=y
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_SUSPEND is not set
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_PACKET_DIAG=y
@@ -49,8 +56,14 @@ CONFIG_SYN_COOKIES=y
 # CONFIG_INET_XFRM_MODE_TUNNEL is not set
 # CONFIG_INET_XFRM_MODE_BEET is not set
 # CONFIG_INET_DIAG is not set
-# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET6_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET6_XFRM_MODE_BEET is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_ADVANCED is not set
+CONFIG_VLAN_8021Q=y
 CONFIG_NET_NCSI=y
+CONFIG_BPF_STREAM_PARSER=y
 # CONFIG_WIRELESS is not set
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_DEVTMPFS=y
@@ -60,11 +73,12 @@ CONFIG_MTD=y
 CONFIG_MTD_BLOCK=y
 CONFIG_MTD_PARTITIONED_MASTER=y
 CONFIG_MTD_SPI_NOR=y
+# CONFIG_MTD_SPI_NOR_USE_4K_SECTORS is not set
 CONFIG_SPI_ASPEED_SMC=y
 CONFIG_MTD_UBI=y
 CONFIG_MTD_UBI_FASTMAP=y
 CONFIG_MTD_UBI_BLOCK=y
-CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_LOOP=y
 CONFIG_ASPEED_LPC_CTRL=y
 CONFIG_ASPEED_LPC_SNOOP=y
 CONFIG_EEPROM_AT24=y
@@ -72,18 +86,26 @@ CONFIG_NETDEVICES=y
 CONFIG_NETCONSOLE=y
 # CONFIG_NET_VENDOR_ALACRITECH is not set
 # CONFIG_NET_VENDOR_AMAZON is not set
+# CONFIG_NET_VENDOR_AQUANTIA is not set
 # CONFIG_NET_VENDOR_ARC is not set
-# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_AURORA is not set
 # CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_CADENCE is not set
+# CONFIG_NET_VENDOR_CAVIUM is not set
 # CONFIG_NET_VENDOR_CIRRUS is not set
+# CONFIG_NET_VENDOR_CORTINA is not set
 # CONFIG_NET_VENDOR_EZCHIP is not set
 CONFIG_FTGMAC100=y
 # CONFIG_NET_VENDOR_HISILICON is not set
+# CONFIG_NET_VENDOR_HUAWEI is not set
 # CONFIG_NET_VENDOR_INTEL is not set
 # CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MELLANOX is not set
 # CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_MICROSEMI is not set
 # CONFIG_NET_VENDOR_NATSEMI is not set
 # CONFIG_NET_VENDOR_NETRONOME is not set
+# CONFIG_NET_VENDOR_NI is not set
 # CONFIG_NET_VENDOR_QUALCOMM is not set
 # CONFIG_NET_VENDOR_RENESAS is not set
 # CONFIG_NET_VENDOR_ROCKER is not set
@@ -91,13 +113,20 @@ CONFIG_FTGMAC100=y
 # CONFIG_NET_VENDOR_SEEQ is not set
 # CONFIG_NET_VENDOR_SOLARFLARE is not set
 # CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_SOCIONEXT is not set
 # CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_SYNOPSYS is not set
 # CONFIG_NET_VENDOR_VIA is not set
 # CONFIG_NET_VENDOR_WIZNET is not set
 CONFIG_BROADCOM_PHY=y
 CONFIG_REALTEK_PHY=y
+# CONFIG_USB_NET_DRIVERS is not set
 # CONFIG_WLAN is not set
-# CONFIG_INPUT is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_KEYBOARD_ATKBD is not set
+CONFIG_KEYBOARD_GPIO=y
+CONFIG_KEYBOARD_GPIO_POLLED=y
+# CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
 # CONFIG_VT is not set
 # CONFIG_LEGACY_PTYS is not set
@@ -110,15 +139,16 @@ CONFIG_SERIAL_8250_EXTENDED=y
 CONFIG_SERIAL_8250_ASPEED_VUART=y
 CONFIG_SERIAL_8250_SHARE_IRQ=y
 CONFIG_SERIAL_OF_PLATFORM=y
+CONFIG_ASPEED_KCS_IPMI_BMC=y
 CONFIG_ASPEED_BT_IPMI_BMC=y
-# CONFIG_HW_RANDOM is not set
-CONFIG_I2C=y
+CONFIG_HW_RANDOM_TIMERIOMEM=y
 # CONFIG_I2C_COMPAT is not set
 CONFIG_I2C_CHARDEV=y
 CONFIG_I2C_MUX=y
 CONFIG_I2C_MUX_PCA9541=y
 CONFIG_I2C_MUX_PCA954x=y
 CONFIG_I2C_ASPEED=y
+CONFIG_I2C_FSI=y
 CONFIG_GPIOLIB=y
 CONFIG_GPIO_SYSFS=y
 CONFIG_GPIO_ASPEED=y
@@ -131,19 +161,45 @@ CONFIG_SENSORS_LM75=y
 CONFIG_SENSORS_NCT7904=y
 CONFIG_PMBUS=y
 CONFIG_SENSORS_ADM1275=y
+CONFIG_SENSORS_IBM_CFFPS=y
+CONFIG_SENSORS_IR35221=y
 CONFIG_SENSORS_LM25066=y
+CONFIG_SENSORS_MAX31785=y
 CONFIG_SENSORS_UCD9000=y
+CONFIG_SENSORS_UCD9200=y
 CONFIG_SENSORS_TMP421=y
+CONFIG_SENSORS_W83773G=y
+CONFIG_WATCHDOG_SYSFS=y
+CONFIG_DRM=y
 CONFIG_USB=y
 CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
 CONFIG_USB_DYNAMIC_MINORS=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_EHCI_ROOT_HUB_TT=y
 CONFIG_USB_EHCI_HCD_PLATFORM=y
+CONFIG_USB_GADGET=y
+CONFIG_U_SERIAL_CONSOLE=y
+CONFIG_USB_ASPEED_VHUB=y
+CONFIG_USB_CONFIGFS=y
+CONFIG_USB_CONFIGFS_SERIAL=y
+CONFIG_USB_CONFIGFS_ACM=y
+CONFIG_USB_CONFIGFS_OBEX=y
+CONFIG_USB_CONFIGFS_NCM=y
+CONFIG_USB_CONFIGFS_ECM=y
+CONFIG_USB_CONFIGFS_ECM_SUBSET=y
+CONFIG_USB_CONFIGFS_RNDIS=y
+CONFIG_USB_CONFIGFS_EEM=y
+CONFIG_USB_CONFIGFS_MASS_STORAGE=y
+CONFIG_USB_CONFIGFS_F_LB_SS=y
+CONFIG_USB_CONFIGFS_F_FS=y
+CONFIG_USB_CONFIGFS_F_HID=y
+CONFIG_USB_CONFIGFS_F_PRINTER=y
 CONFIG_NEW_LEDS=y
 CONFIG_LEDS_CLASS=y
 CONFIG_LEDS_CLASS_FLASH=y
 CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_PCA955X=y
+CONFIG_LEDS_PCA955X_GPIO=y
 CONFIG_LEDS_TRIGGERS=y
 CONFIG_LEDS_TRIGGER_TIMER=y
 CONFIG_LEDS_TRIGGER_HEARTBEAT=y
@@ -152,33 +208,56 @@ CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_DS1307=y
 CONFIG_RTC_DRV_PCF8523=y
 CONFIG_RTC_DRV_RV8803=y
-CONFIG_MAILBOX=y
+# CONFIG_VIRTIO_MENU is not set
 # CONFIG_IOMMU_SUPPORT is not set
 CONFIG_IIO=y
 CONFIG_ASPEED_ADC=y
+CONFIG_MAX1363=y
 CONFIG_BMP280=y
+CONFIG_FSI=y
+CONFIG_FSI_MASTER_GPIO=y
+CONFIG_FSI_MASTER_HUB=y
+CONFIG_FSI_MASTER_AST_CF=y
+CONFIG_FSI_SCOM=y
+CONFIG_FSI_SBEFIFO=y
 CONFIG_FIRMWARE_MEMMAP=y
 CONFIG_FANOTIFY=y
 CONFIG_OVERLAY_FS=y
 CONFIG_TMPFS=y
 CONFIG_JFFS2_FS=y
+# CONFIG_JFFS2_FS_WRITEBUFFER is not set
 CONFIG_JFFS2_SUMMARY=y
 CONFIG_JFFS2_FS_XATTR=y
 CONFIG_UBIFS_FS=y
 CONFIG_SQUASHFS=y
 CONFIG_SQUASHFS_XZ=y
+CONFIG_SQUASHFS_ZSTD=y
+# CONFIG_NETWORK_FILESYSTEMS is not set
 CONFIG_PRINTK_TIME=y
 CONFIG_DYNAMIC_DEBUG=y
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_INFO_REDUCED=y
+CONFIG_DEBUG_INFO_DWARF4=y
+CONFIG_GDB_SCRIPTS=y
 CONFIG_STRIP_ASM_SYMS=y
-CONFIG_DEBUG_FS=y
+CONFIG_SOFTLOCKUP_DETECTOR=y
+# CONFIG_DETECT_HUNG_TASK is not set
 CONFIG_WQ_WATCHDOG=y
+CONFIG_PANIC_ON_OOPS=y
 CONFIG_PANIC_TIMEOUT=-1
 # CONFIG_SCHED_DEBUG is not set
 CONFIG_SCHED_STACK_END_CHECK=y
-CONFIG_STACKTRACE=y
-# CONFIG_FTRACE is not set
+CONFIG_FUNCTION_TRACER=y
+# CONFIG_TRACING_EVENTS_GPIO is not set
+# CONFIG_RUNTIME_TESTING_MENU is not set
+CONFIG_DEBUG_WX=y
 CONFIG_DEBUG_USER=y
+CONFIG_HARDENED_USERCOPY=y
+CONFIG_FORTIFY_SOURCE=y
 # CONFIG_CRYPTO_ECHAINIV is not set
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_SHA256=y
+CONFIG_CRYPTO_USER_API_HASH=y
 # CONFIG_CRYPTO_HW is not set
 # CONFIG_XZ_DEC_X86 is not set
 # CONFIG_XZ_DEC_POWERPC is not set
index e4d188f..e9bc889 100644 (file)
@@ -86,7 +86,7 @@ CONFIG_SPI=y
 CONFIG_SPI_BCM2835=y
 CONFIG_SPI_BCM2835AUX=y
 CONFIG_GPIO_SYSFS=y
-# CONFIG_HWMON is not set
+CONFIG_SENSORS_RASPBERRYPI_HWMON=m
 CONFIG_THERMAL=y
 CONFIG_BCM2835_THERMAL=y
 CONFIG_WATCHDOG=y
index 21b2d77..07b2ead 100644 (file)
@@ -31,7 +31,6 @@ CONFIG_MACH_MITYOMAPL138=y
 CONFIG_MACH_OMAPL138_HAWKBOARD=y
 CONFIG_DAVINCI_MUX_DEBUG=y
 CONFIG_DAVINCI_MUX_WARNINGS=y
-CONFIG_DAVINCI_RESET_CLOCKS=y
 CONFIG_PREEMPT=y
 CONFIG_AEABI=y
 CONFIG_CMA=y
@@ -54,6 +53,13 @@ CONFIG_INET=y
 CONFIG_IP_PNP=y
 CONFIG_IP_PNP_DHCP=y
 CONFIG_NETFILTER=y
+CONFIG_BT=m
+CONFIG_BT_RFCOMM=m
+CONFIG_BT_BNEP=m
+CONFIG_BT_HIDP=m
+CONFIG_BT_LEDS=y
+CONFIG_BT_HCIUART=m
+CONFIG_BT_HCIUART_LL=y
 CONFIG_DEVTMPFS=y
 CONFIG_DEVTMPFS_MOUNT=y
 CONFIG_FW_LOADER=m
@@ -113,6 +119,7 @@ CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_NR_UARTS=3
 CONFIG_SERIAL_8250_RUNTIME_UARTS=3
 CONFIG_SERIAL_OF_PLATFORM=y
+CONFIG_SERIAL_DEV_BUS=y
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
@@ -153,6 +160,7 @@ CONFIG_TINYDRM_ST7586=m
 CONFIG_FB=y
 CONFIG_FIRMWARE_EDID=y
 CONFIG_FB_DA8XX=y
+CONFIG_BACKLIGHT_PWM=m
 CONFIG_FRAMEBUFFER_CONSOLE=y
 CONFIG_LOGO=y
 CONFIG_SOUND=m
@@ -212,6 +220,7 @@ CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_OMAP=m
 CONFIG_DMADEVICES=y
 CONFIG_TI_EDMA=y
+CONFIG_COMMON_CLK_PWM=m
 CONFIG_REMOTEPROC=m
 CONFIG_DA8XX_REMOTEPROC=m
 CONFIG_MEMORY=y
index 85b2369..27ea6df 100644 (file)
@@ -155,8 +155,8 @@ CONFIG_THERMAL_EMULATION=y
 CONFIG_WATCHDOG=y
 CONFIG_S3C2410_WATCHDOG=y
 CONFIG_MFD_CROS_EC=y
-CONFIG_MFD_CROS_EC_I2C=y
-CONFIG_MFD_CROS_EC_SPI=y
+CONFIG_CROS_EC_I2C=y
+CONFIG_CROS_EC_SPI=y
 CONFIG_MFD_MAX14577=y
 CONFIG_MFD_MAX77686=y
 CONFIG_MFD_MAX77693=y
index 200ebda..e2c1276 100644 (file)
@@ -81,7 +81,6 @@ CONFIG_CAN=y
 CONFIG_CAN_FLEXCAN=y
 CONFIG_BT=y
 CONFIG_BT_HCIUART=y
-CONFIG_BT_HCIUART_H4=y
 CONFIG_BT_HCIUART_LL=y
 CONFIG_CFG80211=y
 CONFIG_CFG80211_WEXT=y
@@ -266,7 +265,8 @@ CONFIG_DRM_IMX_TVE=y
 CONFIG_DRM_IMX_LDB=y
 CONFIG_DRM_IMX_HDMI=y
 CONFIG_DRM_ETNAVIV=y
-CONFIG_FB_MXS=y
+CONFIG_DRM_MXSFB=y
+CONFIG_FB_MODE_HELPERS=y
 CONFIG_LCD_CLASS_DEVICE=y
 CONFIG_LCD_L4F00242T03=y
 CONFIG_LCD_PLATFORM=y
@@ -282,7 +282,6 @@ CONFIG_SND_SOC_FSL_ASRC=y
 CONFIG_SND_IMX_SOC=y
 CONFIG_SND_SOC_PHYCORE_AC97=y
 CONFIG_SND_SOC_EUKREA_TLV320=y
-CONFIG_SND_SOC_IMX_WM8962=y
 CONFIG_SND_SOC_IMX_ES8328=y
 CONFIG_SND_SOC_IMX_SGTL5000=y
 CONFIG_SND_SOC_IMX_SPDIF=y
@@ -371,13 +370,16 @@ CONFIG_DMADEVICES=y
 CONFIG_FSL_EDMA=y
 CONFIG_IMX_SDMA=y
 CONFIG_MXS_DMA=y
+CONFIG_DMATEST=m
 CONFIG_STAGING=y
 CONFIG_STAGING_MEDIA=y
 CONFIG_VIDEO_IMX_MEDIA=y
 CONFIG_COMMON_CLK_PWM=y
 CONFIG_IIO=y
+CONFIG_MMA8452=y
 CONFIG_IMX7D_ADC=y
 CONFIG_VF610_ADC=y
+CONFIG_SENSORS_ISL29018=y
 CONFIG_MAG3110=y
 CONFIG_MPL3115=y
 CONFIG_PWM=y
index 2536c23..3ded35a 100644 (file)
@@ -170,7 +170,10 @@ CONFIG_USB_DWC3=y
 CONFIG_NOP_USB_XCEIV=y
 CONFIG_KEYSTONE_USB_PHY=y
 CONFIG_MMC=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=y
 CONFIG_MMC_OMAP_HS=y
+CONFIG_MMC_SDHCI_OMAP=y
 CONFIG_NEW_LEDS=y
 CONFIG_LEDS_CLASS=y
 CONFIG_LEDS_GPIO=y
@@ -235,3 +238,5 @@ CONFIG_INPUT_GPIO_DECODER=m
 CONFIG_GPIO_PCA953X=m
 CONFIG_LEDS_TRIGGER_ACTIVITY=y
 CONFIG_LEDS_TRIGGER_CPU=y
+CONFIG_MICREL_PHY=y
+CONFIG_DP83867_PHY=y
index 7c41bee..318b76f 100644 (file)
@@ -1,5 +1,4 @@
 CONFIG_SYSVIPC=y
-CONFIG_FHANDLE=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_LOG_BUF_SHIFT=19
@@ -11,12 +10,10 @@ CONFIG_KPROBES=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_ARCH_MULTI_V7 is not set
-CONFIG_ARCH_MVEBU=y
-CONFIG_MACH_KIRKWOOD=y
-CONFIG_ARCH_AT91=y
-CONFIG_SOC_AT91SAM9=y
 CONFIG_ARCH_ASPEED=y
 CONFIG_MACH_ASPEED_G4=y
+CONFIG_ARCH_AT91=y
+CONFIG_SOC_AT91SAM9=y
 CONFIG_ARCH_MXC=y
 CONFIG_MACH_MX21ADS=y
 CONFIG_MACH_MX27ADS=y
@@ -25,6 +22,8 @@ CONFIG_MACH_IMX27_VISSTRIM_M10=y
 CONFIG_MACH_PCA100=y
 CONFIG_MACH_IMX27_DT=y
 CONFIG_SOC_IMX25=y
+CONFIG_ARCH_MVEBU=y
+CONFIG_MACH_KIRKWOOD=y
 CONFIG_ARCH_ORION5X=y
 CONFIG_MACH_DB88F5281=y
 CONFIG_MACH_RD88F5182=y
@@ -34,7 +33,6 @@ CONFIG_MACH_DNS323=y
 CONFIG_MACH_TS209=y
 CONFIG_MACH_TERASTATION_PRO2=y
 CONFIG_MACH_LINKSTATION_PRO=y
-CONFIG_MACH_LINKSTATION_LSCHL=y
 CONFIG_MACH_LINKSTATION_MINI=y
 CONFIG_MACH_LINKSTATION_LS_HGL=y
 CONFIG_MACH_TS409=y
@@ -71,7 +69,6 @@ CONFIG_IP_PNP=y
 CONFIG_IP_PNP_DHCP=y
 CONFIG_IP_PNP_BOOTP=y
 CONFIG_NET_DSA=y
-CONFIG_NET_SWITCHDEV=y
 CONFIG_NET_PKTGEN=m
 CONFIG_CFG80211=y
 CONFIG_MAC80211=y
@@ -93,10 +90,14 @@ CONFIG_MTD_PHYSMAP=y
 CONFIG_MTD_NAND=y
 CONFIG_MTD_NAND_ATMEL=y
 CONFIG_MTD_NAND_ORION=y
+CONFIG_MTD_SPI_NOR=y
+CONFIG_SPI_ASPEED_SMC=y
 CONFIG_MTD_UBI=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_ATMEL_TCLIB=y
 CONFIG_ATMEL_SSC=m
+CONFIG_ASPEED_LPC_CTRL=m
+CONFIG_ASPEED_LPC_SNOOP=m
 CONFIG_EEPROM_AT24=y
 # CONFIG_SCSI_PROC_FS is not set
 CONFIG_BLK_DEV_SD=y
@@ -110,10 +111,11 @@ CONFIG_NET_DSA_MV88E6060=y
 CONFIG_NET_DSA_MV88E6XXX=y
 CONFIG_MACB=y
 CONFIG_DM9000=y
+CONFIG_FTGMAC100=m
 CONFIG_MV643XX_ETH=y
 CONFIG_R8169=y
-CONFIG_MARVELL_PHY=y
 CONFIG_DAVICOM_PHY=y
+CONFIG_MARVELL_PHY=y
 CONFIG_MICREL_PHY=y
 CONFIG_LIBERTAS=y
 CONFIG_LIBERTAS_SDIO=y
@@ -125,23 +127,26 @@ CONFIG_KEYBOARD_GPIO=y
 CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_TOUCHSCREEN_ADS7846=m
 CONFIG_LEGACY_PTY_COUNT=16
-# CONFIG_DEVKMEM is not set
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_NR_UARTS=6
 CONFIG_SERIAL_8250_RUNTIME_UARTS=6
 CONFIG_SERIAL_8250_EXTENDED=y
 CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_ASPEED_VUART=m
 CONFIG_SERIAL_OF_PLATFORM=y
 CONFIG_SERIAL_ATMEL=y
 CONFIG_SERIAL_ATMEL_CONSOLE=y
 CONFIG_SERIAL_ATMEL_TTYAT=y
 CONFIG_SERIAL_IMX=y
 CONFIG_SERIAL_IMX_CONSOLE=y
+CONFIG_ASPEED_KCS_IPMI_BMC=m
+CONFIG_ASPEED_BT_IPMI_BMC=m
 CONFIG_HW_RANDOM=y
-CONFIG_I2C=y
+CONFIG_HW_RANDOM_TIMERIOMEM=m
 # CONFIG_I2C_COMPAT is not set
 CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_ASPEED=m
 CONFIG_I2C_AT91=y
 CONFIG_I2C_IMX=y
 CONFIG_I2C_MV64XXX=y
@@ -150,10 +155,12 @@ CONFIG_SPI=y
 CONFIG_SPI_ATMEL=y
 CONFIG_SPI_IMX=y
 CONFIG_SPI_ORION=y
+CONFIG_GPIO_ASPEED=m
 CONFIG_POWER_RESET=y
 CONFIG_POWER_RESET_GPIO=y
 CONFIG_POWER_RESET_QNAP=y
 CONFIG_SENSORS_ADT7475=y
+CONFIG_SENSORS_ASPEED=y
 CONFIG_SENSORS_G762=y
 CONFIG_SENSORS_LM63=y
 CONFIG_SENSORS_LM75=y
@@ -172,11 +179,9 @@ CONFIG_MEDIA_CAMERA_SUPPORT=y
 CONFIG_V4L_PLATFORM_DRIVERS=y
 CONFIG_SOC_CAMERA=y
 CONFIG_VIDEO_ATMEL_ISI=m
-CONFIG_SOC_CAMERA_OV2640=m
 CONFIG_DRM=y
 CONFIG_DRM_ATMEL_HLCDC=m
 CONFIG_DRM_PANEL_SIMPLE=y
-CONFIG_FB=y
 CONFIG_FB_IMX=y
 CONFIG_FB_ATMEL=y
 CONFIG_BACKLIGHT_ATMEL_LCDC=y
@@ -246,6 +251,7 @@ CONFIG_MV_XOR=y
 CONFIG_STAGING=y
 CONFIG_FB_XGI=y
 CONFIG_IIO=m
+CONFIG_ASPEED_ADC=m
 CONFIG_AT91_ADC=m
 CONFIG_PWM=y
 CONFIG_PWM_ATMEL=m
index 8f6be19..fc33444 100644 (file)
@@ -88,6 +88,7 @@ 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
@@ -184,6 +185,7 @@ CONFIG_MTD_NAND_DENALI_DT=y
 CONFIG_MTD_NAND_OMAP2=y
 CONFIG_MTD_NAND_OMAP_BCH=y
 CONFIG_MTD_NAND_ATMEL=y
+CONFIG_MTD_NAND_MARVELL=y
 CONFIG_MTD_NAND_GPMI_NAND=y
 CONFIG_MTD_NAND_BRCMNAND=y
 CONFIG_MTD_NAND_VF610_NFC=y
@@ -243,6 +245,7 @@ CONFIG_KS8851=y
 CONFIG_R8169=y
 CONFIG_SH_ETH=y
 CONFIG_SMSC911X=y
+CONFIG_SNI_AVE=y
 CONFIG_STMMAC_ETH=y
 CONFIG_DWMAC_DWC_QOS_ETH=y
 CONFIG_TI_CPSW=y
@@ -447,6 +450,7 @@ CONFIG_SENSORS_LM90=y
 CONFIG_SENSORS_LM95245=y
 CONFIG_SENSORS_NTC_THERMISTOR=m
 CONFIG_SENSORS_PWM_FAN=m
+CONFIG_SENSORS_RASPBERRYPI_HWMON=m
 CONFIG_SENSORS_INA2XX=m
 CONFIG_CPU_THERMAL=y
 CONFIG_IMX_THERMAL=y
@@ -456,6 +460,7 @@ CONFIG_ARMADA_THERMAL=y
 CONFIG_BCM2835_THERMAL=m
 CONFIG_BRCMSTB_THERMAL=m
 CONFIG_ST_THERMAL_MEMMAP=y
+CONFIG_UNIPHIER_THERMAL=y
 CONFIG_WATCHDOG=y
 CONFIG_DA9063_WATCHDOG=m
 CONFIG_XILINX_WATCHDOG=y
@@ -490,8 +495,8 @@ CONFIG_MFD_AC100=y
 CONFIG_MFD_AXP20X_I2C=y
 CONFIG_MFD_AXP20X_RSB=y
 CONFIG_MFD_CROS_EC=m
-CONFIG_MFD_CROS_EC_I2C=m
-CONFIG_MFD_CROS_EC_SPI=m
+CONFIG_CROS_EC_I2C=m
+CONFIG_CROS_EC_SPI=m
 CONFIG_MFD_DA9063=m
 CONFIG_MFD_MAX14577=y
 CONFIG_MFD_MAX77686=y
@@ -562,6 +567,7 @@ CONFIG_VIDEO_V4L2_SUBDEV_API=y
 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
@@ -825,6 +831,7 @@ CONFIG_RTC_DRV_SUNXI=y
 CONFIG_RTC_DRV_MV=y
 CONFIG_RTC_DRV_TEGRA=y
 CONFIG_RTC_DRV_ST_LPC=y
+CONFIG_RTC_DRV_STM32=y
 CONFIG_RTC_DRV_CPCAP=m
 CONFIG_DMADEVICES=y
 CONFIG_AT_HDMAC=y
@@ -840,6 +847,9 @@ CONFIG_PL330_DMA=y
 CONFIG_SIRF_DMA=y
 CONFIG_STE_DMA40=y
 CONFIG_ST_FDMA=m
+CONFIG_STM32_DMA=y
+CONFIG_STM32_DMAMUX=y
+CONFIG_STM32_MDMA=y
 CONFIG_TEGRA20_APB_DMA=y
 CONFIG_XILINX_DMA=y
 CONFIG_QCOM_BAM_DMA=y
index ddaeda4..5514021 100644 (file)
@@ -1,5 +1,4 @@
 CONFIG_SYSVIPC=y
-CONFIG_FHANDLE=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
@@ -16,10 +15,8 @@ CONFIG_MACH_ARMADA_39X=y
 CONFIG_MACH_ARMADA_XP=y
 CONFIG_MACH_DOVE=y
 CONFIG_PCI=y
-CONFIG_PCI_MSI=y
 CONFIG_PCI_MVEBU=y
 CONFIG_SMP=y
-CONFIG_AEABI=y
 CONFIG_HIGHMEM=y
 # CONFIG_COMPACTION is not set
 CONFIG_ZBOOT_ROM_TEXT=0x0
@@ -58,7 +55,6 @@ CONFIG_MTD_M25P80=y
 CONFIG_MTD_NAND=y
 CONFIG_MTD_NAND_MARVELL=y
 CONFIG_MTD_SPI_NOR=y
-CONFIG_SRAM=y
 CONFIG_MTD_UBI=y
 CONFIG_EEPROM_AT24=y
 CONFIG_BLK_DEV_SD=y
@@ -67,12 +63,11 @@ CONFIG_SATA_AHCI=y
 CONFIG_AHCI_MVEBU=y
 CONFIG_SATA_MV=y
 CONFIG_NETDEVICES=y
-CONFIG_NET_DSA_MV88E6XXX=y
 CONFIG_MV643XX_ETH=y
 CONFIG_MVNETA=y
 CONFIG_MVPP2=y
+CONFIG_SFP=y
 CONFIG_MARVELL_PHY=y
-CONFIG_FIXED_PHY=y
 CONFIG_MWIFIEX=y
 CONFIG_MWIFIEX_SDIO=y
 CONFIG_INPUT_EVDEV=y
@@ -88,10 +83,11 @@ CONFIG_SPI=y
 CONFIG_SPI_ORION=y
 CONFIG_GPIO_SYSFS=y
 CONFIG_GPIO_PCA953X=y
-CONFIG_POWER_SUPPLY=y
 CONFIG_POWER_RESET=y
 CONFIG_POWER_RESET_GPIO=y
+CONFIG_POWER_SUPPLY=y
 CONFIG_SENSORS_GPIO_FAN=y
+CONFIG_SENSORS_PWM_FAN=y
 CONFIG_THERMAL=y
 CONFIG_ARMADA_THERMAL=y
 CONFIG_WATCHDOG=y
@@ -135,7 +131,6 @@ CONFIG_MV_XOR=y
 # CONFIG_IOMMU_SUPPORT is not set
 CONFIG_MEMORY=y
 CONFIG_PWM=y
-CONFIG_SENSORS_PWM_FAN=y
 CONFIG_EXT4_FS=y
 CONFIG_ISO9660_FS=y
 CONFIG_JOLIET=y
@@ -153,10 +148,8 @@ CONFIG_NLS_ISO8859_2=y
 CONFIG_NLS_UTF8=y
 CONFIG_PRINTK_TIME=y
 CONFIG_DEBUG_INFO=y
-CONFIG_DEBUG_FS=y
 CONFIG_MAGIC_SYSRQ=y
 # CONFIG_SCHED_DEBUG is not set
-CONFIG_TIMER_STATS=y
 # CONFIG_DEBUG_BUGVERBOSE is not set
 CONFIG_DEBUG_USER=y
 CONFIG_CRYPTO_DEV_MARVELL_CESA=y
index a508eb3..148226e 100644 (file)
@@ -94,8 +94,9 @@ CONFIG_STMP3XXX_RTC_WATCHDOG=y
 CONFIG_MFD_MXS_LRADC=y
 CONFIG_REGULATOR=y
 CONFIG_REGULATOR_FIXED_VOLTAGE=y
-CONFIG_FB=y
-CONFIG_FB_MXS=y
+CONFIG_DRM=y
+CONFIG_DRM_MXSFB=y
+CONFIG_FB_MODE_HELPERS=y
 CONFIG_BACKLIGHT_LCD_SUPPORT=y
 CONFIG_LCD_CLASS_DEVICE=y
 CONFIG_BACKLIGHT_CLASS_DEVICE=y
index 5655a1c..6bb506e 100644 (file)
@@ -398,8 +398,8 @@ CONFIG_MFD_AS3711=y
 CONFIG_MFD_BCM590XX=m
 CONFIG_MFD_AXP20X=y
 CONFIG_MFD_CROS_EC=m
-CONFIG_MFD_CROS_EC_I2C=m
-CONFIG_MFD_CROS_EC_SPI=m
+CONFIG_CROS_EC_I2C=m
+CONFIG_CROS_EC_SPI=m
 CONFIG_MFD_ASIC3=y
 CONFIG_PMIC_DA903X=y
 CONFIG_HTC_EGPIO=y
index dd2a089..6aa7046 100644 (file)
@@ -57,6 +57,8 @@ CONFIG_DEVTMPFS_MOUNT=y
 CONFIG_MTD=y
 CONFIG_MTD_BLOCK=y
 CONFIG_MTD_M25P80=y
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_QCOM=y
 CONFIG_MTD_SPI_NOR=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
index 09b5a73..a077597 100644 (file)
@@ -1,5 +1,7 @@
+CONFIG_SYSVIPC=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
+CONFIG_CGROUPS=y
 CONFIG_SYSFS_DEPRECATED=y
 CONFIG_SYSFS_DEPRECATED_V2=y
 CONFIG_BLK_DEV_INITRD=y
@@ -13,28 +15,68 @@ CONFIG_SOLARIS_X86_PARTITION=y
 CONFIG_ARCH_S5PV210=y
 CONFIG_VMSPLIT_2G=y
 CONFIG_PREEMPT=y
-CONFIG_AEABI=y
+CONFIG_ARM_APPENDED_DTB=y
 CONFIG_CMDLINE="root=/dev/ram0 rw ramdisk=8192 initrd=0x20800000,8M console=ttySAC1,115200 init=/linuxrc"
 CONFIG_VFP=y
 CONFIG_NEON=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+CONFIG_CFG80211=m
+CONFIG_MAC80211=m
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=8192
 CONFIG_SCSI=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_SG=y
+CONFIG_NETDEVICES=y
+CONFIG_BRCMFMAC=m
 CONFIG_INPUT_EVDEV=y
-# CONFIG_INPUT_KEYBOARD is not set
+CONFIG_KEYBOARD_GPIO=y
 # CONFIG_INPUT_MOUSE is not set
 CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_SAMSUNG=y
 CONFIG_SERIAL_SAMSUNG_CONSOLE=y
 CONFIG_HW_RANDOM=y
+CONFIG_I2C_GPIO=y
+CONFIG_POWER_SUPPLY=y
+CONFIG_BATTERY_MAX17040=y
 # CONFIG_HWMON is not set
-# CONFIG_USB_SUPPORT is not set
+CONFIG_MFD_MAX8998=y
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_MAX8998=y
+CONFIG_DRM=y
+CONFIG_DRM_EXYNOS=y
+CONFIG_DRM_EXYNOS_FIMD=y
+CONFIG_DRM_EXYNOS_DPI=y
+CONFIG_USB=y
+CONFIG_USB_OTG=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_EXYNOS=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_OHCI_EXYNOS=y
+CONFIG_USB_DWC2=y
+CONFIG_MMC=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_S3C=y
+CONFIG_MMC_SDHCI_S3C_DMA=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_MAX8998=m
+CONFIG_PHY_SAMSUNG_USB2=m
+CONFIG_PHY_S5PV210_USB2=y
 CONFIG_EXT2_FS=y
+CONFIG_EXT4_FS=y
+CONFIG_AUTOFS4_FS=y
 CONFIG_MSDOS_FS=y
 CONFIG_VFAT_FS=y
 CONFIG_TMPFS=y
@@ -44,6 +86,7 @@ CONFIG_ROMFS_FS=y
 CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_ASCII=y
 CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_UTF8=y
 CONFIG_DEBUG_INFO=y
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_DEBUG_KERNEL=y
index b49887e..f8faf37 100644 (file)
@@ -22,6 +22,7 @@ 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_PL310_ERRATA_588369=y
 CONFIG_ARM_ERRATA_754322=y
@@ -57,7 +58,6 @@ CONFIG_IP_PNP=y
 CONFIG_IP_PNP_DHCP=y
 CONFIG_CAN=y
 CONFIG_CAN_RCAR=y
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_DEVTMPFS=y
 CONFIG_DEVTMPFS_MOUNT=y
 CONFIG_DMA_CMA=y
@@ -72,22 +72,9 @@ CONFIG_BLK_DEV_SD=y
 CONFIG_ATA=y
 CONFIG_SATA_RCAR=y
 CONFIG_NETDEVICES=y
-# CONFIG_NET_VENDOR_ARC is not set
-# CONFIG_NET_CADENCE is not set
-# CONFIG_NET_VENDOR_BROADCOM is not set
-# CONFIG_NET_VENDOR_CIRRUS is not set
-# CONFIG_NET_VENDOR_FARADAY is not set
-# CONFIG_NET_VENDOR_INTEL is not set
-# CONFIG_NET_VENDOR_MARVELL is not set
-# CONFIG_NET_VENDOR_MICREL is not set
-# CONFIG_NET_VENDOR_NATSEMI is not set
 CONFIG_SH_ETH=y
 CONFIG_RAVB=y
-# CONFIG_NET_VENDOR_SEEQ is not set
 CONFIG_SMSC911X=y
-# CONFIG_NET_VENDOR_STMICRO is not set
-# CONFIG_NET_VENDOR_VIA is not set
-# CONFIG_NET_VENDOR_WIZNET is not set
 CONFIG_MICREL_PHY=y
 CONFIG_SMSC_PHY=y
 CONFIG_INPUT_EVDEV=y
@@ -100,6 +87,7 @@ CONFIG_INPUT_ADXL34X=y
 # CONFIG_LEGACY_PTYS is not set
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_DW=y
 CONFIG_SERIAL_8250_EM=y
 CONFIG_SERIAL_SH_SCI=y
 CONFIG_I2C_CHARDEV=y
@@ -205,6 +193,7 @@ CONFIG_AK8975=y
 CONFIG_PWM=y
 CONFIG_PWM_RCAR=y
 CONFIG_PWM_RENESAS_TPU=y
+CONFIG_RESET_CONTROLLER=y
 CONFIG_GENERIC_PHY=y
 CONFIG_PHY_RCAR_GEN2=y
 # CONFIG_DNOTIFY is not set
index bf8ccff..0ae900e 100644 (file)
@@ -2,7 +2,7 @@
  * Glue code for the SHA256 Secure Hash Algorithm assembly implementation
  * using optimized ARM assembler and NEON instructions.
  *
- * Copyright © 2015 Google Inc.
+ * Copyright Â© 2015 Google Inc.
  *
  * This file is based on sha256_ssse3_glue.c:
  *   Copyright (C) 2013 Intel Corporation
index 9bbee56..1d82c6c 100644 (file)
@@ -2,10 +2,10 @@
  * Glue code for the SHA256 Secure Hash Algorithm assembly implementation
  * using NEON instructions.
  *
- * Copyright © 2015 Google Inc.
+ * Copyright Â© 2015 Google Inc.
  *
  * This file is based on sha512_neon_glue.c:
- *   Copyright © 2014 Jussi Kivilinna <jussi.kivilinna@iki.fi>
+ *   Copyright Â© 2014 Jussi Kivilinna <jussi.kivilinna@iki.fi>
  *
  * 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
index 3fb1b5a..689e656 100644 (file)
 
 static unsigned long cpu_boot_addr;
 
-static void __naked tf_generic_smc(u32 type, u32 arg1, u32 arg2)
+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, lr}\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, pc}"
+               "ldmfd  sp!, {r4 - r11}\n\t"
                :
-               : "r" (type), "r" (arg1), "r" (arg2)
-               : "memory");
+               : "r" (r0), "r" (r1), "r" (r2)
+               : "memory", "r3", "r12", "lr");
 }
 
 static int tf_set_cpu_boot_addr(int cpu, unsigned long boot_addr)
index fe2fb1d..77121b7 100644 (file)
@@ -107,9 +107,19 @@ static inline unsigned long *vcpu_hcr(const struct kvm_vcpu *vcpu)
        return (unsigned long *)&vcpu->arch.hcr;
 }
 
+static inline void vcpu_clear_wfe_traps(struct kvm_vcpu *vcpu)
+{
+       vcpu->arch.hcr &= ~HCR_TWE;
+}
+
+static inline void vcpu_set_wfe_traps(struct kvm_vcpu *vcpu)
+{
+       vcpu->arch.hcr |= HCR_TWE;
+}
+
 static inline bool vcpu_mode_is_32bit(const struct kvm_vcpu *vcpu)
 {
-       return 1;
+       return true;
 }
 
 static inline unsigned long *vcpu_pc(struct kvm_vcpu *vcpu)
index 1f1fe41..79906ce 100644 (file)
@@ -216,6 +216,11 @@ int kvm_arm_get_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg);
 int kvm_arm_set_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg);
 unsigned long kvm_call_hyp(void *hypfn, ...);
 void force_vm_exit(const cpumask_t *mask);
+int __kvm_arm_vcpu_get_events(struct kvm_vcpu *vcpu,
+                             struct kvm_vcpu_events *events);
+
+int __kvm_arm_vcpu_set_events(struct kvm_vcpu *vcpu,
+                             struct kvm_vcpu_events *events);
 
 #define KVM_ARCH_WANT_MMU_NOTIFIER
 int kvm_unmap_hva(struct kvm *kvm, unsigned long hva);
index 8553d68..265ea9c 100644 (file)
@@ -75,17 +75,9 @@ phys_addr_t kvm_get_idmap_vector(void);
 int kvm_mmu_init(void);
 void kvm_clear_hyp_idmap(void);
 
-static inline void kvm_set_pmd(pmd_t *pmd, pmd_t new_pmd)
-{
-       *pmd = new_pmd;
-       dsb(ishst);
-}
-
-static inline void kvm_set_pte(pte_t *pte, pte_t new_pte)
-{
-       *pte = new_pte;
-       dsb(ishst);
-}
+#define kvm_mk_pmd(ptep)       __pmd(__pa(ptep) | PMD_TYPE_TABLE)
+#define kvm_mk_pud(pmdp)       __pud(__pa(pmdp) | PMD_TYPE_TABLE)
+#define kvm_mk_pgd(pudp)       ({ BUILD_BUG(); 0; })
 
 static inline pte_t kvm_s2pte_mkwrite(pte_t pte)
 {
index 97820a8..1c5f795 100644 (file)
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Renesas SCIF(A) debugging macro include header
  *
@@ -5,10 +6,6 @@
  *
  * Copyright (C) 2012-2013 Renesas Electronics Corporation
  * Copyright (C) 1994-1999 Russell King
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
  */
 
 #define SCIF_PHYS      CONFIG_DEBUG_UART_PHYS
index 16e006f..4602464 100644 (file)
@@ -27,6 +27,7 @@
 #define __KVM_HAVE_GUEST_DEBUG
 #define __KVM_HAVE_IRQ_LINE
 #define __KVM_HAVE_READONLY_MEM
+#define __KVM_HAVE_VCPU_EVENTS
 
 #define KVM_COALESCED_MMIO_PAGE_OFFSET 1
 
@@ -125,6 +126,18 @@ struct kvm_sync_regs {
 struct kvm_arch_memory_slot {
 };
 
+/* for KVM_GET/SET_VCPU_EVENTS */
+struct kvm_vcpu_events {
+       struct {
+               __u8 serror_pending;
+               __u8 serror_has_esr;
+               /* Align it to 8 bytes */
+               __u8 pad[6];
+               __u64 serror_esr;
+       } exception;
+       __u32 reserved[12];
+};
+
 /* If you need to interpret the index values, here is the key: */
 #define KVM_REG_ARM_COPROC_MASK                0x000000000FFF0000
 #define KVM_REG_ARM_COPROC_SHIFT       16
index 974d8d7..3968d6c 100644 (file)
 #error Sorry, your compiler targets APCS-26 but this kernel requires APCS-32
 #endif
 /*
- * GCC 3.0, 3.1: general bad code generation.
- * GCC 3.2.0: incorrect function argument offset calculation.
- * GCC 3.2.x: miscompiles NEW_AUX_ENT in fs/binfmt_elf.c
- *            (http://gcc.gnu.org/PR8896) and incorrect structure
- *           initialisation in fs/jffs2/erase.c
  * GCC 4.8.0-4.8.2: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58854
  *           miscompiles find_get_entry(), and can result in EXT3 and EXT4
  *           filesystem corruption (possibly other FS too).
  */
-#ifdef __GNUC__
-#if (__GNUC__ == 3 && __GNUC_MINOR__ < 3)
-#error Your compiler is too buggy; it is known to miscompile kernels.
-#error    Known good compilers: 3.3, 4.x
-#endif
-#if GCC_VERSION >= 40800 && GCC_VERSION < 40803
+#if defined(GCC_VERSION) && GCC_VERSION >= 40800 && GCC_VERSION < 40803
 #error Your compiler is too buggy; it is known to miscompile kernels
 #error and result in filesystem corruption and oopses.
 #endif
-#endif
 
 int main(void)
 {
index d9c2991..82ab015 100644 (file)
@@ -330,16 +330,15 @@ unsigned long arch_randomize_brk(struct mm_struct *mm)
  * atomic helpers. Insert it into the gate_vma so that it is visible
  * through ptrace and /proc/<pid>/mem.
  */
-static struct vm_area_struct gate_vma = {
-       .vm_start       = 0xffff0000,
-       .vm_end         = 0xffff0000 + PAGE_SIZE,
-       .vm_flags       = VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYEXEC,
-};
+static struct vm_area_struct gate_vma;
 
 static int __init gate_vma_init(void)
 {
        vma_init(&gate_vma, NULL);
        gate_vma.vm_page_prot = PAGE_READONLY_EXEC;
+       gate_vma.vm_start = 0xffff0000;
+       gate_vma.vm_end = 0xffff0000 + PAGE_SIZE;
+       gate_vma.vm_flags = VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYEXEC;
        return 0;
 }
 arch_initcall(gate_vma_init);
index 3a02e76..450c7a4 100644 (file)
@@ -246,6 +246,7 @@ static bool access_gic_sgi(struct kvm_vcpu *vcpu,
                           const struct coproc_reg *r)
 {
        u64 reg;
+       bool g1;
 
        if (!p->is_write)
                return read_from_write_only(vcpu, p);
@@ -253,7 +254,25 @@ static bool access_gic_sgi(struct kvm_vcpu *vcpu,
        reg = (u64)*vcpu_reg(vcpu, p->Rt2) << 32;
        reg |= *vcpu_reg(vcpu, p->Rt1) ;
 
-       vgic_v3_dispatch_sgi(vcpu, reg);
+       /*
+        * In a system where GICD_CTLR.DS=1, a ICC_SGI0R access generates
+        * Group0 SGIs only, while ICC_SGI1R can generate either group,
+        * depending on the SGI configuration. ICC_ASGI1R is effectively
+        * equivalent to ICC_SGI0R, as there is no "alternative" secure
+        * group.
+        */
+       switch (p->Op1) {
+       default:                /* Keep GCC quiet */
+       case 0:                 /* ICC_SGI1R */
+               g1 = true;
+               break;
+       case 1:                 /* ICC_ASGI1R */
+       case 2:                 /* ICC_SGI0R */
+               g1 = false;
+               break;
+       }
+
+       vgic_v3_dispatch_sgi(vcpu, reg, g1);
 
        return true;
 }
@@ -459,6 +478,10 @@ static const struct coproc_reg cp15_regs[] = {
 
        /* ICC_SGI1R */
        { CRm64(12), Op1( 0), is64, access_gic_sgi},
+       /* ICC_ASGI1R */
+       { CRm64(12), Op1( 1), is64, access_gic_sgi},
+       /* ICC_SGI0R */
+       { CRm64(12), Op1( 2), is64, access_gic_sgi},
 
        /* VBAR: swapped by interrupt.S. */
        { CRn(12), CRm( 0), Op1( 0), Op2( 0), is32,
index a18f33e..2b8de88 100644 (file)
@@ -261,6 +261,29 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
        return -EINVAL;
 }
 
+
+int __kvm_arm_vcpu_get_events(struct kvm_vcpu *vcpu,
+                             struct kvm_vcpu_events *events)
+{
+       events->exception.serror_pending = !!(*vcpu_hcr(vcpu) & HCR_VA);
+
+       return 0;
+}
+
+int __kvm_arm_vcpu_set_events(struct kvm_vcpu *vcpu,
+                             struct kvm_vcpu_events *events)
+{
+       bool serror_pending = events->exception.serror_pending;
+       bool has_esr = events->exception.serror_has_esr;
+
+       if (serror_pending && has_esr)
+               return -EINVAL;
+       else if (serror_pending)
+               kvm_inject_vabt(vcpu);
+
+       return 0;
+}
+
 int __attribute_const__ kvm_target_cpu(void)
 {
        switch (read_cpuid_part()) {
index 849014c..32fae4d 100644 (file)
@@ -40,15 +40,16 @@ extern void at91_pinctrl_gpio_resume(void);
 #endif
 
 static const match_table_t pm_modes __initconst = {
-       { 0, "standby" },
-       { AT91_PM_SLOW_CLOCK, "ulp0" },
+       { AT91_PM_STANDBY, "standby" },
+       { AT91_PM_ULP0, "ulp0" },
+       { AT91_PM_ULP1, "ulp1" },
        { AT91_PM_BACKUP, "backup" },
        { -1, NULL },
 };
 
 static struct at91_pm_data pm_data = {
-       .standby_mode = 0,
-       .suspend_mode = AT91_PM_SLOW_CLOCK,
+       .standby_mode = AT91_PM_STANDBY,
+       .suspend_mode = AT91_PM_ULP0,
 };
 
 #define at91_ramc_read(id, field) \
@@ -79,6 +80,90 @@ static struct at91_pm_bu {
        phys_addr_t resume;
 } *pm_bu;
 
+struct wakeup_source_info {
+       unsigned int pmc_fsmr_bit;
+       unsigned int shdwc_mr_bit;
+       bool set_polarity;
+};
+
+static const struct wakeup_source_info ws_info[] = {
+       { .pmc_fsmr_bit = AT91_PMC_FSTT(10),    .set_polarity = true },
+       { .pmc_fsmr_bit = AT91_PMC_RTCAL,       .shdwc_mr_bit = BIT(17) },
+       { .pmc_fsmr_bit = AT91_PMC_USBAL },
+       { .pmc_fsmr_bit = AT91_PMC_SDMMC_CD },
+};
+
+static const struct of_device_id sama5d2_ws_ids[] = {
+       { .compatible = "atmel,sama5d2-gem",            .data = &ws_info[0] },
+       { .compatible = "atmel,at91rm9200-rtc",         .data = &ws_info[1] },
+       { .compatible = "atmel,sama5d3-udc",            .data = &ws_info[2] },
+       { .compatible = "atmel,at91rm9200-ohci",        .data = &ws_info[2] },
+       { .compatible = "usb-ohci",                     .data = &ws_info[2] },
+       { .compatible = "atmel,at91sam9g45-ehci",       .data = &ws_info[2] },
+       { .compatible = "usb-ehci",                     .data = &ws_info[2] },
+       { .compatible = "atmel,sama5d2-sdhci",          .data = &ws_info[3] },
+       { /* sentinel */ }
+};
+
+static int at91_pm_config_ws(unsigned int pm_mode, bool set)
+{
+       const struct wakeup_source_info *wsi;
+       const struct of_device_id *match;
+       struct platform_device *pdev;
+       struct device_node *np;
+       unsigned int mode = 0, polarity = 0, val = 0;
+
+       if (pm_mode != AT91_PM_ULP1)
+               return 0;
+
+       if (!pm_data.pmc || !pm_data.shdwc)
+               return -EPERM;
+
+       if (!set) {
+               writel(mode, pm_data.pmc + AT91_PMC_FSMR);
+               return 0;
+       }
+
+       /* SHDWC.WUIR */
+       val = readl(pm_data.shdwc + 0x0c);
+       mode |= (val & 0x3ff);
+       polarity |= ((val >> 16) & 0x3ff);
+
+       /* SHDWC.MR */
+       val = readl(pm_data.shdwc + 0x04);
+
+       /* Loop through defined wakeup sources. */
+       for_each_matching_node_and_match(np, sama5d2_ws_ids, &match) {
+               pdev = of_find_device_by_node(np);
+               if (!pdev)
+                       continue;
+
+               if (device_may_wakeup(&pdev->dev)) {
+                       wsi = match->data;
+
+                       /* Check if enabled on SHDWC. */
+                       if (wsi->shdwc_mr_bit && !(val & wsi->shdwc_mr_bit))
+                               goto put_node;
+
+                       mode |= wsi->pmc_fsmr_bit;
+                       if (wsi->set_polarity)
+                               polarity |= wsi->pmc_fsmr_bit;
+               }
+
+put_node:
+               of_node_put(np);
+       }
+
+       if (mode) {
+               writel(mode, pm_data.pmc + AT91_PMC_FSMR);
+               writel(polarity, pm_data.pmc + AT91_PMC_FSPR);
+       } else {
+               pr_err("AT91: PM: no ULP1 wakeup sources found!");
+       }
+
+       return mode ? 0 : -EPERM;
+}
+
 /*
  * Called after processes are frozen, but before we shutdown devices.
  */
@@ -97,7 +182,7 @@ static int at91_pm_begin(suspend_state_t state)
                pm_data.mode = -1;
        }
 
-       return 0;
+       return at91_pm_config_ws(pm_data.mode, true);
 }
 
 /*
@@ -145,7 +230,7 @@ static int at91_pm_verify_clocks(void)
  */
 int at91_suspend_entering_slow_clock(void)
 {
-       return (pm_data.mode >= AT91_PM_SLOW_CLOCK);
+       return (pm_data.mode >= AT91_PM_ULP0);
 }
 EXPORT_SYMBOL(at91_suspend_entering_slow_clock);
 
@@ -186,7 +271,7 @@ static void at91_pm_suspend(suspend_state_t state)
  * event sources; and reduces DRAM power.  But otherwise it's identical to
  * PM_SUSPEND_ON: cpu idle, and nothing fancy done with main or cpu clocks.
  *
- * AT91_PM_SLOW_CLOCK is like STANDBY plus slow clock mode, so drivers must
+ * AT91_PM_ULP0 is like STANDBY plus slow clock mode, so drivers must
  * suspend more deeply, the master clock switches to the clk32k and turns off
  * the main oscillator
  *
@@ -204,7 +289,7 @@ static int at91_pm_enter(suspend_state_t state)
                /*
                 * Ensure that clocks are in a valid state.
                 */
-               if ((pm_data.mode >= AT91_PM_SLOW_CLOCK) &&
+               if (pm_data.mode >= AT91_PM_ULP0 &&
                    !at91_pm_verify_clocks())
                        goto error;
 
@@ -233,6 +318,7 @@ error:
  */
 static void at91_pm_end(void)
 {
+       at91_pm_config_ws(pm_data.mode, false);
 }
 
 
@@ -478,31 +564,28 @@ static void __init at91_pm_sram_init(void)
                        &at91_pm_suspend_in_sram, at91_pm_suspend_in_sram_sz);
 }
 
-static void __init at91_pm_backup_init(void)
+static bool __init at91_is_pm_mode_active(int pm_mode)
+{
+       return (pm_data.standby_mode == pm_mode ||
+               pm_data.suspend_mode == pm_mode);
+}
+
+static int __init at91_pm_backup_init(void)
 {
        struct gen_pool *sram_pool;
        struct device_node *np;
        struct platform_device *pdev = NULL;
+       int ret = -ENODEV;
 
-       if ((pm_data.standby_mode != AT91_PM_BACKUP) &&
-           (pm_data.suspend_mode != AT91_PM_BACKUP))
-               return;
+       if (!at91_is_pm_mode_active(AT91_PM_BACKUP))
+               return 0;
 
        pm_bu = NULL;
 
-       np = of_find_compatible_node(NULL, NULL, "atmel,sama5d2-shdwc");
-       if (!np) {
-               pr_warn("%s: failed to find shdwc!\n", __func__);
-               return;
-       }
-
-       pm_data.shdwc = of_iomap(np, 0);
-       of_node_put(np);
-
        np = of_find_compatible_node(NULL, NULL, "atmel,sama5d2-sfrbu");
        if (!np) {
                pr_warn("%s: failed to find sfrbu!\n", __func__);
-               goto sfrbu_fail;
+               return ret;
        }
 
        pm_data.sfrbu = of_iomap(np, 0);
@@ -529,6 +612,7 @@ static void __init at91_pm_backup_init(void)
        pm_bu = (void *)gen_pool_alloc(sram_pool, sizeof(struct at91_pm_bu));
        if (!pm_bu) {
                pr_warn("%s: unable to alloc securam!\n", __func__);
+               ret = -ENOMEM;
                goto securam_fail;
        }
 
@@ -536,19 +620,60 @@ static void __init at91_pm_backup_init(void)
        pm_bu->canary = __pa_symbol(&canary);
        pm_bu->resume = __pa_symbol(cpu_resume);
 
-       return;
+       return 0;
 
-sfrbu_fail:
-       iounmap(pm_data.shdwc);
-       pm_data.shdwc = NULL;
 securam_fail:
        iounmap(pm_data.sfrbu);
        pm_data.sfrbu = NULL;
+       return ret;
+}
 
-       if (pm_data.standby_mode == AT91_PM_BACKUP)
-               pm_data.standby_mode = AT91_PM_SLOW_CLOCK;
-       if (pm_data.suspend_mode == AT91_PM_BACKUP)
-               pm_data.suspend_mode = AT91_PM_SLOW_CLOCK;
+static void __init at91_pm_use_default_mode(int pm_mode)
+{
+       if (pm_mode != AT91_PM_ULP1 && pm_mode != AT91_PM_BACKUP)
+               return;
+
+       if (pm_data.standby_mode == pm_mode)
+               pm_data.standby_mode = AT91_PM_ULP0;
+       if (pm_data.suspend_mode == pm_mode)
+               pm_data.suspend_mode = AT91_PM_ULP0;
+}
+
+static void __init at91_pm_modes_init(void)
+{
+       struct device_node *np;
+       int ret;
+
+       if (!at91_is_pm_mode_active(AT91_PM_BACKUP) &&
+           !at91_is_pm_mode_active(AT91_PM_ULP1))
+               return;
+
+       np = of_find_compatible_node(NULL, NULL, "atmel,sama5d2-shdwc");
+       if (!np) {
+               pr_warn("%s: failed to find shdwc!\n", __func__);
+               goto ulp1_default;
+       }
+
+       pm_data.shdwc = of_iomap(np, 0);
+       of_node_put(np);
+
+       ret = at91_pm_backup_init();
+       if (ret) {
+               if (!at91_is_pm_mode_active(AT91_PM_ULP1))
+                       goto unmap;
+               else
+                       goto backup_default;
+       }
+
+       return;
+
+unmap:
+       iounmap(pm_data.shdwc);
+       pm_data.shdwc = NULL;
+ulp1_default:
+       at91_pm_use_default_mode(AT91_PM_ULP1);
+backup_default:
+       at91_pm_use_default_mode(AT91_PM_BACKUP);
 }
 
 struct pmc_info {
@@ -559,15 +684,20 @@ static const struct pmc_info pmc_infos[] __initconst = {
        { .uhp_udp_mask = AT91RM9200_PMC_UHP | AT91RM9200_PMC_UDP },
        { .uhp_udp_mask = AT91SAM926x_PMC_UHP | AT91SAM926x_PMC_UDP },
        { .uhp_udp_mask = AT91SAM926x_PMC_UHP },
+       { .uhp_udp_mask = 0 },
 };
 
 static const struct of_device_id atmel_pmc_ids[] __initconst = {
        { .compatible = "atmel,at91rm9200-pmc", .data = &pmc_infos[0] },
        { .compatible = "atmel,at91sam9260-pmc", .data = &pmc_infos[1] },
+       { .compatible = "atmel,at91sam9261-pmc", .data = &pmc_infos[1] },
+       { .compatible = "atmel,at91sam9263-pmc", .data = &pmc_infos[1] },
        { .compatible = "atmel,at91sam9g45-pmc", .data = &pmc_infos[2] },
        { .compatible = "atmel,at91sam9n12-pmc", .data = &pmc_infos[1] },
+       { .compatible = "atmel,at91sam9rl-pmc", .data = &pmc_infos[3] },
        { .compatible = "atmel,at91sam9x5-pmc", .data = &pmc_infos[1] },
        { .compatible = "atmel,sama5d3-pmc", .data = &pmc_infos[1] },
+       { .compatible = "atmel,sama5d4-pmc", .data = &pmc_infos[1] },
        { .compatible = "atmel,sama5d2-pmc", .data = &pmc_infos[1] },
        { /* sentinel */ },
 };
@@ -644,7 +774,7 @@ void __init sama5d2_pm_init(void)
        if (!IS_ENABLED(CONFIG_SOC_SAMA5D2))
                return;
 
-       at91_pm_backup_init();
+       at91_pm_modes_init();
        sama5_pm_init();
 }
 
index f95d314..9bd4e6c 100644 (file)
 #define AT91_MEMCTRL_SDRAMC    1
 #define AT91_MEMCTRL_DDRSDR    2
 
-#define        AT91_PM_SLOW_CLOCK      0x01
-#define        AT91_PM_BACKUP          0x02
+#define        AT91_PM_STANDBY         0x00
+#define AT91_PM_ULP0           0x01
+#define AT91_PM_ULP1           0x02
+#define        AT91_PM_BACKUP          0x03
 
 #ifndef __ASSEMBLY__
 struct at91_pm_data {
index daca91f..a7c6ae1 100644 (file)
@@ -42,6 +42,15 @@ tmp2 .req    r5
        .endm
 
 /*
+ * Wait for main oscillator selection is done
+ */
+       .macro wait_moscsels
+1:     ldr     tmp1, [pmc, #AT91_PMC_SR]
+       tst     tmp1, #AT91_PMC_MOSCSELS
+       beq     1b
+       .endm
+
+/*
  * Wait until PLLA has locked.
  */
        .macro wait_pllalock
@@ -112,19 +121,20 @@ ENTRY(at91_pm_suspend_in_sram)
        bl      at91_sramc_self_refresh
 
        ldr     r0, .pm_mode
-       cmp     r0, #AT91_PM_SLOW_CLOCK
-       beq     slow_clock
+       cmp     r0, #AT91_PM_STANDBY
+       beq     standby
        cmp     r0, #AT91_PM_BACKUP
        beq     backup_mode
 
+       bl      at91_ulp_mode
+       b       exit_suspend
+
+standby:
        /* Wait for interrupt */
        ldr     pmc, .pmc_base
        at91_cpu_idle
        b       exit_suspend
 
-slow_clock:
-       bl      at91_slowck_mode
-       b       exit_suspend
 backup_mode:
        bl      at91_backup_mode
        b       exit_suspend
@@ -151,7 +161,102 @@ ENTRY(at91_backup_mode)
        str     tmp1, [r0, #0]
 ENDPROC(at91_backup_mode)
 
-ENTRY(at91_slowck_mode)
+.macro at91_pm_ulp0_mode
+       ldr     pmc, .pmc_base
+
+       /* Turn off the crystal oscillator */
+       ldr     tmp1, [pmc, #AT91_CKGR_MOR]
+       bic     tmp1, tmp1, #AT91_PMC_MOSCEN
+       orr     tmp1, tmp1, #AT91_PMC_KEY
+       str     tmp1, [pmc, #AT91_CKGR_MOR]
+
+       /* Wait for interrupt */
+       at91_cpu_idle
+
+       /* Turn on the crystal oscillator */
+       ldr     tmp1, [pmc, #AT91_CKGR_MOR]
+       orr     tmp1, tmp1, #AT91_PMC_MOSCEN
+       orr     tmp1, tmp1, #AT91_PMC_KEY
+       str     tmp1, [pmc, #AT91_CKGR_MOR]
+
+       wait_moscrdy
+.endm
+
+/**
+ * Note: This procedure only applies on the platform which uses
+ * the external crystal oscillator as a main clock source.
+ */
+.macro at91_pm_ulp1_mode
+       ldr     pmc, .pmc_base
+
+       /* Switch the main clock source to 12-MHz RC oscillator */
+       ldr     tmp1, [pmc, #AT91_CKGR_MOR]
+       bic     tmp1, tmp1, #AT91_PMC_MOSCSEL
+       bic     tmp1, tmp1, #AT91_PMC_KEY_MASK
+       orr     tmp1, tmp1, #AT91_PMC_KEY
+       str     tmp1, [pmc, #AT91_CKGR_MOR]
+
+       wait_moscsels
+
+       /* Disable the crystal oscillator */
+       ldr     tmp1, [pmc, #AT91_CKGR_MOR]
+       bic     tmp1, tmp1, #AT91_PMC_MOSCEN
+       bic     tmp1, tmp1, #AT91_PMC_KEY_MASK
+       orr     tmp1, tmp1, #AT91_PMC_KEY
+       str     tmp1, [pmc, #AT91_CKGR_MOR]
+
+       /* Switch the master clock source to main clock */
+       ldr     tmp1, [pmc, #AT91_PMC_MCKR]
+       bic     tmp1, tmp1, #AT91_PMC_CSS
+       orr     tmp1, tmp1, #AT91_PMC_CSS_MAIN
+       str     tmp1, [pmc, #AT91_PMC_MCKR]
+
+       wait_mckrdy
+
+       /* Enter the ULP1 mode by set WAITMODE bit in CKGR_MOR */
+       ldr     tmp1, [pmc, #AT91_CKGR_MOR]
+       orr     tmp1, tmp1, #AT91_PMC_WAITMODE
+       bic     tmp1, tmp1, #AT91_PMC_KEY_MASK
+       orr     tmp1, tmp1, #AT91_PMC_KEY
+       str     tmp1, [pmc, #AT91_CKGR_MOR]
+
+       wait_mckrdy
+
+       /* Enable the crystal oscillator */
+       ldr     tmp1, [pmc, #AT91_CKGR_MOR]
+       orr     tmp1, tmp1, #AT91_PMC_MOSCEN
+       bic     tmp1, tmp1, #AT91_PMC_KEY_MASK
+       orr     tmp1, tmp1, #AT91_PMC_KEY
+       str     tmp1, [pmc, #AT91_CKGR_MOR]
+
+       wait_moscrdy
+
+       /* Switch the master clock source to slow clock */
+       ldr     tmp1, [pmc, #AT91_PMC_MCKR]
+       bic     tmp1, tmp1, #AT91_PMC_CSS
+       str     tmp1, [pmc, #AT91_PMC_MCKR]
+
+       wait_mckrdy
+
+       /* Switch main clock source to crystal oscillator */
+       ldr     tmp1, [pmc, #AT91_CKGR_MOR]
+       orr     tmp1, tmp1, #AT91_PMC_MOSCSEL
+       bic     tmp1, tmp1, #AT91_PMC_KEY_MASK
+       orr     tmp1, tmp1, #AT91_PMC_KEY
+       str     tmp1, [pmc, #AT91_CKGR_MOR]
+
+       wait_moscsels
+
+       /* Switch the master clock source to main clock */
+       ldr     tmp1, [pmc, #AT91_PMC_MCKR]
+       bic     tmp1, tmp1, #AT91_PMC_CSS
+       orr     tmp1, tmp1, #AT91_PMC_CSS_MAIN
+       str     tmp1, [pmc, #AT91_PMC_MCKR]
+
+       wait_mckrdy
+.endm
+
+ENTRY(at91_ulp_mode)
        ldr     pmc, .pmc_base
 
        /* Save Master clock setting */
@@ -174,22 +279,19 @@ ENTRY(at91_slowck_mode)
        orr     tmp1, tmp1, #(1 << 29)          /* bit 29 always set */
        str     tmp1, [pmc, #AT91_CKGR_PLLAR]
 
-       /* Turn off the main oscillator */
-       ldr     tmp1, [pmc, #AT91_CKGR_MOR]
-       bic     tmp1, tmp1, #AT91_PMC_MOSCEN
-       orr     tmp1, tmp1, #AT91_PMC_KEY
-       str     tmp1, [pmc, #AT91_CKGR_MOR]
+       ldr     r0, .pm_mode
+       cmp     r0, #AT91_PM_ULP1
+       beq     ulp1_mode
 
-       /* Wait for interrupt */
-       at91_cpu_idle
+       at91_pm_ulp0_mode
+       b       ulp_exit
 
-       /* Turn on the main oscillator */
-       ldr     tmp1, [pmc, #AT91_CKGR_MOR]
-       orr     tmp1, tmp1, #AT91_PMC_MOSCEN
-       orr     tmp1, tmp1, #AT91_PMC_KEY
-       str     tmp1, [pmc, #AT91_CKGR_MOR]
+ulp1_mode:
+       at91_pm_ulp1_mode
+       b       ulp_exit
 
-       wait_moscrdy
+ulp_exit:
+       ldr     pmc, .pmc_base
 
        /* Restore PLLA setting */
        ldr     tmp1, .saved_pllar
@@ -212,7 +314,7 @@ ENTRY(at91_slowck_mode)
        wait_mckrdy
 
        mov     pc, lr
-ENDPROC(at91_slowck_mode)
+ENDPROC(at91_ulp_mode)
 
 /*
  * void at91_sramc_self_refresh(unsigned int is_active)
index 05c3eec..da8a039 100644 (file)
@@ -59,6 +59,7 @@ config MACH_DA8XX_DT
        default y
        depends on ARCH_DAVINCI_DA850
        select PINCTRL
+       select TIMER_OF
        help
          Say y here to include support for TI DaVinci DA850 based using
          Flattened Device Tree. More information at Documentation/devicetree
@@ -231,18 +232,6 @@ config DAVINCI_MUX_WARNINGS
          to change the pin multiplexing setup. When there are no warnings
          printed, it's safe to deselect DAVINCI_MUX for your product.
 
-config DAVINCI_RESET_CLOCKS
-       bool "Reset unused clocks during boot"
-       depends on ARCH_DAVINCI
-       help
-         Say Y if you want to reset unused clocks during boot.
-         This option saves power, but assumes all drivers are
-         using the clock framework. Broken drivers that do not
-         yet use clock framework may not work with this option.
-         If you are booting from another operating system, you
-         probably do not want this option enabled until your
-         device drivers work properly.
-
 endmenu
 
 endif
index 4e81780..93d271b 100644 (file)
@@ -5,8 +5,8 @@
 #
 
 # Common objects
-obj-y                  := time.o clock.o serial.o psc.o \
-                          usb.o common.o sram.o aemif.o
+obj-y                                  := time.o serial.o usb.o \
+                                          common.o sram.o
 
 obj-$(CONFIG_DAVINCI_MUX)              += mux.o
 
diff --git a/arch/arm/mach-davinci/aemif.c b/arch/arm/mach-davinci/aemif.c
deleted file mode 100644 (file)
index e4ab3f3..0000000
+++ /dev/null
@@ -1,218 +0,0 @@
-/*
- * AEMIF support for DaVinci SoCs
- *
- * Copyright (C) 2010 Texas Instruments Incorporated. http://www.ti.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/kernel.h>
-#include <linux/io.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/module.h>
-#include <linux/time.h>
-
-#include <linux/platform_data/mtd-davinci-aemif.h>
-#include <linux/platform_data/mtd-davinci.h>
-
-/* Timing value configuration */
-
-#define TA(x)          ((x) << 2)
-#define RHOLD(x)       ((x) << 4)
-#define RSTROBE(x)     ((x) << 7)
-#define RSETUP(x)      ((x) << 13)
-#define WHOLD(x)       ((x) << 17)
-#define WSTROBE(x)     ((x) << 20)
-#define WSETUP(x)      ((x) << 26)
-
-#define TA_MAX         0x3
-#define RHOLD_MAX      0x7
-#define RSTROBE_MAX    0x3f
-#define RSETUP_MAX     0xf
-#define WHOLD_MAX      0x7
-#define WSTROBE_MAX    0x3f
-#define WSETUP_MAX     0xf
-
-#define TIMING_MASK    (TA(TA_MAX) | \
-                               RHOLD(RHOLD_MAX) | \
-                               RSTROBE(RSTROBE_MAX) |  \
-                               RSETUP(RSETUP_MAX) | \
-                               WHOLD(WHOLD_MAX) | \
-                               WSTROBE(WSTROBE_MAX) | \
-                               WSETUP(WSETUP_MAX))
-
-static inline unsigned int davinci_aemif_readl(void __iomem *base, int offset)
-{
-       return readl_relaxed(base + offset);
-}
-
-static inline void davinci_aemif_writel(void __iomem *base,
-                                       int offset, unsigned long value)
-{
-       writel_relaxed(value, base + offset);
-}
-
-/*
- * aemif_calc_rate - calculate timing data.
- * @wanted: The cycle time needed in nanoseconds.
- * @clk: The input clock rate in kHz.
- * @max: The maximum divider value that can be programmed.
- *
- * On success, returns the calculated timing value minus 1 for easy
- * programming into AEMIF timing registers, else negative errno.
- */
-static int aemif_calc_rate(int wanted, unsigned long clk, int max)
-{
-       int result;
-
-       result = DIV_ROUND_UP((wanted * clk), NSEC_PER_MSEC) - 1;
-
-       pr_debug("%s: result %d from %ld, %d\n", __func__, result, clk, wanted);
-
-       /* It is generally OK to have a more relaxed timing than requested... */
-       if (result < 0)
-               result = 0;
-
-       /* ... But configuring tighter timings is not an option. */
-       else if (result > max)
-               result = -EINVAL;
-
-       return result;
-}
-
-/**
- * davinci_aemif_setup_timing - setup timing values for a given AEMIF interface
- * @t: timing values to be progammed
- * @base: The virtual base address of the AEMIF interface
- * @cs: chip-select to program the timing values for
- * @clkrate: the AEMIF clkrate
- *
- * This function programs the given timing values (in real clock) into the
- * AEMIF registers taking the AEMIF clock into account.
- *
- * This function does not use any locking while programming the AEMIF
- * because it is expected that there is only one user of a given
- * chip-select.
- *
- * Returns 0 on success, else negative errno.
- */
-static int davinci_aemif_setup_timing(struct davinci_aemif_timing *t,
-                                       void __iomem *base, unsigned cs,
-                                       unsigned long clkrate)
-{
-       unsigned set, val;
-       int ta, rhold, rstrobe, rsetup, whold, wstrobe, wsetup;
-       unsigned offset = A1CR_OFFSET + cs * 4;
-
-       if (!t)
-               return 0;       /* Nothing to do */
-
-       clkrate /= 1000;        /* turn clock into kHz for ease of use */
-
-       ta      = aemif_calc_rate(t->ta, clkrate, TA_MAX);
-       rhold   = aemif_calc_rate(t->rhold, clkrate, RHOLD_MAX);
-       rstrobe = aemif_calc_rate(t->rstrobe, clkrate, RSTROBE_MAX);
-       rsetup  = aemif_calc_rate(t->rsetup, clkrate, RSETUP_MAX);
-       whold   = aemif_calc_rate(t->whold, clkrate, WHOLD_MAX);
-       wstrobe = aemif_calc_rate(t->wstrobe, clkrate, WSTROBE_MAX);
-       wsetup  = aemif_calc_rate(t->wsetup, clkrate, WSETUP_MAX);
-
-       if (ta < 0 || rhold < 0 || rstrobe < 0 || rsetup < 0 ||
-                       whold < 0 || wstrobe < 0 || wsetup < 0) {
-               pr_err("%s: cannot get suitable timings\n", __func__);
-               return -EINVAL;
-       }
-
-       set = TA(ta) | RHOLD(rhold) | RSTROBE(rstrobe) | RSETUP(rsetup) |
-               WHOLD(whold) | WSTROBE(wstrobe) | WSETUP(wsetup);
-
-       val = __raw_readl(base + offset);
-       val &= ~TIMING_MASK;
-       val |= set;
-       __raw_writel(val, base + offset);
-
-       return 0;
-}
-
-/**
- * davinci_aemif_setup - setup AEMIF interface by davinci_nand_pdata
- * @pdev - link to platform device to setup settings for
- *
- * This function does not use any locking while programming the AEMIF
- * because it is expected that there is only one user of a given
- * chip-select.
- *
- * Returns 0 on success, else negative errno.
- */
-int davinci_aemif_setup(struct platform_device *pdev)
-{
-       struct davinci_nand_pdata *pdata = dev_get_platdata(&pdev->dev);
-       uint32_t val;
-       unsigned long clkrate;
-       struct resource *res;
-       void __iomem *base;
-       struct clk *clk;
-       int ret = 0;
-
-       clk = clk_get(&pdev->dev, "aemif");
-       if (IS_ERR(clk)) {
-               ret = PTR_ERR(clk);
-               dev_dbg(&pdev->dev, "unable to get AEMIF clock, err %d\n", ret);
-               return ret;
-       }
-
-       ret = clk_prepare_enable(clk);
-       if (ret < 0) {
-               dev_dbg(&pdev->dev, "unable to enable AEMIF clock, err %d\n",
-                       ret);
-               goto err_put;
-       }
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-       if (!res) {
-               dev_err(&pdev->dev, "cannot get IORESOURCE_MEM\n");
-               ret = -ENOMEM;
-               goto err;
-       }
-
-       base = ioremap(res->start, resource_size(res));
-       if (!base) {
-               dev_err(&pdev->dev, "ioremap failed for resource %pR\n", res);
-               ret = -ENOMEM;
-               goto err;
-       }
-
-       /*
-        * Setup Async configuration register in case we did not boot
-        * from NAND and so bootloader did not bother to set it up.
-        */
-       val = davinci_aemif_readl(base, A1CR_OFFSET + pdata->core_chipsel * 4);
-       /*
-        * Extended Wait is not valid and Select Strobe mode is not
-        * used
-        */
-       val &= ~(ACR_ASIZE_MASK | ACR_EW_MASK | ACR_SS_MASK);
-       if (pdata->options & NAND_BUSWIDTH_16)
-               val |= 0x1;
-
-       davinci_aemif_writel(base, A1CR_OFFSET + pdata->core_chipsel * 4, val);
-
-       clkrate = clk_get_rate(clk);
-
-       if (pdata->timing)
-               ret = davinci_aemif_setup_timing(pdata->timing, base,
-                                                pdata->core_chipsel, clkrate);
-
-       if (ret < 0)
-               dev_dbg(&pdev->dev, "NAND timing values setup fail\n");
-
-       iounmap(base);
-err:
-       clk_disable_unprepare(clk);
-err_put:
-       clk_put(clk);
-       return ret;
-}
index 14a6fc0..7d8ab36 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/platform_data/mtd-davinci-aemif.h>
 #include <linux/platform_data/spi-davinci.h>
 #include <linux/platform_data/usb-davinci.h>
+#include <linux/platform_data/ti-aemif.h>
 #include <linux/regulator/machine.h>
 
 #include <asm/mach-types.h>
@@ -110,15 +111,9 @@ static __init void da830_evm_usb_init(void)
 {
        int ret;
 
-       /* USB_REFCLKIN is not used. */
-       ret = da8xx_register_usb20_phy_clk(false);
+       ret = da8xx_register_usb_phy_clocks();
        if (ret)
-               pr_warn("%s: USB 2.0 PHY CLK registration failed: %d\n",
-                       __func__, ret);
-
-       ret = da8xx_register_usb11_phy_clk(false);
-       if (ret)
-               pr_warn("%s: USB 1.1 PHY CLK registration failed: %d\n",
+               pr_warn("%s: USB PHY CLK registration failed: %d\n",
                        __func__, ret);
 
        ret = da8xx_register_usb_phy();
@@ -339,14 +334,48 @@ static struct resource da830_evm_nand_resources[] = {
        },
 };
 
-static struct platform_device da830_evm_nand_device = {
-       .name           = "davinci_nand",
-       .id             = 1,
-       .dev            = {
-               .platform_data  = &da830_evm_nand_pdata,
+static struct platform_device da830_evm_aemif_devices[] = {
+       {
+               .name           = "davinci_nand",
+               .id             = 1,
+               .dev            = {
+                       .platform_data  = &da830_evm_nand_pdata,
+               },
+               .num_resources  = ARRAY_SIZE(da830_evm_nand_resources),
+               .resource       = da830_evm_nand_resources,
+       },
+};
+
+static struct resource da830_evm_aemif_resource[] = {
+       {
+               .start  = DA8XX_AEMIF_CTL_BASE,
+               .end    = DA8XX_AEMIF_CTL_BASE + SZ_32K - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+};
+
+static struct aemif_abus_data da830_evm_aemif_abus_data[] = {
+       {
+               .cs     = 3,
        },
-       .num_resources  = ARRAY_SIZE(da830_evm_nand_resources),
-       .resource       = da830_evm_nand_resources,
+};
+
+static struct aemif_platform_data da830_evm_aemif_pdata = {
+       .abus_data              = da830_evm_aemif_abus_data,
+       .num_abus_data          = ARRAY_SIZE(da830_evm_aemif_abus_data),
+       .sub_devices            = da830_evm_aemif_devices,
+       .num_sub_devices        = ARRAY_SIZE(da830_evm_aemif_devices),
+       .cs_offset              = 2,
+};
+
+static struct platform_device da830_evm_aemif_device = {
+       .name           = "ti-aemif",
+       .id             = -1,
+       .dev = {
+               .platform_data = &da830_evm_aemif_pdata,
+       },
+       .resource       = da830_evm_aemif_resource,
+       .num_resources  = ARRAY_SIZE(da830_evm_aemif_resource),
 };
 
 /*
@@ -377,12 +406,9 @@ static inline void da830_evm_init_nand(int mux_mode)
        if (ret)
                pr_warn("%s: emif25 mux setup failed: %d\n", __func__, ret);
 
-       ret = platform_device_register(&da830_evm_nand_device);
+       ret = platform_device_register(&da830_evm_aemif_device);
        if (ret)
-               pr_warn("%s: NAND device not registered\n", __func__);
-
-       if (davinci_aemif_setup(&da830_evm_nand_device))
-               pr_warn("%s: Cannot configure AEMIF\n", __func__);
+               pr_warn("%s: AEMIF device not registered\n", __func__);
 
        gpio_direction_output(mux_mode, 1);
 }
@@ -557,6 +583,8 @@ static __init void da830_evm_init(void)
        struct davinci_soc_info *soc_info = &davinci_soc_info;
        int ret;
 
+       da830_register_clocks();
+
        ret = da830_register_gpio();
        if (ret)
                pr_warn("%s: GPIO init failed: %d\n", __func__, ret);
index 6d5beb1..e1a949b 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/platform_data/gpio-davinci.h>
 #include <linux/platform_data/mtd-davinci.h>
 #include <linux/platform_data/mtd-davinci-aemif.h>
+#include <linux/platform_data/ti-aemif.h>
 #include <linux/platform_data/spi-davinci.h>
 #include <linux/platform_data/uio_pruss.h>
 #include <linux/regulator/machine.h>
@@ -185,16 +186,6 @@ static struct resource da850_evm_norflash_resource[] = {
        },
 };
 
-static struct platform_device da850_evm_norflash_device = {
-       .name           = "physmap-flash",
-       .id             = 0,
-       .dev            = {
-               .platform_data  = &da850_evm_norflash_data,
-       },
-       .num_resources  = 1,
-       .resource       = da850_evm_norflash_resource,
-};
-
 /* DA850/OMAP-L138 EVM includes a 512 MByte large-page NAND flash
  * (128K blocks). It may be used instead of the (default) SPI flash
  * to boot, using TI's tools to install the secondary boot loader
@@ -266,37 +257,58 @@ static struct resource da850_evm_nandflash_resource[] = {
        },
 };
 
-static struct platform_device da850_evm_nandflash_device = {
-       .name           = "davinci_nand",
-       .id             = 1,
-       .dev            = {
-               .platform_data  = &da850_evm_nandflash_data,
-       },
-       .num_resources  = ARRAY_SIZE(da850_evm_nandflash_resource),
-       .resource       = da850_evm_nandflash_resource,
+static struct resource da850_evm_aemif_resource[] = {
+       {
+               .start  = DA8XX_AEMIF_CTL_BASE,
+               .end    = DA8XX_AEMIF_CTL_BASE + SZ_32K,
+               .flags  = IORESOURCE_MEM,
+       }
 };
 
-static struct platform_device *da850_evm_devices[] = {
-       &da850_evm_nandflash_device,
-       &da850_evm_norflash_device,
+static struct aemif_abus_data da850_evm_aemif_abus_data[] = {
+       {
+               .cs     = 3,
+       }
 };
 
-#define DA8XX_AEMIF_CE2CFG_OFFSET      0x10
-#define DA8XX_AEMIF_ASIZE_16BIT                0x1
-
-static void __init da850_evm_init_nor(void)
-{
-       void __iomem *aemif_addr;
-
-       aemif_addr = ioremap(DA8XX_AEMIF_CTL_BASE, SZ_32K);
+static struct platform_device da850_evm_aemif_devices[] = {
+       {
+               .name           = "davinci_nand",
+               .id             = 1,
+               .dev            = {
+                       .platform_data  = &da850_evm_nandflash_data,
+               },
+               .num_resources  = ARRAY_SIZE(da850_evm_nandflash_resource),
+               .resource       = da850_evm_nandflash_resource,
+       },
+       {
+               .name           = "physmap-flash",
+               .id             = 0,
+               .dev            = {
+                       .platform_data  = &da850_evm_norflash_data,
+               },
+               .num_resources  = 1,
+               .resource       = da850_evm_norflash_resource,
+       }
+};
 
-       /* Configure data bus width of CS2 to 16 bit */
-       writel(readl(aemif_addr + DA8XX_AEMIF_CE2CFG_OFFSET) |
-               DA8XX_AEMIF_ASIZE_16BIT,
-               aemif_addr + DA8XX_AEMIF_CE2CFG_OFFSET);
+static struct aemif_platform_data da850_evm_aemif_pdata = {
+       .cs_offset = 2,
+       .abus_data = da850_evm_aemif_abus_data,
+       .num_abus_data = ARRAY_SIZE(da850_evm_aemif_abus_data),
+       .sub_devices = da850_evm_aemif_devices,
+       .num_sub_devices = ARRAY_SIZE(da850_evm_aemif_devices),
+};
 
-       iounmap(aemif_addr);
-}
+static struct platform_device da850_evm_aemif_device = {
+       .name           = "ti-aemif",
+       .id             = -1,
+       .dev = {
+               .platform_data  = &da850_evm_aemif_pdata,
+       },
+       .resource       = da850_evm_aemif_resource,
+       .num_resources  = ARRAY_SIZE(da850_evm_aemif_resource),
+};
 
 static const short da850_evm_nand_pins[] = {
        DA850_EMA_D_0, DA850_EMA_D_1, DA850_EMA_D_2, DA850_EMA_D_3,
@@ -339,13 +351,10 @@ static inline void da850_evm_setup_nor_nand(void)
                        pr_warn("%s: NOR mux setup failed: %d\n",
                                __func__, ret);
 
-               da850_evm_init_nor();
-
-               platform_add_devices(da850_evm_devices,
-                                       ARRAY_SIZE(da850_evm_devices));
-
-               if (davinci_aemif_setup(&da850_evm_nandflash_device))
-                       pr_warn("%s: Cannot configure AEMIF.\n", __func__);
+               ret = platform_device_register(&da850_evm_aemif_device);
+               if (ret)
+                       pr_warn("%s: registering aemif failed: %d\n",
+                               __func__, ret);
        }
 }
 
@@ -1340,6 +1349,8 @@ static __init void da850_evm_init(void)
 {
        int ret;
 
+       da850_register_clocks();
+
        ret = da850_register_gpio();
        if (ret)
                pr_warn("%s: GPIO init failed: %d\n", __func__, ret);
index a3377f9..f53a461 100644 (file)
@@ -394,6 +394,8 @@ static __init void dm355_evm_init(void)
        struct clk *aemif;
        int ret;
 
+       dm355_register_clocks();
+
        ret = dm355_gpio_register();
        if (ret)
                pr_warn("%s: GPIO init failed: %d\n", __func__, ret);
index 8249a0b..0fdf1d0 100644 (file)
@@ -234,6 +234,8 @@ static __init void dm355_leopard_init(void)
        struct clk *aemif;
        int ret;
 
+       dm355_register_clocks();
+
        ret = dm355_gpio_register();
        if (ret)
                pr_warn("%s: GPIO init failed: %d\n", __func__, ret);
index 435f7ec..8143756 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/spi/spi.h>
 #include <linux/spi/eeprom.h>
 #include <linux/v4l2-dv-timings.h>
+#include <linux/platform_data/ti-aemif.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -159,16 +160,49 @@ static struct resource davinci_nand_resources[] = {
        },
 };
 
-static struct platform_device davinci_nand_device = {
-       .name                   = "davinci_nand",
-       .id                     = 0,
-       .num_resources          = ARRAY_SIZE(davinci_nand_resources),
-       .resource               = davinci_nand_resources,
-       .dev                    = {
-               .platform_data  = &davinci_nand_data,
+static struct platform_device davinci_aemif_devices[] = {
+       {
+               .name           = "davinci_nand",
+               .id             = 0,
+               .num_resources  = ARRAY_SIZE(davinci_nand_resources),
+               .resource       = davinci_nand_resources,
+               .dev            = {
+                       .platform_data  = &davinci_nand_data,
+               },
+       }
+};
+
+static struct resource davinci_aemif_resources[] = {
+       {
+               .start          = DM365_ASYNC_EMIF_CONTROL_BASE,
+               .end            = DM365_ASYNC_EMIF_CONTROL_BASE + SZ_4K - 1,
+               .flags          = IORESOURCE_MEM,
        },
 };
 
+static struct aemif_abus_data da850_evm_aemif_abus_data[] = {
+       {
+               .cs             = 1,
+       },
+};
+
+static struct aemif_platform_data davinci_aemif_pdata = {
+       .abus_data              = da850_evm_aemif_abus_data,
+       .num_abus_data          = ARRAY_SIZE(da850_evm_aemif_abus_data),
+       .sub_devices            = davinci_aemif_devices,
+       .num_sub_devices        = ARRAY_SIZE(davinci_aemif_devices),
+};
+
+static struct platform_device davinci_aemif_device = {
+       .name                   = "ti-aemif",
+       .id                     = -1,
+       .dev = {
+               .platform_data  = &davinci_aemif_pdata,
+       },
+       .resource               = davinci_aemif_resources,
+       .num_resources          = ARRAY_SIZE(davinci_aemif_resources),
+};
+
 static struct at24_platform_data eeprom_info = {
        .byte_len       = (256*1024) / 8,
        .page_size      = 64,
@@ -537,10 +571,6 @@ static void __init evm_init_i2c(void)
        i2c_register_board_info(1, i2c_info, ARRAY_SIZE(i2c_info));
 }
 
-static struct platform_device *dm365_evm_nand_devices[] __initdata = {
-       &davinci_nand_device,
-};
-
 static inline int have_leds(void)
 {
 #ifdef CONFIG_LEDS_CLASS
@@ -628,6 +658,7 @@ static void __init evm_init_cpld(void)
        u8 mux, resets;
        const char *label;
        struct clk *aemif_clk;
+       int rc;
 
        /* Make sure we can configure the CPLD through CS1.  Then
         * leave it on for later access to MMC and LED registers.
@@ -660,8 +691,10 @@ fail:
                /* external keypad mux */
                mux |= BIT(7);
 
-               platform_add_devices(dm365_evm_nand_devices,
-                               ARRAY_SIZE(dm365_evm_nand_devices));
+               rc = platform_device_register(&davinci_aemif_device);
+               if (rc)
+                       pr_warn("%s(): error registering the aemif device: %d\n",
+                               __func__, rc);
        } else {
                /* no OneNAND support yet */
        }
@@ -742,6 +775,8 @@ static __init void dm365_evm_init(void)
 {
        int ret;
 
+       dm365_register_clocks();
+
        ret = dm365_gpio_register();
        if (ret)
                pr_warn("%s: GPIO init failed: %d\n", __func__, ret);
index 48436f7..e4a8f92 100644 (file)
@@ -42,6 +42,7 @@
 #include <linux/platform_data/mmc-davinci.h>
 #include <linux/platform_data/usb-davinci.h>
 #include <linux/platform_data/mtd-davinci-aemif.h>
+#include <linux/platform_data/ti-aemif.h>
 
 #include "davinci.h"
 
@@ -174,14 +175,47 @@ static struct resource davinci_evm_nandflash_resource[] = {
        },
 };
 
-static struct platform_device davinci_evm_nandflash_device = {
-       .name           = "davinci_nand",
-       .id             = 0,
-       .dev            = {
-               .platform_data  = &davinci_evm_nandflash_data,
+static struct resource davinci_evm_aemif_resource[] = {
+       {
+               .start          = DM644X_ASYNC_EMIF_CONTROL_BASE,
+               .end            = DM644X_ASYNC_EMIF_CONTROL_BASE + SZ_4K - 1,
+               .flags          = IORESOURCE_MEM,
+       },
+};
+
+static struct aemif_abus_data davinci_evm_aemif_abus_data[] = {
+       {
+               .cs             = 1,
+       },
+};
+
+static struct platform_device davinci_evm_nandflash_devices[] = {
+       {
+               .name           = "davinci_nand",
+               .id             = 0,
+               .dev            = {
+                       .platform_data  = &davinci_evm_nandflash_data,
+               },
+               .num_resources  = ARRAY_SIZE(davinci_evm_nandflash_resource),
+               .resource       = davinci_evm_nandflash_resource,
+       },
+};
+
+static struct aemif_platform_data davinci_evm_aemif_pdata = {
+       .abus_data = davinci_evm_aemif_abus_data,
+       .num_abus_data = ARRAY_SIZE(davinci_evm_aemif_abus_data),
+       .sub_devices = davinci_evm_nandflash_devices,
+       .num_sub_devices = ARRAY_SIZE(davinci_evm_nandflash_devices),
+};
+
+static struct platform_device davinci_evm_aemif_device = {
+       .name                   = "ti-aemif",
+       .id                     = -1,
+       .dev = {
+               .platform_data  = &davinci_evm_aemif_pdata,
        },
-       .num_resources  = ARRAY_SIZE(davinci_evm_nandflash_resource),
-       .resource       = davinci_evm_nandflash_resource,
+       .resource               = davinci_evm_aemif_resource,
+       .num_resources          = ARRAY_SIZE(davinci_evm_aemif_resource),
 };
 
 static u64 davinci_fb_dma_mask = DMA_BIT_MASK(32);
@@ -773,6 +807,8 @@ static __init void davinci_evm_init(void)
        struct clk *aemif_clk;
        struct davinci_soc_info *soc_info = &davinci_soc_info;
 
+       dm644x_register_clocks();
+
        dm644x_init_devices();
 
        ret = dm644x_gpio_register();
@@ -793,12 +829,7 @@ static __init void davinci_evm_init(void)
 
                /* only one device will be jumpered and detected */
                if (HAS_NAND) {
-                       platform_device_register(&davinci_evm_nandflash_device);
-
-                       if (davinci_aemif_setup(&davinci_evm_nandflash_device))
-                               pr_warn("%s: Cannot configure AEMIF\n",
-                                       __func__);
-
+                       platform_device_register(&davinci_evm_aemif_device);
 #ifdef CONFIG_I2C
                        evm_leds[7].default_trigger = "nand-disk";
 #endif
index 584064f..3e5ee09 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/i2c.h>
 #include <linux/platform_data/at24.h>
 #include <linux/platform_data/pcf857x.h>
+#include <linux/platform_data/ti-aemif.h>
 
 #include <media/i2c/tvp514x.h>
 #include <media/i2c/adv7343.h>
@@ -106,18 +107,49 @@ static struct resource davinci_nand_resources[] = {
        },
 };
 
-static struct platform_device davinci_nand_device = {
-       .name                   = "davinci_nand",
-       .id                     = 0,
+static struct platform_device davinci_aemif_devices[] = {
+       {
+               .name           = "davinci_nand",
+               .id             = 0,
+               .num_resources  = ARRAY_SIZE(davinci_nand_resources),
+               .resource       = davinci_nand_resources,
+               .dev            = {
+                       .platform_data  = &davinci_nand_data,
+               },
+       },
+};
 
-       .num_resources          = ARRAY_SIZE(davinci_nand_resources),
-       .resource               = davinci_nand_resources,
+static struct resource davinci_aemif_resources[] = {
+       {
+               .start  = DM646X_ASYNC_EMIF_CONTROL_BASE,
+               .end    = DM646X_ASYNC_EMIF_CONTROL_BASE + SZ_4K - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+};
 
-       .dev                    = {
-               .platform_data  = &davinci_nand_data,
+static struct aemif_abus_data davinci_aemif_abus_data[] = {
+       {
+               .cs     = 1,
        },
 };
 
+static struct aemif_platform_data davinci_aemif_pdata = {
+       .abus_data              = davinci_aemif_abus_data,
+       .num_abus_data          = ARRAY_SIZE(davinci_aemif_abus_data),
+       .sub_devices            = davinci_aemif_devices,
+       .num_sub_devices        = ARRAY_SIZE(davinci_aemif_devices),
+};
+
+static struct platform_device davinci_aemif_device = {
+       .name           = "ti-aemif",
+       .id             = -1,
+       .dev = {
+               .platform_data  = &davinci_aemif_pdata,
+       },
+       .resource       = davinci_aemif_resources,
+       .num_resources  = ARRAY_SIZE(davinci_aemif_resources),
+};
+
 #define HAS_ATA                (IS_ENABLED(CONFIG_BLK_DEV_PALMCHIP_BK3710) || \
                         IS_ENABLED(CONFIG_PATA_BK3710))
 
@@ -776,6 +808,8 @@ static __init void evm_init(void)
        int ret;
        struct davinci_soc_info *soc_info = &davinci_soc_info;
 
+       dm646x_register_clocks();
+
        ret = dm646x_gpio_register();
        if (ret)
                pr_warn("%s: GPIO init failed: %d\n", __func__, ret);
@@ -791,10 +825,8 @@ static __init void evm_init(void)
        if (machine_is_davinci_dm6467tevm())
                davinci_nand_data.timing = &dm6467tevm_nandflash_timing;
 
-       platform_device_register(&davinci_nand_device);
-
-       if (davinci_aemif_setup(&davinci_nand_device))
-               pr_warn("%s: Cannot configure AEMIF.\n", __func__);
+       if (platform_device_register(&davinci_aemif_device))
+               pr_warn("%s: Cannot register AEMIF device.\n", __func__);
 
        dm646x_init_edma(dm646x_edma_rsv);
 
index 37b3e48..2933e0c 100644 (file)
@@ -30,6 +30,7 @@
 #include <mach/da8xx.h>
 #include <linux/platform_data/mtd-davinci.h>
 #include <linux/platform_data/mtd-davinci-aemif.h>
+#include <linux/platform_data/ti-aemif.h>
 #include <mach/mux.h>
 #include <linux/platform_data/spi-davinci.h>
 
@@ -422,27 +423,53 @@ static struct resource mityomapl138_nandflash_resource[] = {
        },
 };
 
-static struct platform_device mityomapl138_nandflash_device = {
-       .name           = "davinci_nand",
-       .id             = 1,
-       .dev            = {
-               .platform_data  = &mityomapl138_nandflash_data,
+static struct platform_device mityomapl138_aemif_devices[] = {
+       {
+               .name           = "davinci_nand",
+               .id             = 1,
+               .dev            = {
+                       .platform_data  = &mityomapl138_nandflash_data,
+               },
+               .num_resources  = ARRAY_SIZE(mityomapl138_nandflash_resource),
+               .resource       = mityomapl138_nandflash_resource,
+       },
+};
+
+static struct resource mityomapl138_aemif_resources[] = {
+       {
+               .start  = DA8XX_AEMIF_CTL_BASE,
+               .end    = DA8XX_AEMIF_CTL_BASE + SZ_32K - 1,
+               .flags  = IORESOURCE_MEM,
        },
-       .num_resources  = ARRAY_SIZE(mityomapl138_nandflash_resource),
-       .resource       = mityomapl138_nandflash_resource,
 };
 
-static struct platform_device *mityomapl138_devices[] __initdata = {
-       &mityomapl138_nandflash_device,
+static struct aemif_abus_data mityomapl138_aemif_abus_data[] = {
+       {
+               .cs     = 1,
+       },
+};
+
+static struct aemif_platform_data mityomapl138_aemif_pdata = {
+       .abus_data              = mityomapl138_aemif_abus_data,
+       .num_abus_data          = ARRAY_SIZE(mityomapl138_aemif_abus_data),
+       .sub_devices            = mityomapl138_aemif_devices,
+       .num_sub_devices        = ARRAY_SIZE(mityomapl138_aemif_devices),
+};
+
+static struct platform_device mityomapl138_aemif_device = {
+       .name           = "ti-aemif",
+       .id             = -1,
+       .dev = {
+               .platform_data  = &mityomapl138_aemif_pdata,
+       },
+       .resource       = mityomapl138_aemif_resources,
+       .num_resources  = ARRAY_SIZE(mityomapl138_aemif_resources),
 };
 
 static void __init mityomapl138_setup_nand(void)
 {
-       platform_add_devices(mityomapl138_devices,
-                                ARRAY_SIZE(mityomapl138_devices));
-
-       if (davinci_aemif_setup(&mityomapl138_nandflash_device))
-               pr_warn("%s: Cannot configure AEMIF\n", __func__);
+       if (platform_device_register(&mityomapl138_aemif_device))
+               pr_warn("%s: Cannot register AEMIF device\n", __func__);
 }
 
 static const short mityomap_mii_pins[] = {
@@ -503,6 +530,8 @@ static void __init mityomapl138_init(void)
 {
        int ret;
 
+       da850_register_clocks();
+
        /* for now, no special EDMA channels are reserved */
        ret = da850_register_edma(NULL);
        if (ret)
index 25ad9b0..353f9e5 100644 (file)
@@ -175,6 +175,8 @@ static __init void davinci_ntosd2_init(void)
        struct clk *aemif_clk;
        struct davinci_soc_info *soc_info = &davinci_soc_info;
 
+       dm644x_register_clocks();
+
        dm644x_init_devices();
 
        ret = dm644x_gpio_register();
index be8b892..8e8d51f 100644 (file)
 #include <linux/interrupt.h>
 #include <linux/gpio.h>
 #include <linux/gpio/machine.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/rawnand.h>
 #include <linux/platform_data/gpio-davinci.h>
+#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/machine.h>
 
 #include <asm/mach-types.h>
@@ -166,6 +171,129 @@ mmc_setup_mmcsd_fail:
        gpiod_remove_lookup_table(&mmc_gpios_table);
 }
 
+static struct mtd_partition omapl138_hawk_nandflash_partition[] = {
+       {
+               .name           = "u-boot env",
+               .offset         = 0,
+               .size           = SZ_128K,
+               .mask_flags     = MTD_WRITEABLE,
+        },
+       {
+               .name           = "u-boot",
+               .offset         = MTDPART_OFS_APPEND,
+               .size           = SZ_512K,
+               .mask_flags     = MTD_WRITEABLE,
+       },
+       {
+               .name           = "free space",
+               .offset         = MTDPART_OFS_APPEND,
+               .size           = MTDPART_SIZ_FULL,
+               .mask_flags     = 0,
+       },
+};
+
+static struct davinci_aemif_timing omapl138_hawk_nandflash_timing = {
+       .wsetup         = 24,
+       .wstrobe        = 21,
+       .whold          = 14,
+       .rsetup         = 19,
+       .rstrobe        = 50,
+       .rhold          = 0,
+       .ta             = 20,
+};
+
+static struct davinci_nand_pdata omapl138_hawk_nandflash_data = {
+       .core_chipsel   = 1,
+       .parts          = omapl138_hawk_nandflash_partition,
+       .nr_parts       = ARRAY_SIZE(omapl138_hawk_nandflash_partition),
+       .ecc_mode       = NAND_ECC_HW,
+       .ecc_bits       = 4,
+       .bbt_options    = NAND_BBT_USE_FLASH,
+       .options        = NAND_BUSWIDTH_16,
+       .timing         = &omapl138_hawk_nandflash_timing,
+       .mask_chipsel   = 0,
+       .mask_ale       = 0,
+       .mask_cle       = 0,
+};
+
+static struct resource omapl138_hawk_nandflash_resource[] = {
+       {
+               .start  = DA8XX_AEMIF_CS3_BASE,
+               .end    = DA8XX_AEMIF_CS3_BASE + SZ_32M,
+               .flags  = IORESOURCE_MEM,
+       },
+       {
+               .start  = DA8XX_AEMIF_CTL_BASE,
+               .end    = DA8XX_AEMIF_CTL_BASE + SZ_32K,
+               .flags  = IORESOURCE_MEM,
+       },
+};
+
+static struct resource omapl138_hawk_aemif_resource[] = {
+       {
+               .start  = DA8XX_AEMIF_CTL_BASE,
+               .end    = DA8XX_AEMIF_CTL_BASE + SZ_32K,
+               .flags  = IORESOURCE_MEM,
+       }
+};
+
+static struct aemif_abus_data omapl138_hawk_aemif_abus_data[] = {
+       {
+               .cs     = 3,
+       }
+};
+
+static struct platform_device omapl138_hawk_aemif_devices[] = {
+       {
+               .name           = "davinci_nand",
+               .id             = -1,
+               .dev            = {
+                       .platform_data  = &omapl138_hawk_nandflash_data,
+               },
+               .resource       = omapl138_hawk_nandflash_resource,
+               .num_resources  = ARRAY_SIZE(omapl138_hawk_nandflash_resource),
+       }
+};
+
+static struct aemif_platform_data omapl138_hawk_aemif_pdata = {
+       .cs_offset = 2,
+       .abus_data = omapl138_hawk_aemif_abus_data,
+       .num_abus_data = ARRAY_SIZE(omapl138_hawk_aemif_abus_data),
+       .sub_devices = omapl138_hawk_aemif_devices,
+       .num_sub_devices = ARRAY_SIZE(omapl138_hawk_aemif_devices),
+};
+
+static struct platform_device omapl138_hawk_aemif_device = {
+       .name           = "ti-aemif",
+       .id             = -1,
+       .dev = {
+               .platform_data  = &omapl138_hawk_aemif_pdata,
+       },
+       .resource       = omapl138_hawk_aemif_resource,
+       .num_resources  = ARRAY_SIZE(omapl138_hawk_aemif_resource),
+};
+
+static const short omapl138_hawk_nand_pins[] = {
+       DA850_EMA_WAIT_1, DA850_NEMA_OE, DA850_NEMA_WE, DA850_NEMA_CS_3,
+       DA850_EMA_D_0, DA850_EMA_D_1, DA850_EMA_D_2, DA850_EMA_D_3,
+       DA850_EMA_D_4, DA850_EMA_D_5, DA850_EMA_D_6, DA850_EMA_D_7,
+       DA850_EMA_D_8, DA850_EMA_D_9, DA850_EMA_D_10, DA850_EMA_D_11,
+       DA850_EMA_D_12, DA850_EMA_D_13, DA850_EMA_D_14, DA850_EMA_D_15,
+       DA850_EMA_A_1, DA850_EMA_A_2,
+       -1
+};
+
+static int omapl138_hawk_register_aemif(void)
+{
+       int ret;
+
+       ret = davinci_cfg_reg_list(omapl138_hawk_nand_pins);
+       if (ret)
+               pr_warn("%s: NAND mux setup failed: %d\n", __func__, ret);
+
+       return platform_device_register(&omapl138_hawk_aemif_device);
+}
+
 static irqreturn_t omapl138_hawk_usb_ocic_irq(int irq, void *dev_id);
 static da8xx_ocic_handler_t hawk_usb_ocic_handler;
 
@@ -236,14 +364,9 @@ static __init void omapl138_hawk_usb_init(void)
                return;
        }
 
-       ret = da8xx_register_usb20_phy_clk(false);
-       if (ret)
-               pr_warn("%s: USB 2.0 PHY CLK registration failed: %d\n",
-                       __func__, ret);
-
-       ret = da8xx_register_usb11_phy_clk(false);
+       ret = da8xx_register_usb_phy_clocks();
        if (ret)
-               pr_warn("%s: USB 1.1 PHY CLK registration failed: %d\n",
+               pr_warn("%s: USB PHY CLK registration failed: %d\n",
                        __func__, ret);
 
        ret = da8xx_register_usb_phy();
@@ -285,6 +408,8 @@ static __init void omapl138_hawk_init(void)
 {
        int ret;
 
+       da850_register_clocks();
+
        ret = da850_register_gpio();
        if (ret)
                pr_warn("%s: GPIO init failed: %d\n", __func__, ret);
@@ -301,6 +426,10 @@ static __init void omapl138_hawk_init(void)
 
        omapl138_hawk_usb_init();
 
+       ret = omapl138_hawk_register_aemif();
+       if (ret)
+               pr_warn("%s: aemif registration failed: %d\n", __func__, ret);
+
        ret = da8xx_register_watchdog();
        if (ret)
                pr_warn("%s: watchdog registration failed: %d\n",
index e7c1728..792bb84 100644 (file)
@@ -134,6 +134,8 @@ static __init void davinci_sffsdr_init(void)
 {
        struct davinci_soc_info *soc_info = &davinci_soc_info;
 
+       dm644x_register_clocks();
+
        dm644x_init_devices();
 
        platform_add_devices(davinci_sffsdr_devices,
diff --git a/arch/arm/mach-davinci/clock.c b/arch/arm/mach-davinci/clock.c
deleted file mode 100644 (file)
index f77a4f7..0000000
+++ /dev/null
@@ -1,745 +0,0 @@
-/*
- * Clock and PLL control for DaVinci devices
- *
- * Copyright (C) 2006-2007 Texas Instruments.
- * Copyright (C) 2008-2009 Deep Root Systems, LLC
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/errno.h>
-#include <linux/clk.h>
-#include <linux/err.h>
-#include <linux/mutex.h>
-#include <linux/io.h>
-#include <linux/delay.h>
-
-#include <mach/hardware.h>
-
-#include <mach/clock.h>
-#include "psc.h"
-#include <mach/cputype.h>
-#include "clock.h"
-
-static LIST_HEAD(clocks);
-static DEFINE_MUTEX(clocks_mutex);
-static DEFINE_SPINLOCK(clockfw_lock);
-
-void davinci_clk_enable(struct clk *clk)
-{
-       if (clk->parent)
-               davinci_clk_enable(clk->parent);
-       if (clk->usecount++ == 0) {
-               if (clk->flags & CLK_PSC)
-                       davinci_psc_config(clk->domain, clk->gpsc, clk->lpsc,
-                                          true, clk->flags);
-               else if (clk->clk_enable)
-                       clk->clk_enable(clk);
-       }
-}
-
-void davinci_clk_disable(struct clk *clk)
-{
-       if (WARN_ON(clk->usecount == 0))
-               return;
-       if (--clk->usecount == 0) {
-               if (!(clk->flags & CLK_PLL) && (clk->flags & CLK_PSC))
-                       davinci_psc_config(clk->domain, clk->gpsc, clk->lpsc,
-                                          false, clk->flags);
-               else if (clk->clk_disable)
-                       clk->clk_disable(clk);
-       }
-       if (clk->parent)
-               davinci_clk_disable(clk->parent);
-}
-
-int davinci_clk_reset(struct clk *clk, bool reset)
-{
-       unsigned long flags;
-
-       if (clk == NULL || IS_ERR(clk))
-               return -EINVAL;
-
-       spin_lock_irqsave(&clockfw_lock, flags);
-       if (clk->flags & CLK_PSC)
-               davinci_psc_reset(clk->gpsc, clk->lpsc, reset);
-       spin_unlock_irqrestore(&clockfw_lock, flags);
-
-       return 0;
-}
-EXPORT_SYMBOL(davinci_clk_reset);
-
-int davinci_clk_reset_assert(struct clk *clk)
-{
-       if (clk == NULL || IS_ERR(clk) || !clk->reset)
-               return -EINVAL;
-
-       return clk->reset(clk, true);
-}
-EXPORT_SYMBOL(davinci_clk_reset_assert);
-
-int davinci_clk_reset_deassert(struct clk *clk)
-{
-       if (clk == NULL || IS_ERR(clk) || !clk->reset)
-               return -EINVAL;
-
-       return clk->reset(clk, false);
-}
-EXPORT_SYMBOL(davinci_clk_reset_deassert);
-
-int clk_enable(struct clk *clk)
-{
-       unsigned long flags;
-
-       if (!clk)
-               return 0;
-       else if (IS_ERR(clk))
-               return -EINVAL;
-
-       spin_lock_irqsave(&clockfw_lock, flags);
-       davinci_clk_enable(clk);
-       spin_unlock_irqrestore(&clockfw_lock, flags);
-
-       return 0;
-}
-EXPORT_SYMBOL(clk_enable);
-
-void clk_disable(struct clk *clk)
-{
-       unsigned long flags;
-
-       if (clk == NULL || IS_ERR(clk))
-               return;
-
-       spin_lock_irqsave(&clockfw_lock, flags);
-       davinci_clk_disable(clk);
-       spin_unlock_irqrestore(&clockfw_lock, flags);
-}
-EXPORT_SYMBOL(clk_disable);
-
-unsigned long clk_get_rate(struct clk *clk)
-{
-       if (clk == NULL || IS_ERR(clk))
-               return 0;
-
-       return clk->rate;
-}
-EXPORT_SYMBOL(clk_get_rate);
-
-long clk_round_rate(struct clk *clk, unsigned long rate)
-{
-       if (clk == NULL || IS_ERR(clk))
-               return 0;
-
-       if (clk->round_rate)
-               return clk->round_rate(clk, rate);
-
-       return clk->rate;
-}
-EXPORT_SYMBOL(clk_round_rate);
-
-/* Propagate rate to children */
-static void propagate_rate(struct clk *root)
-{
-       struct clk *clk;
-
-       list_for_each_entry(clk, &root->children, childnode) {
-               if (clk->recalc)
-                       clk->rate = clk->recalc(clk);
-               propagate_rate(clk);
-       }
-}
-
-int clk_set_rate(struct clk *clk, unsigned long rate)
-{
-       unsigned long flags;
-       int ret = -EINVAL;
-
-       if (!clk)
-               return 0;
-       else if (IS_ERR(clk))
-               return -EINVAL;
-
-       if (clk->set_rate)
-               ret = clk->set_rate(clk, rate);
-
-       spin_lock_irqsave(&clockfw_lock, flags);
-       if (ret == 0) {
-               if (clk->recalc)
-                       clk->rate = clk->recalc(clk);
-               propagate_rate(clk);
-       }
-       spin_unlock_irqrestore(&clockfw_lock, flags);
-
-       return ret;
-}
-EXPORT_SYMBOL(clk_set_rate);
-
-int clk_set_parent(struct clk *clk, struct clk *parent)
-{
-       unsigned long flags;
-
-       if (!clk)
-               return 0;
-       else if (IS_ERR(clk))
-               return -EINVAL;
-
-       /* Cannot change parent on enabled clock */
-       if (WARN_ON(clk->usecount))
-               return -EINVAL;
-
-       mutex_lock(&clocks_mutex);
-       if (clk->set_parent) {
-               int ret = clk->set_parent(clk, parent);
-
-               if (ret) {
-                       mutex_unlock(&clocks_mutex);
-                       return ret;
-               }
-       }
-       clk->parent = parent;
-       list_del_init(&clk->childnode);
-       list_add(&clk->childnode, &clk->parent->children);
-       mutex_unlock(&clocks_mutex);
-
-       spin_lock_irqsave(&clockfw_lock, flags);
-       if (clk->recalc)
-               clk->rate = clk->recalc(clk);
-       propagate_rate(clk);
-       spin_unlock_irqrestore(&clockfw_lock, flags);
-
-       return 0;
-}
-EXPORT_SYMBOL(clk_set_parent);
-
-struct clk *clk_get_parent(struct clk *clk)
-{
-       if (!clk)
-               return NULL;
-
-       return clk->parent;
-}
-EXPORT_SYMBOL(clk_get_parent);
-
-int clk_register(struct clk *clk)
-{
-       if (clk == NULL || IS_ERR(clk))
-               return -EINVAL;
-
-       if (WARN(clk->parent && !clk->parent->rate,
-                       "CLK: %s parent %s has no rate!\n",
-                       clk->name, clk->parent->name))
-               return -EINVAL;
-
-       INIT_LIST_HEAD(&clk->children);
-
-       mutex_lock(&clocks_mutex);
-       list_add_tail(&clk->node, &clocks);
-       if (clk->parent) {
-               if (clk->set_parent) {
-                       int ret = clk->set_parent(clk, clk->parent);
-
-                       if (ret) {
-                               mutex_unlock(&clocks_mutex);
-                               return ret;
-                       }
-               }
-               list_add_tail(&clk->childnode, &clk->parent->children);
-       }
-       mutex_unlock(&clocks_mutex);
-
-       /* If rate is already set, use it */
-       if (clk->rate)
-               return 0;
-
-       /* Else, see if there is a way to calculate it */
-       if (clk->recalc)
-               clk->rate = clk->recalc(clk);
-
-       /* Otherwise, default to parent rate */
-       else if (clk->parent)
-               clk->rate = clk->parent->rate;
-
-       return 0;
-}
-EXPORT_SYMBOL(clk_register);
-
-void clk_unregister(struct clk *clk)
-{
-       if (clk == NULL || IS_ERR(clk))
-               return;
-
-       mutex_lock(&clocks_mutex);
-       list_del(&clk->node);
-       list_del(&clk->childnode);
-       mutex_unlock(&clocks_mutex);
-}
-EXPORT_SYMBOL(clk_unregister);
-
-#ifdef CONFIG_DAVINCI_RESET_CLOCKS
-/*
- * Disable any unused clocks left on by the bootloader
- */
-int __init davinci_clk_disable_unused(void)
-{
-       struct clk *ck;
-
-       spin_lock_irq(&clockfw_lock);
-       list_for_each_entry(ck, &clocks, node) {
-               if (ck->usecount > 0)
-                       continue;
-               if (!(ck->flags & CLK_PSC))
-                       continue;
-
-               /* ignore if in Disabled or SwRstDisable states */
-               if (!davinci_psc_is_clk_active(ck->gpsc, ck->lpsc))
-                       continue;
-
-               pr_debug("Clocks: disable unused %s\n", ck->name);
-
-               davinci_psc_config(ck->domain, ck->gpsc, ck->lpsc,
-                               false, ck->flags);
-       }
-       spin_unlock_irq(&clockfw_lock);
-
-       return 0;
-}
-#endif
-
-static unsigned long clk_sysclk_recalc(struct clk *clk)
-{
-       u32 v, plldiv;
-       struct pll_data *pll;
-       unsigned long rate = clk->rate;
-
-       /* If this is the PLL base clock, no more calculations needed */
-       if (clk->pll_data)
-               return rate;
-
-       if (WARN_ON(!clk->parent))
-               return rate;
-
-       rate = clk->parent->rate;
-
-       /* Otherwise, the parent must be a PLL */
-       if (WARN_ON(!clk->parent->pll_data))
-               return rate;
-
-       pll = clk->parent->pll_data;
-
-       /* If pre-PLL, source clock is before the multiplier and divider(s) */
-       if (clk->flags & PRE_PLL)
-               rate = pll->input_rate;
-
-       if (!clk->div_reg)
-               return rate;
-
-       v = __raw_readl(pll->base + clk->div_reg);
-       if (v & PLLDIV_EN) {
-               plldiv = (v & pll->div_ratio_mask) + 1;
-               if (plldiv)
-                       rate /= plldiv;
-       }
-
-       return rate;
-}
-
-int davinci_set_sysclk_rate(struct clk *clk, unsigned long rate)
-{
-       unsigned v;
-       struct pll_data *pll;
-       unsigned long input;
-       unsigned ratio = 0;
-
-       /* If this is the PLL base clock, wrong function to call */
-       if (clk->pll_data)
-               return -EINVAL;
-
-       /* There must be a parent... */
-       if (WARN_ON(!clk->parent))
-               return -EINVAL;
-
-       /* ... the parent must be a PLL... */
-       if (WARN_ON(!clk->parent->pll_data))
-               return -EINVAL;
-
-       /* ... and this clock must have a divider. */
-       if (WARN_ON(!clk->div_reg))
-               return -EINVAL;
-
-       pll = clk->parent->pll_data;
-
-       input = clk->parent->rate;
-
-       /* If pre-PLL, source clock is before the multiplier and divider(s) */
-       if (clk->flags & PRE_PLL)
-               input = pll->input_rate;
-
-       if (input > rate) {
-               /*
-                * Can afford to provide an output little higher than requested
-                * only if maximum rate supported by hardware on this sysclk
-                * is known.
-                */
-               if (clk->maxrate) {
-                       ratio = DIV_ROUND_CLOSEST(input, rate);
-                       if (input / ratio > clk->maxrate)
-                               ratio = 0;
-               }
-
-               if (ratio == 0)
-                       ratio = DIV_ROUND_UP(input, rate);
-
-               ratio--;
-       }
-
-       if (ratio > pll->div_ratio_mask)
-               return -EINVAL;
-
-       do {
-               v = __raw_readl(pll->base + PLLSTAT);
-       } while (v & PLLSTAT_GOSTAT);
-
-       v = __raw_readl(pll->base + clk->div_reg);
-       v &= ~pll->div_ratio_mask;
-       v |= ratio | PLLDIV_EN;
-       __raw_writel(v, pll->base + clk->div_reg);
-
-       v = __raw_readl(pll->base + PLLCMD);
-       v |= PLLCMD_GOSET;
-       __raw_writel(v, pll->base + PLLCMD);
-
-       do {
-               v = __raw_readl(pll->base + PLLSTAT);
-       } while (v & PLLSTAT_GOSTAT);
-
-       return 0;
-}
-EXPORT_SYMBOL(davinci_set_sysclk_rate);
-
-static unsigned long clk_leafclk_recalc(struct clk *clk)
-{
-       if (WARN_ON(!clk->parent))
-               return clk->rate;
-
-       return clk->parent->rate;
-}
-
-int davinci_simple_set_rate(struct clk *clk, unsigned long rate)
-{
-       clk->rate = rate;
-       return 0;
-}
-
-static unsigned long clk_pllclk_recalc(struct clk *clk)
-{
-       u32 ctrl, mult = 1, prediv = 1, postdiv = 1;
-       u8 bypass;
-       struct pll_data *pll = clk->pll_data;
-       unsigned long rate = clk->rate;
-
-       ctrl = __raw_readl(pll->base + PLLCTL);
-       rate = pll->input_rate = clk->parent->rate;
-
-       if (ctrl & PLLCTL_PLLEN) {
-               bypass = 0;
-               mult = __raw_readl(pll->base + PLLM);
-               if (cpu_is_davinci_dm365())
-                       mult = 2 * (mult & PLLM_PLLM_MASK);
-               else
-                       mult = (mult & PLLM_PLLM_MASK) + 1;
-       } else
-               bypass = 1;
-
-       if (pll->flags & PLL_HAS_PREDIV) {
-               prediv = __raw_readl(pll->base + PREDIV);
-               if (prediv & PLLDIV_EN)
-                       prediv = (prediv & pll->div_ratio_mask) + 1;
-               else
-                       prediv = 1;
-       }
-
-       /* pre-divider is fixed, but (some?) chips won't report that */
-       if (cpu_is_davinci_dm355() && pll->num == 1)
-               prediv = 8;
-
-       if (pll->flags & PLL_HAS_POSTDIV) {
-               postdiv = __raw_readl(pll->base + POSTDIV);
-               if (postdiv & PLLDIV_EN)
-                       postdiv = (postdiv & pll->div_ratio_mask) + 1;
-               else
-                       postdiv = 1;
-       }
-
-       if (!bypass) {
-               rate /= prediv;
-               rate *= mult;
-               rate /= postdiv;
-       }
-
-       pr_debug("PLL%d: input = %lu MHz [ ",
-                pll->num, clk->parent->rate / 1000000);
-       if (bypass)
-               pr_debug("bypass ");
-       if (prediv > 1)
-               pr_debug("/ %d ", prediv);
-       if (mult > 1)
-               pr_debug("* %d ", mult);
-       if (postdiv > 1)
-               pr_debug("/ %d ", postdiv);
-       pr_debug("] --> %lu MHz output.\n", rate / 1000000);
-
-       return rate;
-}
-
-/**
- * davinci_set_pllrate - set the output rate of a given PLL.
- *
- * Note: Currently tested to work with OMAP-L138 only.
- *
- * @pll: pll whose rate needs to be changed.
- * @prediv: The pre divider value. Passing 0 disables the pre-divider.
- * @pllm: The multiplier value. Passing 0 leads to multiply-by-one.
- * @postdiv: The post divider value. Passing 0 disables the post-divider.
- */
-int davinci_set_pllrate(struct pll_data *pll, unsigned int prediv,
-                                       unsigned int mult, unsigned int postdiv)
-{
-       u32 ctrl;
-       unsigned int locktime;
-       unsigned long flags;
-
-       if (pll->base == NULL)
-               return -EINVAL;
-
-       /*
-        *  PLL lock time required per OMAP-L138 datasheet is
-        * (2000 * prediv)/sqrt(pllm) OSCIN cycles. We approximate sqrt(pllm)
-        * as 4 and OSCIN cycle as 25 MHz.
-        */
-       if (prediv) {
-               locktime = ((2000 * prediv) / 100);
-               prediv = (prediv - 1) | PLLDIV_EN;
-       } else {
-               locktime = PLL_LOCK_TIME;
-       }
-       if (postdiv)
-               postdiv = (postdiv - 1) | PLLDIV_EN;
-       if (mult)
-               mult = mult - 1;
-
-       /* Protect against simultaneous calls to PLL setting seqeunce */
-       spin_lock_irqsave(&clockfw_lock, flags);
-
-       ctrl = __raw_readl(pll->base + PLLCTL);
-
-       /* Switch the PLL to bypass mode */
-       ctrl &= ~(PLLCTL_PLLENSRC | PLLCTL_PLLEN);
-       __raw_writel(ctrl, pll->base + PLLCTL);
-
-       udelay(PLL_BYPASS_TIME);
-
-       /* Reset and enable PLL */
-       ctrl &= ~(PLLCTL_PLLRST | PLLCTL_PLLDIS);
-       __raw_writel(ctrl, pll->base + PLLCTL);
-
-       if (pll->flags & PLL_HAS_PREDIV)
-               __raw_writel(prediv, pll->base + PREDIV);
-
-       __raw_writel(mult, pll->base + PLLM);
-
-       if (pll->flags & PLL_HAS_POSTDIV)
-               __raw_writel(postdiv, pll->base + POSTDIV);
-
-       udelay(PLL_RESET_TIME);
-
-       /* Bring PLL out of reset */
-       ctrl |= PLLCTL_PLLRST;
-       __raw_writel(ctrl, pll->base + PLLCTL);
-
-       udelay(locktime);
-
-       /* Remove PLL from bypass mode */
-       ctrl |= PLLCTL_PLLEN;
-       __raw_writel(ctrl, pll->base + PLLCTL);
-
-       spin_unlock_irqrestore(&clockfw_lock, flags);
-
-       return 0;
-}
-EXPORT_SYMBOL(davinci_set_pllrate);
-
-/**
- * davinci_set_refclk_rate() - Set the reference clock rate
- * @rate:      The new rate.
- *
- * Sets the reference clock rate to a given value. This will most likely
- * result in the entire clock tree getting updated.
- *
- * This is used to support boards which use a reference clock different
- * than that used by default in <soc>.c file. The reference clock rate
- * should be updated early in the boot process; ideally soon after the
- * clock tree has been initialized once with the default reference clock
- * rate (davinci_clk_init()).
- *
- * Returns 0 on success, error otherwise.
- */
-int davinci_set_refclk_rate(unsigned long rate)
-{
-       struct clk *refclk;
-
-       refclk = clk_get(NULL, "ref");
-       if (IS_ERR(refclk)) {
-               pr_err("%s: failed to get reference clock\n", __func__);
-               return PTR_ERR(refclk);
-       }
-
-       clk_set_rate(refclk, rate);
-
-       clk_put(refclk);
-
-       return 0;
-}
-
-int __init davinci_clk_init(struct clk_lookup *clocks)
-{
-       struct clk_lookup *c;
-       struct clk *clk;
-       size_t num_clocks = 0;
-
-       for (c = clocks; c->clk; c++) {
-               clk = c->clk;
-
-               if (!clk->recalc) {
-
-                       /* Check if clock is a PLL */
-                       if (clk->pll_data)
-                               clk->recalc = clk_pllclk_recalc;
-
-                       /* Else, if it is a PLL-derived clock */
-                       else if (clk->flags & CLK_PLL)
-                               clk->recalc = clk_sysclk_recalc;
-
-                       /* Otherwise, it is a leaf clock (PSC clock) */
-                       else if (clk->parent)
-                               clk->recalc = clk_leafclk_recalc;
-               }
-
-               if (clk->pll_data) {
-                       struct pll_data *pll = clk->pll_data;
-
-                       if (!pll->div_ratio_mask)
-                               pll->div_ratio_mask = PLLDIV_RATIO_MASK;
-
-                       if (pll->phys_base && !pll->base) {
-                               pll->base = ioremap(pll->phys_base, SZ_4K);
-                               WARN_ON(!pll->base);
-                       }
-               }
-
-               if (clk->recalc)
-                       clk->rate = clk->recalc(clk);
-
-               if (clk->lpsc)
-                       clk->flags |= CLK_PSC;
-
-               if (clk->flags & PSC_LRST)
-                       clk->reset = davinci_clk_reset;
-
-               clk_register(clk);
-               num_clocks++;
-
-               /* Turn on clocks that Linux doesn't otherwise manage */
-               if (clk->flags & ALWAYS_ENABLED)
-                       clk_enable(clk);
-       }
-
-       clkdev_add_table(clocks, num_clocks);
-
-       return 0;
-}
-
-#ifdef CONFIG_DEBUG_FS
-
-#include <linux/debugfs.h>
-#include <linux/seq_file.h>
-
-#define CLKNAME_MAX    10              /* longest clock name */
-#define NEST_DELTA     2
-#define NEST_MAX       4
-
-static void
-dump_clock(struct seq_file *s, unsigned nest, struct clk *parent)
-{
-       char            *state;
-       char            buf[CLKNAME_MAX + NEST_DELTA * NEST_MAX];
-       struct clk      *clk;
-       unsigned        i;
-
-       if (parent->flags & CLK_PLL)
-               state = "pll";
-       else if (parent->flags & CLK_PSC)
-               state = "psc";
-       else
-               state = "";
-
-       /* <nest spaces> name <pad to end> */
-       memset(buf, ' ', sizeof(buf) - 1);
-       buf[sizeof(buf) - 1] = 0;
-       i = strlen(parent->name);
-       memcpy(buf + nest, parent->name,
-                       min(i, (unsigned)(sizeof(buf) - 1 - nest)));
-
-       seq_printf(s, "%s users=%2d %-3s %9ld Hz\n",
-                  buf, parent->usecount, state, clk_get_rate(parent));
-       /* REVISIT show device associations too */
-
-       /* cost is now small, but not linear... */
-       list_for_each_entry(clk, &parent->children, childnode) {
-               dump_clock(s, nest + NEST_DELTA, clk);
-       }
-}
-
-static int davinci_ck_show(struct seq_file *m, void *v)
-{
-       struct clk *clk;
-
-       /*
-        * Show clock tree; We trust nonzero usecounts equate to PSC enables...
-        */
-       mutex_lock(&clocks_mutex);
-       list_for_each_entry(clk, &clocks, node)
-               if (!clk->parent)
-                       dump_clock(m, 0, clk);
-       mutex_unlock(&clocks_mutex);
-
-       return 0;
-}
-
-static int davinci_ck_open(struct inode *inode, struct file *file)
-{
-       return single_open(file, davinci_ck_show, NULL);
-}
-
-static const struct file_operations davinci_ck_operations = {
-       .open           = davinci_ck_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-};
-
-static int __init davinci_clk_debugfs_init(void)
-{
-       debugfs_create_file("davinci_clocks", S_IFREG | S_IRUGO, NULL, NULL,
-                                               &davinci_ck_operations);
-       return 0;
-
-}
-device_initcall(davinci_clk_debugfs_init);
-#endif /* CONFIG_DEBUG_FS */
index d7894d5..3073834 100644 (file)
 #ifndef __ARCH_ARM_DAVINCI_CLOCK_H
 #define __ARCH_ARM_DAVINCI_CLOCK_H
 
-#define DAVINCI_PLL1_BASE 0x01c40800
-#define DAVINCI_PLL2_BASE 0x01c40c00
-#define MAX_PLL 2
-
 /* PLL/Reset register offsets */
 #define PLLCTL          0x100
 #define PLLCTL_PLLEN    BIT(0)
  */
 #define PLL_LOCK_TIME          20
 
-#ifndef __ASSEMBLER__
-
-#include <linux/list.h>
-#include <linux/clkdev.h>
-
-#define PLLSTAT_GOSTAT BIT(0)
-#define PLLCMD_GOSET   BIT(0)
-
-struct pll_data {
-       u32 phys_base;
-       void __iomem *base;
-       u32 num;
-       u32 flags;
-       u32 input_rate;
-       u32 div_ratio_mask;
-};
-#define PLL_HAS_PREDIV          0x01
-#define PLL_HAS_POSTDIV         0x02
-
-struct clk {
-       struct list_head        node;
-       struct module           *owner;
-       const char              *name;
-       unsigned long           rate;
-       unsigned long           maxrate;        /* H/W supported max rate */
-       u8                      usecount;
-       u8                      lpsc;
-       u8                      gpsc;
-       u8                      domain;
-       u32                     flags;
-       struct clk              *parent;
-       struct list_head        children;       /* list of children */
-       struct list_head        childnode;      /* parent's child list node */
-       struct pll_data         *pll_data;
-       u32                     div_reg;
-       unsigned long (*recalc) (struct clk *);
-       int (*set_rate) (struct clk *clk, unsigned long rate);
-       int (*round_rate) (struct clk *clk, unsigned long rate);
-       int (*reset) (struct clk *clk, bool reset);
-       void (*clk_enable) (struct clk *clk);
-       void (*clk_disable) (struct clk *clk);
-       int (*set_parent) (struct clk *clk, struct clk *parent);
-};
-
-/* Clock flags: SoC-specific flags start at BIT(16) */
-#define ALWAYS_ENABLED         BIT(1)
-#define CLK_PSC                        BIT(2)
-#define CLK_PLL                        BIT(3) /* PLL-derived clock */
-#define PRE_PLL                        BIT(4) /* source is before PLL mult/div */
-#define PSC_SWRSTDISABLE       BIT(5) /* Disable state is SwRstDisable */
-#define PSC_FORCE              BIT(6) /* Force module state transtition */
-#define PSC_LRST               BIT(8) /* Use local reset on enable/disable */
-
-#define CLK(dev, con, ck)      \
-       {                       \
-               .dev_id = dev,  \
-               .con_id = con,  \
-               .clk = ck,      \
-       }                       \
-
-int davinci_clk_init(struct clk_lookup *clocks);
-int davinci_set_pllrate(struct pll_data *pll, unsigned int prediv,
-                               unsigned int mult, unsigned int postdiv);
-int davinci_set_sysclk_rate(struct clk *clk, unsigned long rate);
-int davinci_set_refclk_rate(unsigned long rate);
-int davinci_simple_set_rate(struct clk *clk, unsigned long rate);
-int davinci_clk_reset(struct clk *clk, bool reset);
-void davinci_clk_enable(struct clk *clk);
-void davinci_clk_disable(struct clk *clk);
-
-#endif
-
 #endif
index bcb6a7b..e1d0f0d 100644 (file)
@@ -20,8 +20,6 @@
 #include <mach/common.h>
 #include <mach/cputype.h>
 
-#include "clock.h"
-
 struct davinci_soc_info davinci_soc_info;
 EXPORT_SYMBOL(davinci_soc_info);
 
@@ -118,5 +116,4 @@ err:
 void __init davinci_init_late(void)
 {
        davinci_cpufreq_init();
-       davinci_clk_disable_unused();
 }
index 350d767..0bc5bd2 100644 (file)
@@ -8,21 +8,20 @@
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
+#include <linux/clk-provider.h>
+#include <linux/clk/davinci.h>
 #include <linux/gpio.h>
 #include <linux/init.h>
-#include <linux/clk.h>
 #include <linux/platform_data/gpio-davinci.h>
 
 #include <asm/mach/map.h>
 
-#include "psc.h"
-#include <mach/irqs.h>
-#include <mach/cputype.h>
 #include <mach/common.h>
-#include <mach/time.h>
+#include <mach/cputype.h>
 #include <mach/da8xx.h>
+#include <mach/irqs.h>
+#include <mach/time.h>
 
-#include "clock.h"
 #include "mux.h"
 
 /* Offsets of the 8 compare registers on the da830 */
 
 #define DA830_REF_FREQ         24000000
 
-static struct pll_data pll0_data = {
-       .num            = 1,
-       .phys_base      = DA8XX_PLL0_BASE,
-       .flags          = PLL_HAS_PREDIV | PLL_HAS_POSTDIV,
-};
-
-static struct clk ref_clk = {
-       .name           = "ref_clk",
-       .rate           = DA830_REF_FREQ,
-};
-
-static struct clk pll0_clk = {
-       .name           = "pll0",
-       .parent         = &ref_clk,
-       .pll_data       = &pll0_data,
-       .flags          = CLK_PLL,
-};
-
-static struct clk pll0_aux_clk = {
-       .name           = "pll0_aux_clk",
-       .parent         = &pll0_clk,
-       .flags          = CLK_PLL | PRE_PLL,
-};
-
-static struct clk pll0_sysclk2 = {
-       .name           = "pll0_sysclk2",
-       .parent         = &pll0_clk,
-       .flags          = CLK_PLL,
-       .div_reg        = PLLDIV2,
-};
-
-static struct clk pll0_sysclk3 = {
-       .name           = "pll0_sysclk3",
-       .parent         = &pll0_clk,
-       .flags          = CLK_PLL,
-       .div_reg        = PLLDIV3,
-};
-
-static struct clk pll0_sysclk4 = {
-       .name           = "pll0_sysclk4",
-       .parent         = &pll0_clk,
-       .flags          = CLK_PLL,
-       .div_reg        = PLLDIV4,
-};
-
-static struct clk pll0_sysclk5 = {
-       .name           = "pll0_sysclk5",
-       .parent         = &pll0_clk,
-       .flags          = CLK_PLL,
-       .div_reg        = PLLDIV5,
-};
-
-static struct clk pll0_sysclk6 = {
-       .name           = "pll0_sysclk6",
-       .parent         = &pll0_clk,
-       .flags          = CLK_PLL,
-       .div_reg        = PLLDIV6,
-};
-
-static struct clk pll0_sysclk7 = {
-       .name           = "pll0_sysclk7",
-       .parent         = &pll0_clk,
-       .flags          = CLK_PLL,
-       .div_reg        = PLLDIV7,
-};
-
-static struct clk i2c0_clk = {
-       .name           = "i2c0",
-       .parent         = &pll0_aux_clk,
-};
-
-static struct clk timerp64_0_clk = {
-       .name           = "timer0",
-       .parent         = &pll0_aux_clk,
-};
-
-static struct clk timerp64_1_clk = {
-       .name           = "timer1",
-       .parent         = &pll0_aux_clk,
-};
-
-static struct clk arm_rom_clk = {
-       .name           = "arm_rom",
-       .parent         = &pll0_sysclk2,
-       .lpsc           = DA8XX_LPSC0_ARM_RAM_ROM,
-       .flags          = ALWAYS_ENABLED,
-};
-
-static struct clk scr0_ss_clk = {
-       .name           = "scr0_ss",
-       .parent         = &pll0_sysclk2,
-       .lpsc           = DA8XX_LPSC0_SCR0_SS,
-       .flags          = ALWAYS_ENABLED,
-};
-
-static struct clk scr1_ss_clk = {
-       .name           = "scr1_ss",
-       .parent         = &pll0_sysclk2,
-       .lpsc           = DA8XX_LPSC0_SCR1_SS,
-       .flags          = ALWAYS_ENABLED,
-};
-
-static struct clk scr2_ss_clk = {
-       .name           = "scr2_ss",
-       .parent         = &pll0_sysclk2,
-       .lpsc           = DA8XX_LPSC0_SCR2_SS,
-       .flags          = ALWAYS_ENABLED,
-};
-
-static struct clk dmax_clk = {
-       .name           = "dmax",
-       .parent         = &pll0_sysclk2,
-       .lpsc           = DA8XX_LPSC0_PRUSS,
-       .flags          = ALWAYS_ENABLED,
-};
-
-static struct clk tpcc_clk = {
-       .name           = "tpcc",
-       .parent         = &pll0_sysclk2,
-       .lpsc           = DA8XX_LPSC0_TPCC,
-       .flags          = ALWAYS_ENABLED | CLK_PSC,
-};
-
-static struct clk tptc0_clk = {
-       .name           = "tptc0",
-       .parent         = &pll0_sysclk2,
-       .lpsc           = DA8XX_LPSC0_TPTC0,
-       .flags          = ALWAYS_ENABLED,
-};
-
-static struct clk tptc1_clk = {
-       .name           = "tptc1",
-       .parent         = &pll0_sysclk2,
-       .lpsc           = DA8XX_LPSC0_TPTC1,
-       .flags          = ALWAYS_ENABLED,
-};
-
-static struct clk mmcsd_clk = {
-       .name           = "mmcsd",
-       .parent         = &pll0_sysclk2,
-       .lpsc           = DA8XX_LPSC0_MMC_SD,
-};
-
-static struct clk uart0_clk = {
-       .name           = "uart0",
-       .parent         = &pll0_sysclk2,
-       .lpsc           = DA8XX_LPSC0_UART0,
-};
-
-static struct clk uart1_clk = {
-       .name           = "uart1",
-       .parent         = &pll0_sysclk2,
-       .lpsc           = DA8XX_LPSC1_UART1,
-       .gpsc           = 1,
-};
-
-static struct clk uart2_clk = {
-       .name           = "uart2",
-       .parent         = &pll0_sysclk2,
-       .lpsc           = DA8XX_LPSC1_UART2,
-       .gpsc           = 1,
-};
-
-static struct clk spi0_clk = {
-       .name           = "spi0",
-       .parent         = &pll0_sysclk2,
-       .lpsc           = DA8XX_LPSC0_SPI0,
-};
-
-static struct clk spi1_clk = {
-       .name           = "spi1",
-       .parent         = &pll0_sysclk2,
-       .lpsc           = DA8XX_LPSC1_SPI1,
-       .gpsc           = 1,
-};
-
-static struct clk ecap0_clk = {
-       .name           = "ecap0",
-       .parent         = &pll0_sysclk2,
-       .lpsc           = DA8XX_LPSC1_ECAP,
-       .gpsc           = 1,
-};
-
-static struct clk ecap1_clk = {
-       .name           = "ecap1",
-       .parent         = &pll0_sysclk2,
-       .lpsc           = DA8XX_LPSC1_ECAP,
-       .gpsc           = 1,
-};
-
-static struct clk ecap2_clk = {
-       .name           = "ecap2",
-       .parent         = &pll0_sysclk2,
-       .lpsc           = DA8XX_LPSC1_ECAP,
-       .gpsc           = 1,
-};
-
-static struct clk pwm0_clk = {
-       .name           = "pwm0",
-       .parent         = &pll0_sysclk2,
-       .lpsc           = DA8XX_LPSC1_PWM,
-       .gpsc           = 1,
-};
-
-static struct clk pwm1_clk = {
-       .name           = "pwm1",
-       .parent         = &pll0_sysclk2,
-       .lpsc           = DA8XX_LPSC1_PWM,
-       .gpsc           = 1,
-};
-
-static struct clk pwm2_clk = {
-       .name           = "pwm2",
-       .parent         = &pll0_sysclk2,
-       .lpsc           = DA8XX_LPSC1_PWM,
-       .gpsc           = 1,
-};
-
-static struct clk eqep0_clk = {
-       .name           = "eqep0",
-       .parent         = &pll0_sysclk2,
-       .lpsc           = DA830_LPSC1_EQEP,
-       .gpsc           = 1,
-};
-
-static struct clk eqep1_clk = {
-       .name           = "eqep1",
-       .parent         = &pll0_sysclk2,
-       .lpsc           = DA830_LPSC1_EQEP,
-       .gpsc           = 1,
-};
-
-static struct clk lcdc_clk = {
-       .name           = "lcdc",
-       .parent         = &pll0_sysclk2,
-       .lpsc           = DA8XX_LPSC1_LCDC,
-       .gpsc           = 1,
-};
-
-static struct clk mcasp0_clk = {
-       .name           = "mcasp0",
-       .parent         = &pll0_sysclk2,
-       .lpsc           = DA8XX_LPSC1_McASP0,
-       .gpsc           = 1,
-};
-
-static struct clk mcasp1_clk = {
-       .name           = "mcasp1",
-       .parent         = &pll0_sysclk2,
-       .lpsc           = DA830_LPSC1_McASP1,
-       .gpsc           = 1,
-};
-
-static struct clk mcasp2_clk = {
-       .name           = "mcasp2",
-       .parent         = &pll0_sysclk2,
-       .lpsc           = DA830_LPSC1_McASP2,
-       .gpsc           = 1,
-};
-
-static struct clk usb20_clk = {
-       .name           = "usb20",
-       .parent         = &pll0_sysclk2,
-       .lpsc           = DA8XX_LPSC1_USB20,
-       .gpsc           = 1,
-};
-
-static struct clk cppi41_clk = {
-       .name           = "cppi41",
-       .parent         = &usb20_clk,
-};
-
-static struct clk aemif_clk = {
-       .name           = "aemif",
-       .parent         = &pll0_sysclk3,
-       .lpsc           = DA8XX_LPSC0_EMIF25,
-       .flags          = ALWAYS_ENABLED,
-};
-
-static struct clk aintc_clk = {
-       .name           = "aintc",
-       .parent         = &pll0_sysclk4,
-       .lpsc           = DA8XX_LPSC0_AINTC,
-       .flags          = ALWAYS_ENABLED,
-};
-
-static struct clk secu_mgr_clk = {
-       .name           = "secu_mgr",
-       .parent         = &pll0_sysclk4,
-       .lpsc           = DA8XX_LPSC0_SECU_MGR,
-       .flags          = ALWAYS_ENABLED,
-};
-
-static struct clk emac_clk = {
-       .name           = "emac",
-       .parent         = &pll0_sysclk4,
-       .lpsc           = DA8XX_LPSC1_CPGMAC,
-       .gpsc           = 1,
-};
-
-static struct clk gpio_clk = {
-       .name           = "gpio",
-       .parent         = &pll0_sysclk4,
-       .lpsc           = DA8XX_LPSC1_GPIO,
-       .gpsc           = 1,
-};
-
-static struct clk i2c1_clk = {
-       .name           = "i2c1",
-       .parent         = &pll0_sysclk4,
-       .lpsc           = DA8XX_LPSC1_I2C,
-       .gpsc           = 1,
-};
-
-static struct clk usb11_clk = {
-       .name           = "usb11",
-       .parent         = &pll0_sysclk4,
-       .lpsc           = DA8XX_LPSC1_USB11,
-       .gpsc           = 1,
-};
-
-static struct clk emif3_clk = {
-       .name           = "emif3",
-       .parent         = &pll0_sysclk5,
-       .lpsc           = DA8XX_LPSC1_EMIF3C,
-       .gpsc           = 1,
-       .flags          = ALWAYS_ENABLED,
-};
-
-static struct clk arm_clk = {
-       .name           = "arm",
-       .parent         = &pll0_sysclk6,
-       .lpsc           = DA8XX_LPSC0_ARM,
-       .flags          = ALWAYS_ENABLED,
-};
-
-static struct clk rmii_clk = {
-       .name           = "rmii",
-       .parent         = &pll0_sysclk7,
-};
-
-static struct clk_lookup da830_clks[] = {
-       CLK(NULL,               "ref",          &ref_clk),
-       CLK(NULL,               "pll0",         &pll0_clk),
-       CLK(NULL,               "pll0_aux",     &pll0_aux_clk),
-       CLK(NULL,               "pll0_sysclk2", &pll0_sysclk2),
-       CLK(NULL,               "pll0_sysclk3", &pll0_sysclk3),
-       CLK(NULL,               "pll0_sysclk4", &pll0_sysclk4),
-       CLK(NULL,               "pll0_sysclk5", &pll0_sysclk5),
-       CLK(NULL,               "pll0_sysclk6", &pll0_sysclk6),
-       CLK(NULL,               "pll0_sysclk7", &pll0_sysclk7),
-       CLK("i2c_davinci.1",    NULL,           &i2c0_clk),
-       CLK(NULL,               "timer0",       &timerp64_0_clk),
-       CLK("davinci-wdt",      NULL,           &timerp64_1_clk),
-       CLK(NULL,               "arm_rom",      &arm_rom_clk),
-       CLK(NULL,               "scr0_ss",      &scr0_ss_clk),
-       CLK(NULL,               "scr1_ss",      &scr1_ss_clk),
-       CLK(NULL,               "scr2_ss",      &scr2_ss_clk),
-       CLK(NULL,               "dmax",         &dmax_clk),
-       CLK(NULL,               "tpcc",         &tpcc_clk),
-       CLK(NULL,               "tptc0",        &tptc0_clk),
-       CLK(NULL,               "tptc1",        &tptc1_clk),
-       CLK("da830-mmc.0",      NULL,           &mmcsd_clk),
-       CLK("serial8250.0",     NULL,           &uart0_clk),
-       CLK("serial8250.1",     NULL,           &uart1_clk),
-       CLK("serial8250.2",     NULL,           &uart2_clk),
-       CLK("spi_davinci.0",    NULL,           &spi0_clk),
-       CLK("spi_davinci.1",    NULL,           &spi1_clk),
-       CLK(NULL,               "ecap0",        &ecap0_clk),
-       CLK(NULL,               "ecap1",        &ecap1_clk),
-       CLK(NULL,               "ecap2",        &ecap2_clk),
-       CLK(NULL,               "pwm0",         &pwm0_clk),
-       CLK(NULL,               "pwm1",         &pwm1_clk),
-       CLK(NULL,               "pwm2",         &pwm2_clk),
-       CLK("eqep.0",           NULL,           &eqep0_clk),
-       CLK("eqep.1",           NULL,           &eqep1_clk),
-       CLK("da8xx_lcdc.0",     "fck",          &lcdc_clk),
-       CLK("davinci-mcasp.0",  NULL,           &mcasp0_clk),
-       CLK("davinci-mcasp.1",  NULL,           &mcasp1_clk),
-       CLK("davinci-mcasp.2",  NULL,           &mcasp2_clk),
-       CLK("musb-da8xx",       NULL,           &usb20_clk),
-       CLK("cppi41-dmaengine", NULL,           &cppi41_clk),
-       CLK(NULL,               "aemif",        &aemif_clk),
-       CLK(NULL,               "aintc",        &aintc_clk),
-       CLK(NULL,               "secu_mgr",     &secu_mgr_clk),
-       CLK("davinci_emac.1",   NULL,           &emac_clk),
-       CLK("davinci_mdio.0",   "fck",          &emac_clk),
-       CLK(NULL,               "gpio",         &gpio_clk),
-       CLK("i2c_davinci.2",    NULL,           &i2c1_clk),
-       CLK("ohci-da8xx",       NULL,   &usb11_clk),
-       CLK(NULL,               "emif3",        &emif3_clk),
-       CLK(NULL,               "arm",          &arm_clk),
-       CLK(NULL,               "rmii",         &rmii_clk),
-       CLK(NULL,               NULL,           NULL),
-};
-
 /*
  * Device specific mux setup
  *
@@ -1130,8 +733,6 @@ static struct map_desc da830_io_desc[] = {
        },
 };
 
-static u32 da830_psc_bases[] = { DA8XX_PSC0_BASE, DA8XX_PSC1_BASE };
-
 /* Contents of JTAG ID register used to identify exact cpu type */
 static struct davinci_id da830_ids[] = {
        {
@@ -1200,8 +801,6 @@ static const struct davinci_soc_info davinci_soc_info_da830 = {
        .jtag_id_reg            = DA8XX_SYSCFG0_BASE + DA8XX_JTAG_ID_REG,
        .ids                    = da830_ids,
        .ids_num                = ARRAY_SIZE(da830_ids),
-       .psc_bases              = da830_psc_bases,
-       .psc_bases_num          = ARRAY_SIZE(da830_psc_bases),
        .pinmux_base            = DA8XX_SYSCFG0_BASE + 0x120,
        .pinmux_pins            = da830_pins,
        .pinmux_pins_num        = ARRAY_SIZE(da830_pins),
@@ -1223,6 +822,53 @@ void __init da830_init(void)
 
 void __init da830_init_time(void)
 {
-       davinci_clk_init(da830_clks);
-       davinci_timer_init();
+       void __iomem *pll;
+       struct clk *clk;
+
+       clk_register_fixed_rate(NULL, "ref_clk", NULL, 0, DA830_REF_FREQ);
+
+       pll = ioremap(DA8XX_PLL0_BASE, SZ_4K);
+
+       da830_pll_init(NULL, pll, NULL);
+
+       clk = clk_get(NULL, "timer0");
+
+       davinci_timer_init(clk);
+}
+
+static struct resource da830_psc0_resources[] = {
+       {
+               .start  = DA8XX_PSC0_BASE,
+               .end    = DA8XX_PSC0_BASE + SZ_4K - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+};
+
+static struct platform_device da830_psc0_device = {
+       .name           = "da830-psc0",
+       .id             = -1,
+       .resource       = da830_psc0_resources,
+       .num_resources  = ARRAY_SIZE(da830_psc0_resources),
+};
+
+static struct resource da830_psc1_resources[] = {
+       {
+               .start  = DA8XX_PSC1_BASE,
+               .end    = DA8XX_PSC1_BASE + SZ_4K - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+};
+
+static struct platform_device da830_psc1_device = {
+       .name           = "da830-psc1",
+       .id             = -1,
+       .resource       = da830_psc1_resources,
+       .num_resources  = ARRAY_SIZE(da830_psc1_resources),
+};
+
+void __init da830_register_clocks(void)
+{
+       /* PLL is registered in da830_init_time() */
+       platform_device_register(&da830_psc0_device);
+       platform_device_register(&da830_psc1_device);
 }
index 34117e6..4528bbf 100644 (file)
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
+
+#include <linux/clk-provider.h>
+#include <linux/clk/davinci.h>
 #include <linux/clkdev.h>
+#include <linux/cpufreq.h>
 #include <linux/gpio.h>
 #include <linux/init.h>
-#include <linux/clk.h>
+#include <linux/mfd/da8xx-cfgchip.h>
+#include <linux/platform_data/clk-da8xx-cfgchip.h>
+#include <linux/platform_data/clk-davinci-pll.h>
+#include <linux/platform_data/gpio-davinci.h>
 #include <linux/platform_device.h>
-#include <linux/cpufreq.h>
+#include <linux/regmap.h>
 #include <linux/regulator/consumer.h>
-#include <linux/platform_data/gpio-davinci.h>
 
 #include <asm/mach/map.h>
 
-#include "psc.h"
-#include <mach/irqs.h>
-#include <mach/cputype.h>
 #include <mach/common.h>
-#include <mach/time.h>
-#include <mach/da8xx.h>
 #include <mach/cpufreq.h>
+#include <mach/cputype.h>
+#include <mach/da8xx.h>
+#include <mach/irqs.h>
 #include <mach/pm.h>
+#include <mach/time.h>
 
-#include "clock.h"
 #include "mux.h"
 
 #define DA850_PLL1_BASE                0x01e1a000
 
 #define DA850_REF_FREQ         24000000
 
-#define CFGCHIP3_ASYNC3_CLKSRC BIT(4)
-#define CFGCHIP3_PLL1_MASTER_LOCK      BIT(5)
-#define CFGCHIP0_PLL_MASTER_LOCK       BIT(4)
-
-static int da850_set_armrate(struct clk *clk, unsigned long rate);
-static int da850_round_armrate(struct clk *clk, unsigned long rate);
-static int da850_set_pll0rate(struct clk *clk, unsigned long armrate);
-
-static struct pll_data pll0_data = {
-       .num            = 1,
-       .phys_base      = DA8XX_PLL0_BASE,
-       .flags          = PLL_HAS_PREDIV | PLL_HAS_POSTDIV,
-};
-
-static struct clk ref_clk = {
-       .name           = "ref_clk",
-       .rate           = DA850_REF_FREQ,
-       .set_rate       = davinci_simple_set_rate,
-};
-
-static struct clk pll0_clk = {
-       .name           = "pll0",
-       .parent         = &ref_clk,
-       .pll_data       = &pll0_data,
-       .flags          = CLK_PLL,
-       .set_rate       = da850_set_pll0rate,
-};
-
-static struct clk pll0_aux_clk = {
-       .name           = "pll0_aux_clk",
-       .parent         = &pll0_clk,
-       .flags          = CLK_PLL | PRE_PLL,
-};
-
-static struct clk pll0_sysclk1 = {
-       .name           = "pll0_sysclk1",
-       .parent         = &pll0_clk,
-       .flags          = CLK_PLL,
-       .div_reg        = PLLDIV1,
-};
-
-static struct clk pll0_sysclk2 = {
-       .name           = "pll0_sysclk2",
-       .parent         = &pll0_clk,
-       .flags          = CLK_PLL,
-       .div_reg        = PLLDIV2,
-};
-
-static struct clk pll0_sysclk3 = {
-       .name           = "pll0_sysclk3",
-       .parent         = &pll0_clk,
-       .flags          = CLK_PLL,
-       .div_reg        = PLLDIV3,
-       .set_rate       = davinci_set_sysclk_rate,
-       .maxrate        = 100000000,
-};
-
-static struct clk pll0_sysclk4 = {
-       .name           = "pll0_sysclk4",
-       .parent         = &pll0_clk,
-       .flags          = CLK_PLL,
-       .div_reg        = PLLDIV4,
-};
-
-static struct clk pll0_sysclk5 = {
-       .name           = "pll0_sysclk5",
-       .parent         = &pll0_clk,
-       .flags          = CLK_PLL,
-       .div_reg        = PLLDIV5,
-};
-
-static struct clk pll0_sysclk6 = {
-       .name           = "pll0_sysclk6",
-       .parent         = &pll0_clk,
-       .flags          = CLK_PLL,
-       .div_reg        = PLLDIV6,
-};
-
-static struct clk pll0_sysclk7 = {
-       .name           = "pll0_sysclk7",
-       .parent         = &pll0_clk,
-       .flags          = CLK_PLL,
-       .div_reg        = PLLDIV7,
-};
-
-static struct pll_data pll1_data = {
-       .num            = 2,
-       .phys_base      = DA850_PLL1_BASE,
-       .flags          = PLL_HAS_POSTDIV,
-};
-
-static struct clk pll1_clk = {
-       .name           = "pll1",
-       .parent         = &ref_clk,
-       .pll_data       = &pll1_data,
-       .flags          = CLK_PLL,
-};
-
-static struct clk pll1_aux_clk = {
-       .name           = "pll1_aux_clk",
-       .parent         = &pll1_clk,
-       .flags          = CLK_PLL | PRE_PLL,
-};
-
-static struct clk pll1_sysclk2 = {
-       .name           = "pll1_sysclk2",
-       .parent         = &pll1_clk,
-       .flags          = CLK_PLL,
-       .div_reg        = PLLDIV2,
-};
-
-static struct clk pll1_sysclk3 = {
-       .name           = "pll1_sysclk3",
-       .parent         = &pll1_clk,
-       .flags          = CLK_PLL,
-       .div_reg        = PLLDIV3,
-};
-
-static int da850_async3_set_parent(struct clk *clk, struct clk *parent)
-{
-       u32 val;
-
-       val = readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP3_REG));
-
-       if (parent == &pll0_sysclk2) {
-               val &= ~CFGCHIP3_ASYNC3_CLKSRC;
-       } else if (parent == &pll1_sysclk2) {
-               val |= CFGCHIP3_ASYNC3_CLKSRC;
-       } else {
-               pr_err("Bad parent on async3 clock mux\n");
-               return -EINVAL;
-       }
-
-       writel(val, DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP3_REG));
-
-       return 0;
-}
-
-static struct clk async3_clk = {
-       .name           = "async3",
-       .parent         = &pll1_sysclk2,
-       .set_parent     = da850_async3_set_parent,
-};
-
-static struct clk i2c0_clk = {
-       .name           = "i2c0",
-       .parent         = &pll0_aux_clk,
-};
-
-static struct clk timerp64_0_clk = {
-       .name           = "timer0",
-       .parent         = &pll0_aux_clk,
-};
-
-static struct clk timerp64_1_clk = {
-       .name           = "timer1",
-       .parent         = &pll0_aux_clk,
-};
-
-static struct clk arm_rom_clk = {
-       .name           = "arm_rom",
-       .parent         = &pll0_sysclk2,
-       .lpsc           = DA8XX_LPSC0_ARM_RAM_ROM,
-       .flags          = ALWAYS_ENABLED,
-};
-
-static struct clk tpcc0_clk = {
-       .name           = "tpcc0",
-       .parent         = &pll0_sysclk2,
-       .lpsc           = DA8XX_LPSC0_TPCC,
-       .flags          = ALWAYS_ENABLED | CLK_PSC,
-};
-
-static struct clk tptc0_clk = {
-       .name           = "tptc0",
-       .parent         = &pll0_sysclk2,
-       .lpsc           = DA8XX_LPSC0_TPTC0,
-       .flags          = ALWAYS_ENABLED,
-};
-
-static struct clk tptc1_clk = {
-       .name           = "tptc1",
-       .parent         = &pll0_sysclk2,
-       .lpsc           = DA8XX_LPSC0_TPTC1,
-       .flags          = ALWAYS_ENABLED,
-};
-
-static struct clk tpcc1_clk = {
-       .name           = "tpcc1",
-       .parent         = &pll0_sysclk2,
-       .lpsc           = DA850_LPSC1_TPCC1,
-       .gpsc           = 1,
-       .flags          = CLK_PSC | ALWAYS_ENABLED,
-};
-
-static struct clk tptc2_clk = {
-       .name           = "tptc2",
-       .parent         = &pll0_sysclk2,
-       .lpsc           = DA850_LPSC1_TPTC2,
-       .gpsc           = 1,
-       .flags          = ALWAYS_ENABLED,
-};
-
-static struct clk pruss_clk = {
-       .name           = "pruss",
-       .parent         = &pll0_sysclk2,
-       .lpsc           = DA8XX_LPSC0_PRUSS,
-};
-
-static struct clk uart0_clk = {
-       .name           = "uart0",
-       .parent         = &pll0_sysclk2,
-       .lpsc           = DA8XX_LPSC0_UART0,
-};
-
-static struct clk uart1_clk = {
-       .name           = "uart1",
-       .parent         = &async3_clk,
-       .lpsc           = DA8XX_LPSC1_UART1,
-       .gpsc           = 1,
-};
-
-static struct clk uart2_clk = {
-       .name           = "uart2",
-       .parent         = &async3_clk,
-       .lpsc           = DA8XX_LPSC1_UART2,
-       .gpsc           = 1,
-};
-
-static struct clk aintc_clk = {
-       .name           = "aintc",
-       .parent         = &pll0_sysclk4,
-       .lpsc           = DA8XX_LPSC0_AINTC,
-       .flags          = ALWAYS_ENABLED,
-};
-
-static struct clk gpio_clk = {
-       .name           = "gpio",
-       .parent         = &pll0_sysclk4,
-       .lpsc           = DA8XX_LPSC1_GPIO,
-       .gpsc           = 1,
-};
-
-static struct clk i2c1_clk = {
-       .name           = "i2c1",
-       .parent         = &pll0_sysclk4,
-       .lpsc           = DA8XX_LPSC1_I2C,
-       .gpsc           = 1,
-};
-
-static struct clk emif3_clk = {
-       .name           = "emif3",
-       .parent         = &pll0_sysclk5,
-       .lpsc           = DA8XX_LPSC1_EMIF3C,
-       .gpsc           = 1,
-       .flags          = ALWAYS_ENABLED,
-};
-
-static struct clk arm_clk = {
-       .name           = "arm",
-       .parent         = &pll0_sysclk6,
-       .lpsc           = DA8XX_LPSC0_ARM,
-       .flags          = ALWAYS_ENABLED,
-       .set_rate       = da850_set_armrate,
-       .round_rate     = da850_round_armrate,
-};
-
-static struct clk rmii_clk = {
-       .name           = "rmii",
-       .parent         = &pll0_sysclk7,
-};
-
-static struct clk emac_clk = {
-       .name           = "emac",
-       .parent         = &pll0_sysclk4,
-       .lpsc           = DA8XX_LPSC1_CPGMAC,
-       .gpsc           = 1,
-};
-
-/*
- * In order to avoid adding the emac_clk to the clock lookup table twice (and
- * screwing up the linked list in the process) create a separate clock for
- * mdio inheriting the rate from emac_clk.
- */
-static struct clk mdio_clk = {
-       .name           = "mdio",
-       .parent         = &emac_clk,
-};
-
-static struct clk mcasp_clk = {
-       .name           = "mcasp",
-       .parent         = &async3_clk,
-       .lpsc           = DA8XX_LPSC1_McASP0,
-       .gpsc           = 1,
-};
-
-static struct clk mcbsp0_clk = {
-       .name           = "mcbsp0",
-       .parent         = &async3_clk,
-       .lpsc           = DA850_LPSC1_McBSP0,
-       .gpsc           = 1,
-};
-
-static struct clk mcbsp1_clk = {
-       .name           = "mcbsp1",
-       .parent         = &async3_clk,
-       .lpsc           = DA850_LPSC1_McBSP1,
-       .gpsc           = 1,
-};
-
-static struct clk lcdc_clk = {
-       .name           = "lcdc",
-       .parent         = &pll0_sysclk2,
-       .lpsc           = DA8XX_LPSC1_LCDC,
-       .gpsc           = 1,
-};
-
-static struct clk mmcsd0_clk = {
-       .name           = "mmcsd0",
-       .parent         = &pll0_sysclk2,
-       .lpsc           = DA8XX_LPSC0_MMC_SD,
-};
-
-static struct clk mmcsd1_clk = {
-       .name           = "mmcsd1",
-       .parent         = &pll0_sysclk2,
-       .lpsc           = DA850_LPSC1_MMC_SD1,
-       .gpsc           = 1,
-};
-
-static struct clk aemif_clk = {
-       .name           = "aemif",
-       .parent         = &pll0_sysclk3,
-       .lpsc           = DA8XX_LPSC0_EMIF25,
-       .flags          = ALWAYS_ENABLED,
-};
-
-/*
- * In order to avoid adding the aemif_clk to the clock lookup table twice (and
- * screwing up the linked list in the process) create a separate clock for
- * nand inheriting the rate from aemif_clk.
- */
-static struct clk aemif_nand_clk = {
-       .name           = "nand",
-       .parent         = &aemif_clk,
-};
-
-static struct clk usb11_clk = {
-       .name           = "usb11",
-       .parent         = &pll0_sysclk4,
-       .lpsc           = DA8XX_LPSC1_USB11,
-       .gpsc           = 1,
-};
-
-static struct clk usb20_clk = {
-       .name           = "usb20",
-       .parent         = &pll0_sysclk2,
-       .lpsc           = DA8XX_LPSC1_USB20,
-       .gpsc           = 1,
-};
-
-static struct clk cppi41_clk = {
-       .name           = "cppi41",
-       .parent         = &usb20_clk,
-};
-
-static struct clk spi0_clk = {
-       .name           = "spi0",
-       .parent         = &pll0_sysclk2,
-       .lpsc           = DA8XX_LPSC0_SPI0,
-};
-
-static struct clk spi1_clk = {
-       .name           = "spi1",
-       .parent         = &async3_clk,
-       .lpsc           = DA8XX_LPSC1_SPI1,
-       .gpsc           = 1,
-};
-
-static struct clk vpif_clk = {
-       .name           = "vpif",
-       .parent         = &pll0_sysclk2,
-       .lpsc           = DA850_LPSC1_VPIF,
-       .gpsc           = 1,
-};
-
-static struct clk sata_clk = {
-       .name           = "sata",
-       .parent         = &pll0_sysclk2,
-       .lpsc           = DA850_LPSC1_SATA,
-       .gpsc           = 1,
-       .flags          = PSC_FORCE,
-};
-
-static struct clk dsp_clk = {
-       .name           = "dsp",
-       .parent         = &pll0_sysclk1,
-       .domain         = DAVINCI_GPSC_DSPDOMAIN,
-       .lpsc           = DA8XX_LPSC0_GEM,
-       .flags          = PSC_LRST | PSC_FORCE,
-};
-
-static struct clk ehrpwm_clk = {
-       .name           = "ehrpwm",
-       .parent         = &async3_clk,
-       .lpsc           = DA8XX_LPSC1_PWM,
-       .gpsc           = 1,
-};
-
-static struct clk ehrpwm0_clk = {
-       .name           = "ehrpwm0",
-       .parent         = &ehrpwm_clk,
-};
-
-static struct clk ehrpwm1_clk = {
-       .name           = "ehrpwm1",
-       .parent         = &ehrpwm_clk,
-};
-
-#define DA8XX_EHRPWM_TBCLKSYNC BIT(12)
-
-static void ehrpwm_tblck_enable(struct clk *clk)
-{
-       u32 val;
-
-       val = readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP1_REG));
-       val |= DA8XX_EHRPWM_TBCLKSYNC;
-       writel(val, DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP1_REG));
-}
-
-static void ehrpwm_tblck_disable(struct clk *clk)
-{
-       u32 val;
-
-       val = readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP1_REG));
-       val &= ~DA8XX_EHRPWM_TBCLKSYNC;
-       writel(val, DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP1_REG));
-}
-
-static struct clk ehrpwm_tbclk = {
-       .name           = "ehrpwm_tbclk",
-       .parent         = &ehrpwm_clk,
-       .clk_enable     = ehrpwm_tblck_enable,
-       .clk_disable    = ehrpwm_tblck_disable,
-};
-
-static struct clk ehrpwm0_tbclk = {
-       .name           = "ehrpwm0_tbclk",
-       .parent         = &ehrpwm_tbclk,
-};
-
-static struct clk ehrpwm1_tbclk = {
-       .name           = "ehrpwm1_tbclk",
-       .parent         = &ehrpwm_tbclk,
-};
-
-static struct clk ecap_clk = {
-       .name           = "ecap",
-       .parent         = &async3_clk,
-       .lpsc           = DA8XX_LPSC1_ECAP,
-       .gpsc           = 1,
-};
-
-static struct clk ecap0_clk = {
-       .name           = "ecap0_clk",
-       .parent         = &ecap_clk,
-};
-
-static struct clk ecap1_clk = {
-       .name           = "ecap1_clk",
-       .parent         = &ecap_clk,
-};
-
-static struct clk ecap2_clk = {
-       .name           = "ecap2_clk",
-       .parent         = &ecap_clk,
-};
-
-static struct clk_lookup da850_clks[] = {
-       CLK(NULL,               "ref",          &ref_clk),
-       CLK(NULL,               "pll0",         &pll0_clk),
-       CLK(NULL,               "pll0_aux",     &pll0_aux_clk),
-       CLK(NULL,               "pll0_sysclk1", &pll0_sysclk1),
-       CLK(NULL,               "pll0_sysclk2", &pll0_sysclk2),
-       CLK(NULL,               "pll0_sysclk3", &pll0_sysclk3),
-       CLK(NULL,               "pll0_sysclk4", &pll0_sysclk4),
-       CLK(NULL,               "pll0_sysclk5", &pll0_sysclk5),
-       CLK(NULL,               "pll0_sysclk6", &pll0_sysclk6),
-       CLK(NULL,               "pll0_sysclk7", &pll0_sysclk7),
-       CLK(NULL,               "pll1",         &pll1_clk),
-       CLK(NULL,               "pll1_aux",     &pll1_aux_clk),
-       CLK(NULL,               "pll1_sysclk2", &pll1_sysclk2),
-       CLK(NULL,               "pll1_sysclk3", &pll1_sysclk3),
-       CLK(NULL,               "async3",       &async3_clk),
-       CLK("i2c_davinci.1",    NULL,           &i2c0_clk),
-       CLK(NULL,               "timer0",       &timerp64_0_clk),
-       CLK("davinci-wdt",      NULL,           &timerp64_1_clk),
-       CLK(NULL,               "arm_rom",      &arm_rom_clk),
-       CLK(NULL,               "tpcc0",        &tpcc0_clk),
-       CLK(NULL,               "tptc0",        &tptc0_clk),
-       CLK(NULL,               "tptc1",        &tptc1_clk),
-       CLK(NULL,               "tpcc1",        &tpcc1_clk),
-       CLK(NULL,               "tptc2",        &tptc2_clk),
-       CLK("pruss_uio",        "pruss",        &pruss_clk),
-       CLK("serial8250.0",     NULL,           &uart0_clk),
-       CLK("serial8250.1",     NULL,           &uart1_clk),
-       CLK("serial8250.2",     NULL,           &uart2_clk),
-       CLK(NULL,               "aintc",        &aintc_clk),
-       CLK(NULL,               "gpio",         &gpio_clk),
-       CLK("i2c_davinci.2",    NULL,           &i2c1_clk),
-       CLK(NULL,               "emif3",        &emif3_clk),
-       CLK(NULL,               "arm",          &arm_clk),
-       CLK(NULL,               "rmii",         &rmii_clk),
-       CLK("davinci_emac.1",   NULL,           &emac_clk),
-       CLK("davinci_mdio.0",   "fck",          &mdio_clk),
-       CLK("davinci-mcasp.0",  NULL,           &mcasp_clk),
-       CLK("davinci-mcbsp.0",  NULL,           &mcbsp0_clk),
-       CLK("davinci-mcbsp.1",  NULL,           &mcbsp1_clk),
-       CLK("da8xx_lcdc.0",     "fck",          &lcdc_clk),
-       CLK("da830-mmc.0",      NULL,           &mmcsd0_clk),
-       CLK("da830-mmc.1",      NULL,           &mmcsd1_clk),
-       CLK("ti-aemif",         NULL,           &aemif_clk),
-       CLK("davinci-nand.0",   "aemif",        &aemif_nand_clk),
-       CLK("ohci-da8xx",       NULL,           &usb11_clk),
-       CLK("musb-da8xx",       NULL,           &usb20_clk),
-       CLK("cppi41-dmaengine", NULL,           &cppi41_clk),
-       CLK("spi_davinci.0",    NULL,           &spi0_clk),
-       CLK("spi_davinci.1",    NULL,           &spi1_clk),
-       CLK("vpif",             NULL,           &vpif_clk),
-       CLK("ahci_da850",       "fck",          &sata_clk),
-       CLK("davinci-rproc.0",  NULL,           &dsp_clk),
-       CLK(NULL,               NULL,           &ehrpwm_clk),
-       CLK("ehrpwm.0",         "fck",          &ehrpwm0_clk),
-       CLK("ehrpwm.1",         "fck",          &ehrpwm1_clk),
-       CLK(NULL,               NULL,           &ehrpwm_tbclk),
-       CLK("ehrpwm.0",         "tbclk",        &ehrpwm0_tbclk),
-       CLK("ehrpwm.1",         "tbclk",        &ehrpwm1_tbclk),
-       CLK(NULL,               NULL,           &ecap_clk),
-       CLK("ecap.0",           "fck",          &ecap0_clk),
-       CLK("ecap.1",           "fck",          &ecap1_clk),
-       CLK("ecap.2",           "fck",          &ecap2_clk),
-       CLK(NULL,               NULL,           NULL),
-};
-
 /*
  * Device specific mux setup
  *
@@ -958,8 +418,6 @@ static struct map_desc da850_io_desc[] = {
        },
 };
 
-static u32 da850_psc_bases[] = { DA8XX_PSC0_BASE, DA8XX_PSC1_BASE };
-
 /* Contents of JTAG ID register used to identify exact cpu type */
 static struct davinci_id da850_ids[] = {
        {
@@ -1169,89 +627,11 @@ int da850_register_cpufreq(char *async_clk)
 
        return platform_device_register(&da850_cpufreq_device);
 }
-
-static int da850_round_armrate(struct clk *clk, unsigned long rate)
-{
-       int ret = 0, diff;
-       unsigned int best = (unsigned int) -1;
-       struct cpufreq_frequency_table *table = cpufreq_info.freq_table;
-       struct cpufreq_frequency_table *pos;
-
-       rate /= 1000; /* convert to kHz */
-
-       cpufreq_for_each_entry(pos, table) {
-               diff = pos->frequency - rate;
-               if (diff < 0)
-                       diff = -diff;
-
-               if (diff < best) {
-                       best = diff;
-                       ret = pos->frequency;
-               }
-       }
-
-       return ret * 1000;
-}
-
-static int da850_set_armrate(struct clk *clk, unsigned long index)
-{
-       struct clk *pllclk = &pll0_clk;
-
-       return clk_set_rate(pllclk, index);
-}
-
-static int da850_set_pll0rate(struct clk *clk, unsigned long rate)
-{
-       struct pll_data *pll = clk->pll_data;
-       struct cpufreq_frequency_table *freq;
-       unsigned int prediv, mult, postdiv;
-       struct da850_opp *opp = NULL;
-       int ret;
-
-       rate /= 1000;
-
-       for (freq = da850_freq_table;
-            freq->frequency != CPUFREQ_TABLE_END; freq++) {
-               /* rate is in Hz, freq->frequency is in KHz */
-               if (freq->frequency == rate) {
-                       opp = (struct da850_opp *)freq->driver_data;
-                       break;
-               }
-       }
-
-       if (!opp)
-               return -EINVAL;
-
-       prediv = opp->prediv;
-       mult = opp->mult;
-       postdiv = opp->postdiv;
-
-       ret = davinci_set_pllrate(pll, prediv, mult, postdiv);
-       if (WARN_ON(ret))
-               return ret;
-
-       return 0;
-}
 #else
 int __init da850_register_cpufreq(char *async_clk)
 {
        return 0;
 }
-
-static int da850_set_armrate(struct clk *clk, unsigned long rate)
-{
-       return -EINVAL;
-}
-
-static int da850_set_pll0rate(struct clk *clk, unsigned long armrate)
-{
-       return -EINVAL;
-}
-
-static int da850_round_armrate(struct clk *clk, unsigned long rate)
-{
-       return clk->rate;
-}
 #endif
 
 /* VPIF resource, platform data */
@@ -1353,8 +733,6 @@ static const struct davinci_soc_info davinci_soc_info_da850 = {
        .jtag_id_reg            = DA8XX_SYSCFG0_BASE + DA8XX_JTAG_ID_REG,
        .ids                    = da850_ids,
        .ids_num                = ARRAY_SIZE(da850_ids),
-       .psc_bases              = da850_psc_bases,
-       .psc_bases_num          = ARRAY_SIZE(da850_psc_bases),
        .pinmux_base            = DA8XX_SYSCFG0_BASE + 0x120,
        .pinmux_pins            = da850_pins,
        .pinmux_pins_num        = ARRAY_SIZE(da850_pins),
@@ -1370,8 +748,6 @@ static const struct davinci_soc_info davinci_soc_info_da850 = {
 
 void __init da850_init(void)
 {
-       unsigned int v;
-
        davinci_common_init(&davinci_soc_info_da850);
 
        da8xx_syscfg0_base = ioremap(DA8XX_SYSCFG0_BASE, SZ_4K);
@@ -1379,22 +755,124 @@ void __init da850_init(void)
                return;
 
        da8xx_syscfg1_base = ioremap(DA8XX_SYSCFG1_BASE, SZ_4K);
-       if (WARN(!da8xx_syscfg1_base, "Unable to map syscfg1 module"))
-               return;
+       WARN(!da8xx_syscfg1_base, "Unable to map syscfg1 module");
+}
+
+void __init da850_init_time(void)
+{
+       void __iomem *pll0;
+       struct regmap *cfgchip;
+       struct clk *clk;
 
-       /* Unlock writing to PLL0 registers */
-       v = __raw_readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP0_REG));
-       v &= ~CFGCHIP0_PLL_MASTER_LOCK;
-       __raw_writel(v, DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP0_REG));
+       clk_register_fixed_rate(NULL, "ref_clk", NULL, 0, DA850_REF_FREQ);
 
-       /* Unlock writing to PLL1 registers */
-       v = __raw_readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP3_REG));
-       v &= ~CFGCHIP3_PLL1_MASTER_LOCK;
-       __raw_writel(v, DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP3_REG));
+       pll0 = ioremap(DA8XX_PLL0_BASE, SZ_4K);
+       cfgchip = da8xx_get_cfgchip();
+
+       da850_pll0_init(NULL, pll0, cfgchip);
+
+       clk = clk_get(NULL, "timer0");
+
+       davinci_timer_init(clk);
 }
 
-void __init da850_init_time(void)
+static struct resource da850_pll1_resources[] = {
+       {
+               .start  = DA850_PLL1_BASE,
+               .end    = DA850_PLL1_BASE + SZ_4K - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+};
+
+static struct davinci_pll_platform_data da850_pll1_pdata;
+
+static struct platform_device da850_pll1_device = {
+       .name           = "da850-pll1",
+       .id             = -1,
+       .resource       = da850_pll1_resources,
+       .num_resources  = ARRAY_SIZE(da850_pll1_resources),
+       .dev            = {
+               .platform_data  = &da850_pll1_pdata,
+       },
+};
+
+static struct resource da850_psc0_resources[] = {
+       {
+               .start  = DA8XX_PSC0_BASE,
+               .end    = DA8XX_PSC0_BASE + SZ_4K - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+};
+
+static struct platform_device da850_psc0_device = {
+       .name           = "da850-psc0",
+       .id             = -1,
+       .resource       = da850_psc0_resources,
+       .num_resources  = ARRAY_SIZE(da850_psc0_resources),
+};
+
+static struct resource da850_psc1_resources[] = {
+       {
+               .start  = DA8XX_PSC1_BASE,
+               .end    = DA8XX_PSC1_BASE + SZ_4K - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+};
+
+static struct platform_device da850_psc1_device = {
+       .name           = "da850-psc1",
+       .id             = -1,
+       .resource       = da850_psc1_resources,
+       .num_resources  = ARRAY_SIZE(da850_psc1_resources),
+};
+
+static struct da8xx_cfgchip_clk_platform_data da850_async1_pdata;
+
+static struct platform_device da850_async1_clksrc_device = {
+       .name           = "da850-async1-clksrc",
+       .id             = -1,
+       .dev            = {
+               .platform_data  = &da850_async1_pdata,
+       },
+};
+
+static struct da8xx_cfgchip_clk_platform_data da850_async3_pdata;
+
+static struct platform_device da850_async3_clksrc_device = {
+       .name           = "da850-async3-clksrc",
+       .id             = -1,
+       .dev            = {
+               .platform_data  = &da850_async3_pdata,
+       },
+};
+
+static struct da8xx_cfgchip_clk_platform_data da850_tbclksync_pdata;
+
+static struct platform_device da850_tbclksync_device = {
+       .name           = "da830-tbclksync",
+       .id             = -1,
+       .dev            = {
+               .platform_data  = &da850_tbclksync_pdata,
+       },
+};
+
+void __init da850_register_clocks(void)
 {
-       davinci_clk_init(da850_clks);
-       davinci_timer_init();
+       /* PLL0 is registered in da850_init_time() */
+
+       da850_pll1_pdata.cfgchip = da8xx_get_cfgchip();
+       platform_device_register(&da850_pll1_device);
+
+       da850_async1_pdata.cfgchip = da8xx_get_cfgchip();
+       platform_device_register(&da850_async1_clksrc_device);
+
+       da850_async3_pdata.cfgchip = da8xx_get_cfgchip();
+       platform_device_register(&da850_async3_clksrc_device);
+
+       platform_device_register(&da850_psc0_device);
+
+       platform_device_register(&da850_psc1_device);
+
+       da850_tbclksync_pdata.cfgchip = da8xx_get_cfgchip();
+       platform_device_register(&da850_tbclksync_device);
 }
index ab199f4..beac80e 100644 (file)
@@ -7,81 +7,16 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-#include <linux/io.h>
-#include <linux/of_irq.h>
-#include <linux/of_platform.h>
-#include <linux/irqdomain.h>
-#include <linux/platform_data/ti-aemif.h>
 
 #include <asm/mach/arch.h>
 
 #include <mach/common.h>
-#include "cp_intc.h"
 #include <mach/da8xx.h>
 
-static struct of_dev_auxdata da850_aemif_auxdata_lookup[] = {
-       OF_DEV_AUXDATA("ti,davinci-nand", 0x62000000, "davinci-nand.0", NULL),
-       {}
-};
-
-static struct aemif_platform_data aemif_data = {
-       .dev_lookup = da850_aemif_auxdata_lookup,
-};
-
-static struct of_dev_auxdata da850_auxdata_lookup[] __initdata = {
-       OF_DEV_AUXDATA("ti,davinci-i2c", 0x01c22000, "i2c_davinci.1", NULL),
-       OF_DEV_AUXDATA("ti,davinci-i2c", 0x01e28000, "i2c_davinci.2", NULL),
-       OF_DEV_AUXDATA("ti,davinci-wdt", 0x01c21000, "davinci-wdt", NULL),
-       OF_DEV_AUXDATA("ti,da830-mmc", 0x01c40000, "da830-mmc.0", NULL),
-       OF_DEV_AUXDATA("ti,da850-ehrpwm", 0x01f00000, "ehrpwm.0", NULL),
-       OF_DEV_AUXDATA("ti,da850-ehrpwm", 0x01f02000, "ehrpwm.1", NULL),
-       OF_DEV_AUXDATA("ti,da850-ecap", 0x01f06000, "ecap.0", NULL),
-       OF_DEV_AUXDATA("ti,da850-ecap", 0x01f07000, "ecap.1", NULL),
-       OF_DEV_AUXDATA("ti,da850-ecap", 0x01f08000, "ecap.2", NULL),
-       OF_DEV_AUXDATA("ti,da830-spi", 0x01c41000, "spi_davinci.0", NULL),
-       OF_DEV_AUXDATA("ti,da830-spi", 0x01f0e000, "spi_davinci.1", NULL),
-       OF_DEV_AUXDATA("ns16550a", 0x01c42000, "serial8250.0", NULL),
-       OF_DEV_AUXDATA("ns16550a", 0x01d0c000, "serial8250.1", NULL),
-       OF_DEV_AUXDATA("ns16550a", 0x01d0d000, "serial8250.2", NULL),
-       OF_DEV_AUXDATA("ti,davinci_mdio", 0x01e24000, "davinci_mdio.0", NULL),
-       OF_DEV_AUXDATA("ti,davinci-dm6467-emac", 0x01e20000, "davinci_emac.1",
-                      NULL),
-       OF_DEV_AUXDATA("ti,da830-mcasp-audio", 0x01d00000, "davinci-mcasp.0", NULL),
-       OF_DEV_AUXDATA("ti,da850-aemif", 0x68000000, "ti-aemif", &aemif_data),
-       OF_DEV_AUXDATA("ti,da850-tilcdc", 0x01e13000, "da8xx_lcdc.0", NULL),
-       OF_DEV_AUXDATA("ti,da830-ohci", 0x01e25000, "ohci-da8xx", NULL),
-       OF_DEV_AUXDATA("ti,da830-musb", 0x01e00000, "musb-da8xx", NULL),
-       OF_DEV_AUXDATA("ti,da830-usb-phy", 0x01c1417c, "da8xx-usb-phy", NULL),
-       OF_DEV_AUXDATA("ti,da850-ahci", 0x01e18000, "ahci_da850", NULL),
-       OF_DEV_AUXDATA("ti,da850-vpif", 0x01e17000, "vpif", NULL),
-       OF_DEV_AUXDATA("ti,da850-dsp", 0x11800000, "davinci-rproc.0", NULL),
-       {}
-};
-
 #ifdef CONFIG_ARCH_DAVINCI_DA850
 
 static void __init da850_init_machine(void)
 {
-       /* All existing boards use 100MHz SATA refclkpn */
-       static const unsigned long sata_refclkpn = 100 * 1000 * 1000;
-
-       int ret;
-
-       ret = da8xx_register_usb20_phy_clk(false);
-       if (ret)
-               pr_warn("%s: registering USB 2.0 PHY clock failed: %d",
-                       __func__, ret);
-       ret = da8xx_register_usb11_phy_clk(false);
-       if (ret)
-               pr_warn("%s: registering USB 1.1 PHY clock failed: %d",
-                       __func__, ret);
-
-       ret = da850_register_sata_refclk(sata_refclkpn);
-       if (ret)
-               pr_warn("%s: registering SATA REFCLK failed: %d",
-                       __func__, ret);
-
-       of_platform_default_populate(NULL, da850_auxdata_lookup, NULL);
        davinci_pm_init();
        pdata_quirks_init();
 }
@@ -96,7 +31,6 @@ static const char *const da850_boards_compat[] __initconst = {
 
 DT_MACHINE_START(DA850_DT, "Generic DA850/OMAP-L138/AM18x")
        .map_io         = da850_init,
-       .init_time      = da850_init_time,
        .init_machine   = da850_init_machine,
        .dt_compat      = da850_boards_compat,
        .init_late      = davinci_init_late,
index 376cdd5..db4c95e 100644 (file)
 #include <media/davinci/vpbe.h>
 #include <media/davinci/vpbe_osd.h>
 
+#define DAVINCI_PLL1_BASE              0x01c40800
+#define DAVINCI_PLL2_BASE              0x01c40c00
+#define DAVINCI_PWR_SLEEP_CNTRL_BASE   0x01c41000
+
 #define DAVINCI_SYSTEM_MODULE_BASE     0x01c40000
 #define SYSMOD_VDAC_CONFIG             0x2c
 #define SYSMOD_VIDCLKCTL               0x38
@@ -84,6 +88,7 @@ int davinci_init_wdt(void);
 /* DM355 function declarations */
 void dm355_init(void);
 void dm355_init_time(void);
+void dm355_register_clocks(void);
 void dm355_init_spi0(unsigned chipselect_mask,
                const struct spi_board_info *info, unsigned len);
 void dm355_init_asp1(u32 evt_enable);
@@ -93,6 +98,7 @@ int dm355_gpio_register(void);
 /* DM365 function declarations */
 void dm365_init(void);
 void dm365_init_time(void);
+void dm365_register_clocks(void);
 void dm365_init_asp(void);
 void dm365_init_vc(void);
 void dm365_init_ks(struct davinci_ks_platform_data *pdata);
@@ -106,6 +112,7 @@ int dm365_gpio_register(void);
 void dm644x_init(void);
 void dm644x_init_devices(void);
 void dm644x_init_time(void);
+void dm644x_register_clocks(void);
 void dm644x_init_asp(void);
 int dm644x_init_video(struct vpfe_config *, struct vpbe_config *);
 int dm644x_gpio_register(void);
@@ -113,6 +120,7 @@ int dm644x_gpio_register(void);
 /* DM646x function declarations */
 void dm646x_init(void);
 void dm646x_init_time(unsigned long ref_clk_rate, unsigned long aux_clkin_rate);
+void dm646x_register_clocks(void);
 void dm646x_init_mcasp0(struct snd_platform_data *pdata);
 void dm646x_init_mcasp1(struct snd_platform_data *pdata);
 int dm646x_init_edma(struct edma_rsv_info *rsv);
index 78390c6..1fd3619 100644 (file)
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version.
  */
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/dma-contiguous.h>
-#include <linux/serial_8250.h>
 #include <linux/ahci_platform.h>
+#include <linux/clk-provider.h>
 #include <linux/clk.h>
-#include <linux/reboot.h>
+#include <linux/clkdev.h>
+#include <linux/dma-contiguous.h>
 #include <linux/dmaengine.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/reboot.h>
+#include <linux/serial_8250.h>
 
-#include <mach/cputype.h>
 #include <mach/common.h>
-#include <mach/time.h>
+#include <mach/cputype.h>
 #include <mach/da8xx.h>
-#include <mach/clock.h>
-#include "cpuidle.h"
-#include "sram.h"
+#include <mach/time.h>
 
-#include "clock.h"
 #include "asp.h"
+#include "cpuidle.h"
+#include "sram.h"
 
 #define DA8XX_TPCC_BASE                        0x01c00000
 #define DA8XX_TPTC0_BASE               0x01c08000
@@ -1040,26 +1040,15 @@ int __init da8xx_register_spi_bus(int instance, unsigned num_chipselect)
 }
 
 #ifdef CONFIG_ARCH_DAVINCI_DA850
-static struct clk sata_refclk = {
-       .name           = "sata_refclk",
-       .set_rate       = davinci_simple_set_rate,
-};
-
-static struct clk_lookup sata_refclk_lookup =
-               CLK("ahci_da850", "refclk", &sata_refclk);
-
 int __init da850_register_sata_refclk(int rate)
 {
-       int ret;
-
-       sata_refclk.rate = rate;
-       ret = clk_register(&sata_refclk);
-       if (ret)
-               return ret;
+       struct clk *clk;
 
-       clkdev_add(&sata_refclk_lookup);
+       clk = clk_register_fixed_rate(NULL, "sata_refclk", NULL, 0, rate);
+       if (IS_ERR(clk))
+               return PTR_ERR(clk);
 
-       return 0;
+       return clk_register_clkdev(clk, "refclk", "ahci_da850");
 }
 
 static struct resource da850_sata_resources[] = {
index 0edda40..e8dbbb7 100644 (file)
@@ -26,7 +26,6 @@
 
 
 #include "davinci.h"
-#include "clock.h"
 
 #define DAVINCI_I2C_BASE            0x01C21000
 #define DAVINCI_ATA_BASE            0x01C66000
index f294804..9f7d38d 100644 (file)
@@ -8,31 +8,32 @@
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
-#include <linux/init.h>
-#include <linux/clk.h>
-#include <linux/serial_8250.h>
-#include <linux/platform_device.h>
+
+#include <linux/clk-provider.h>
+#include <linux/clk/davinci.h>
+#include <linux/clkdev.h>
 #include <linux/dma-mapping.h>
 #include <linux/dmaengine.h>
-#include <linux/spi/spi.h>
+#include <linux/init.h>
 #include <linux/platform_data/edma.h>
 #include <linux/platform_data/gpio-davinci.h>
 #include <linux/platform_data/spi-davinci.h>
+#include <linux/platform_device.h>
+#include <linux/serial_8250.h>
+#include <linux/spi/spi.h>
 
 #include <asm/mach/map.h>
 
+#include <mach/common.h>
 #include <mach/cputype.h>
-#include "psc.h"
-#include <mach/mux.h>
 #include <mach/irqs.h>
-#include <mach/time.h>
+#include <mach/mux.h>
 #include <mach/serial.h>
-#include <mach/common.h>
+#include <mach/time.h>
 
+#include "asp.h"
 #include "davinci.h"
-#include "clock.h"
 #include "mux.h"
-#include "asp.h"
 
 #define DM355_UART2_BASE       (IO_PHYS + 0x206000)
 #define DM355_OSD_BASE         (IO_PHYS + 0x70200)
  */
 #define DM355_REF_FREQ         24000000        /* 24 or 36 MHz */
 
-static struct pll_data pll1_data = {
-       .num       = 1,
-       .phys_base = DAVINCI_PLL1_BASE,
-       .flags     = PLL_HAS_PREDIV | PLL_HAS_POSTDIV,
-};
-
-static struct pll_data pll2_data = {
-       .num       = 2,
-       .phys_base = DAVINCI_PLL2_BASE,
-       .flags     = PLL_HAS_PREDIV,
-};
-
-static struct clk ref_clk = {
-       .name = "ref_clk",
-       /* FIXME -- crystal rate is board-specific */
-       .rate = DM355_REF_FREQ,
-};
-
-static struct clk pll1_clk = {
-       .name = "pll1",
-       .parent = &ref_clk,
-       .flags = CLK_PLL,
-       .pll_data = &pll1_data,
-};
-
-static struct clk pll1_aux_clk = {
-       .name = "pll1_aux_clk",
-       .parent = &pll1_clk,
-       .flags = CLK_PLL | PRE_PLL,
-};
-
-static struct clk pll1_sysclk1 = {
-       .name = "pll1_sysclk1",
-       .parent = &pll1_clk,
-       .flags = CLK_PLL,
-       .div_reg = PLLDIV1,
-};
-
-static struct clk pll1_sysclk2 = {
-       .name = "pll1_sysclk2",
-       .parent = &pll1_clk,
-       .flags = CLK_PLL,
-       .div_reg = PLLDIV2,
-};
-
-static struct clk pll1_sysclk3 = {
-       .name = "pll1_sysclk3",
-       .parent = &pll1_clk,
-       .flags = CLK_PLL,
-       .div_reg = PLLDIV3,
-};
-
-static struct clk pll1_sysclk4 = {
-       .name = "pll1_sysclk4",
-       .parent = &pll1_clk,
-       .flags = CLK_PLL,
-       .div_reg = PLLDIV4,
-};
-
-static struct clk pll1_sysclkbp = {
-       .name = "pll1_sysclkbp",
-       .parent = &pll1_clk,
-       .flags = CLK_PLL | PRE_PLL,
-       .div_reg = BPDIV
-};
-
-static struct clk vpss_dac_clk = {
-       .name = "vpss_dac",
-       .parent = &pll1_sysclk3,
-       .lpsc = DM355_LPSC_VPSS_DAC,
-};
-
-static struct clk vpss_master_clk = {
-       .name = "vpss_master",
-       .parent = &pll1_sysclk4,
-       .lpsc = DAVINCI_LPSC_VPSSMSTR,
-       .flags = CLK_PSC,
-};
-
-static struct clk vpss_slave_clk = {
-       .name = "vpss_slave",
-       .parent = &pll1_sysclk4,
-       .lpsc = DAVINCI_LPSC_VPSSSLV,
-};
-
-static struct clk clkout1_clk = {
-       .name = "clkout1",
-       .parent = &pll1_aux_clk,
-       /* NOTE:  clkout1 can be externally gated by muxing GPIO-18 */
-};
-
-static struct clk clkout2_clk = {
-       .name = "clkout2",
-       .parent = &pll1_sysclkbp,
-};
-
-static struct clk pll2_clk = {
-       .name = "pll2",
-       .parent = &ref_clk,
-       .flags = CLK_PLL,
-       .pll_data = &pll2_data,
-};
-
-static struct clk pll2_sysclk1 = {
-       .name = "pll2_sysclk1",
-       .parent = &pll2_clk,
-       .flags = CLK_PLL,
-       .div_reg = PLLDIV1,
-};
-
-static struct clk pll2_sysclkbp = {
-       .name = "pll2_sysclkbp",
-       .parent = &pll2_clk,
-       .flags = CLK_PLL | PRE_PLL,
-       .div_reg = BPDIV
-};
-
-static struct clk clkout3_clk = {
-       .name = "clkout3",
-       .parent = &pll2_sysclkbp,
-       /* NOTE:  clkout3 can be externally gated by muxing GPIO-16 */
-};
-
-static struct clk arm_clk = {
-       .name = "arm_clk",
-       .parent = &pll1_sysclk1,
-       .lpsc = DAVINCI_LPSC_ARM,
-       .flags = ALWAYS_ENABLED,
-};
-
-/*
- * NOT LISTED below, and not touched by Linux
- *   - in SyncReset state by default
- *     .lpsc = DAVINCI_LPSC_TPCC,
- *     .lpsc = DAVINCI_LPSC_TPTC0,
- *     .lpsc = DAVINCI_LPSC_TPTC1,
- *     .lpsc = DAVINCI_LPSC_DDR_EMIF, .parent = &sysclk2_clk,
- *     .lpsc = DAVINCI_LPSC_MEMSTICK,
- *   - in Enabled state by default
- *     .lpsc = DAVINCI_LPSC_SYSTEM_SUBSYS,
- *     .lpsc = DAVINCI_LPSC_SCR2,      // "bus"
- *     .lpsc = DAVINCI_LPSC_SCR3,      // "bus"
- *     .lpsc = DAVINCI_LPSC_SCR4,      // "bus"
- *     .lpsc = DAVINCI_LPSC_CROSSBAR,  // "emulation"
- *     .lpsc = DAVINCI_LPSC_CFG27,     // "test"
- *     .lpsc = DAVINCI_LPSC_CFG3,      // "test"
- *     .lpsc = DAVINCI_LPSC_CFG5,      // "test"
- */
-
-static struct clk mjcp_clk = {
-       .name = "mjcp",
-       .parent = &pll1_sysclk1,
-       .lpsc = DAVINCI_LPSC_IMCOP,
-};
-
-static struct clk uart0_clk = {
-       .name = "uart0",
-       .parent = &pll1_aux_clk,
-       .lpsc = DAVINCI_LPSC_UART0,
-};
-
-static struct clk uart1_clk = {
-       .name = "uart1",
-       .parent = &pll1_aux_clk,
-       .lpsc = DAVINCI_LPSC_UART1,
-};
-
-static struct clk uart2_clk = {
-       .name = "uart2",
-       .parent = &pll1_sysclk2,
-       .lpsc = DAVINCI_LPSC_UART2,
-};
-
-static struct clk i2c_clk = {
-       .name = "i2c",
-       .parent = &pll1_aux_clk,
-       .lpsc = DAVINCI_LPSC_I2C,
-};
-
-static struct clk asp0_clk = {
-       .name = "asp0",
-       .parent = &pll1_sysclk2,
-       .lpsc = DAVINCI_LPSC_McBSP,
-};
-
-static struct clk asp1_clk = {
-       .name = "asp1",
-       .parent = &pll1_sysclk2,
-       .lpsc = DM355_LPSC_McBSP1,
-};
-
-static struct clk mmcsd0_clk = {
-       .name = "mmcsd0",
-       .parent = &pll1_sysclk2,
-       .lpsc = DAVINCI_LPSC_MMC_SD,
-};
-
-static struct clk mmcsd1_clk = {
-       .name = "mmcsd1",
-       .parent = &pll1_sysclk2,
-       .lpsc = DM355_LPSC_MMC_SD1,
-};
-
-static struct clk spi0_clk = {
-       .name = "spi0",
-       .parent = &pll1_sysclk2,
-       .lpsc = DAVINCI_LPSC_SPI,
-};
-
-static struct clk spi1_clk = {
-       .name = "spi1",
-       .parent = &pll1_sysclk2,
-       .lpsc = DM355_LPSC_SPI1,
-};
-
-static struct clk spi2_clk = {
-       .name = "spi2",
-       .parent = &pll1_sysclk2,
-       .lpsc = DM355_LPSC_SPI2,
-};
-
-static struct clk gpio_clk = {
-       .name = "gpio",
-       .parent = &pll1_sysclk2,
-       .lpsc = DAVINCI_LPSC_GPIO,
-};
-
-static struct clk aemif_clk = {
-       .name = "aemif",
-       .parent = &pll1_sysclk2,
-       .lpsc = DAVINCI_LPSC_AEMIF,
-};
-
-static struct clk pwm0_clk = {
-       .name = "pwm0",
-       .parent = &pll1_aux_clk,
-       .lpsc = DAVINCI_LPSC_PWM0,
-};
-
-static struct clk pwm1_clk = {
-       .name = "pwm1",
-       .parent = &pll1_aux_clk,
-       .lpsc = DAVINCI_LPSC_PWM1,
-};
-
-static struct clk pwm2_clk = {
-       .name = "pwm2",
-       .parent = &pll1_aux_clk,
-       .lpsc = DAVINCI_LPSC_PWM2,
-};
-
-static struct clk pwm3_clk = {
-       .name = "pwm3",
-       .parent = &pll1_aux_clk,
-       .lpsc = DM355_LPSC_PWM3,
-};
-
-static struct clk timer0_clk = {
-       .name = "timer0",
-       .parent = &pll1_aux_clk,
-       .lpsc = DAVINCI_LPSC_TIMER0,
-};
-
-static struct clk timer1_clk = {
-       .name = "timer1",
-       .parent = &pll1_aux_clk,
-       .lpsc = DAVINCI_LPSC_TIMER1,
-};
-
-static struct clk timer2_clk = {
-       .name = "timer2",
-       .parent = &pll1_aux_clk,
-       .lpsc = DAVINCI_LPSC_TIMER2,
-       .usecount = 1,              /* REVISIT: why can't this be disabled? */
-};
-
-static struct clk timer3_clk = {
-       .name = "timer3",
-       .parent = &pll1_aux_clk,
-       .lpsc = DM355_LPSC_TIMER3,
-};
-
-static struct clk rto_clk = {
-       .name = "rto",
-       .parent = &pll1_aux_clk,
-       .lpsc = DM355_LPSC_RTO,
-};
-
-static struct clk usb_clk = {
-       .name = "usb",
-       .parent = &pll1_sysclk2,
-       .lpsc = DAVINCI_LPSC_USB,
-};
-
-static struct clk_lookup dm355_clks[] = {
-       CLK(NULL, "ref", &ref_clk),
-       CLK(NULL, "pll1", &pll1_clk),
-       CLK(NULL, "pll1_sysclk1", &pll1_sysclk1),
-       CLK(NULL, "pll1_sysclk2", &pll1_sysclk2),
-       CLK(NULL, "pll1_sysclk3", &pll1_sysclk3),
-       CLK(NULL, "pll1_sysclk4", &pll1_sysclk4),
-       CLK(NULL, "pll1_aux", &pll1_aux_clk),
-       CLK(NULL, "pll1_sysclkbp", &pll1_sysclkbp),
-       CLK(NULL, "vpss_dac", &vpss_dac_clk),
-       CLK("vpss", "master", &vpss_master_clk),
-       CLK("vpss", "slave", &vpss_slave_clk),
-       CLK(NULL, "clkout1", &clkout1_clk),
-       CLK(NULL, "clkout2", &clkout2_clk),
-       CLK(NULL, "pll2", &pll2_clk),
-       CLK(NULL, "pll2_sysclk1", &pll2_sysclk1),
-       CLK(NULL, "pll2_sysclkbp", &pll2_sysclkbp),
-       CLK(NULL, "clkout3", &clkout3_clk),
-       CLK(NULL, "arm", &arm_clk),
-       CLK(NULL, "mjcp", &mjcp_clk),
-       CLK("serial8250.0", NULL, &uart0_clk),
-       CLK("serial8250.1", NULL, &uart1_clk),
-       CLK("serial8250.2", NULL, &uart2_clk),
-       CLK("i2c_davinci.1", NULL, &i2c_clk),
-       CLK("davinci-mcbsp.0", NULL, &asp0_clk),
-       CLK("davinci-mcbsp.1", NULL, &asp1_clk),
-       CLK("dm6441-mmc.0", NULL, &mmcsd0_clk),
-       CLK("dm6441-mmc.1", NULL, &mmcsd1_clk),
-       CLK("spi_davinci.0", NULL, &spi0_clk),
-       CLK("spi_davinci.1", NULL, &spi1_clk),
-       CLK("spi_davinci.2", NULL, &spi2_clk),
-       CLK(NULL, "gpio", &gpio_clk),
-       CLK(NULL, "aemif", &aemif_clk),
-       CLK(NULL, "pwm0", &pwm0_clk),
-       CLK(NULL, "pwm1", &pwm1_clk),
-       CLK(NULL, "pwm2", &pwm2_clk),
-       CLK(NULL, "pwm3", &pwm3_clk),
-       CLK(NULL, "timer0", &timer0_clk),
-       CLK(NULL, "timer1", &timer1_clk),
-       CLK("davinci-wdt", NULL, &timer2_clk),
-       CLK(NULL, "timer3", &timer3_clk),
-       CLK(NULL, "rto", &rto_clk),
-       CLK(NULL, "usb", &usb_clk),
-       CLK(NULL, NULL, NULL),
-};
-
-/*----------------------------------------------------------------------*/
-
 static u64 dm355_spi0_dma_mask = DMA_BIT_MASK(32);
 
 static struct resource dm355_spi0_resources[] = {
@@ -926,8 +585,6 @@ static struct davinci_id dm355_ids[] = {
        },
 };
 
-static u32 dm355_psc_bases[] = { DAVINCI_PWR_SLEEP_CNTRL_BASE };
-
 /*
  * T0_BOT: Timer 0, bottom:  clockevent source for hrtimers
  * T0_TOP: Timer 0, top   :  clocksource for generic timekeeping
@@ -1012,8 +669,6 @@ static const struct davinci_soc_info davinci_soc_info_dm355 = {
        .jtag_id_reg            = 0x01c40028,
        .ids                    = dm355_ids,
        .ids_num                = ARRAY_SIZE(dm355_ids),
-       .psc_bases              = dm355_psc_bases,
-       .psc_bases_num          = ARRAY_SIZE(dm355_psc_bases),
        .pinmux_base            = DAVINCI_SYSTEM_MODULE_BASE,
        .pinmux_pins            = dm355_pins,
        .pinmux_pins_num        = ARRAY_SIZE(dm355_pins),
@@ -1046,8 +701,41 @@ void __init dm355_init(void)
 
 void __init dm355_init_time(void)
 {
-       davinci_clk_init(dm355_clks);
-       davinci_timer_init();
+       void __iomem *pll1, *psc;
+       struct clk *clk;
+
+       clk_register_fixed_rate(NULL, "ref_clk", NULL, 0, DM355_REF_FREQ);
+
+       pll1 = ioremap(DAVINCI_PLL1_BASE, SZ_1K);
+       dm355_pll1_init(NULL, pll1, NULL);
+
+       psc = ioremap(DAVINCI_PWR_SLEEP_CNTRL_BASE, SZ_4K);
+       dm355_psc_init(NULL, psc);
+
+       clk = clk_get(NULL, "timer0");
+
+       davinci_timer_init(clk);
+}
+
+static struct resource dm355_pll2_resources[] = {
+       {
+               .start  = DAVINCI_PLL2_BASE,
+               .end    = DAVINCI_PLL2_BASE + SZ_1K - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+};
+
+static struct platform_device dm355_pll2_device = {
+       .name           = "dm355-pll2",
+       .id             = -1,
+       .resource       = dm355_pll2_resources,
+       .num_resources  = ARRAY_SIZE(dm355_pll2_resources),
+};
+
+void __init dm355_register_clocks(void)
+{
+       /* PLL1 and PSC are registered in dm355_init_time() */
+       platform_device_register(&dm355_pll2_device);
 }
 
 int __init dm355_init_video(struct vpfe_config *vpfe_cfg,
index 1e3df9d..abcf2a5 100644 (file)
  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  */
-#include <linux/init.h>
-#include <linux/clk.h>
-#include <linux/serial_8250.h>
-#include <linux/platform_device.h>
+
+#include <linux/clk-provider.h>
+#include <linux/clk/davinci.h>
+#include <linux/clkdev.h>
 #include <linux/dma-mapping.h>
 #include <linux/dmaengine.h>
-#include <linux/spi/spi.h>
+#include <linux/init.h>
 #include <linux/platform_data/edma.h>
 #include <linux/platform_data/gpio-davinci.h>
 #include <linux/platform_data/keyscan-davinci.h>
 #include <linux/platform_data/spi-davinci.h>
+#include <linux/platform_device.h>
+#include <linux/serial_8250.h>
+#include <linux/spi/spi.h>
 
 #include <asm/mach/map.h>
 
+#include <mach/common.h>
 #include <mach/cputype.h>
-#include "psc.h"
-#include <mach/mux.h>
 #include <mach/irqs.h>
-#include <mach/time.h>
+#include <mach/mux.h>
 #include <mach/serial.h>
-#include <mach/common.h>
+#include <mach/time.h>
 
+#include "asp.h"
 #include "davinci.h"
-#include "clock.h"
 #include "mux.h"
-#include "asp.h"
 
 #define DM365_REF_FREQ         24000000        /* 24 MHz on the DM365 EVM */
 #define DM365_RTC_BASE                 0x01c69000
 #define DM365_EMAC_CNTRL_RAM_OFFSET    0x1000
 #define DM365_EMAC_CNTRL_RAM_SIZE      0x2000
 
-static struct pll_data pll1_data = {
-       .num            = 1,
-       .phys_base      = DAVINCI_PLL1_BASE,
-       .flags          = PLL_HAS_POSTDIV | PLL_HAS_PREDIV,
-};
-
-static struct pll_data pll2_data = {
-       .num            = 2,
-       .phys_base      = DAVINCI_PLL2_BASE,
-       .flags          = PLL_HAS_POSTDIV | PLL_HAS_PREDIV,
-};
-
-static struct clk ref_clk = {
-       .name           = "ref_clk",
-       .rate           = DM365_REF_FREQ,
-};
-
-static struct clk pll1_clk = {
-       .name           = "pll1",
-       .parent         = &ref_clk,
-       .flags          = CLK_PLL,
-       .pll_data       = &pll1_data,
-};
-
-static struct clk pll1_aux_clk = {
-       .name           = "pll1_aux_clk",
-       .parent         = &pll1_clk,
-       .flags          = CLK_PLL | PRE_PLL,
-};
-
-static struct clk pll1_sysclkbp = {
-       .name           = "pll1_sysclkbp",
-       .parent         = &pll1_clk,
-       .flags          = CLK_PLL | PRE_PLL,
-       .div_reg        = BPDIV
-};
-
-static struct clk clkout0_clk = {
-       .name           = "clkout0",
-       .parent         = &pll1_clk,
-       .flags          = CLK_PLL | PRE_PLL,
-};
-
-static struct clk pll1_sysclk1 = {
-       .name           = "pll1_sysclk1",
-       .parent         = &pll1_clk,
-       .flags          = CLK_PLL,
-       .div_reg        = PLLDIV1,
-};
-
-static struct clk pll1_sysclk2 = {
-       .name           = "pll1_sysclk2",
-       .parent         = &pll1_clk,
-       .flags          = CLK_PLL,
-       .div_reg        = PLLDIV2,
-};
-
-static struct clk pll1_sysclk3 = {
-       .name           = "pll1_sysclk3",
-       .parent         = &pll1_clk,
-       .flags          = CLK_PLL,
-       .div_reg        = PLLDIV3,
-};
-
-static struct clk pll1_sysclk4 = {
-       .name           = "pll1_sysclk4",
-       .parent         = &pll1_clk,
-       .flags          = CLK_PLL,
-       .div_reg        = PLLDIV4,
-};
-
-static struct clk pll1_sysclk5 = {
-       .name           = "pll1_sysclk5",
-       .parent         = &pll1_clk,
-       .flags          = CLK_PLL,
-       .div_reg        = PLLDIV5,
-};
-
-static struct clk pll1_sysclk6 = {
-       .name           = "pll1_sysclk6",
-       .parent         = &pll1_clk,
-       .flags          = CLK_PLL,
-       .div_reg        = PLLDIV6,
-};
-
-static struct clk pll1_sysclk7 = {
-       .name           = "pll1_sysclk7",
-       .parent         = &pll1_clk,
-       .flags          = CLK_PLL,
-       .div_reg        = PLLDIV7,
-};
-
-static struct clk pll1_sysclk8 = {
-       .name           = "pll1_sysclk8",
-       .parent         = &pll1_clk,
-       .flags          = CLK_PLL,
-       .div_reg        = PLLDIV8,
-};
-
-static struct clk pll1_sysclk9 = {
-       .name           = "pll1_sysclk9",
-       .parent         = &pll1_clk,
-       .flags          = CLK_PLL,
-       .div_reg        = PLLDIV9,
-};
-
-static struct clk pll2_clk = {
-       .name           = "pll2",
-       .parent         = &ref_clk,
-       .flags          = CLK_PLL,
-       .pll_data       = &pll2_data,
-};
-
-static struct clk pll2_aux_clk = {
-       .name           = "pll2_aux_clk",
-       .parent         = &pll2_clk,
-       .flags          = CLK_PLL | PRE_PLL,
-};
-
-static struct clk clkout1_clk = {
-       .name           = "clkout1",
-       .parent         = &pll2_clk,
-       .flags          = CLK_PLL | PRE_PLL,
-};
-
-static struct clk pll2_sysclk1 = {
-       .name           = "pll2_sysclk1",
-       .parent         = &pll2_clk,
-       .flags          = CLK_PLL,
-       .div_reg        = PLLDIV1,
-};
-
-static struct clk pll2_sysclk2 = {
-       .name           = "pll2_sysclk2",
-       .parent         = &pll2_clk,
-       .flags          = CLK_PLL,
-       .div_reg        = PLLDIV2,
-};
-
-static struct clk pll2_sysclk3 = {
-       .name           = "pll2_sysclk3",
-       .parent         = &pll2_clk,
-       .flags          = CLK_PLL,
-       .div_reg        = PLLDIV3,
-};
-
-static struct clk pll2_sysclk4 = {
-       .name           = "pll2_sysclk4",
-       .parent         = &pll2_clk,
-       .flags          = CLK_PLL,
-       .div_reg        = PLLDIV4,
-};
-
-static struct clk pll2_sysclk5 = {
-       .name           = "pll2_sysclk5",
-       .parent         = &pll2_clk,
-       .flags          = CLK_PLL,
-       .div_reg        = PLLDIV5,
-};
-
-static struct clk pll2_sysclk6 = {
-       .name           = "pll2_sysclk6",
-       .parent         = &pll2_clk,
-       .flags          = CLK_PLL,
-       .div_reg        = PLLDIV6,
-};
-
-static struct clk pll2_sysclk7 = {
-       .name           = "pll2_sysclk7",
-       .parent         = &pll2_clk,
-       .flags          = CLK_PLL,
-       .div_reg        = PLLDIV7,
-};
-
-static struct clk pll2_sysclk8 = {
-       .name           = "pll2_sysclk8",
-       .parent         = &pll2_clk,
-       .flags          = CLK_PLL,
-       .div_reg        = PLLDIV8,
-};
-
-static struct clk pll2_sysclk9 = {
-       .name           = "pll2_sysclk9",
-       .parent         = &pll2_clk,
-       .flags          = CLK_PLL,
-       .div_reg        = PLLDIV9,
-};
-
-static struct clk vpss_dac_clk = {
-       .name           = "vpss_dac",
-       .parent         = &pll1_sysclk3,
-       .lpsc           = DM365_LPSC_DAC_CLK,
-};
-
-static struct clk vpss_master_clk = {
-       .name           = "vpss_master",
-       .parent         = &pll1_sysclk5,
-       .lpsc           = DM365_LPSC_VPSSMSTR,
-       .flags          = CLK_PSC,
-};
-
-static struct clk vpss_slave_clk = {
-       .name           = "vpss_slave",
-       .parent         = &pll1_sysclk5,
-       .lpsc           = DAVINCI_LPSC_VPSSSLV,
-};
-
-static struct clk arm_clk = {
-       .name           = "arm_clk",
-       .parent         = &pll2_sysclk2,
-       .lpsc           = DAVINCI_LPSC_ARM,
-       .flags          = ALWAYS_ENABLED,
-};
-
-static struct clk uart0_clk = {
-       .name           = "uart0",
-       .parent         = &pll1_aux_clk,
-       .lpsc           = DAVINCI_LPSC_UART0,
-};
-
-static struct clk uart1_clk = {
-       .name           = "uart1",
-       .parent         = &pll1_sysclk4,
-       .lpsc           = DAVINCI_LPSC_UART1,
-};
-
-static struct clk i2c_clk = {
-       .name           = "i2c",
-       .parent         = &pll1_aux_clk,
-       .lpsc           = DAVINCI_LPSC_I2C,
-};
-
-static struct clk mmcsd0_clk = {
-       .name           = "mmcsd0",
-       .parent         = &pll1_sysclk8,
-       .lpsc           = DAVINCI_LPSC_MMC_SD,
-};
-
-static struct clk mmcsd1_clk = {
-       .name           = "mmcsd1",
-       .parent         = &pll1_sysclk4,
-       .lpsc           = DM365_LPSC_MMC_SD1,
-};
-
-static struct clk spi0_clk = {
-       .name           = "spi0",
-       .parent         = &pll1_sysclk4,
-       .lpsc           = DAVINCI_LPSC_SPI,
-};
-
-static struct clk spi1_clk = {
-       .name           = "spi1",
-       .parent         = &pll1_sysclk4,
-       .lpsc           = DM365_LPSC_SPI1,
-};
-
-static struct clk spi2_clk = {
-       .name           = "spi2",
-       .parent         = &pll1_sysclk4,
-       .lpsc           = DM365_LPSC_SPI2,
-};
-
-static struct clk spi3_clk = {
-       .name           = "spi3",
-       .parent         = &pll1_sysclk4,
-       .lpsc           = DM365_LPSC_SPI3,
-};
-
-static struct clk spi4_clk = {
-       .name           = "spi4",
-       .parent         = &pll1_aux_clk,
-       .lpsc           = DM365_LPSC_SPI4,
-};
-
-static struct clk gpio_clk = {
-       .name           = "gpio",
-       .parent         = &pll1_sysclk4,
-       .lpsc           = DAVINCI_LPSC_GPIO,
-};
-
-static struct clk aemif_clk = {
-       .name           = "aemif",
-       .parent         = &pll1_sysclk4,
-       .lpsc           = DAVINCI_LPSC_AEMIF,
-};
-
-static struct clk pwm0_clk = {
-       .name           = "pwm0",
-       .parent         = &pll1_aux_clk,
-       .lpsc           = DAVINCI_LPSC_PWM0,
-};
-
-static struct clk pwm1_clk = {
-       .name           = "pwm1",
-       .parent         = &pll1_aux_clk,
-       .lpsc           = DAVINCI_LPSC_PWM1,
-};
-
-static struct clk pwm2_clk = {
-       .name           = "pwm2",
-       .parent         = &pll1_aux_clk,
-       .lpsc           = DAVINCI_LPSC_PWM2,
-};
-
-static struct clk pwm3_clk = {
-       .name           = "pwm3",
-       .parent         = &ref_clk,
-       .lpsc           = DM365_LPSC_PWM3,
-};
-
-static struct clk timer0_clk = {
-       .name           = "timer0",
-       .parent         = &pll1_aux_clk,
-       .lpsc           = DAVINCI_LPSC_TIMER0,
-};
-
-static struct clk timer1_clk = {
-       .name           = "timer1",
-       .parent         = &pll1_aux_clk,
-       .lpsc           = DAVINCI_LPSC_TIMER1,
-};
-
-static struct clk timer2_clk = {
-       .name           = "timer2",
-       .parent         = &pll1_aux_clk,
-       .lpsc           = DAVINCI_LPSC_TIMER2,
-       .usecount       = 1,
-};
-
-static struct clk timer3_clk = {
-       .name           = "timer3",
-       .parent         = &pll1_aux_clk,
-       .lpsc           = DM365_LPSC_TIMER3,
-};
-
-static struct clk usb_clk = {
-       .name           = "usb",
-       .parent         = &pll1_aux_clk,
-       .lpsc           = DAVINCI_LPSC_USB,
-};
-
-static struct clk emac_clk = {
-       .name           = "emac",
-       .parent         = &pll1_sysclk4,
-       .lpsc           = DM365_LPSC_EMAC,
-};
-
-static struct clk voicecodec_clk = {
-       .name           = "voice_codec",
-       .parent         = &pll2_sysclk4,
-       .lpsc           = DM365_LPSC_VOICE_CODEC,
-};
-
-static struct clk asp0_clk = {
-       .name           = "asp0",
-       .parent         = &pll1_sysclk4,
-       .lpsc           = DM365_LPSC_McBSP1,
-};
-
-static struct clk rto_clk = {
-       .name           = "rto",
-       .parent         = &pll1_sysclk4,
-       .lpsc           = DM365_LPSC_RTO,
-};
-
-static struct clk mjcp_clk = {
-       .name           = "mjcp",
-       .parent         = &pll1_sysclk3,
-       .lpsc           = DM365_LPSC_MJCP,
-};
-
-static struct clk_lookup dm365_clks[] = {
-       CLK(NULL, "ref", &ref_clk),
-       CLK(NULL, "pll1", &pll1_clk),
-       CLK(NULL, "pll1_aux", &pll1_aux_clk),
-       CLK(NULL, "pll1_sysclkbp", &pll1_sysclkbp),
-       CLK(NULL, "clkout0", &clkout0_clk),
-       CLK(NULL, "pll1_sysclk1", &pll1_sysclk1),
-       CLK(NULL, "pll1_sysclk2", &pll1_sysclk2),
-       CLK(NULL, "pll1_sysclk3", &pll1_sysclk3),
-       CLK(NULL, "pll1_sysclk4", &pll1_sysclk4),
-       CLK(NULL, "pll1_sysclk5", &pll1_sysclk5),
-       CLK(NULL, "pll1_sysclk6", &pll1_sysclk6),
-       CLK(NULL, "pll1_sysclk7", &pll1_sysclk7),
-       CLK(NULL, "pll1_sysclk8", &pll1_sysclk8),
-       CLK(NULL, "pll1_sysclk9", &pll1_sysclk9),
-       CLK(NULL, "pll2", &pll2_clk),
-       CLK(NULL, "pll2_aux", &pll2_aux_clk),
-       CLK(NULL, "clkout1", &clkout1_clk),
-       CLK(NULL, "pll2_sysclk1", &pll2_sysclk1),
-       CLK(NULL, "pll2_sysclk2", &pll2_sysclk2),
-       CLK(NULL, "pll2_sysclk3", &pll2_sysclk3),
-       CLK(NULL, "pll2_sysclk4", &pll2_sysclk4),
-       CLK(NULL, "pll2_sysclk5", &pll2_sysclk5),
-       CLK(NULL, "pll2_sysclk6", &pll2_sysclk6),
-       CLK(NULL, "pll2_sysclk7", &pll2_sysclk7),
-       CLK(NULL, "pll2_sysclk8", &pll2_sysclk8),
-       CLK(NULL, "pll2_sysclk9", &pll2_sysclk9),
-       CLK(NULL, "vpss_dac", &vpss_dac_clk),
-       CLK("vpss", "master", &vpss_master_clk),
-       CLK("vpss", "slave", &vpss_slave_clk),
-       CLK(NULL, "arm", &arm_clk),
-       CLK("serial8250.0", NULL, &uart0_clk),
-       CLK("serial8250.1", NULL, &uart1_clk),
-       CLK("i2c_davinci.1", NULL, &i2c_clk),
-       CLK("da830-mmc.0", NULL, &mmcsd0_clk),
-       CLK("da830-mmc.1", NULL, &mmcsd1_clk),
-       CLK("spi_davinci.0", NULL, &spi0_clk),
-       CLK("spi_davinci.1", NULL, &spi1_clk),
-       CLK("spi_davinci.2", NULL, &spi2_clk),
-       CLK("spi_davinci.3", NULL, &spi3_clk),
-       CLK("spi_davinci.4", NULL, &spi4_clk),
-       CLK(NULL, "gpio", &gpio_clk),
-       CLK(NULL, "aemif", &aemif_clk),
-       CLK(NULL, "pwm0", &pwm0_clk),
-       CLK(NULL, "pwm1", &pwm1_clk),
-       CLK(NULL, "pwm2", &pwm2_clk),
-       CLK(NULL, "pwm3", &pwm3_clk),
-       CLK(NULL, "timer0", &timer0_clk),
-       CLK(NULL, "timer1", &timer1_clk),
-       CLK("davinci-wdt", NULL, &timer2_clk),
-       CLK(NULL, "timer3", &timer3_clk),
-       CLK(NULL, "usb", &usb_clk),
-       CLK("davinci_emac.1", NULL, &emac_clk),
-       CLK("davinci_mdio.0", "fck", &emac_clk),
-       CLK("davinci_voicecodec", NULL, &voicecodec_clk),
-       CLK("davinci-mcbsp", NULL, &asp0_clk),
-       CLK(NULL, "rto", &rto_clk),
-       CLK(NULL, "mjcp", &mjcp_clk),
-       CLK(NULL, NULL, NULL),
-};
-
-/*----------------------------------------------------------------------*/
-
 #define INTMUX         0x18
 #define EVTMUX         0x1c
 
@@ -1054,8 +621,6 @@ static struct davinci_id dm365_ids[] = {
        },
 };
 
-static u32 dm365_psc_bases[] = { DAVINCI_PWR_SLEEP_CNTRL_BASE };
-
 static struct davinci_timer_info dm365_timer_info = {
        .timers         = davinci_timer_instance,
        .clockevent_id  = T0_BOT,
@@ -1116,8 +681,6 @@ static const struct davinci_soc_info davinci_soc_info_dm365 = {
        .jtag_id_reg            = 0x01c40028,
        .ids                    = dm365_ids,
        .ids_num                = ARRAY_SIZE(dm365_ids),
-       .psc_bases              = dm365_psc_bases,
-       .psc_bases_num          = ARRAY_SIZE(dm365_psc_bases),
        .pinmux_base            = DAVINCI_SYSTEM_MODULE_BASE,
        .pinmux_pins            = dm365_pins,
        .pinmux_pins_num        = ARRAY_SIZE(dm365_pins),
@@ -1171,8 +734,28 @@ void __init dm365_init(void)
 
 void __init dm365_init_time(void)
 {
-       davinci_clk_init(dm365_clks);
-       davinci_timer_init();
+       void __iomem *pll1, *pll2, *psc;
+       struct clk *clk;
+
+       clk_register_fixed_rate(NULL, "ref_clk", NULL, 0, DM365_REF_FREQ);
+
+       pll1 = ioremap(DAVINCI_PLL1_BASE, SZ_1K);
+       dm365_pll1_init(NULL, pll1, NULL);
+
+       pll2 = ioremap(DAVINCI_PLL2_BASE, SZ_1K);
+       dm365_pll2_init(NULL, pll2, NULL);
+
+       psc = ioremap(DAVINCI_PWR_SLEEP_CNTRL_BASE, SZ_4K);
+       dm365_psc_init(NULL, psc);
+
+       clk = clk_get(NULL, "timer0");
+
+       davinci_timer_init(clk);
+}
+
+void __init dm365_register_clocks(void)
+{
+       /* all clocks are currently registered in dm365_init_time() */
 }
 
 static struct resource dm365_vpss_resources[] = {
index a2e8586..0720da7 100644 (file)
@@ -8,28 +8,29 @@
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
-#include <linux/init.h>
-#include <linux/clk.h>
-#include <linux/serial_8250.h>
+
+#include <linux/clk-provider.h>
+#include <linux/clk/davinci.h>
+#include <linux/clkdev.h>
 #include <linux/dmaengine.h>
-#include <linux/platform_device.h>
+#include <linux/init.h>
 #include <linux/platform_data/edma.h>
 #include <linux/platform_data/gpio-davinci.h>
+#include <linux/platform_device.h>
+#include <linux/serial_8250.h>
 
 #include <asm/mach/map.h>
 
+#include <mach/common.h>
 #include <mach/cputype.h>
 #include <mach/irqs.h>
-#include "psc.h"
 #include <mach/mux.h>
-#include <mach/time.h>
 #include <mach/serial.h>
-#include <mach/common.h>
+#include <mach/time.h>
 
+#include "asp.h"
 #include "davinci.h"
-#include "clock.h"
 #include "mux.h"
-#include "asp.h"
 
 /*
  * Device specific clocks
 #define DM644X_EMAC_CNTRL_RAM_OFFSET   0x2000
 #define DM644X_EMAC_CNTRL_RAM_SIZE     0x2000
 
-static struct pll_data pll1_data = {
-       .num       = 1,
-       .phys_base = DAVINCI_PLL1_BASE,
-};
-
-static struct pll_data pll2_data = {
-       .num       = 2,
-       .phys_base = DAVINCI_PLL2_BASE,
-};
-
-static struct clk ref_clk = {
-       .name = "ref_clk",
-       .rate = DM644X_REF_FREQ,
-};
-
-static struct clk pll1_clk = {
-       .name = "pll1",
-       .parent = &ref_clk,
-       .pll_data = &pll1_data,
-       .flags = CLK_PLL,
-};
-
-static struct clk pll1_sysclk1 = {
-       .name = "pll1_sysclk1",
-       .parent = &pll1_clk,
-       .flags = CLK_PLL,
-       .div_reg = PLLDIV1,
-};
-
-static struct clk pll1_sysclk2 = {
-       .name = "pll1_sysclk2",
-       .parent = &pll1_clk,
-       .flags = CLK_PLL,
-       .div_reg = PLLDIV2,
-};
-
-static struct clk pll1_sysclk3 = {
-       .name = "pll1_sysclk3",
-       .parent = &pll1_clk,
-       .flags = CLK_PLL,
-       .div_reg = PLLDIV3,
-};
-
-static struct clk pll1_sysclk5 = {
-       .name = "pll1_sysclk5",
-       .parent = &pll1_clk,
-       .flags = CLK_PLL,
-       .div_reg = PLLDIV5,
-};
-
-static struct clk pll1_aux_clk = {
-       .name = "pll1_aux_clk",
-       .parent = &pll1_clk,
-       .flags = CLK_PLL | PRE_PLL,
-};
-
-static struct clk pll1_sysclkbp = {
-       .name = "pll1_sysclkbp",
-       .parent = &pll1_clk,
-       .flags = CLK_PLL | PRE_PLL,
-       .div_reg = BPDIV
-};
-
-static struct clk pll2_clk = {
-       .name = "pll2",
-       .parent = &ref_clk,
-       .pll_data = &pll2_data,
-       .flags = CLK_PLL,
-};
-
-static struct clk pll2_sysclk1 = {
-       .name = "pll2_sysclk1",
-       .parent = &pll2_clk,
-       .flags = CLK_PLL,
-       .div_reg = PLLDIV1,
-};
-
-static struct clk pll2_sysclk2 = {
-       .name = "pll2_sysclk2",
-       .parent = &pll2_clk,
-       .flags = CLK_PLL,
-       .div_reg = PLLDIV2,
-};
-
-static struct clk pll2_sysclkbp = {
-       .name = "pll2_sysclkbp",
-       .parent = &pll2_clk,
-       .flags = CLK_PLL | PRE_PLL,
-       .div_reg = BPDIV
-};
-
-static struct clk dsp_clk = {
-       .name = "dsp",
-       .parent = &pll1_sysclk1,
-       .lpsc = DAVINCI_LPSC_GEM,
-       .domain = DAVINCI_GPSC_DSPDOMAIN,
-       .usecount = 1,                  /* REVISIT how to disable? */
-};
-
-static struct clk arm_clk = {
-       .name = "arm",
-       .parent = &pll1_sysclk2,
-       .lpsc = DAVINCI_LPSC_ARM,
-       .flags = ALWAYS_ENABLED,
-};
-
-static struct clk vicp_clk = {
-       .name = "vicp",
-       .parent = &pll1_sysclk2,
-       .lpsc = DAVINCI_LPSC_IMCOP,
-       .domain = DAVINCI_GPSC_DSPDOMAIN,
-       .usecount = 1,                  /* REVISIT how to disable? */
-};
-
-static struct clk vpss_master_clk = {
-       .name = "vpss_master",
-       .parent = &pll1_sysclk3,
-       .lpsc = DAVINCI_LPSC_VPSSMSTR,
-       .flags = CLK_PSC,
-};
-
-static struct clk vpss_slave_clk = {
-       .name = "vpss_slave",
-       .parent = &pll1_sysclk3,
-       .lpsc = DAVINCI_LPSC_VPSSSLV,
-};
-
-static struct clk uart0_clk = {
-       .name = "uart0",
-       .parent = &pll1_aux_clk,
-       .lpsc = DAVINCI_LPSC_UART0,
-};
-
-static struct clk uart1_clk = {
-       .name = "uart1",
-       .parent = &pll1_aux_clk,
-       .lpsc = DAVINCI_LPSC_UART1,
-};
-
-static struct clk uart2_clk = {
-       .name = "uart2",
-       .parent = &pll1_aux_clk,
-       .lpsc = DAVINCI_LPSC_UART2,
-};
-
-static struct clk emac_clk = {
-       .name = "emac",
-       .parent = &pll1_sysclk5,
-       .lpsc = DAVINCI_LPSC_EMAC_WRAPPER,
-};
-
-static struct clk i2c_clk = {
-       .name = "i2c",
-       .parent = &pll1_aux_clk,
-       .lpsc = DAVINCI_LPSC_I2C,
-};
-
-static struct clk ide_clk = {
-       .name = "ide",
-       .parent = &pll1_sysclk5,
-       .lpsc = DAVINCI_LPSC_ATA,
-};
-
-static struct clk asp_clk = {
-       .name = "asp0",
-       .parent = &pll1_sysclk5,
-       .lpsc = DAVINCI_LPSC_McBSP,
-};
-
-static struct clk mmcsd_clk = {
-       .name = "mmcsd",
-       .parent = &pll1_sysclk5,
-       .lpsc = DAVINCI_LPSC_MMC_SD,
-};
-
-static struct clk spi_clk = {
-       .name = "spi",
-       .parent = &pll1_sysclk5,
-       .lpsc = DAVINCI_LPSC_SPI,
-};
-
-static struct clk gpio_clk = {
-       .name = "gpio",
-       .parent = &pll1_sysclk5,
-       .lpsc = DAVINCI_LPSC_GPIO,
-};
-
-static struct clk usb_clk = {
-       .name = "usb",
-       .parent = &pll1_sysclk5,
-       .lpsc = DAVINCI_LPSC_USB,
-};
-
-static struct clk vlynq_clk = {
-       .name = "vlynq",
-       .parent = &pll1_sysclk5,
-       .lpsc = DAVINCI_LPSC_VLYNQ,
-};
-
-static struct clk aemif_clk = {
-       .name = "aemif",
-       .parent = &pll1_sysclk5,
-       .lpsc = DAVINCI_LPSC_AEMIF,
-};
-
-static struct clk pwm0_clk = {
-       .name = "pwm0",
-       .parent = &pll1_aux_clk,
-       .lpsc = DAVINCI_LPSC_PWM0,
-};
-
-static struct clk pwm1_clk = {
-       .name = "pwm1",
-       .parent = &pll1_aux_clk,
-       .lpsc = DAVINCI_LPSC_PWM1,
-};
-
-static struct clk pwm2_clk = {
-       .name = "pwm2",
-       .parent = &pll1_aux_clk,
-       .lpsc = DAVINCI_LPSC_PWM2,
-};
-
-static struct clk timer0_clk = {
-       .name = "timer0",
-       .parent = &pll1_aux_clk,
-       .lpsc = DAVINCI_LPSC_TIMER0,
-};
-
-static struct clk timer1_clk = {
-       .name = "timer1",
-       .parent = &pll1_aux_clk,
-       .lpsc = DAVINCI_LPSC_TIMER1,
-};
-
-static struct clk timer2_clk = {
-       .name = "timer2",
-       .parent = &pll1_aux_clk,
-       .lpsc = DAVINCI_LPSC_TIMER2,
-       .usecount = 1,              /* REVISIT: why can't this be disabled? */
-};
-
-static struct clk_lookup dm644x_clks[] = {
-       CLK(NULL, "ref", &ref_clk),
-       CLK(NULL, "pll1", &pll1_clk),
-       CLK(NULL, "pll1_sysclk1", &pll1_sysclk1),
-       CLK(NULL, "pll1_sysclk2", &pll1_sysclk2),
-       CLK(NULL, "pll1_sysclk3", &pll1_sysclk3),
-       CLK(NULL, "pll1_sysclk5", &pll1_sysclk5),
-       CLK(NULL, "pll1_aux", &pll1_aux_clk),
-       CLK(NULL, "pll1_sysclkbp", &pll1_sysclkbp),
-       CLK(NULL, "pll2", &pll2_clk),
-       CLK(NULL, "pll2_sysclk1", &pll2_sysclk1),
-       CLK(NULL, "pll2_sysclk2", &pll2_sysclk2),
-       CLK(NULL, "pll2_sysclkbp", &pll2_sysclkbp),
-       CLK(NULL, "dsp", &dsp_clk),
-       CLK(NULL, "arm", &arm_clk),
-       CLK(NULL, "vicp", &vicp_clk),
-       CLK("vpss", "master", &vpss_master_clk),
-       CLK("vpss", "slave", &vpss_slave_clk),
-       CLK(NULL, "arm", &arm_clk),
-       CLK("serial8250.0", NULL, &uart0_clk),
-       CLK("serial8250.1", NULL, &uart1_clk),
-       CLK("serial8250.2", NULL, &uart2_clk),
-       CLK("davinci_emac.1", NULL, &emac_clk),
-       CLK("davinci_mdio.0", "fck", &emac_clk),
-       CLK("i2c_davinci.1", NULL, &i2c_clk),
-       CLK("palm_bk3710", NULL, &ide_clk),
-       CLK("davinci-mcbsp", NULL, &asp_clk),
-       CLK("dm6441-mmc.0", NULL, &mmcsd_clk),
-       CLK(NULL, "spi", &spi_clk),
-       CLK(NULL, "gpio", &gpio_clk),
-       CLK(NULL, "usb", &usb_clk),
-       CLK(NULL, "vlynq", &vlynq_clk),
-       CLK(NULL, "aemif", &aemif_clk),
-       CLK(NULL, "pwm0", &pwm0_clk),
-       CLK(NULL, "pwm1", &pwm1_clk),
-       CLK(NULL, "pwm2", &pwm2_clk),
-       CLK(NULL, "timer0", &timer0_clk),
-       CLK(NULL, "timer1", &timer1_clk),
-       CLK("davinci-wdt", NULL, &timer2_clk),
-       CLK(NULL, NULL, NULL),
-};
-
 static struct emac_platform_data dm644x_emac_pdata = {
        .ctrl_reg_offset        = DM644X_EMAC_CNTRL_OFFSET,
        .ctrl_mod_reg_offset    = DM644X_EMAC_CNTRL_MOD_OFFSET,
@@ -819,8 +536,6 @@ static struct davinci_id dm644x_ids[] = {
        },
 };
 
-static u32 dm644x_psc_bases[] = { DAVINCI_PWR_SLEEP_CNTRL_BASE };
-
 /*
  * T0_BOT: Timer 0, bottom:  clockevent source for hrtimers
  * T0_TOP: Timer 0, top   :  clocksource for generic timekeeping
@@ -905,8 +620,6 @@ static const struct davinci_soc_info davinci_soc_info_dm644x = {
        .jtag_id_reg            = 0x01c40028,
        .ids                    = dm644x_ids,
        .ids_num                = ARRAY_SIZE(dm644x_ids),
-       .psc_bases              = dm644x_psc_bases,
-       .psc_bases_num          = ARRAY_SIZE(dm644x_psc_bases),
        .pinmux_base            = DAVINCI_SYSTEM_MODULE_BASE,
        .pinmux_pins            = dm644x_pins,
        .pinmux_pins_num        = ARRAY_SIZE(dm644x_pins),
@@ -934,8 +647,41 @@ void __init dm644x_init(void)
 
 void __init dm644x_init_time(void)
 {
-       davinci_clk_init(dm644x_clks);
-       davinci_timer_init();
+       void __iomem *pll1, *psc;
+       struct clk *clk;
+
+       clk_register_fixed_rate(NULL, "ref_clk", NULL, 0, DM644X_REF_FREQ);
+
+       pll1 = ioremap(DAVINCI_PLL1_BASE, SZ_1K);
+       dm644x_pll1_init(NULL, pll1, NULL);
+
+       psc = ioremap(DAVINCI_PWR_SLEEP_CNTRL_BASE, SZ_4K);
+       dm644x_psc_init(NULL, psc);
+
+       clk = clk_get(NULL, "timer0");
+
+       davinci_timer_init(clk);
+}
+
+static struct resource dm644x_pll2_resources[] = {
+       {
+               .start  = DAVINCI_PLL2_BASE,
+               .end    = DAVINCI_PLL2_BASE + SZ_1K - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+};
+
+static struct platform_device dm644x_pll2_device = {
+       .name           = "dm644x-pll2",
+       .id             = -1,
+       .resource       = dm644x_pll2_resources,
+       .num_resources  = ARRAY_SIZE(dm644x_pll2_resources),
+};
+
+void __init dm644x_register_clocks(void)
+{
+       /* PLL1 and PSC are registered in dm644x_init_time() */
+       platform_device_register(&dm644x_pll2_device);
 }
 
 int __init dm644x_init_video(struct vpfe_config *vpfe_cfg,
index c32ca27..6bd2ed0 100644 (file)
@@ -8,29 +8,30 @@
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
  */
+
+#include <linux/clk-provider.h>
+#include <linux/clk/davinci.h>
+#include <linux/clkdev.h>
 #include <linux/dma-mapping.h>
 #include <linux/dmaengine.h>
 #include <linux/init.h>
-#include <linux/clk.h>
-#include <linux/serial_8250.h>
-#include <linux/platform_device.h>
 #include <linux/platform_data/edma.h>
 #include <linux/platform_data/gpio-davinci.h>
+#include <linux/platform_device.h>
+#include <linux/serial_8250.h>
 
 #include <asm/mach/map.h>
 
+#include <mach/common.h>
 #include <mach/cputype.h>
 #include <mach/irqs.h>
-#include "psc.h"
 #include <mach/mux.h>
-#include <mach/time.h>
 #include <mach/serial.h>
-#include <mach/common.h>
+#include <mach/time.h>
 
+#include "asp.h"
 #include "davinci.h"
-#include "clock.h"
 #include "mux.h"
-#include "asp.h"
 
 #define DAVINCI_VPIF_BASE       (0x01C12000)
 
 #define DM646X_EMAC_CNTRL_RAM_OFFSET   0x2000
 #define DM646X_EMAC_CNTRL_RAM_SIZE     0x2000
 
-static struct pll_data pll1_data = {
-       .num       = 1,
-       .phys_base = DAVINCI_PLL1_BASE,
-};
-
-static struct pll_data pll2_data = {
-       .num       = 2,
-       .phys_base = DAVINCI_PLL2_BASE,
-};
-
-static struct clk ref_clk = {
-       .name = "ref_clk",
-       /* rate is initialized in dm646x_init_time() */
-};
-
-static struct clk aux_clkin = {
-       .name = "aux_clkin",
-       /* rate is initialized in dm646x_init_time() */
-};
-
-static struct clk pll1_clk = {
-       .name = "pll1",
-       .parent = &ref_clk,
-       .pll_data = &pll1_data,
-       .flags = CLK_PLL,
-};
-
-static struct clk pll1_sysclk1 = {
-       .name = "pll1_sysclk1",
-       .parent = &pll1_clk,
-       .flags = CLK_PLL,
-       .div_reg = PLLDIV1,
-};
-
-static struct clk pll1_sysclk2 = {
-       .name = "pll1_sysclk2",
-       .parent = &pll1_clk,
-       .flags = CLK_PLL,
-       .div_reg = PLLDIV2,
-};
-
-static struct clk pll1_sysclk3 = {
-       .name = "pll1_sysclk3",
-       .parent = &pll1_clk,
-       .flags = CLK_PLL,
-       .div_reg = PLLDIV3,
-};
-
-static struct clk pll1_sysclk4 = {
-       .name = "pll1_sysclk4",
-       .parent = &pll1_clk,
-       .flags = CLK_PLL,
-       .div_reg = PLLDIV4,
-};
-
-static struct clk pll1_sysclk5 = {
-       .name = "pll1_sysclk5",
-       .parent = &pll1_clk,
-       .flags = CLK_PLL,
-       .div_reg = PLLDIV5,
-};
-
-static struct clk pll1_sysclk6 = {
-       .name = "pll1_sysclk6",
-       .parent = &pll1_clk,
-       .flags = CLK_PLL,
-       .div_reg = PLLDIV6,
-};
-
-static struct clk pll1_sysclk8 = {
-       .name = "pll1_sysclk8",
-       .parent = &pll1_clk,
-       .flags = CLK_PLL,
-       .div_reg = PLLDIV8,
-};
-
-static struct clk pll1_sysclk9 = {
-       .name = "pll1_sysclk9",
-       .parent = &pll1_clk,
-       .flags = CLK_PLL,
-       .div_reg = PLLDIV9,
-};
-
-static struct clk pll1_sysclkbp = {
-       .name = "pll1_sysclkbp",
-       .parent = &pll1_clk,
-       .flags = CLK_PLL | PRE_PLL,
-       .div_reg = BPDIV,
-};
-
-static struct clk pll1_aux_clk = {
-       .name = "pll1_aux_clk",
-       .parent = &pll1_clk,
-       .flags = CLK_PLL | PRE_PLL,
-};
-
-static struct clk pll2_clk = {
-       .name = "pll2_clk",
-       .parent = &ref_clk,
-       .pll_data = &pll2_data,
-       .flags = CLK_PLL,
-};
-
-static struct clk pll2_sysclk1 = {
-       .name = "pll2_sysclk1",
-       .parent = &pll2_clk,
-       .flags = CLK_PLL,
-       .div_reg = PLLDIV1,
-};
-
-static struct clk dsp_clk = {
-       .name = "dsp",
-       .parent = &pll1_sysclk1,
-       .lpsc = DM646X_LPSC_C64X_CPU,
-       .usecount = 1,                  /* REVISIT how to disable? */
-};
-
-static struct clk arm_clk = {
-       .name = "arm",
-       .parent = &pll1_sysclk2,
-       .lpsc = DM646X_LPSC_ARM,
-       .flags = ALWAYS_ENABLED,
-};
-
-static struct clk edma_cc_clk = {
-       .name = "edma_cc",
-       .parent = &pll1_sysclk2,
-       .lpsc = DM646X_LPSC_TPCC,
-       .flags = ALWAYS_ENABLED,
-};
-
-static struct clk edma_tc0_clk = {
-       .name = "edma_tc0",
-       .parent = &pll1_sysclk2,
-       .lpsc = DM646X_LPSC_TPTC0,
-       .flags = ALWAYS_ENABLED,
-};
-
-static struct clk edma_tc1_clk = {
-       .name = "edma_tc1",
-       .parent = &pll1_sysclk2,
-       .lpsc = DM646X_LPSC_TPTC1,
-       .flags = ALWAYS_ENABLED,
-};
-
-static struct clk edma_tc2_clk = {
-       .name = "edma_tc2",
-       .parent = &pll1_sysclk2,
-       .lpsc = DM646X_LPSC_TPTC2,
-       .flags = ALWAYS_ENABLED,
-};
-
-static struct clk edma_tc3_clk = {
-       .name = "edma_tc3",
-       .parent = &pll1_sysclk2,
-       .lpsc = DM646X_LPSC_TPTC3,
-       .flags = ALWAYS_ENABLED,
-};
-
-static struct clk uart0_clk = {
-       .name = "uart0",
-       .parent = &aux_clkin,
-       .lpsc = DM646X_LPSC_UART0,
-};
-
-static struct clk uart1_clk = {
-       .name = "uart1",
-       .parent = &aux_clkin,
-       .lpsc = DM646X_LPSC_UART1,
-};
-
-static struct clk uart2_clk = {
-       .name = "uart2",
-       .parent = &aux_clkin,
-       .lpsc = DM646X_LPSC_UART2,
-};
-
-static struct clk i2c_clk = {
-       .name = "I2CCLK",
-       .parent = &pll1_sysclk3,
-       .lpsc = DM646X_LPSC_I2C,
-};
-
-static struct clk gpio_clk = {
-       .name = "gpio",
-       .parent = &pll1_sysclk3,
-       .lpsc = DM646X_LPSC_GPIO,
-};
-
-static struct clk mcasp0_clk = {
-       .name = "mcasp0",
-       .parent = &pll1_sysclk3,
-       .lpsc = DM646X_LPSC_McASP0,
-};
-
-static struct clk mcasp1_clk = {
-       .name = "mcasp1",
-       .parent = &pll1_sysclk3,
-       .lpsc = DM646X_LPSC_McASP1,
-};
-
-static struct clk aemif_clk = {
-       .name = "aemif",
-       .parent = &pll1_sysclk3,
-       .lpsc = DM646X_LPSC_AEMIF,
-       .flags = ALWAYS_ENABLED,
-};
-
-static struct clk emac_clk = {
-       .name = "emac",
-       .parent = &pll1_sysclk3,
-       .lpsc = DM646X_LPSC_EMAC,
-};
-
-static struct clk pwm0_clk = {
-       .name = "pwm0",
-       .parent = &pll1_sysclk3,
-       .lpsc = DM646X_LPSC_PWM0,
-       .usecount = 1,            /* REVIST: disabling hangs system */
-};
-
-static struct clk pwm1_clk = {
-       .name = "pwm1",
-       .parent = &pll1_sysclk3,
-       .lpsc = DM646X_LPSC_PWM1,
-       .usecount = 1,            /* REVIST: disabling hangs system */
-};
-
-static struct clk timer0_clk = {
-       .name = "timer0",
-       .parent = &pll1_sysclk3,
-       .lpsc = DM646X_LPSC_TIMER0,
-};
-
-static struct clk timer1_clk = {
-       .name = "timer1",
-       .parent = &pll1_sysclk3,
-       .lpsc = DM646X_LPSC_TIMER1,
-};
-
-static struct clk timer2_clk = {
-       .name = "timer2",
-       .parent = &pll1_sysclk3,
-       .flags = ALWAYS_ENABLED, /* no LPSC, always enabled; c.f. spruep9a */
-};
-
-
-static struct clk ide_clk = {
-       .name = "ide",
-       .parent = &pll1_sysclk4,
-       .lpsc = DAVINCI_LPSC_ATA,
-};
-
-static struct clk vpif0_clk = {
-       .name = "vpif0",
-       .parent = &ref_clk,
-       .lpsc = DM646X_LPSC_VPSSMSTR,
-       .flags = ALWAYS_ENABLED,
-};
-
-static struct clk vpif1_clk = {
-       .name = "vpif1",
-       .parent = &ref_clk,
-       .lpsc = DM646X_LPSC_VPSSSLV,
-       .flags = ALWAYS_ENABLED,
-};
-
-static struct clk_lookup dm646x_clks[] = {
-       CLK(NULL, "ref", &ref_clk),
-       CLK(NULL, "aux", &aux_clkin),
-       CLK(NULL, "pll1", &pll1_clk),
-       CLK(NULL, "pll1_sysclk", &pll1_sysclk1),
-       CLK(NULL, "pll1_sysclk", &pll1_sysclk2),
-       CLK(NULL, "pll1_sysclk", &pll1_sysclk3),
-       CLK(NULL, "pll1_sysclk", &pll1_sysclk4),
-       CLK(NULL, "pll1_sysclk", &pll1_sysclk5),
-       CLK(NULL, "pll1_sysclk", &pll1_sysclk6),
-       CLK(NULL, "pll1_sysclk", &pll1_sysclk8),
-       CLK(NULL, "pll1_sysclk", &pll1_sysclk9),
-       CLK(NULL, "pll1_sysclk", &pll1_sysclkbp),
-       CLK(NULL, "pll1_aux", &pll1_aux_clk),
-       CLK(NULL, "pll2", &pll2_clk),
-       CLK(NULL, "pll2_sysclk1", &pll2_sysclk1),
-       CLK(NULL, "dsp", &dsp_clk),
-       CLK(NULL, "arm", &arm_clk),
-       CLK(NULL, "edma_cc", &edma_cc_clk),
-       CLK(NULL, "edma_tc0", &edma_tc0_clk),
-       CLK(NULL, "edma_tc1", &edma_tc1_clk),
-       CLK(NULL, "edma_tc2", &edma_tc2_clk),
-       CLK(NULL, "edma_tc3", &edma_tc3_clk),
-       CLK("serial8250.0", NULL, &uart0_clk),
-       CLK("serial8250.1", NULL, &uart1_clk),
-       CLK("serial8250.2", NULL, &uart2_clk),
-       CLK("i2c_davinci.1", NULL, &i2c_clk),
-       CLK(NULL, "gpio", &gpio_clk),
-       CLK("davinci-mcasp.0", NULL, &mcasp0_clk),
-       CLK("davinci-mcasp.1", NULL, &mcasp1_clk),
-       CLK(NULL, "aemif", &aemif_clk),
-       CLK("davinci_emac.1", NULL, &emac_clk),
-       CLK("davinci_mdio.0", "fck", &emac_clk),
-       CLK(NULL, "pwm0", &pwm0_clk),
-       CLK(NULL, "pwm1", &pwm1_clk),
-       CLK(NULL, "timer0", &timer0_clk),
-       CLK(NULL, "timer1", &timer1_clk),
-       CLK("davinci-wdt", NULL, &timer2_clk),
-       CLK("palm_bk3710", NULL, &ide_clk),
-       CLK(NULL, "vpif0", &vpif0_clk),
-       CLK(NULL, "vpif1", &vpif1_clk),
-       CLK(NULL, NULL, NULL),
-};
-
 static struct emac_platform_data dm646x_emac_pdata = {
        .ctrl_reg_offset        = DM646X_EMAC_CNTRL_OFFSET,
        .ctrl_mod_reg_offset    = DM646X_EMAC_CNTRL_MOD_OFFSET,
@@ -796,8 +486,6 @@ static struct davinci_id dm646x_ids[] = {
        },
 };
 
-static u32 dm646x_psc_bases[] = { DAVINCI_PWR_SLEEP_CNTRL_BASE };
-
 /*
  * T0_BOT: Timer 0, bottom:  clockevent source for hrtimers
  * T0_TOP: Timer 0, top   :  clocksource for generic timekeeping
@@ -882,8 +570,6 @@ static const struct davinci_soc_info davinci_soc_info_dm646x = {
        .jtag_id_reg            = 0x01c40028,
        .ids                    = dm646x_ids,
        .ids_num                = ARRAY_SIZE(dm646x_ids),
-       .psc_bases              = dm646x_psc_bases,
-       .psc_bases_num          = ARRAY_SIZE(dm646x_psc_bases),
        .pinmux_base            = DAVINCI_SYSTEM_MODULE_BASE,
        .pinmux_pins            = dm646x_pins,
        .pinmux_pins_num        = ARRAY_SIZE(dm646x_pins),
@@ -954,10 +640,42 @@ void __init dm646x_init(void)
 void __init dm646x_init_time(unsigned long ref_clk_rate,
                             unsigned long aux_clkin_rate)
 {
-       ref_clk.rate = ref_clk_rate;
-       aux_clkin.rate = aux_clkin_rate;
-       davinci_clk_init(dm646x_clks);
-       davinci_timer_init();
+       void __iomem *pll1, *psc;
+       struct clk *clk;
+
+       clk_register_fixed_rate(NULL, "ref_clk", NULL, 0, ref_clk_rate);
+       clk_register_fixed_rate(NULL, "aux_clkin", NULL, 0, aux_clkin_rate);
+
+       pll1 = ioremap(DAVINCI_PLL1_BASE, SZ_1K);
+       dm646x_pll1_init(NULL, pll1, NULL);
+
+       psc = ioremap(DAVINCI_PWR_SLEEP_CNTRL_BASE, SZ_4K);
+       dm646x_psc_init(NULL, psc);
+
+       clk = clk_get(NULL, "timer0");
+
+       davinci_timer_init(clk);
+}
+
+static struct resource dm646x_pll2_resources[] = {
+       {
+               .start  = DAVINCI_PLL2_BASE,
+               .end    = DAVINCI_PLL2_BASE + SZ_1K - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+};
+
+static struct platform_device dm646x_pll2_device = {
+       .name           = "dm646x-pll2",
+       .id             = -1,
+       .resource       = dm646x_pll2_resources,
+       .num_resources  = ARRAY_SIZE(dm646x_pll2_resources),
+};
+
+void __init dm646x_register_clocks(void)
+{
+       /* PLL1 and PSC are registered in dm646x_init_time() */
+       platform_device_register(&dm646x_pll2_device);
 }
 
 static int __init dm646x_init_devices(void)
index 3e8af6a..42ed4f2 100644 (file)
@@ -15,9 +15,6 @@
 
 struct clk;
 
-extern int clk_register(struct clk *clk);
-extern void clk_unregister(struct clk *clk);
-
 int davinci_clk_reset_assert(struct clk *c);
 int davinci_clk_reset_deassert(struct clk *c);
 
index f0d5e85..b577e13 100644 (file)
 #ifndef __ARCH_ARM_MACH_DAVINCI_COMMON_H
 #define __ARCH_ARM_MACH_DAVINCI_COMMON_H
 
+#include <linux/clk.h>
 #include <linux/compiler.h>
 #include <linux/types.h>
 #include <linux/reboot.h>
 
-extern void davinci_timer_init(void);
+void davinci_timer_init(struct clk *clk);
 
 extern void davinci_irq_init(void);
 extern void __iomem *davinci_intc_base;
@@ -53,8 +54,6 @@ struct davinci_soc_info {
        u32                             jtag_id_reg;
        struct davinci_id               *ids;
        unsigned long                   ids_num;
-       u32                             *psc_bases;
-       unsigned long                   psc_bases_num;
        u32                             pinmux_base;
        const struct mux_config         *pinmux_pins;
        unsigned long                   pinmux_pins_num;
@@ -82,12 +81,6 @@ extern void davinci_common_init(const struct davinci_soc_info *soc_info);
 extern void davinci_init_ide(void);
 void davinci_init_late(void);
 
-#ifdef CONFIG_DAVINCI_RESET_CLOCKS
-int davinci_clk_disable_unused(void);
-#else
-static inline int davinci_clk_disable_unused(void) { return 0; }
-#endif
-
 #ifdef CONFIG_CPU_FREQ
 int davinci_cpufreq_init(void);
 #else
index 9fd6d01..ab4a57f 100644 (file)
@@ -89,9 +89,11 @@ extern unsigned int da850_max_speed;
 
 void da830_init(void);
 void da830_init_time(void);
+void da830_register_clocks(void);
 
 void da850_init(void);
 void da850_init_time(void);
+void da850_register_clocks(void);
 
 int da830_register_edma(struct edma_rsv_info *rsv);
 int da850_register_edma(struct edma_rsv_info *rsv[2]);
@@ -101,9 +103,7 @@ int da8xx_register_watchdog(void);
 int da8xx_register_usb_phy(void);
 int da8xx_register_usb20(unsigned mA, unsigned potpgt);
 int da8xx_register_usb11(struct da8xx_ohci_root_hub *pdata);
-int da8xx_register_usb_refclkin(int rate);
-int da8xx_register_usb20_phy_clk(bool use_usb_refclkin);
-int da8xx_register_usb11_phy_clk(bool use_usb_refclkin);
+int da8xx_register_usb_phy_clocks(void);
 int da850_register_sata_refclk(int rate);
 int da8xx_register_emac(void);
 int da8xx_register_uio_pruss(void);
index 78eac2c..e251fd5 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/pm_runtime.h>
 #include <linux/pm_clock.h>
 #include <linux/platform_device.h>
+#include <linux/of.h>
 
 static struct dev_pm_domain davinci_pm_domain = {
        .ops = {
@@ -28,6 +29,10 @@ static struct pm_clk_notifier_block platform_bus_notifier = {
 
 static int __init davinci_pm_runtime_init(void)
 {
+       if (of_have_populated_dt())
+               return 0;
+
+       /* Use pm_clk as fallback if we're not using genpd. */
        pm_clk_add_notifier(&platform_bus_type, &platform_bus_notifier);
 
        return 0;
diff --git a/arch/arm/mach-davinci/psc.c b/arch/arm/mach-davinci/psc.c
deleted file mode 100644 (file)
index e5dc6bf..0000000
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * TI DaVinci Power and Sleep Controller (PSC)
- *
- * Copyright (C) 2006 Texas Instruments.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/io.h>
-
-#include <mach/cputype.h>
-#include "psc.h"
-
-#include "clock.h"
-
-/* Return nonzero iff the domain's clock is active */
-int __init davinci_psc_is_clk_active(unsigned int ctlr, unsigned int id)
-{
-       void __iomem *psc_base;
-       u32 mdstat;
-       struct davinci_soc_info *soc_info = &davinci_soc_info;
-
-       if (!soc_info->psc_bases || (ctlr >= soc_info->psc_bases_num)) {
-               pr_warn("PSC: Bad psc data: 0x%x[%d]\n",
-                               (int)soc_info->psc_bases, ctlr);
-               return 0;
-       }
-
-       psc_base = ioremap(soc_info->psc_bases[ctlr], SZ_4K);
-       mdstat = __raw_readl(psc_base + MDSTAT + 4 * id);
-       iounmap(psc_base);
-
-       /* if clocked, state can be "Enable" or "SyncReset" */
-       return mdstat & BIT(12);
-}
-
-/* Control "reset" line associated with PSC domain */
-void davinci_psc_reset(unsigned int ctlr, unsigned int id, bool reset)
-{
-       u32 mdctl;
-       void __iomem *psc_base;
-       struct davinci_soc_info *soc_info = &davinci_soc_info;
-
-       if (!soc_info->psc_bases || (ctlr >= soc_info->psc_bases_num)) {
-               pr_warn("PSC: Bad psc data: 0x%x[%d]\n",
-                               (int)soc_info->psc_bases, ctlr);
-               return;
-       }
-
-       psc_base = ioremap(soc_info->psc_bases[ctlr], SZ_4K);
-
-       mdctl = readl(psc_base + MDCTL + 4 * id);
-       if (reset)
-               mdctl &= ~MDCTL_LRST;
-       else
-               mdctl |= MDCTL_LRST;
-       writel(mdctl, psc_base + MDCTL + 4 * id);
-
-       iounmap(psc_base);
-}
-
-/* Enable or disable a PSC domain */
-void davinci_psc_config(unsigned int domain, unsigned int ctlr,
-               unsigned int id, bool enable, u32 flags)
-{
-       u32 epcpr, ptcmd, ptstat, pdstat, pdctl, mdstat, mdctl;
-       void __iomem *psc_base;
-       struct davinci_soc_info *soc_info = &davinci_soc_info;
-       u32 next_state = PSC_STATE_ENABLE;
-
-       if (!soc_info->psc_bases || (ctlr >= soc_info->psc_bases_num)) {
-               pr_warn("PSC: Bad psc data: 0x%x[%d]\n",
-                               (int)soc_info->psc_bases, ctlr);
-               return;
-       }
-
-       psc_base = ioremap(soc_info->psc_bases[ctlr], SZ_4K);
-
-       if (!enable) {
-               if (flags & PSC_SWRSTDISABLE)
-                       next_state = PSC_STATE_SWRSTDISABLE;
-               else
-                       next_state = PSC_STATE_DISABLE;
-       }
-
-       mdctl = __raw_readl(psc_base + MDCTL + 4 * id);
-       mdctl &= ~MDSTAT_STATE_MASK;
-       mdctl |= next_state;
-       if (flags & PSC_FORCE)
-               mdctl |= MDCTL_FORCE;
-       __raw_writel(mdctl, psc_base + MDCTL + 4 * id);
-
-       pdstat = __raw_readl(psc_base + PDSTAT + 4 * domain);
-       if ((pdstat & PDSTAT_STATE_MASK) == 0) {
-               pdctl = __raw_readl(psc_base + PDCTL + 4 * domain);
-               pdctl |= PDCTL_NEXT;
-               __raw_writel(pdctl, psc_base + PDCTL + 4 * domain);
-
-               ptcmd = 1 << domain;
-               __raw_writel(ptcmd, psc_base + PTCMD);
-
-               do {
-                       epcpr = __raw_readl(psc_base + EPCPR);
-               } while ((((epcpr >> domain) & 1) == 0));
-
-               pdctl = __raw_readl(psc_base + PDCTL + 4 * domain);
-               pdctl |= PDCTL_EPCGOOD;
-               __raw_writel(pdctl, psc_base + PDCTL + 4 * domain);
-       } else {
-               ptcmd = 1 << domain;
-               __raw_writel(ptcmd, psc_base + PTCMD);
-       }
-
-       do {
-               ptstat = __raw_readl(psc_base + PTSTAT);
-       } while (!(((ptstat >> domain) & 1) == 0));
-
-       do {
-               mdstat = __raw_readl(psc_base + MDSTAT + 4 * id);
-       } while (!((mdstat & MDSTAT_STATE_MASK) == next_state));
-
-       iounmap(psc_base);
-}
index 8af9f09..68cd9d3 100644 (file)
@@ -27,8 +27,6 @@
 #ifndef __ASM_ARCH_PSC_H
 #define __ASM_ARCH_PSC_H
 
-#define        DAVINCI_PWR_SLEEP_CNTRL_BASE    0x01C41000
-
 /* Power and Sleep Controller (PSC) Domains */
 #define DAVINCI_GPSC_ARMDOMAIN         0
 #define DAVINCI_GPSC_DSPDOMAIN         1
 #define PDCTL_NEXT             BIT(0)
 #define PDCTL_EPCGOOD          BIT(8)
 
-#ifndef __ASSEMBLER__
-
-extern int davinci_psc_is_clk_active(unsigned int ctlr, unsigned int id);
-extern void davinci_psc_reset(unsigned int ctlr, unsigned int id,
-               bool reset);
-extern void davinci_psc_config(unsigned int domain, unsigned int ctlr,
-               unsigned int id, bool enable, u32 flags);
-
-#endif
-
 #endif /* __ASM_ARCH_PSC_H */
index 1bb991a..5a6de53 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/io.h>
 #include <linux/clk.h>
 #include <linux/err.h>
+#include <linux/of.h>
 #include <linux/platform_device.h>
 #include <linux/sched_clock.h>
 
@@ -27,8 +28,6 @@
 #include <mach/hardware.h>
 #include <mach/time.h>
 
-#include "clock.h"
-
 static struct clock_event_device clockevent_davinci;
 static unsigned int davinci_clock_tick_rate;
 
@@ -334,10 +333,8 @@ static struct clock_event_device clockevent_davinci = {
        .set_state_oneshot      = davinci_set_oneshot,
 };
 
-
-void __init davinci_timer_init(void)
+void __init davinci_timer_init(struct clk *timer_clk)
 {
-       struct clk *timer_clk;
        struct davinci_soc_info *soc_info = &davinci_soc_info;
        unsigned int clockevent_id;
        unsigned int clocksource_id;
@@ -373,7 +370,6 @@ void __init davinci_timer_init(void)
                }
        }
 
-       timer_clk = clk_get(NULL, "timer0");
        BUG_ON(IS_ERR(timer_clk));
        clk_prepare_enable(timer_clk);
 
@@ -402,3 +398,17 @@ void __init davinci_timer_init(void)
        for (i=0; i< ARRAY_SIZE(timers); i++)
                timer32_config(&timers[i]);
 }
+
+static int __init of_davinci_timer_init(struct device_node *np)
+{
+       struct clk *clk;
+
+       clk = of_clk_get(np, 0);
+       if (IS_ERR(clk))
+               return PTR_ERR(clk);
+
+       davinci_timer_init(clk);
+
+       return 0;
+}
+TIMER_OF_DECLARE(davinci_timer, "ti,da830-timer", of_davinci_timer_init);
index 50445f0..c17ce66 100644 (file)
@@ -2,29 +2,30 @@
 /*
  * DA8xx USB
  */
-#include <linux/clk.h>
+#include <linux/clk-provider.h>
 #include <linux/delay.h>
 #include <linux/dma-mapping.h>
 #include <linux/init.h>
 #include <linux/mfd/da8xx-cfgchip.h>
+#include <linux/mfd/syscon.h>
 #include <linux/phy/phy.h>
+#include <linux/platform_data/clk-da8xx-cfgchip.h>
 #include <linux/platform_data/phy-da8xx-usb.h>
 #include <linux/platform_data/usb-davinci.h>
 #include <linux/platform_device.h>
 #include <linux/usb/musb.h>
 
-#include <mach/clock.h>
 #include <mach/common.h>
 #include <mach/cputype.h>
 #include <mach/da8xx.h>
 #include <mach/irqs.h>
 
-#include "clock.h"
-
 #define DA8XX_USB0_BASE                0x01e00000
 #define DA8XX_USB1_BASE                0x01e25000
 
+#ifndef CONFIG_COMMON_CLK
 static struct clk *usb20_clk;
+#endif
 
 static struct da8xx_usb_phy_platform_data da8xx_usb_phy_pdata;
 
@@ -81,11 +82,6 @@ static struct platform_device da8xx_usb20_dev = {
        .name           = "musb-da8xx",
        .id             = -1,
        .dev = {
-               /*
-                * Setting init_name so that clock lookup will work in
-                * usb20_phy_clk_enable() even if this device is not registered.
-                */
-               .init_name              = "musb-da8xx",
                .platform_data          = &usb_data,
                .dma_mask               = &usb_dmamask,
                .coherent_dma_mask      = DMA_BIT_MASK(32),
@@ -134,229 +130,17 @@ int __init da8xx_register_usb11(struct da8xx_ohci_root_hub *pdata)
        return platform_device_register(&da8xx_usb11_device);
 }
 
-static struct clk usb_refclkin = {
-       .name           = "usb_refclkin",
-       .set_rate       = davinci_simple_set_rate,
-};
-
-static struct clk_lookup usb_refclkin_lookup =
-       CLK(NULL, "usb_refclkin", &usb_refclkin);
-
-/**
- * da8xx_register_usb_refclkin - register USB_REFCLKIN clock
- *
- * @rate: The clock rate in Hz
- *
- * This clock is only needed if the board provides an external USB_REFCLKIN
- * signal, in which case it will be used as the parent of usb20_phy_clk and/or
- * usb11_phy_clk.
- */
-int __init da8xx_register_usb_refclkin(int rate)
-{
-       int ret;
-
-       usb_refclkin.rate = rate;
-       ret = clk_register(&usb_refclkin);
-       if (ret)
-               return ret;
-
-       clkdev_add(&usb_refclkin_lookup);
-
-       return 0;
-}
-
-static void usb20_phy_clk_enable(struct clk *clk)
-{
-       u32 val;
-       u32 timeout = 500000; /* 500 msec */
-
-       val = readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
-
-       /* The USB 2.O PLL requires that the USB 2.O PSC is enabled as well. */
-       davinci_clk_enable(usb20_clk);
-
-       /*
-        * Turn on the USB 2.0 PHY, but just the PLL, and not OTG. The USB 1.1
-        * host may use the PLL clock without USB 2.0 OTG being used.
-        */
-       val &= ~(CFGCHIP2_RESET | CFGCHIP2_PHYPWRDN);
-       val |= CFGCHIP2_PHY_PLLON;
-
-       writel(val, DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
-
-       while (--timeout) {
-               val = readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
-               if (val & CFGCHIP2_PHYCLKGD)
-                       goto done;
-               udelay(1);
-       }
-
-       pr_err("Timeout waiting for USB 2.0 PHY clock good\n");
-done:
-       davinci_clk_disable(usb20_clk);
-}
-
-static void usb20_phy_clk_disable(struct clk *clk)
-{
-       u32 val;
-
-       val = readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
-       val |= CFGCHIP2_PHYPWRDN;
-       writel(val, DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
-}
-
-static int usb20_phy_clk_set_parent(struct clk *clk, struct clk *parent)
-{
-       u32 val;
-
-       val = readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
-
-       /* Set the mux depending on the parent clock. */
-       if (parent == &usb_refclkin) {
-               val &= ~CFGCHIP2_USB2PHYCLKMUX;
-       } else if (strcmp(parent->name, "pll0_aux_clk") == 0) {
-               val |= CFGCHIP2_USB2PHYCLKMUX;
-       } else {
-               pr_err("Bad parent on USB 2.0 PHY clock\n");
-               return -EINVAL;
-       }
-
-       /* reference frequency also comes from parent clock */
-       val &= ~CFGCHIP2_REFFREQ_MASK;
-       switch (clk_get_rate(parent)) {
-       case 12000000:
-               val |= CFGCHIP2_REFFREQ_12MHZ;
-               break;
-       case 13000000:
-               val |= CFGCHIP2_REFFREQ_13MHZ;
-               break;
-       case 19200000:
-               val |= CFGCHIP2_REFFREQ_19_2MHZ;
-               break;
-       case 20000000:
-               val |= CFGCHIP2_REFFREQ_20MHZ;
-               break;
-       case 24000000:
-               val |= CFGCHIP2_REFFREQ_24MHZ;
-               break;
-       case 26000000:
-               val |= CFGCHIP2_REFFREQ_26MHZ;
-               break;
-       case 38400000:
-               val |= CFGCHIP2_REFFREQ_38_4MHZ;
-               break;
-       case 40000000:
-               val |= CFGCHIP2_REFFREQ_40MHZ;
-               break;
-       case 48000000:
-               val |= CFGCHIP2_REFFREQ_48MHZ;
-               break;
-       default:
-               pr_err("Bad parent clock rate on USB 2.0 PHY clock\n");
-               return -EINVAL;
-       }
-
-       writel(val, DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
-
-       return 0;
-}
-
-static struct clk usb20_phy_clk = {
-       .name           = "usb0_clk48",
-       .clk_enable     = usb20_phy_clk_enable,
-       .clk_disable    = usb20_phy_clk_disable,
-       .set_parent     = usb20_phy_clk_set_parent,
-};
-
-static struct clk_lookup usb20_phy_clk_lookup =
-       CLK("da8xx-usb-phy", "usb0_clk48", &usb20_phy_clk);
-
-/**
- * da8xx_register_usb20_phy_clk - register USB0PHYCLKMUX clock
- *
- * @use_usb_refclkin: Selects the parent clock - either "usb_refclkin" if true
- *     or "pll0_aux" if false.
- */
-int __init da8xx_register_usb20_phy_clk(bool use_usb_refclkin)
-{
-       struct clk *parent;
-       int ret;
-
-       usb20_clk = clk_get(&da8xx_usb20_dev.dev, "usb20");
-       ret = PTR_ERR_OR_ZERO(usb20_clk);
-       if (ret)
-               return ret;
-
-       parent = clk_get(NULL, use_usb_refclkin ? "usb_refclkin" : "pll0_aux");
-       ret = PTR_ERR_OR_ZERO(parent);
-       if (ret) {
-               clk_put(usb20_clk);
-               return ret;
-       }
-
-       usb20_phy_clk.parent = parent;
-       ret = clk_register(&usb20_phy_clk);
-       if (!ret)
-               clkdev_add(&usb20_phy_clk_lookup);
-
-       clk_put(parent);
-
-       return ret;
-}
-
-static int usb11_phy_clk_set_parent(struct clk *clk, struct clk *parent)
-{
-       u32 val;
-
-       val = readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
-
-       /* Set the USB 1.1 PHY clock mux based on the parent clock. */
-       if (parent == &usb20_phy_clk) {
-               val &= ~CFGCHIP2_USB1PHYCLKMUX;
-       } else if (parent == &usb_refclkin) {
-               val |= CFGCHIP2_USB1PHYCLKMUX;
-       } else {
-               pr_err("Bad parent on USB 1.1 PHY clock\n");
-               return -EINVAL;
-       }
-
-       writel(val, DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
-
-       return 0;
-}
-
-static struct clk usb11_phy_clk = {
-       .name           = "usb1_clk48",
-       .set_parent     = usb11_phy_clk_set_parent,
+static struct platform_device da8xx_usb_phy_clks_device = {
+       .name           = "da830-usb-phy-clks",
+       .id             = -1,
 };
 
-static struct clk_lookup usb11_phy_clk_lookup =
-       CLK("da8xx-usb-phy", "usb1_clk48", &usb11_phy_clk);
-
-/**
- * da8xx_register_usb11_phy_clk - register USB1PHYCLKMUX clock
- *
- * @use_usb_refclkin: Selects the parent clock - either "usb_refclkin" if true
- *     or "usb0_clk48" if false.
- */
-int __init da8xx_register_usb11_phy_clk(bool use_usb_refclkin)
+int __init da8xx_register_usb_phy_clocks(void)
 {
-       struct clk *parent;
-       int ret = 0;
-
-       if (use_usb_refclkin)
-               parent = clk_get(NULL, "usb_refclkin");
-       else
-               parent = clk_get(&da8xx_usb_phy.dev, "usb0_clk48");
-       if (IS_ERR(parent))
-               return PTR_ERR(parent);
-
-       usb11_phy_clk.parent = parent;
-       ret = clk_register(&usb11_phy_clk);
-       if (!ret)
-               clkdev_add(&usb11_phy_clk_lookup);
+       struct da8xx_cfgchip_clk_platform_data pdata;
 
-       clk_put(parent);
+       pdata.cfgchip = da8xx_get_cfgchip();
+       da8xx_usb_phy_clks_device.dev.platform_data = &pdata;
 
-       return ret;
+       return platform_device_register(&da8xx_usb_phy_clks_device);
 }
index f4b6c93..865dcc4 100644 (file)
@@ -190,8 +190,6 @@ static void __init exynos_dt_fixup(void)
 }
 
 DT_MACHINE_START(EXYNOS_DT, "SAMSUNG EXYNOS (Flattened Device Tree)")
-       /* Maintainer: Thomas Abraham <thomas.abraham@linaro.org> */
-       /* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
        .l2c_aux_val    = 0x3c400001,
        .l2c_aux_mask   = 0xc20fffff,
        .smp            = smp_ops(exynos_smp_ops),
index f3384e3..7ead3ac 100644 (file)
@@ -203,6 +203,7 @@ static int __init exynos_pmu_irq_init(struct device_node *node,
                                          NULL);
        if (!domain) {
                iounmap(pmu_base_addr);
+               pmu_base_addr = NULL;
                return -ENOMEM;
        }
 
index a129aae..909bb24 100644 (file)
@@ -148,13 +148,20 @@ static int hi3xxx_hotplug_init(void)
        struct device_node *node;
 
        node = of_find_compatible_node(NULL, NULL, "hisilicon,sysctrl");
-       if (node) {
-               ctrl_base = of_iomap(node, 0);
-               id = HI3620_CTRL;
-               return 0;
+       if (!node) {
+               id = ERROR_CTRL;
+               return -ENOENT;
        }
-       id = ERROR_CTRL;
-       return -ENOENT;
+
+       ctrl_base = of_iomap(node, 0);
+       of_node_put(node);
+       if (!ctrl_base) {
+               id = ERROR_CTRL;
+               return -ENOMEM;
+       }
+
+       id = HI3620_CTRL;
+       return 0;
 }
 
 void hi3xxx_set_cpu(int cpu, bool enable)
@@ -173,11 +180,15 @@ static bool hix5hd2_hotplug_init(void)
        struct device_node *np;
 
        np = of_find_compatible_node(NULL, NULL, "hisilicon,cpuctrl");
-       if (np) {
-               ctrl_base = of_iomap(np, 0);
-               return true;
-       }
-       return false;
+       if (!np)
+               return false;
+
+       ctrl_base = of_iomap(np, 0);
+       of_node_put(np);
+       if (!ctrl_base)
+               return false;
+
+       return true;
 }
 
 void hix5hd2_set_cpu(int cpu, bool enable)
@@ -219,10 +230,10 @@ void hip01_set_cpu(int cpu, bool enable)
 
        if (!ctrl_base) {
                np = of_find_compatible_node(NULL, NULL, "hisilicon,hip01-sysctrl");
-               if (np)
-                       ctrl_base = of_iomap(np, 0);
-               else
-                       BUG();
+               BUG_ON(!np);
+               ctrl_base = of_iomap(np, 0);
+               of_node_put(np);
+               BUG_ON(!ctrl_base);
        }
 
        if (enable) {
index 6f42323..abc3371 100644 (file)
@@ -523,18 +523,6 @@ config SOC_IMX6UL
        help
          This enables support for Freescale i.MX6 UltraLite processor.
 
-config SOC_IMX7D
-       bool "i.MX7 Dual support"
-       select PINCTRL_IMX7D
-       select ARM_GIC
-       select HAVE_ARM_ARCH_TIMER
-       select HAVE_IMX_ANATOP
-       select HAVE_IMX_MMDC
-       select HAVE_IMX_SRC
-       select IMX_GPCV2
-       help
-               This enables support for Freescale i.MX7 Dual processor.
-
 config SOC_LS1021A
        bool "Freescale LS1021A support"
        select ARM_GIC
@@ -549,6 +537,27 @@ comment "Cortex-A/Cortex-M asymmetric multiprocessing platforms"
 
 if ARCH_MULTI_V7 || ARM_SINGLE_ARMV7M
 
+config SOC_IMX7D_CA7
+       bool
+       select ARM_GIC
+       select HAVE_ARM_ARCH_TIMER
+       select HAVE_IMX_ANATOP
+       select HAVE_IMX_MMDC
+       select HAVE_IMX_SRC
+       select IMX_GPCV2
+
+config SOC_IMX7D_CM4
+       bool
+       select ARMV7M_SYSTICK
+
+config SOC_IMX7D
+       bool "i.MX7 Dual support"
+       select PINCTRL_IMX7D
+       select SOC_IMX7D_CA7 if ARCH_MULTI_V7
+       select SOC_IMX7D_CM4 if ARM_SINGLE_ARMV7M
+       help
+               This enables support for Freescale i.MX7 Dual processor.
+
 config SOC_VF610
        bool "Vybrid Family VF610 support"
        select ARM_GIC if ARCH_MULTI_V7
index 2327e3e..bae179a 100644 (file)
@@ -26,7 +26,7 @@ ifeq ($(CONFIG_CPU_IDLE),y)
 obj-$(CONFIG_SOC_IMX5) += cpuidle-imx5.o
 obj-$(CONFIG_SOC_IMX6Q) += cpuidle-imx6q.o
 obj-$(CONFIG_SOC_IMX6SL) += cpuidle-imx6sl.o
-obj-$(CONFIG_SOC_IMX6SLL) += cpuidle-imx6sl.o
+obj-$(CONFIG_SOC_IMX6SLL) += cpuidle-imx6sx.o
 obj-$(CONFIG_SOC_IMX6SX) += cpuidle-imx6sx.o
 obj-$(CONFIG_SOC_IMX6UL) += cpuidle-imx6sx.o
 endif
@@ -81,7 +81,8 @@ obj-$(CONFIG_SOC_IMX6SL) += mach-imx6sl.o
 obj-$(CONFIG_SOC_IMX6SLL) += mach-imx6sl.o
 obj-$(CONFIG_SOC_IMX6SX) += mach-imx6sx.o
 obj-$(CONFIG_SOC_IMX6UL) += mach-imx6ul.o
-obj-$(CONFIG_SOC_IMX7D) += mach-imx7d.o
+obj-$(CONFIG_SOC_IMX7D_CA7) += mach-imx7d.o
+obj-$(CONFIG_SOC_IMX7D_CM4) += mach-imx7d-cm4.o
 
 ifeq ($(CONFIG_SUSPEND),y)
 AFLAGS_suspend-imx6.o :=-Wa,-march=armv7-a
index c8d68e9..423dd76 100644 (file)
@@ -38,7 +38,6 @@ void imx21_soc_init(void);
 void imx27_soc_init(void);
 void imx31_soc_init(void);
 void imx35_soc_init(void);
-void epit_timer_init(void __iomem *base, int irq);
 int mx21_clocks_init(unsigned long lref, unsigned long fref);
 int mx27_clocks_init(unsigned long fref);
 int mx31_clocks_init(unsigned long fref);
@@ -58,10 +57,12 @@ struct device *imx_soc_device_init(void);
 void imx6_enable_rbc(bool enable);
 void imx_gpc_check_dt(void);
 void imx_gpc_set_arm_power_in_lpm(bool power_off);
+void imx_gpc_set_l2_mem_power_in_lpm(bool power_off);
 void imx_gpc_set_arm_power_up_timing(u32 sw2iso, u32 sw);
 void imx_gpc_set_arm_power_down_timing(u32 sw2iso, u32 sw);
 void imx25_pm_init(void);
 void imx27_pm_init(void);
+void imx5_pmu_init(void);
 
 enum mxc_cpu_pwr_mode {
        WAIT_CLOCKED,           /* wfi only */
index 4f2d1c7..e210bac 100644 (file)
@@ -117,3 +117,48 @@ int mx53_revision(void)
        return mx5_cpu_rev;
 }
 EXPORT_SYMBOL(mx53_revision);
+
+#define ARM_GPC                0x4
+#define DBGEN          BIT(16)
+
+/*
+ * This enables the DBGEN bit in ARM_GPC register, which is
+ * required for accessing some performance counter features.
+ * Technically it is only required while perf is used, but to
+ * keep the source code simple we just enable it all the time
+ * when the kernel configuration allows using the feature.
+ */
+void __init imx5_pmu_init(void)
+{
+       void __iomem *tigerp_base;
+       struct device_node *np;
+       u32 gpc;
+
+       if (!IS_ENABLED(CONFIG_ARM_PMU))
+               return;
+
+       np = of_find_compatible_node(NULL, NULL, "arm,cortex-a8-pmu");
+       if (!np)
+               return;
+
+       if (!of_property_read_bool(np, "secure-reg-access"))
+               goto exit;
+
+       of_node_put(np);
+
+       np = of_find_compatible_node(NULL, NULL, "fsl,imx51-tigerp");
+       if (!np)
+               return;
+
+       tigerp_base = of_iomap(np, 0);
+       if (!tigerp_base)
+               goto exit;
+
+       gpc = readl_relaxed(tigerp_base + ARM_GPC);
+       gpc |= DBGEN;
+       writel_relaxed(gpc, tigerp_base + ARM_GPC);
+       iounmap(tigerp_base);
+exit:
+       of_node_put(np);
+
+}
index 32969f3..c6b1bf9 100644 (file)
@@ -68,6 +68,7 @@ void __init imx_aips_allow_unprivileged_access(
 
        for_each_compatible_node(np, NULL, compat) {
                aips_base_addr = of_iomap(np, 0);
+               WARN_ON(!aips_base_addr);
                imx_set_aips(aips_base_addr);
        }
 }
index fa8ead1..8d866fb 100644 (file)
@@ -12,7 +12,6 @@
 
 #include "common.h"
 #include "cpuidle.h"
-#include "hardware.h"
 
 static int imx6sl_enter_wait(struct cpuidle_device *dev,
                            struct cpuidle_driver *drv, int index)
@@ -22,11 +21,9 @@ static int imx6sl_enter_wait(struct cpuidle_device *dev,
         * Software workaround for ERR005311, see function
         * description for details.
         */
-       if (cpu_is_imx6sl())
-               imx6sl_set_wait_clk(true);
+       imx6sl_set_wait_clk(true);
        cpu_do_idle();
-       if (cpu_is_imx6sl())
-               imx6sl_set_wait_clk(false);
+       imx6sl_set_wait_clk(false);
        imx6_set_lpm(WAIT_CLOCKED);
 
        return index;
index d0f14b7..243a108 100644 (file)
@@ -103,6 +103,7 @@ int __init imx6sx_cpuidle_init(void)
 {
        imx6_set_int_mem_clk_lpm(true);
        imx6_enable_rbc(false);
+       imx_gpc_set_l2_mem_power_in_lpm(false);
        /*
         * set ARM power up/down timing to the fastest,
         * sw2iso and sw can be set to one 32K cycle = 31us
index de535cb..e11159d 100644 (file)
@@ -20,6 +20,7 @@
 #include "common.h"
 #include "hardware.h"
 
+#define GPC_CNTR               0x0
 #define GPC_IMR1               0x008
 #define GPC_PGC_CPU_PDN                0x2a0
 #define GPC_PGC_CPU_PUPSCR     0x2a4
@@ -27,6 +28,8 @@
 #define GPC_PGC_SW2ISO_SHIFT   0x8
 #define GPC_PGC_SW_SHIFT       0x0
 
+#define GPC_CNTR_L2_PGE_SHIFT  22
+
 #define IMR_NUM                        4
 #define GPC_MAX_IRQS           (IMR_NUM * 32)
 
@@ -51,6 +54,17 @@ void imx_gpc_set_arm_power_in_lpm(bool power_off)
        writel_relaxed(power_off, gpc_base + GPC_PGC_CPU_PDN);
 }
 
+void imx_gpc_set_l2_mem_power_in_lpm(bool power_off)
+{
+       u32 val;
+
+       val = readl_relaxed(gpc_base + GPC_CNTR);
+       val &= ~(1 << GPC_CNTR_L2_PGE_SHIFT);
+       if (power_off)
+               val |= 1 << GPC_CNTR_L2_PGE_SHIFT;
+       writel_relaxed(val, gpc_base + GPC_CNTR);
+}
+
 void imx_gpc_pre_suspend(bool arm_power_off)
 {
        void __iomem *reg_imr1 = gpc_base + GPC_IMR1;
index 668d74b..9d9640a 100644 (file)
@@ -9,35 +9,17 @@
  * http://www.gnu.org/copyleft/gpl.html
  */
 
-#include <linux/irq.h>
-#include <linux/of_irq.h>
-#include <linux/of_platform.h>
 #include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-
 #include "common.h"
-#include "mx31.h"
 
 static const char * const imx31_dt_board_compat[] __initconst = {
        "fsl,imx31",
        NULL
 };
 
-/* FIXME: replace with DT binding */
-static const struct resource imx31_rnga_res[] __initconst = {
-       DEFINE_RES_MEM(MX31_RNGA_BASE_ADDR, SZ_16K),
-};
-
-static void __init imx31_dt_mach_init(void)
-{
-       platform_device_register_simple("mxc_rnga", -1, imx31_rnga_res,
-                                       ARRAY_SIZE(imx31_rnga_res));
-}
-
 DT_MACHINE_START(IMX31_DT, "Freescale i.MX31 (Device Tree Support)")
        .map_io         = mx31_map_io,
        .init_early     = imx31_init_early,
        .init_irq       = mx31_init_irq,
-       .init_machine   = imx31_dt_mach_init,
        .dt_compat      = imx31_dt_board_compat,
 MACHINE_END
index 3835b6a..c7169c2 100644 (file)
@@ -12,6 +12,7 @@
 
 #include <linux/io.h>
 #include <linux/irq.h>
+#include <linux/of_address.h>
 #include <linux/of_irq.h>
 #include <linux/of_platform.h>
 #include <asm/mach/arch.h>
@@ -48,11 +49,38 @@ static void __init imx51_ipu_mipi_setup(void)
        iounmap(hsc_addr);
 }
 
+static void __init imx51_m4if_setup(void)
+{
+       void __iomem *m4if_base;
+       struct device_node *np;
+
+       np = of_find_compatible_node(NULL, NULL, "fsl,imx51-m4if");
+       if (!np)
+               return;
+
+       m4if_base = of_iomap(np, 0);
+       if (!m4if_base) {
+               pr_err("Unable to map M4IF registers\n");
+               return;
+       }
+
+       /*
+        * Configure VPU and IPU with higher priorities
+        * in order to avoid artifacts during video playback
+        */
+       writel_relaxed(0x00000203, m4if_base + 0x40);
+       writel_relaxed(0x00000000, m4if_base + 0x44);
+       writel_relaxed(0x00120125, m4if_base + 0x9c);
+       writel_relaxed(0x001901A3, m4if_base + 0x48);
+       iounmap(m4if_base);
+}
+
 static void __init imx51_dt_init(void)
 {
        imx51_ipu_mipi_setup();
        imx_src_init();
-
+       imx51_m4if_setup();
+       imx5_pmu_init();
        imx_aips_allow_unprivileged_access("fsl,imx51-aipstz");
 }
 
index 07c2e8d..5ec7100 100644 (file)
@@ -31,7 +31,7 @@ static void __init imx53_init_early(void)
 static void __init imx53_dt_init(void)
 {
        imx_src_init();
-
+       imx5_pmu_init();
        imx_aips_allow_unprivileged_access("fsl,imx53-aipstz");
 }
 
index c7a1ef1..99be422 100644 (file)
@@ -42,7 +42,10 @@ static void __init imx6sl_init_late(void)
        if (IS_ENABLED(CONFIG_ARM_IMX6Q_CPUFREQ))
                platform_device_register_simple("imx6q-cpufreq", -1, NULL, 0);
 
-       imx6sl_cpuidle_init();
+       if (IS_ENABLED(CONFIG_SOC_IMX6SL) && cpu_is_imx6sl())
+               imx6sl_cpuidle_init();
+       else if (IS_ENABLED(CONFIG_SOC_IMX6SLL))
+               imx6sx_cpuidle_init();
 }
 
 static void __init imx6sl_init_machine(void)
diff --git a/arch/arm/mach-imx/mach-imx7d-cm4.c b/arch/arm/mach-imx/mach-imx7d-cm4.c
new file mode 100644 (file)
index 0000000..0800b58
--- /dev/null
@@ -0,0 +1,18 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2018 Pengutronix, Oleksij Rempel <o.rempel@pengutronix.de>
+ */
+
+#include <linux/kernel.h>
+#include <asm/v7m.h>
+#include <asm/mach/arch.h>
+
+static const char * const imx7d_cm4_dt_compat[] __initconst = {
+       "fsl,imx7d-cm4",
+       NULL,
+};
+
+DT_MACHINE_START(IMX7D, "Freescale i.MX7 Dual Cortex-M4 (Device Tree)")
+       .dt_compat = imx7d_cm4_dt_compat,
+       .restart = armv7m_restart,
+MACHINE_END
index 017539d..b08e407 100644 (file)
@@ -130,6 +130,13 @@ static const u32 imx6sl_mmdc_io_offset[] __initconst = {
        0x330, 0x334, 0x320,        /* SDCKE0, SDCKE1, RESET */
 };
 
+static const u32 imx6sll_mmdc_io_offset[] __initconst = {
+       0x294, 0x298, 0x29c, 0x2a0, /* DQM0 ~ DQM3 */
+       0x544, 0x54c, 0x554, 0x558, /* GPR_B0DS ~ GPR_B3DS */
+       0x530, 0x540, 0x2ac, 0x52c, /* MODE_CTL, MODE, SDCLK_0, GPR_ADDDS */
+       0x2a4, 0x2a8,               /* SDCKE0, SDCKE1*/
+};
+
 static const u32 imx6sx_mmdc_io_offset[] __initconst = {
        0x2ec, 0x2f0, 0x2f4, 0x2f8, /* DQM0 ~ DQM3 */
        0x60c, 0x610, 0x61c, 0x620, /* GPR_B0DS ~ GPR_B3DS */
@@ -175,6 +182,16 @@ static const struct imx6_pm_socdata imx6sl_pm_data __initconst = {
        .mmdc_io_offset = imx6sl_mmdc_io_offset,
 };
 
+static const struct imx6_pm_socdata imx6sll_pm_data __initconst = {
+       .mmdc_compat = "fsl,imx6sll-mmdc",
+       .src_compat = "fsl,imx6sll-src",
+       .iomuxc_compat = "fsl,imx6sll-iomuxc",
+       .gpc_compat = "fsl,imx6sll-gpc",
+       .pl310_compat = "arm,pl310-cache",
+       .mmdc_io_num = ARRAY_SIZE(imx6sll_mmdc_io_offset),
+       .mmdc_io_offset = imx6sll_mmdc_io_offset,
+};
+
 static const struct imx6_pm_socdata imx6sx_pm_data __initconst = {
        .mmdc_compat = "fsl,imx6sx-mmdc",
        .src_compat = "fsl,imx6sx-src",
@@ -296,7 +313,7 @@ int imx6_set_lpm(enum mxc_cpu_pwr_mode mode)
                if (cpu_is_imx6sl())
                        val |= BM_CLPCR_BYPASS_PMIC_READY;
                if (cpu_is_imx6sl() || cpu_is_imx6sx() || cpu_is_imx6ul() ||
-                   cpu_is_imx6ull())
+                   cpu_is_imx6ull() || cpu_is_imx6sll())
                        val |= BM_CLPCR_BYP_MMDC_CH0_LPM_HS;
                else
                        val |= BM_CLPCR_BYP_MMDC_CH1_LPM_HS;
@@ -314,7 +331,7 @@ int imx6_set_lpm(enum mxc_cpu_pwr_mode mode)
                if (cpu_is_imx6sl() || cpu_is_imx6sx())
                        val |= BM_CLPCR_BYPASS_PMIC_READY;
                if (cpu_is_imx6sl() || cpu_is_imx6sx() || cpu_is_imx6ul() ||
-                   cpu_is_imx6ull())
+                   cpu_is_imx6ull() || cpu_is_imx6sll())
                        val |= BM_CLPCR_BYP_MMDC_CH0_LPM_HS;
                else
                        val |= BM_CLPCR_BYP_MMDC_CH1_LPM_HS;
@@ -631,7 +648,17 @@ void __init imx6dl_pm_init(void)
 
 void __init imx6sl_pm_init(void)
 {
-       imx6_pm_common_init(&imx6sl_pm_data);
+       struct regmap *gpr;
+
+       if (cpu_is_imx6sl()) {
+               imx6_pm_common_init(&imx6sl_pm_data);
+       } else {
+               imx6_pm_common_init(&imx6sll_pm_data);
+               gpr = syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
+               if (!IS_ERR(gpr))
+                       regmap_update_bits(gpr, IOMUXC_GPR5,
+                               IMX6SLL_GPR5_AFCG_X_BYPASS_MASK, 0);
+       }
 }
 
 void __init imx6sx_pm_init(void)
index 4ffbbd2..c130497 100644 (file)
@@ -35,6 +35,8 @@
 #define AXP_BOOTROM_BASE 0xfff00000
 #define AXP_BOOTROM_SIZE 0x100000
 
+static struct clk *boot_cpu_clk;
+
 static struct clk *get_cpu_clk(int cpu)
 {
        struct clk *cpu_clk;
@@ -48,30 +50,6 @@ static struct clk *get_cpu_clk(int cpu)
        return cpu_clk;
 }
 
-static void set_secondary_cpu_clock(unsigned int cpu)
-{
-       int thiscpu;
-       unsigned long rate;
-       struct clk *cpu_clk;
-
-       thiscpu = get_cpu();
-
-       cpu_clk = get_cpu_clk(thiscpu);
-       if (!cpu_clk)
-               goto out;
-       clk_prepare_enable(cpu_clk);
-       rate = clk_get_rate(cpu_clk);
-
-       cpu_clk = get_cpu_clk(cpu);
-       if (!cpu_clk)
-               goto out;
-       clk_set_rate(cpu_clk, rate);
-       clk_prepare_enable(cpu_clk);
-
-out:
-       put_cpu();
-}
-
 static int armada_xp_boot_secondary(unsigned int cpu, struct task_struct *idle)
 {
        int ret, hw_cpu;
@@ -79,7 +57,6 @@ static int armada_xp_boot_secondary(unsigned int cpu, struct task_struct *idle)
        pr_info("Booting CPU %d\n", cpu);
 
        hw_cpu = cpu_logical_map(cpu);
-       set_secondary_cpu_clock(hw_cpu);
        mvebu_pmsu_set_cpu_boot_addr(hw_cpu, armada_xp_secondary_startup);
 
        /*
@@ -122,6 +99,19 @@ static void __init armada_xp_smp_init_cpus(void)
                panic("Invalid number of CPUs in DT\n");
 }
 
+static int armada_xp_sync_secondary_clk(unsigned int cpu)
+{
+       struct clk *cpu_clk = get_cpu_clk(cpu);
+
+       if (!cpu_clk || !boot_cpu_clk)
+               return 0;
+
+       clk_prepare_enable(cpu_clk);
+       clk_set_rate(cpu_clk, clk_get_rate(boot_cpu_clk));
+
+       return 0;
+}
+
 static void __init armada_xp_smp_prepare_cpus(unsigned int max_cpus)
 {
        struct device_node *node;
@@ -131,6 +121,14 @@ static void __init armada_xp_smp_prepare_cpus(unsigned int max_cpus)
        flush_cache_all();
        set_cpu_coherent();
 
+       boot_cpu_clk = get_cpu_clk(smp_processor_id());
+       if (boot_cpu_clk) {
+               clk_prepare_enable(boot_cpu_clk);
+               cpuhp_setup_state_nocalls(CPUHP_AP_ARM_MVEBU_SYNC_CLOCKS,
+                                         "arm/mvebu/sync_clocks:online",
+                                         armada_xp_sync_secondary_clk, NULL);
+       }
+
        /*
         * In order to boot the secondary CPUs we need to ensure
         * the bootROM is mapped at the correct address.
@@ -223,7 +221,6 @@ static int mv98dx3236_boot_secondary(unsigned int cpu, struct task_struct *idle)
        int ret, hw_cpu;
 
        hw_cpu = cpu_logical_map(cpu);
-       set_secondary_cpu_clock(hw_cpu);
        mv98dx3236_resume_set_cpu_boot_addr(hw_cpu,
                                            armada_xp_secondary_startup);
 
index 27a78c8..73d5d72 100644 (file)
@@ -116,8 +116,8 @@ void mvebu_pmsu_set_cpu_boot_addr(int hw_cpu, void *boot_addr)
                PMSU_BOOT_ADDR_REDIRECT_OFFSET(hw_cpu));
 }
 
-extern unsigned char mvebu_boot_wa_start;
-extern unsigned char mvebu_boot_wa_end;
+extern unsigned char mvebu_boot_wa_start[];
+extern unsigned char mvebu_boot_wa_end[];
 
 /*
  * This function sets up the boot address workaround needed for SMP
@@ -130,7 +130,7 @@ int mvebu_setup_boot_addr_wa(unsigned int crypto_eng_target,
                             phys_addr_t resume_addr_reg)
 {
        void __iomem *sram_virt_base;
-       u32 code_len = &mvebu_boot_wa_end - &mvebu_boot_wa_start;
+       u32 code_len = mvebu_boot_wa_end - mvebu_boot_wa_start;
 
        mvebu_mbus_del_window(BOOTROM_BASE, BOOTROM_SIZE);
        mvebu_mbus_add_window_by_id(crypto_eng_target, crypto_eng_attribute,
index bf60844..ddc2763 100644 (file)
  */
 
 #include <linux/linkage.h>
-#include <asm/assembler.h>
+#include <linux/platform_data/ams-delta-fiq.h>
 
+#include <asm/assembler.h>
 #include <mach/board-ams-delta.h>
-#include <mach/ams-delta-fiq.h>
 
+#include "ams-delta-fiq.h"
 #include "iomap.h"
 #include "soc.h"
 
index d7ca9e2..b0dc7dd 100644 (file)
  * under the terms of the GNU General Public License version 2 as published by
  * the Free Software Foundation.
  */
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
+#include <linux/gpio/driver.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/module.h>
 #include <linux/io.h>
+#include <linux/platform_data/ams-delta-fiq.h>
+#include <linux/platform_device.h>
 
 #include <mach/board-ams-delta.h>
 
 #include <asm/fiq.h>
 
-#include <mach/ams-delta-fiq.h>
+#include "ams-delta-fiq.h"
 
 static struct fiq_handler fh = {
        .name   = "ams-delta-fiq"
@@ -34,20 +37,24 @@ static struct fiq_handler fh = {
  * The FIQ and IRQ isrs can both read and write it.
  * It is structured as a header section several 32bit slots,
  * followed by the circular buffer where the FIQ isr stores
- * keystrokes received from the qwerty keyboard.
- * See ams-delta-fiq.h for details of offsets.
+ * keystrokes received from the qwerty keyboard.  See
+ * <linux/platform_data/ams-delta-fiq.h> for details of offsets.
  */
-unsigned int fiq_buffer[1024];
-EXPORT_SYMBOL(fiq_buffer);
+static unsigned int fiq_buffer[1024];
 
+static struct irq_chip *irq_chip;
+static struct irq_data *irq_data[16];
 static unsigned int irq_counter[16];
 
+static const char *pin_name[16] __initconst = {
+       [AMS_DELTA_GPIO_PIN_KEYBRD_DATA]        = "keybrd_data",
+       [AMS_DELTA_GPIO_PIN_KEYBRD_CLK]         = "keybrd_clk",
+};
+
 static irqreturn_t deferred_fiq(int irq, void *dev_id)
 {
+       struct irq_data *d;
        int gpio, irq_num, fiq_count;
-       struct irq_chip *irq_chip;
-
-       irq_chip = irq_get_chip(gpio_to_irq(AMS_DELTA_GPIO_PIN_KEYBRD_CLK));
 
        /*
         * For each handled GPIO interrupt, keep calling its interrupt handler
@@ -55,24 +62,21 @@ static irqreturn_t deferred_fiq(int irq, void *dev_id)
         */
        for (gpio = AMS_DELTA_GPIO_PIN_KEYBRD_CLK;
                        gpio <= AMS_DELTA_GPIO_PIN_HOOK_SWITCH; gpio++) {
-               irq_num = gpio_to_irq(gpio);
+               d = irq_data[gpio];
+               irq_num = d->irq;
                fiq_count = fiq_buffer[FIQ_CNT_INT_00 + gpio];
 
                if (irq_counter[gpio] < fiq_count &&
                                gpio != AMS_DELTA_GPIO_PIN_KEYBRD_CLK) {
-                       struct irq_data *d = irq_get_irq_data(irq_num);
-
                        /*
                         * handle_simple_irq() that OMAP GPIO edge
                         * interrupts default to since commit 80ac93c27441
                         * requires interrupt already acked and unmasked.
                         */
-                       if (irq_chip) {
-                               if (irq_chip->irq_ack)
-                                       irq_chip->irq_ack(d);
-                               if (irq_chip->irq_unmask)
-                                       irq_chip->irq_unmask(d);
-                       }
+                       if (irq_chip->irq_ack)
+                               irq_chip->irq_ack(d);
+                       if (irq_chip->irq_unmask)
+                               irq_chip->irq_unmask(d);
                }
                for (; irq_counter[gpio] < fiq_count; irq_counter[gpio]++)
                        generic_handle_irq(irq_num);
@@ -80,14 +84,56 @@ static irqreturn_t deferred_fiq(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
-void __init ams_delta_init_fiq(void)
+void __init ams_delta_init_fiq(struct gpio_chip *chip,
+                              struct platform_device *serio)
 {
+       struct gpio_desc *gpiod, *data = NULL, *clk = NULL;
        void *fiqhandler_start;
        unsigned int fiqhandler_length;
        struct pt_regs FIQ_regs;
        unsigned long val, offset;
        int i, retval;
 
+       /* Store irq_chip location for IRQ handler use */
+       irq_chip = chip->irq.chip;
+       if (!irq_chip) {
+               pr_err("%s: GPIO chip %s is missing IRQ function\n", __func__,
+                      chip->label);
+               return;
+       }
+
+       for (i = 0; i < ARRAY_SIZE(irq_data); i++) {
+               gpiod = gpiochip_request_own_desc(chip, i, pin_name[i]);
+               if (IS_ERR(gpiod)) {
+                       pr_err("%s: failed to get GPIO pin %d (%ld)\n",
+                              __func__, i, PTR_ERR(gpiod));
+                       return;
+               }
+               /* Store irq_data location for IRQ handler use */
+               irq_data[i] = irq_get_irq_data(gpiod_to_irq(gpiod));
+
+               /*
+                * FIQ handler takes full control over serio data and clk GPIO
+                * pins.  Initiaize them and keep requested so nobody can
+                * interfere.  Fail if any of those two couldn't be requested.
+                */
+               switch (i) {
+               case AMS_DELTA_GPIO_PIN_KEYBRD_DATA:
+                       data = gpiod;
+                       gpiod_direction_input(data);
+                       break;
+               case AMS_DELTA_GPIO_PIN_KEYBRD_CLK:
+                       clk = gpiod;
+                       gpiod_direction_input(clk);
+                       break;
+               default:
+                       gpiochip_free_own_desc(gpiod);
+                       break;
+               }
+       }
+       if (!data || !clk)
+               goto out_gpio;
+
        fiqhandler_start = &qwerty_fiqin_start;
        fiqhandler_length = &qwerty_fiqin_end - &qwerty_fiqin_start;
        pr_info("Installing fiq handler from %p, length 0x%x\n",
@@ -97,7 +143,7 @@ void __init ams_delta_init_fiq(void)
        if (retval) {
                pr_err("ams_delta_init_fiq(): couldn't claim FIQ, ret=%d\n",
                                retval);
-               return;
+               goto out_gpio;
        }
 
        retval = request_irq(INT_DEFERRED_FIQ, deferred_fiq,
@@ -105,7 +151,7 @@ void __init ams_delta_init_fiq(void)
        if (retval < 0) {
                pr_err("Failed to get deferred_fiq IRQ, ret=%d\n", retval);
                release_fiq(&fh);
-               return;
+               goto out_gpio;
        }
        /*
         * Since no set_type() method is provided by OMAP irq chip,
@@ -155,4 +201,29 @@ void __init ams_delta_init_fiq(void)
        offset = IRQ_ILR0_REG_OFFSET + (INT_GPIO_BANK1 - NR_IRQS_LEGACY) * 0x4;
        val = omap_readl(OMAP_IH1_BASE + offset) | 1;
        omap_writel(val, OMAP_IH1_BASE + offset);
+
+       /* Initialize serio device IRQ resource and platform_data */
+       serio->resource[0].start = gpiod_to_irq(clk);
+       serio->resource[0].end = serio->resource[0].start;
+       serio->dev.platform_data = fiq_buffer;
+
+       /*
+        * Since FIQ handler performs handling of GPIO registers for
+        * "keybrd_clk" IRQ pin, ams_delta_serio driver used to set
+        * handle_simple_irq() as active IRQ handler for that pin to avoid
+        * bad interaction with gpio-omap driver.  This is no longer needed
+        * as handle_simple_irq() is now the default handler for OMAP GPIO
+        * edge interrupts.
+        * This comment replaces the obsolete code which has been removed
+        * from the ams_delta_serio driver and stands here only as a reminder
+        * of that dependency on gpio-omap driver behavior.
+        */
+
+       return;
+
+out_gpio:
+       if (data)
+               gpiochip_free_own_desc(data);
+       if (clk)
+               gpiochip_free_own_desc(clk);
 }
diff --git a/arch/arm/mach-omap1/ams-delta-fiq.h b/arch/arm/mach-omap1/ams-delta-fiq.h
new file mode 100644 (file)
index 0000000..fd76df3
--- /dev/null
@@ -0,0 +1,42 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/*
+ * arch/arm/mach-omap1/ams-delta-fiq.h
+ *
+ * Taken from the original Amstrad modifications to fiq.h
+ *
+ * Copyright (c) 2004 Amstrad Plc
+ * Copyright (c) 2006 Matt Callow
+ * Copyright (c) 2010 Janusz Krzysztofik
+ *
+ * This program is free software; you can 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 __AMS_DELTA_FIQ_H
+#define __AMS_DELTA_FIQ_H
+
+#include <mach/irqs.h>
+
+/*
+ * Interrupt number used for passing control from FIQ to IRQ.
+ * IRQ12, described as reserved, has been selected.
+ */
+#define INT_DEFERRED_FIQ       INT_1510_RES12
+/*
+ * Base address of an interrupt handler that the INT_DEFERRED_FIQ belongs to.
+ */
+#if (INT_DEFERRED_FIQ < IH2_BASE)
+#define DEFERRED_FIQ_IH_BASE   OMAP_IH1_BASE
+#else
+#define DEFERRED_FIQ_IH_BASE   OMAP_IH2_BASE
+#endif
+
+#ifndef __ASSEMBLER__
+extern unsigned char qwerty_fiqin_start, qwerty_fiqin_end;
+
+extern void __init ams_delta_init_fiq(struct gpio_chip *chip,
+                                     struct platform_device *pdev);
+#endif
+
+#endif
index 80f54cb..dd28d26 100644 (file)
 #include <mach/mux.h>
 
 #include <mach/hardware.h>
-#include <mach/ams-delta-fiq.h>
 #include "camera.h"
 #include <mach/usb.h>
 
+#include "ams-delta-fiq.h"
 #include "iomap.h"
 #include "common.h"
 
@@ -179,7 +179,10 @@ static struct resource latch1_resources[] = {
        },
 };
 
+#define LATCH1_LABEL   "latch1"
+
 static struct bgpio_pdata latch1_pdata = {
+       .label  = LATCH1_LABEL,
        .base   = LATCH1_GPIO_BASE,
        .ngpio  = LATCH1_NGPIO,
 };
@@ -194,6 +197,15 @@ static struct platform_device latch1_gpio_device = {
        },
 };
 
+#define LATCH1_PIN_LED_CAMERA          0
+#define LATCH1_PIN_LED_ADVERT          1
+#define LATCH1_PIN_LED_MAIL            2
+#define LATCH1_PIN_LED_HANDSFREE       3
+#define LATCH1_PIN_LED_VOICEMAIL       4
+#define LATCH1_PIN_LED_VOICE           5
+#define LATCH1_PIN_DOCKIT1             6
+#define LATCH1_PIN_DOCKIT2             7
+
 static struct resource latch2_resources[] = {
        [0] = {
                .name   = "dat",
@@ -398,38 +410,43 @@ static struct gpiod_lookup_table ams_delta_lcd_gpio_table = {
        },
 };
 
-static const struct gpio_led gpio_leds[] __initconst = {
-       {
+/*
+ * Dynamically allocated GPIO numbers must be obtained fromm GPIO device
+ * before they can be put in the gpio_led table.  Before that happens,
+ * initialize the table with invalid GPIO numbers, not 0.
+ */
+static struct gpio_led gpio_leds[] __initdata = {
+       [LATCH1_PIN_LED_CAMERA] = {
                .name            = "camera",
-               .gpio            = LATCH1_GPIO_BASE + 0,
+               .gpio            = -EINVAL,
                .default_state   = LEDS_GPIO_DEFSTATE_OFF,
 #ifdef CONFIG_LEDS_TRIGGERS
                .default_trigger = "ams_delta_camera",
 #endif
        },
-       {
+       [LATCH1_PIN_LED_ADVERT] = {
                .name            = "advert",
-               .gpio            = LATCH1_GPIO_BASE + 1,
+               .gpio            = -EINVAL,
                .default_state   = LEDS_GPIO_DEFSTATE_OFF,
        },
-       {
+       [LATCH1_PIN_LED_MAIL] = {
                .name            = "email",
-               .gpio            = LATCH1_GPIO_BASE + 2,
+               .gpio            = -EINVAL,
                .default_state   = LEDS_GPIO_DEFSTATE_OFF,
        },
-       {
+       [LATCH1_PIN_LED_HANDSFREE] = {
                .name            = "handsfree",
-               .gpio            = LATCH1_GPIO_BASE + 3,
+               .gpio            = -EINVAL,
                .default_state   = LEDS_GPIO_DEFSTATE_OFF,
        },
-       {
+       [LATCH1_PIN_LED_VOICEMAIL] = {
                .name            = "voicemail",
-               .gpio            = LATCH1_GPIO_BASE + 4,
+               .gpio            = -EINVAL,
                .default_state   = LEDS_GPIO_DEFSTATE_OFF,
        },
-       {
+       [LATCH1_PIN_LED_VOICE] = {
                .name            = "voice",
-               .gpio            = LATCH1_GPIO_BASE + 5,
+               .gpio            = -EINVAL,
                .default_state   = LEDS_GPIO_DEFSTATE_OFF,
        },
 };
@@ -504,16 +521,70 @@ static struct platform_device cx20442_codec_device = {
        .id     = -1,
 };
 
-static struct gpiod_lookup_table ams_delta_serio_gpio_table = {
+static struct resource ams_delta_serio_resources[] = {
+       {
+               .flags  = IORESOURCE_IRQ,
+               /*
+                * Initialize IRQ resource with invalid IRQ number.
+                * It will be replaced with dynamically allocated GPIO IRQ
+                * obtained from GPIO chip as soon as the chip is available.
+                */
+               .start  = -EINVAL,
+               .end    = -EINVAL,
+       },
+};
+
+static struct platform_device ams_delta_serio_device = {
+       .name           = "ams-delta-serio",
+       .id             = PLATFORM_DEVID_NONE,
+       .dev            = {
+               /*
+                * Initialize .platform_data explicitly with NULL to
+                * indicate it is going to be used.  It will be replaced
+                * with FIQ buffer address as soon as FIQ is initialized.
+                */
+               .platform_data = NULL,
+       },
+       .num_resources  = ARRAY_SIZE(ams_delta_serio_resources),
+       .resource       = ams_delta_serio_resources,
+};
+
+static struct regulator_consumer_supply keybrd_pwr_consumers[] = {
+       /*
+        * Initialize supply .dev_name with NULL.  It will be replaced
+        * with serio dev_name() as soon as the serio device is registered.
+        */
+       REGULATOR_SUPPLY("vcc", NULL),
+};
+
+static struct regulator_init_data keybrd_pwr_initdata = {
+       .constraints            = {
+               .valid_ops_mask         = REGULATOR_CHANGE_STATUS,
+       },
+       .num_consumer_supplies  = ARRAY_SIZE(keybrd_pwr_consumers),
+       .consumer_supplies      = keybrd_pwr_consumers,
+};
+
+static struct fixed_voltage_config keybrd_pwr_config = {
+       .supply_name            = "keybrd_pwr",
+       .microvolts             = 5000000,
+       .gpio                   = AMS_DELTA_GPIO_PIN_KEYBRD_PWR,
+       .enable_high            = 1,
+       .init_data              = &keybrd_pwr_initdata,
+};
+
+static struct platform_device keybrd_pwr_device = {
+       .name   = "reg-fixed-voltage",
+       .id     = PLATFORM_DEVID_AUTO,
+       .dev    = {
+               .platform_data  = &keybrd_pwr_config,
+       },
+};
+
+static struct gpiod_lookup_table keybrd_pwr_gpio_table = {
        .table = {
-               GPIO_LOOKUP(OMAP_GPIO_LABEL, AMS_DELTA_GPIO_PIN_KEYBRD_DATA,
-                           "data", 0),
-               GPIO_LOOKUP(OMAP_GPIO_LABEL, AMS_DELTA_GPIO_PIN_KEYBRD_CLK,
-                           "clock", 0),
-               GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_KEYBRD_PWR,
-                           "power", 0),
-               GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_KEYBRD_DATAOUT,
-                           "dataout", 0),
+               GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_KEYBRD_PWR, NULL,
+                           GPIO_ACTIVE_HIGH),
                { },
        },
 };
@@ -524,9 +595,7 @@ static struct platform_device *ams_delta_devices[] __initdata = {
        &ams_delta_kp_device,
        &ams_delta_camera_device,
        &ams_delta_audio_device,
-};
-
-static struct platform_device *late_devices[] __initdata = {
+       &ams_delta_serio_device,
        &ams_delta_nand_device,
        &ams_delta_lcd_device,
        &cx20442_codec_device,
@@ -534,14 +603,55 @@ static struct platform_device *late_devices[] __initdata = {
 
 static struct gpiod_lookup_table *ams_delta_gpio_tables[] __initdata = {
        &ams_delta_audio_gpio_table,
-       &ams_delta_serio_gpio_table,
-};
-
-static struct gpiod_lookup_table *late_gpio_tables[] __initdata = {
+       &keybrd_pwr_gpio_table,
        &ams_delta_lcd_gpio_table,
        &ams_delta_nand_gpio_table,
 };
 
+/*
+ * Some drivers may not use GPIO lookup tables but need to be provided
+ * with GPIO numbers.  The same applies to GPIO based IRQ lines - some
+ * drivers may even not use GPIO layer but expect just IRQ numbers.
+ * We could either define GPIO lookup tables then use them on behalf
+ * of those devices, or we can use GPIO driver level methods for
+ * identification of GPIO and IRQ numbers. For the purpose of the latter,
+ * defina a helper function which identifies GPIO chips by their labels.
+ */
+static int gpiochip_match_by_label(struct gpio_chip *chip, void *data)
+{
+       char *label = data;
+
+       return !strcmp(label, chip->label);
+}
+
+static struct gpiod_hog ams_delta_gpio_hogs[] = {
+       GPIO_HOG(LATCH2_LABEL, LATCH2_PIN_KEYBRD_DATAOUT, "keybrd_dataout",
+                GPIO_ACTIVE_HIGH, GPIOD_OUT_LOW),
+       {},
+};
+
+/*
+ * The purpose of this function is to take care of proper initialization of
+ * devices and data structures which depend on GPIO lines provided by OMAP GPIO
+ * banks but their drivers don't use GPIO lookup tables or GPIO layer at all.
+ * The function may be called as soon as OMAP GPIO devices are probed.
+ * Since that happens at postcore_initcall, it can be called successfully
+ * from init_machine or later.
+ * Dependent devices may be registered from within this function or later.
+ */
+static void __init omap_gpio_deps_init(void)
+{
+       struct gpio_chip *chip;
+
+       chip = gpiochip_find(OMAP_GPIO_LABEL, gpiochip_match_by_label);
+       if (!chip) {
+               pr_err("%s: OMAP GPIO chip not found\n", __func__);
+               return;
+       }
+
+       ams_delta_init_fiq(chip, &ams_delta_serio_device);
+}
+
 static void __init ams_delta_init(void)
 {
        /* mux pins for uarts */
@@ -562,6 +672,9 @@ static void __init ams_delta_init(void)
        omap_cfg_reg(J19_1610_CAM_D6);
        omap_cfg_reg(J18_1610_CAM_D7);
 
+       omap_gpio_deps_init();
+       gpiod_add_hogs(ams_delta_gpio_hogs);
+
        omap_serial_init();
        omap_register_i2c_bus(1, 100, NULL, 0);
 
@@ -571,25 +684,38 @@ static void __init ams_delta_init(void)
        led_trigger_register_simple("ams_delta_camera",
                        &ams_delta_camera_led_trigger);
 #endif
-       gpio_led_register_device(-1, &leds_pdata);
        platform_add_devices(ams_delta_devices, ARRAY_SIZE(ams_delta_devices));
 
        /*
-        * As soon as devices have been registered, assign their dev_names
-        * to respective GPIO lookup tables before they are added.
+        * As soon as regulator consumers have been registered, assign their
+        * dev_names to consumer supply entries of respective regulators.
+        */
+       keybrd_pwr_consumers[0].dev_name =
+                       dev_name(&ams_delta_serio_device.dev);
+
+       /*
+        * Once consumer supply entries are populated with dev_names,
+        * register regulator devices.  At this stage only the keyboard
+        * power regulator has its consumer supply table fully populated.
+        */
+       platform_device_register(&keybrd_pwr_device);
+
+       /*
+        * As soon as GPIO consumers have been registered, assign
+        * their dev_names to respective GPIO lookup tables.
         */
        ams_delta_audio_gpio_table.dev_id =
                        dev_name(&ams_delta_audio_device.dev);
+       keybrd_pwr_gpio_table.dev_id = dev_name(&keybrd_pwr_device.dev);
+       ams_delta_nand_gpio_table.dev_id = dev_name(&ams_delta_nand_device.dev);
+       ams_delta_lcd_gpio_table.dev_id = dev_name(&ams_delta_lcd_device.dev);
+
        /*
-        * No device name is assigned to GPIO lookup table for serio device
-        * as long as serio driver is not converted to platform device driver.
+        * Once GPIO lookup tables are populated with dev_names, register them.
         */
-
        gpiod_add_lookup_tables(ams_delta_gpio_tables,
                                ARRAY_SIZE(ams_delta_gpio_tables));
 
-       ams_delta_init_fiq();
-
        omap_writew(omap_readw(ARM_RSTCT1) | 0x0004, ARM_RSTCT1);
 
        omapfb_set_lcd_config(&ams_delta_lcd_config);
@@ -643,35 +769,84 @@ static struct platform_device ams_delta_modem_device = {
        },
 };
 
-static int __init late_init(void)
+/*
+ * leds-gpio driver doesn't make use of GPIO lookup tables,
+ * it has to be provided with GPIO numbers over platform data
+ * if GPIO descriptor info can't be obtained from device tree.
+ * We could either define GPIO lookup tables and use them on behalf
+ * of the leds-gpio device, or we can use GPIO driver level methods
+ * for identification of GPIO numbers as long as we don't support
+ * device tree.  Let's do the latter.
+ */
+static void __init ams_delta_led_init(struct gpio_chip *chip)
+{
+       struct gpio_desc *gpiod;
+       int i;
+
+       for (i = LATCH1_PIN_LED_CAMERA; i < LATCH1_PIN_DOCKIT1; i++) {
+               gpiod = gpiochip_request_own_desc(chip, i, NULL);
+               if (IS_ERR(gpiod)) {
+                       pr_warn("%s: %s GPIO %d request failed (%ld)\n",
+                               __func__, LATCH1_LABEL, i, PTR_ERR(gpiod));
+                       continue;
+               }
+
+               /* Assign GPIO numbers to LED device. */
+               gpio_leds[i].gpio = desc_to_gpio(gpiod);
+
+               gpiochip_free_own_desc(gpiod);
+       }
+
+       gpio_led_register_device(PLATFORM_DEVID_NONE, &leds_pdata);
+}
+
+/*
+ * The purpose of this function is to take care of assignment of GPIO numbers
+ * to platform devices which depend on GPIO lines provided by Amstrad Delta
+ * latch1 and/or latch2 GPIO devices but don't use GPIO lookup tables.
+ * The function may be called as soon as latch1/latch2 GPIO devices are
+ * initilized.  Since basic-mmio-gpio driver is not registered before
+ * device_initcall, this may happen at erliest during device_initcall_sync.
+ * Dependent devices shouldn't be registered before that, their
+ * registration may be performed from within this function or later.
+ */
+static int __init ams_delta_gpio_init(void)
 {
+       struct gpio_chip *chip;
        int err;
 
        if (!machine_is_ams_delta())
                return -ENODEV;
 
+       chip = gpiochip_find(LATCH1_LABEL, gpiochip_match_by_label);
+       if (!chip)
+               pr_err("%s: latch1 GPIO chip not found\n", __func__);
+       else
+               ams_delta_led_init(chip);
+
        err = gpio_request_array(latch_gpios, ARRAY_SIZE(latch_gpios));
-       if (err) {
+       if (err)
                pr_err("Couldn't take over latch1/latch2 GPIO pins\n");
-               return err;
-       }
 
-       platform_add_devices(late_devices, ARRAY_SIZE(late_devices));
-
-       /*
-        * As soon as devices have been registered, assign their dev_names
-        * to respective GPIO lookup tables before they are added.
-        */
-       ams_delta_lcd_gpio_table.dev_id = dev_name(&ams_delta_lcd_device.dev);
-       ams_delta_nand_gpio_table.dev_id = dev_name(&ams_delta_nand_device.dev);
+       return err;
+}
+device_initcall_sync(ams_delta_gpio_init);
 
-       gpiod_add_lookup_tables(late_gpio_tables, ARRAY_SIZE(late_gpio_tables));
+static int __init modem_nreset_init(void)
+{
+       int err;
 
        err = platform_device_register(&modem_nreset_device);
-       if (err) {
+       if (err)
                pr_err("Couldn't register the modem regulator device\n");
-               return err;
-       }
+
+       return err;
+}
+
+
+static int __init ams_delta_modem_init(void)
+{
+       int err;
 
        omap_cfg_reg(M14_1510_GPIO2);
        ams_delta_modem_ports[0].irq =
@@ -692,7 +867,22 @@ static int __init late_init(void)
 
        err = platform_device_register(&ams_delta_modem_device);
        if (err)
-               goto gpio_free;
+               gpio_free(AMS_DELTA_GPIO_PIN_MODEM_IRQ);
+
+       return err;
+}
+
+static int __init late_init(void)
+{
+       int err;
+
+       err = modem_nreset_init();
+       if (err)
+               return err;
+
+       err = ams_delta_modem_init();
+       if (err)
+               return err;
 
        /*
         * Once the modem device is registered, the modem_nreset
@@ -708,7 +898,6 @@ static int __init late_init(void)
 
 unregister:
        platform_device_unregister(&ams_delta_modem_device);
-gpio_free:
        gpio_free(AMS_DELTA_GPIO_PIN_MODEM_IRQ);
        return err;
 }
index ab51f85..9aeb8ad 100644 (file)
@@ -274,7 +274,7 @@ static struct platform_device h2_kp_device = {
        .resource       = h2_kp_resources,
 };
 
-static struct gpio_led h2_gpio_led_pins[] = {
+static const struct gpio_led h2_gpio_led_pins[] = {
        {
                .name           = "h2:red",
                .default_trigger = "heartbeat",
index ad339f5..2edcd63 100644 (file)
@@ -326,7 +326,7 @@ static struct spi_board_info h3_spi_board_info[] __initdata = {
        },
 };
 
-static struct gpio_led h3_gpio_led_pins[] = {
+static const struct gpio_led h3_gpio_led_pins[] = {
        {
                .name           = "h3:red",
                .default_trigger = "heartbeat",
index da8f3fc..5733212 100644 (file)
@@ -292,7 +292,7 @@ static struct platform_device herald_gpiokeys_device = {
 };
 
 /* LEDs for the Herald.  These connect to the HTCPLD GPIO device. */
-static struct gpio_led gpio_leds[] = {
+static const struct gpio_led gpio_leds[] = {
        {"dpad",        NULL, HTCPLD_GPIO_LED_DPAD,        0, 0, LEDS_GPIO_DEFSTATE_OFF},
        {"kbd",         NULL, HTCPLD_GPIO_LED_KBD,         0, 0, LEDS_GPIO_DEFSTATE_OFF},
        {"vibrate",     NULL, HTCPLD_GPIO_LED_VIBRATE,     0, 0, LEDS_GPIO_DEFSTATE_OFF},
index 9ffa8d7..4df15e6 100644 (file)
@@ -167,7 +167,7 @@ static struct platform_device *osk5912_devices[] __initdata = {
        &osk5912_cf_device,
 };
 
-static struct gpio_led tps_leds[] = {
+static const struct gpio_led tps_leds[] = {
        /* NOTE:  D9 and D2 have hardware blink support.
         * Also, D9 requires non-battery power.
         */
@@ -385,7 +385,7 @@ static struct platform_device osk5912_lcd_device = {
        .id             = -1,
 };
 
-static struct gpio_led mistral_gpio_led_pins[] = {
+static const struct gpio_led mistral_gpio_led_pins[] = {
        {
                .name           = "mistral:red",
                .default_trigger = "heartbeat",
index b68f9c0..d5ddba0 100644 (file)
@@ -92,11 +92,13 @@ static void omap_rtc_wait_not_busy(struct omap_hwmod *oh)
  */
 void omap_hwmod_rtc_unlock(struct omap_hwmod *oh)
 {
-       local_irq_disable();
+       unsigned long flags;
+
+       local_irq_save(flags);
        omap_rtc_wait_not_busy(oh);
        omap_hwmod_write(OMAP_RTC_KICK0_VALUE, oh, OMAP_RTC_KICK0_REG);
        omap_hwmod_write(OMAP_RTC_KICK1_VALUE, oh, OMAP_RTC_KICK1_REG);
-       local_irq_enable();
+       local_irq_restore(flags);
 }
 
 /**
@@ -110,9 +112,11 @@ void omap_hwmod_rtc_unlock(struct omap_hwmod *oh)
  */
 void omap_hwmod_rtc_lock(struct omap_hwmod *oh)
 {
-       local_irq_disable();
+       unsigned long flags;
+
+       local_irq_save(flags);
        omap_rtc_wait_not_busy(oh);
        omap_hwmod_write(0x0, oh, OMAP_RTC_KICK0_REG);
        omap_hwmod_write(0x0, oh, OMAP_RTC_KICK1_REG);
-       local_irq_enable();
+       local_irq_restore(flags);
 }
index b9846b1..d8ae8a8 100644 (file)
@@ -27,6 +27,8 @@ int main(void)
               offsetof(struct am33xx_pm_ro_sram_data, amx3_pm_sram_data_virt));
        DEFINE(AMX3_PM_RO_SRAM_DATA_PHYS_OFFSET,
               offsetof(struct am33xx_pm_ro_sram_data, amx3_pm_sram_data_phys));
+       DEFINE(AMX3_PM_RTC_BASE_VIRT_OFFSET,
+              offsetof(struct am33xx_pm_ro_sram_data, rtc_base_virt));
        DEFINE(AMX3_PM_RO_SRAM_DATA_SIZE,
               sizeof(struct am33xx_pm_ro_sram_data));
 
index acb698d..5a88392 100644 (file)
@@ -47,11 +47,6 @@ static int pm_dbg_init_done;
 
 static int pm_dbg_init(void);
 
-enum {
-       DEBUG_FILE_COUNTERS = 0,
-       DEBUG_FILE_TIMERS,
-};
-
 static const char pwrdm_state_names[][PWRDM_MAX_PWRSTS] = {
        "OFF",
        "RET",
@@ -141,39 +136,21 @@ static int pwrdm_dbg_show_timer(struct powerdomain *pwrdm, void *user)
        return 0;
 }
 
-static int pm_dbg_show_counters(struct seq_file *s, void *unused)
+static int pm_dbg_counters_show(struct seq_file *s, void *unused)
 {
        pwrdm_for_each(pwrdm_dbg_show_counter, s);
        clkdm_for_each(clkdm_dbg_show_counter, s);
 
        return 0;
 }
+DEFINE_SHOW_ATTRIBUTE(pm_dbg_counters);
 
-static int pm_dbg_show_timers(struct seq_file *s, void *unused)
+static int pm_dbg_timers_show(struct seq_file *s, void *unused)
 {
        pwrdm_for_each(pwrdm_dbg_show_timer, s);
        return 0;
 }
-
-static int pm_dbg_open(struct inode *inode, struct file *file)
-{
-       switch ((int)inode->i_private) {
-       case DEBUG_FILE_COUNTERS:
-               return single_open(file, pm_dbg_show_counters,
-                       &inode->i_private);
-       case DEBUG_FILE_TIMERS:
-       default:
-               return single_open(file, pm_dbg_show_timers,
-                       &inode->i_private);
-       }
-}
-
-static const struct file_operations debug_fops = {
-       .open           = pm_dbg_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-};
+DEFINE_SHOW_ATTRIBUTE(pm_dbg_timers);
 
 static int pwrdm_suspend_get(void *data, u64 *val)
 {
@@ -259,10 +236,8 @@ static int __init pm_dbg_init(void)
        if (!d)
                return -EINVAL;
 
-       (void) debugfs_create_file("count", S_IRUGO,
-               d, (void *)DEBUG_FILE_COUNTERS, &debug_fops);
-       (void) debugfs_create_file("time", S_IRUGO,
-               d, (void *)DEBUG_FILE_TIMERS, &debug_fops);
+       (void) debugfs_create_file("count", 0444, d, NULL, &pm_dbg_counters_fops);
+       (void) debugfs_create_file("time", 0444, d, NULL, &pm_dbg_timers_fops);
 
        pwrdm_for_each(pwrdms_setup, (void *)d);
 
index 9b3755a..f4971e4 100644 (file)
@@ -26,6 +26,7 @@
 static struct powerdomain *cefuse_pwrdm, *gfx_pwrdm, *per_pwrdm, *mpu_pwrdm;
 static struct clockdomain *gfx_l4ls_clkdm;
 static void __iomem *scu_base;
+static struct omap_hwmod *rtc_oh;
 
 static int __init am43xx_map_scu(void)
 {
@@ -106,12 +107,13 @@ static void amx3_post_suspend_common(void)
                pr_err("PM: GFX domain did not transition: %x\n", status);
 }
 
-static int am33xx_suspend(unsigned int state, int (*fn)(unsigned long))
+static int am33xx_suspend(unsigned int state, int (*fn)(unsigned long),
+                         unsigned long args)
 {
        int ret = 0;
 
        amx3_pre_suspend_common();
-       ret = cpu_suspend(0, fn);
+       ret = cpu_suspend(args, fn);
        amx3_post_suspend_common();
 
        /*
@@ -128,13 +130,14 @@ static int am33xx_suspend(unsigned int state, int (*fn)(unsigned long))
        return ret;
 }
 
-static int am43xx_suspend(unsigned int state, int (*fn)(unsigned long))
+static int am43xx_suspend(unsigned int state, int (*fn)(unsigned long),
+                         unsigned long args)
 {
        int ret = 0;
 
        amx3_pre_suspend_common();
        scu_power_mode(scu_base, SCU_PM_POWEROFF);
-       ret = cpu_suspend(0, fn);
+       ret = cpu_suspend(args, fn);
        scu_power_mode(scu_base, SCU_PM_NORMAL);
        amx3_post_suspend_common();
 
@@ -151,16 +154,25 @@ static struct am33xx_pm_sram_addr *amx3_get_sram_addrs(void)
                return NULL;
 }
 
+void __iomem *am43xx_get_rtc_base_addr(void)
+{
+       rtc_oh = omap_hwmod_lookup("rtc");
+
+       return omap_hwmod_get_mpu_rt_va(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,
+       .get_rtc_base_addr = am43xx_get_rtc_base_addr,
 };
 
 static struct am33xx_pm_platform_data am43xx_ops = {
        .init = am43xx_suspend_init,
        .soc_suspend = am43xx_suspend,
        .get_sram_addrs = amx3_get_sram_addrs,
+       .get_rtc_base_addr = am43xx_get_rtc_base_addr,
 };
 
 static struct am33xx_pm_platform_data *am33xx_pm_get_pdata(void)
index 322b3bb..47a8164 100644 (file)
@@ -8,6 +8,7 @@
 
 #include <generated/ti-pm-asm-offsets.h>
 #include <linux/linkage.h>
+#include <linux/platform_data/pm33xx.h>
 #include <linux/ti-emif-sram.h>
 #include <asm/assembler.h>
 #include <asm/memory.h>
 #define AM33XX_CM_CLKCTRL_MODULEMODE_DISABLE                   0x0003
 #define AM33XX_CM_CLKCTRL_MODULEMODE_ENABLE                    0x0002
 
+/* replicated define because linux/bitops.h cannot be included in assembly */
+#define BIT(nr)                        (1 << (nr))
+
        .arm
        .align 3
 
 ENTRY(am33xx_do_wfi)
        stmfd   sp!, {r4 - r11, lr}     @ save registers on stack
 
+       /* Save wfi_flags arg to data space */
+       mov     r4, r0
+       adr     r3, am33xx_pm_ro_sram_data
+       ldr     r2, [r3, #AMX3_PM_RO_SRAM_DATA_VIRT_OFFSET]
+       str     r4, [r2, #AMX3_PM_WFI_FLAGS_OFFSET]
+
+       /* Only flush cache is we know we are losing MPU context */
+       tst     r4, #WFI_FLAG_FLUSH_CACHE
+       beq     cache_skip_flush
+
        /*
         * Flush all data from the L1 and L2 data cache before disabling
         * SCTLR.C bit.
@@ -48,14 +62,33 @@ ENTRY(am33xx_do_wfi)
        ldr     r1, kernel_flush
        blx     r1
 
+       adr     r3, am33xx_pm_ro_sram_data
+       ldr     r2, [r3, #AMX3_PM_RO_SRAM_DATA_VIRT_OFFSET]
+       ldr     r4, [r2, #AMX3_PM_WFI_FLAGS_OFFSET]
+
+cache_skip_flush:
+       /* Check if we want self refresh */
+       tst     r4, #WFI_FLAG_SELF_REFRESH
+       beq     emif_skip_enter_sr
+
        adr     r9, am33xx_emif_sram_table
 
        ldr     r3, [r9, #EMIF_PM_ENTER_SR_OFFSET]
        blx     r3
 
+emif_skip_enter_sr:
+       /* Only necessary if PER is losing context */
+       tst     r4, #WFI_FLAG_SAVE_EMIF
+       beq     emif_skip_save
+
        ldr     r3, [r9, #EMIF_PM_SAVE_CONTEXT_OFFSET]
        blx     r3
 
+emif_skip_save:
+       /* Only can disable EMIF if we have entered self refresh */
+       tst     r4, #WFI_FLAG_SELF_REFRESH
+       beq     emif_skip_disable
+
        /* Disable EMIF */
        ldr     r1, virt_emif_clkctrl
        ldr     r2, [r1]
@@ -69,6 +102,10 @@ wait_emif_disable:
        cmp     r2, r3
        bne     wait_emif_disable
 
+emif_skip_disable:
+       tst     r4, #WFI_FLAG_WAKE_M3
+       beq     wkup_m3_skip
+
        /*
         * For the MPU WFI to be registered as an interrupt
         * to WKUP_M3, MPU_CLKCTRL.MODULEMODE needs to be set
@@ -79,6 +116,7 @@ wait_emif_disable:
        bic     r2, r2, #AM33XX_CM_CLKCTRL_MODULEMODE_DISABLE
        str     r2, [r1]
 
+wkup_m3_skip:
        /*
         * Execute an ISB instruction to ensure that all of the
         * CP15 register changes have been committed.
@@ -132,10 +170,18 @@ wait_emif_enable:
        cmp     r2, r3
        bne     wait_emif_enable
 
+       /* Only necessary if PER is losing context */
+       tst     r4, #WFI_FLAG_SELF_REFRESH
+       beq     emif_skip_exit_sr_abt
 
+       adr     r9, am33xx_emif_sram_table
        ldr     r1, [r9, #EMIF_PM_ABORT_SR_OFFSET]
        blx     r1
 
+emif_skip_exit_sr_abt:
+       tst     r4, #WFI_FLAG_FLUSH_CACHE
+       beq     cache_skip_restore
+
        /*
         * Set SCTLR.C bit to allow data cache allocation
         */
@@ -144,6 +190,7 @@ wait_emif_enable:
        mcr     p15, 0, r0, c1, c0, 0
        isb
 
+cache_skip_restore:
        /* Let the suspend code know about the abort */
        mov     r0, #1
        ldmfd   sp!, {r4 - r11, pc}     @ restore regs and return
@@ -181,8 +228,6 @@ ENDPROC(am33xx_resume_from_deep_sleep)
  * Local variables
  */
        .align
-resume_addr:
-       .word   cpu_resume - PAGE_OFFSET + 0x80000000
 kernel_flush:
        .word   v7_flush_dcache_all
 virt_mpu_clkctrl:
@@ -205,6 +250,9 @@ ENTRY(am33xx_pm_sram)
        .word am33xx_emif_sram_table
        .word am33xx_pm_ro_sram_data
 
+resume_addr:
+.word  cpu_resume - PAGE_OFFSET + 0x80000000
+
 .align 3
 ENTRY(am33xx_pm_ro_sram_data)
        .space AMX3_PM_RO_SRAM_DATA_SIZE
index 8903814..5b9343b 100644 (file)
@@ -9,7 +9,7 @@
 #include <generated/ti-pm-asm-offsets.h>
 #include <linux/linkage.h>
 #include <linux/ti-emif-sram.h>
-
+#include <linux/platform_data/pm33xx.h>
 #include <asm/assembler.h>
 #include <asm/hardware/cache-l2x0.h>
 #include <asm/memory.h>
@@ -22,6 +22,9 @@
 #include "prm33xx.h"
 #include "prcm43xx.h"
 
+/* replicated define because linux/bitops.h cannot be included in assembly */
+#define BIT(nr)                        (1 << (nr))
+
 #define AM33XX_CM_CLKCTRL_MODULESTATE_DISABLED         0x00030000
 #define AM33XX_CM_CLKCTRL_MODULEMODE_DISABLE           0x0003
 #define AM33XX_CM_CLKCTRL_MODULEMODE_ENABLE            0x0002
                                        AM43XX_CM_PER_EMIF_CLKCTRL_OFFSET)
 #define AM43XX_PRM_EMIF_CTRL_OFFSET                    0x0030
 
+#define RTC_SECONDS_REG                                        0x0
+#define RTC_PMIC_REG                                   0x98
+#define RTC_PMIC_POWER_EN                              BIT(16)
+#define RTC_PMIC_EXT_WAKEUP_STS                                BIT(12)
+#define RTC_PMIC_EXT_WAKEUP_POL                                BIT(4)
+#define RTC_PMIC_EXT_WAKEUP_EN                         BIT(0)
+
        .arm
        .align 3
 
 ENTRY(am43xx_do_wfi)
        stmfd   sp!, {r4 - r11, lr}     @ save registers on stack
 
+       /* Save wfi_flags arg to data space */
+       mov     r4, r0
+       adr     r3, am43xx_pm_ro_sram_data
+       ldr     r2, [r3, #AMX3_PM_RO_SRAM_DATA_VIRT_OFFSET]
+       str     r4, [r2, #AMX3_PM_WFI_FLAGS_OFFSET]
+
 #ifdef CONFIG_CACHE_L2X0
        /* Retrieve l2 cache virt address BEFORE we shut off EMIF */
        ldr     r1, get_l2cache_base
@@ -58,6 +74,10 @@ ENTRY(am43xx_do_wfi)
        mov     r8, r0
 #endif
 
+       /* Only flush cache is we know we are losing MPU context */
+       tst     r4, #WFI_FLAG_FLUSH_CACHE
+       beq     cache_skip_flush
+
        /*
         * Flush all data from the L1 and L2 data cache before disabling
         * SCTLR.C bit.
@@ -128,13 +148,47 @@ sync:
        bne     sync
 #endif
 
+       /* Restore wfi_flags */
+       adr     r3, am43xx_pm_ro_sram_data
+       ldr     r2, [r3, #AMX3_PM_RO_SRAM_DATA_VIRT_OFFSET]
+       ldr     r4, [r2, #AMX3_PM_WFI_FLAGS_OFFSET]
+
+cache_skip_flush:
+       /*
+        * If we are trying to enter RTC+DDR mode we must perform
+        * a read from the rtc address space to ensure translation
+        * presence in the TLB to avoid page table walk after DDR
+        * is unavailable.
+        */
+       tst     r4, #WFI_FLAG_RTC_ONLY
+       beq     skip_rtc_va_refresh
+
+       adr     r3, am43xx_pm_ro_sram_data
+       ldr     r1, [r3, #AMX3_PM_RTC_BASE_VIRT_OFFSET]
+       ldr     r0, [r1]
+
+skip_rtc_va_refresh:
+       /* Check if we want self refresh */
+       tst     r4, #WFI_FLAG_SELF_REFRESH
+       beq     emif_skip_enter_sr
+
        adr     r9, am43xx_emif_sram_table
 
        ldr     r3, [r9, #EMIF_PM_ENTER_SR_OFFSET]
        blx     r3
 
+emif_skip_enter_sr:
+       /* Only necessary if PER is losing context */
+       tst     r4, #WFI_FLAG_SAVE_EMIF
+       beq     emif_skip_save
+
        ldr     r3, [r9, #EMIF_PM_SAVE_CONTEXT_OFFSET]
-       blx     r3
+       blx     r3
+
+emif_skip_save:
+       /* Only can disable EMIF if we have entered self refresh */
+       tst     r4, #WFI_FLAG_SELF_REFRESH
+       beq     emif_skip_disable
 
        /* Disable EMIF */
        ldr     r1, am43xx_virt_emif_clkctrl
@@ -148,6 +202,38 @@ wait_emif_disable:
        cmp     r2, r3
        bne     wait_emif_disable
 
+emif_skip_disable:
+       tst     r4, #WFI_FLAG_RTC_ONLY
+       beq     skip_rtc_only
+
+       adr     r3, am43xx_pm_ro_sram_data
+       ldr     r1, [r3, #AMX3_PM_RTC_BASE_VIRT_OFFSET]
+
+       ldr     r0, [r1, #RTC_PMIC_REG]
+       orr     r0, r0, #RTC_PMIC_POWER_EN
+       orr     r0, r0, #RTC_PMIC_EXT_WAKEUP_STS
+       orr     r0, r0, #RTC_PMIC_EXT_WAKEUP_EN
+       orr     r0, r0, #RTC_PMIC_EXT_WAKEUP_POL
+       str     r0, [r1, #RTC_PMIC_REG]
+       ldr     r0, [r1, #RTC_PMIC_REG]
+       /* Wait for 2 seconds to lose power */
+       mov     r3, #2
+       ldr     r2, [r1, #RTC_SECONDS_REG]
+rtc_loop:
+       ldr     r0, [r1, #RTC_SECONDS_REG]
+       cmp     r0, r2
+       beq     rtc_loop
+       mov     r2, r0
+       subs    r3, r3, #1
+       bne     rtc_loop
+
+       b       re_enable_emif
+
+skip_rtc_only:
+
+       tst     r4, #WFI_FLAG_WAKE_M3
+       beq     wkup_m3_skip
+
        /*
         * For the MPU WFI to be registered as an interrupt
         * to WKUP_M3, MPU_CLKCTRL.MODULEMODE needs to be set
@@ -165,6 +251,7 @@ wait_emif_disable:
        mov     r2, #AM43XX_CM_CLKSTCTRL_CLKTRCTRL_SW_SLEEP
        str     r2, [r1]
 
+wkup_m3_skip:
        /*
         * Execute a barrier instruction to ensure that all cache,
         * TLB and branch predictor maintenance operations issued
@@ -209,6 +296,7 @@ wait_emif_disable:
        mov     r2, #AM33XX_CM_CLKCTRL_MODULEMODE_ENABLE
        str     r2, [r1]
 
+re_enable_emif:
        /* Re-enable EMIF */
        ldr     r1, am43xx_virt_emif_clkctrl
        mov     r2, #AM33XX_CM_CLKCTRL_MODULEMODE_ENABLE
@@ -218,6 +306,9 @@ wait_emif_enable:
        cmp     r2, r3
        bne     wait_emif_enable
 
+       tst     r4, #WFI_FLAG_FLUSH_CACHE
+       beq     cache_skip_restore
+
        /*
         * Set SCTLR.C bit to allow data cache allocation
         */
@@ -226,9 +317,16 @@ wait_emif_enable:
        mcr     p15, 0, r0, c1, c0, 0
        isb
 
-       ldr     r1, [r9, #EMIF_PM_ABORT_SR_OFFSET]
-       blx     r1
+cache_skip_restore:
+       /* Only necessary if PER is losing context */
+       tst     r4, #WFI_FLAG_SELF_REFRESH
+       beq     emif_skip_exit_sr_abt
+
+       adr     r9, am43xx_emif_sram_table
+       ldr     r1, [r9, #EMIF_PM_ABORT_SR_OFFSET]
+       blx     r1
 
+emif_skip_exit_sr_abt:
        /* Let the suspend code know about the abort */
        mov     r0, #1
        ldmfd   sp!, {r4 - r11, pc}     @ restore regs and return
@@ -333,8 +431,6 @@ ENDPROC(am43xx_resume_from_deep_sleep)
  * Local variables
  */
        .align
-resume_addr:
-       .word   cpu_resume - PAGE_OFFSET + 0x80000000
 kernel_flush:
        .word   v7_flush_dcache_all
 ddr_start:
@@ -381,6 +477,8 @@ ENTRY(am43xx_pm_sram)
        .word am43xx_emif_sram_table
        .word am43xx_pm_ro_sram_data
 
+resume_addr:
+       .word   cpu_resume - PAGE_OFFSET + 0x80000000
 .align 3
 
 ENTRY(am43xx_pm_ro_sram_data)
index 5a16ea7..a24783a 100644 (file)
@@ -3,6 +3,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
+#include <linux/clkdev.h>
 #include <linux/dma-mapping.h>
 #include <linux/dmaengine.h>
 #include <linux/spi/pxa2xx_spi.h>
@@ -477,6 +478,18 @@ struct platform_device pxa_device_ac97 = {
 
 void __init pxa_set_ac97_info(pxa2xx_audio_ops_t *ops)
 {
+       int ret;
+
+       ret = clk_add_alias("ac97_clk", "pxa2xx-ac97:0", "AC97CLK",
+                          &pxa_device_ac97.dev);
+       if (ret)
+               pr_err("PXA AC97 clock1 alias error: %d\n", ret);
+
+       ret = clk_add_alias("ac97_clk", "pxa2xx-ac97:1", "AC97CLK",
+                           &pxa_device_ac97.dev);
+       if (ret)
+               pr_err("PXA AC97 clock2 alias error: %d\n", ret);
+
        pxa_register_device(&pxa_device_ac97, ops);
 }
 
index e2e7f24..b79b757 100644 (file)
@@ -54,6 +54,7 @@
 
 #include "devices.h"
 #include "generic.h"
+#include "udc.h"
 
 /* Physical address space information */
 
@@ -594,6 +595,8 @@ static struct platform_device gpio_vbus = {
        },
 };
 
+static struct pxa2xx_udc_mach_info hx4700_udc_info;
+
 /*
  * Touchscreen - TSC2046 connected to SSP2
  */
@@ -891,6 +894,7 @@ static void __init hx4700_init(void)
        gpio_set_value(GPIO71_HX4700_ASIC3_nRESET, 1);
        mdelay(10);
 
+       pxa_set_udc_info(&hx4700_udc_info);
        regulator_has_full_constraints();
 }
 
index 9b6c7ea..04dc78d 100644 (file)
@@ -677,14 +677,12 @@ MIO_SIMPLE_DEV(mioa701_led,         "leds-gpio",      &gpio_led_info)
 MIO_SIMPLE_DEV(pxa2xx_pcm,       "pxa2xx-pcm",     NULL)
 MIO_SIMPLE_DEV(mioa701_sound,    "mioa701-wm9713", NULL)
 MIO_SIMPLE_DEV(mioa701_board,    "mioa701-board",  NULL)
-MIO_SIMPLE_DEV(wm9713_acodec,    "wm9713-codec",   NULL);
 MIO_SIMPLE_DEV(gpio_vbus,        "gpio-vbus",      &gpio_vbus_data);
 
 static struct platform_device *devices[] __initdata = {
        &mioa701_gpio_keys,
        &mioa701_backlight,
        &mioa701_led,
-       &wm9713_acodec,
        &pxa2xx_pcm,
        &mioa701_sound,
        &power_dev,
index d69de31..52e70a5 100644 (file)
@@ -47,16 +47,6 @@ int wm9713_irq;
 int lcd_id;
 int lcd_orientation;
 
-struct platform_device pxa_device_wm9713_audio = {
-       .name           = "wm9713-codec",
-       .id             = -1,
-};
-
-static void __init zylonite_init_wm9713_audio(void)
-{
-       platform_device_register(&pxa_device_wm9713_audio);
-}
-
 static struct resource smc91x_resources[] = {
        [0] = {
                .start  = ZYLONITE_ETH_PHYS + 0x300,
@@ -428,7 +418,6 @@ static void __init zylonite_init(void)
        zylonite_init_nand();
        zylonite_init_leds();
        zylonite_init_ohci();
-       zylonite_init_wm9713_audio();
 }
 
 MACHINE_START(ZYLONITE, "PXA3xx Platform Development Kit (aka Zylonite)")
index fafd3d7..8ca9265 100644 (file)
@@ -17,6 +17,7 @@ config ARCH_ROCKCHIP
        select ARM_GLOBAL_TIMER
        select CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK
        select ZONE_DMA if ARM_LPAE
+       select PM
        help
          Support for Rockchip's Cortex-A9 Single-to-Quad-Core-SoCs
          containing the RK2928, RK30xx and RK31xx series.
index b6b3272..4ff83f9 100644 (file)
@@ -6,7 +6,7 @@
  */
 
 #ifndef __ARCH_ARM_MACH_S3C24XX_S3C2412_H
-#define __ARCH_ARM_REGS_S3C24XX_S3C2412_H __FILE__
+#define __ARCH_ARM_MACH_S3C24XX_S3C2412_H __FILE__
 
 #define S3C2412_MEMREG(x)              (S3C24XX_VA_MEMCTRL + (x))
 #define S3C2412_EBIREG(x)              (S3C2412_VA_EBI + (x))
index 0b67254..aeb2eed 100644 (file)
@@ -15,6 +15,7 @@ config ARCH_RCAR_GEN1
 
 config ARCH_RCAR_GEN2
        bool
+       select HAVE_ARM_ARCH_TIMER
        select PM
        select PM_GENERIC_DOMAINS
        select RENESAS_IRQC
@@ -58,6 +59,7 @@ config ARCH_R8A73A4
        bool "R-Mobile APE6 (R8A73A40)"
        select ARCH_RMOBILE
        select ARM_ERRATA_798181 if SMP
+       select HAVE_ARM_ARCH_TIMER
        select RENESAS_IRQC
 
 config ARCH_R8A7740
index 1939f52..b33dc59 100644 (file)
@@ -11,9 +11,7 @@ obj-$(CONFIG_ARCH_SH73A0)     += setup-sh73a0.o
 obj-$(CONFIG_ARCH_R8A73A4)     += setup-r8a73a4.o
 obj-$(CONFIG_ARCH_R8A7740)     += setup-r8a7740.o
 obj-$(CONFIG_ARCH_R8A7778)     += setup-r8a7778.o
-obj-$(CONFIG_ARCH_R8A7779)     += setup-r8a7779.o pm-r8a7779.o
-obj-$(CONFIG_ARCH_R8A7790)     += setup-r8a7790.o
-obj-$(CONFIG_ARCH_R8A7791)     += setup-r8a7791.o
+obj-$(CONFIG_ARCH_R8A7779)     += setup-r8a7779.o
 obj-$(CONFIG_ARCH_EMEV2)       += setup-emev2.o
 obj-$(CONFIG_ARCH_R7S72100)    += setup-r7s72100.o
 
@@ -23,17 +21,15 @@ cpu-y                               := platsmp.o headsmp.o
 # Shared SoC family objects
 obj-$(CONFIG_ARCH_RCAR_GEN2)   += setup-rcar-gen2.o platsmp-apmu.o $(cpu-y)
 CFLAGS_setup-rcar-gen2.o       += -march=armv7-a
-obj-$(CONFIG_ARCH_RCAR_GEN2)   += headsmp-apmu.o
 obj-$(CONFIG_ARCH_R8A7790)     += regulator-quirk-rcar-gen2.o
 obj-$(CONFIG_ARCH_R8A7791)     += regulator-quirk-rcar-gen2.o
 obj-$(CONFIG_ARCH_R8A7793)     += regulator-quirk-rcar-gen2.o
 
 # SMP objects
 smp-y                          := $(cpu-y)
+smp-$(CONFIG_ARCH_RCAR_GEN2)   += headsmp-apmu.o
 smp-$(CONFIG_ARCH_SH73A0)      += smp-sh73a0.o headsmp-scu.o platsmp-scu.o
 smp-$(CONFIG_ARCH_R8A7779)     += smp-r8a7779.o headsmp-scu.o platsmp-scu.o
-smp-$(CONFIG_ARCH_R8A7790)     += smp-r8a7790.o
-smp-$(CONFIG_ARCH_R8A7791)     += smp-r8a7791.o
 smp-$(CONFIG_ARCH_EMEV2)       += smp-emev2.o headsmp-scu.o platsmp-scu.o
 
 # PM objects
index 2109f12..3ac4b36 100644 (file)
@@ -15,7 +15,6 @@ extern void shmobile_smp_sleep(void);
 extern void shmobile_smp_hook(unsigned int cpu, unsigned long fn,
                              unsigned long arg);
 extern bool shmobile_smp_cpu_can_disable(unsigned int cpu);
-extern bool shmobile_smp_init_fallback_ops(void);
 extern void shmobile_boot_apmu(void);
 extern void shmobile_boot_scu(void);
 extern void shmobile_smp_scu_prepare_cpus(phys_addr_t scu_base_phys,
index d49ab19..fabe9ca 100644 (file)
@@ -1,19 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * SMP support for APMU based systems with Cortex A7/A15
  *
  * Copyright (C) 2014  Renesas Electronics Corporation
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
  */
 
 #include <linux/linkage.h>
 #include <asm/assembler.h>
 
-#ifdef CONFIG_SMP
 ENTRY(shmobile_boot_apmu)
        bl      secure_cntvoff_init
        b       secondary_startup
 ENDPROC(shmobile_boot_apmu)
-#endif
index ba732ef..96330ef 100644 (file)
@@ -1,12 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * SMP support for SoCs with APMU
  *
  * Copyright (C) 2014  Renesas Electronics Corporation
  * Copyright (C) 2013  Magnus Damm
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
  */
 #include <linux/cpu_pm.h>
 #include <linux/delay.h>
@@ -23,7 +20,6 @@
 #include <asm/smp_plat.h>
 #include <asm/suspend.h>
 #include "common.h"
-#include "platsmp-apmu.h"
 #include "rcar-gen2.h"
 
 static struct {
@@ -87,6 +83,104 @@ static int __maybe_unused apmu_wrap(int cpu, int (*fn)(void __iomem *p, int cpu)
        return p ? fn(p, apmu_cpus[cpu].bit) : -EINVAL;
 }
 
+#if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_SUSPEND)
+/* nicked from arch/arm/mach-exynos/hotplug.c */
+static inline void cpu_enter_lowpower_a15(void)
+{
+       unsigned int v;
+
+       asm volatile(
+       "       mrc     p15, 0, %0, c1, c0, 0\n"
+       "       bic     %0, %0, %1\n"
+       "       mcr     p15, 0, %0, c1, c0, 0\n"
+               : "=&r" (v)
+               : "Ir" (CR_C)
+               : "cc");
+
+       flush_cache_louis();
+
+       asm volatile(
+       /*
+        * Turn off coherency
+        */
+       "       mrc     p15, 0, %0, c1, c0, 1\n"
+       "       bic     %0, %0, %1\n"
+       "       mcr     p15, 0, %0, c1, c0, 1\n"
+               : "=&r" (v)
+               : "Ir" (0x40)
+               : "cc");
+
+       isb();
+       dsb();
+}
+
+static void shmobile_smp_apmu_cpu_shutdown(unsigned int cpu)
+{
+
+       /* Select next sleep mode using the APMU */
+       apmu_wrap(cpu, apmu_power_off);
+
+       /* Do ARM specific CPU shutdown */
+       cpu_enter_lowpower_a15();
+}
+#endif
+
+#if defined(CONFIG_HOTPLUG_CPU)
+static void shmobile_smp_apmu_cpu_die(unsigned int cpu)
+{
+       /* For this particular CPU deregister boot vector */
+       shmobile_smp_hook(cpu, 0, 0);
+
+       /* Shutdown CPU core */
+       shmobile_smp_apmu_cpu_shutdown(cpu);
+
+       /* jump to shared mach-shmobile sleep / reset code */
+       shmobile_smp_sleep();
+}
+
+static int shmobile_smp_apmu_cpu_kill(unsigned int cpu)
+{
+       return apmu_wrap(cpu, apmu_power_off_poll);
+}
+#endif
+
+#if defined(CONFIG_SUSPEND)
+static int shmobile_smp_apmu_do_suspend(unsigned long cpu)
+{
+       shmobile_smp_hook(cpu, __pa_symbol(cpu_resume), 0);
+       shmobile_smp_apmu_cpu_shutdown(cpu);
+       cpu_do_idle(); /* WFI selects Core Standby */
+       return 1;
+}
+
+static inline void cpu_leave_lowpower(void)
+{
+       unsigned int v;
+
+       asm volatile("mrc    p15, 0, %0, c1, c0, 0\n"
+                    "       orr     %0, %0, %1\n"
+                    "       mcr     p15, 0, %0, c1, c0, 0\n"
+                    "       mrc     p15, 0, %0, c1, c0, 1\n"
+                    "       orr     %0, %0, %2\n"
+                    "       mcr     p15, 0, %0, c1, c0, 1\n"
+                    : "=&r" (v)
+                    : "Ir" (CR_C), "Ir" (0x40)
+                    : "cc");
+}
+
+static int shmobile_smp_apmu_enter_suspend(suspend_state_t state)
+{
+       cpu_suspend(smp_processor_id(), shmobile_smp_apmu_do_suspend);
+       cpu_leave_lowpower();
+       return 0;
+}
+
+void __init shmobile_smp_apmu_suspend_init(void)
+{
+       shmobile_suspend_ops.enter = shmobile_smp_apmu_enter_suspend;
+}
+#endif
+
 #ifdef CONFIG_SMP
 static void apmu_init_cpu(struct resource *res, int cpu, int bit)
 {
@@ -106,38 +200,6 @@ static void apmu_init_cpu(struct resource *res, int cpu, int bit)
        writel(x, apmu_cpus[cpu].iomem + DBGRCR_OFFS);
 }
 
-static void apmu_parse_cfg(void (*fn)(struct resource *res, int cpu, int bit),
-                          struct rcar_apmu_config *apmu_config, int num)
-{
-       int id;
-       int k;
-       int bit, index;
-       bool is_allowed;
-
-       for (k = 0; k < num; k++) {
-               /* only enable the cluster that includes the boot CPU */
-               is_allowed = false;
-               for (bit = 0; bit < ARRAY_SIZE(apmu_config[k].cpus); bit++) {
-                       id = apmu_config[k].cpus[bit];
-                       if (id >= 0) {
-                               if (id == cpu_logical_map(0))
-                                       is_allowed = true;
-                       }
-               }
-               if (!is_allowed)
-                       continue;
-
-               for (bit = 0; bit < ARRAY_SIZE(apmu_config[k].cpus); bit++) {
-                       id = apmu_config[k].cpus[bit];
-                       if (id >= 0) {
-                               index = get_logical_index(id);
-                               if (index >= 0)
-                                       fn(&apmu_config[k].iomem, index, bit);
-                       }
-               }
-       }
-}
-
 static const struct of_device_id apmu_ids[] = {
        { .compatible = "renesas,apmu" },
        { /*sentinel*/ }
@@ -194,15 +256,8 @@ static void __init shmobile_smp_apmu_setup_boot(void)
        shmobile_boot_fn_gen2 = shmobile_boot_fn;
 }
 
-void __init shmobile_smp_apmu_prepare_cpus(unsigned int max_cpus,
-                                          struct rcar_apmu_config *apmu_config,
-                                          int num)
-{
-       shmobile_smp_apmu_setup_boot();
-       apmu_parse_cfg(apmu_init_cpu, apmu_config, num);
-}
-
-int shmobile_smp_apmu_boot_secondary(unsigned int cpu, struct task_struct *idle)
+static int shmobile_smp_apmu_boot_secondary(unsigned int cpu,
+                                           struct task_struct *idle)
 {
        /* For this particular CPU register boot vector */
        shmobile_smp_hook(cpu, __pa_symbol(shmobile_boot_apmu), 0);
@@ -229,101 +284,3 @@ static struct smp_operations apmu_smp_ops __initdata = {
 
 CPU_METHOD_OF_DECLARE(shmobile_smp_apmu, "renesas,apmu", &apmu_smp_ops);
 #endif /* CONFIG_SMP */
-
-#if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_SUSPEND)
-/* nicked from arch/arm/mach-exynos/hotplug.c */
-static inline void cpu_enter_lowpower_a15(void)
-{
-       unsigned int v;
-
-       asm volatile(
-       "       mrc     p15, 0, %0, c1, c0, 0\n"
-       "       bic     %0, %0, %1\n"
-       "       mcr     p15, 0, %0, c1, c0, 0\n"
-               : "=&r" (v)
-               : "Ir" (CR_C)
-               : "cc");
-
-       flush_cache_louis();
-
-       asm volatile(
-       /*
-        * Turn off coherency
-        */
-       "       mrc     p15, 0, %0, c1, c0, 1\n"
-       "       bic     %0, %0, %1\n"
-       "       mcr     p15, 0, %0, c1, c0, 1\n"
-               : "=&r" (v)
-               : "Ir" (0x40)
-               : "cc");
-
-       isb();
-       dsb();
-}
-
-static void shmobile_smp_apmu_cpu_shutdown(unsigned int cpu)
-{
-
-       /* Select next sleep mode using the APMU */
-       apmu_wrap(cpu, apmu_power_off);
-
-       /* Do ARM specific CPU shutdown */
-       cpu_enter_lowpower_a15();
-}
-
-static inline void cpu_leave_lowpower(void)
-{
-       unsigned int v;
-
-       asm volatile("mrc    p15, 0, %0, c1, c0, 0\n"
-                    "       orr     %0, %0, %1\n"
-                    "       mcr     p15, 0, %0, c1, c0, 0\n"
-                    "       mrc     p15, 0, %0, c1, c0, 1\n"
-                    "       orr     %0, %0, %2\n"
-                    "       mcr     p15, 0, %0, c1, c0, 1\n"
-                    : "=&r" (v)
-                    : "Ir" (CR_C), "Ir" (0x40)
-                    : "cc");
-}
-#endif
-
-#if defined(CONFIG_HOTPLUG_CPU)
-void shmobile_smp_apmu_cpu_die(unsigned int cpu)
-{
-       /* For this particular CPU deregister boot vector */
-       shmobile_smp_hook(cpu, 0, 0);
-
-       /* Shutdown CPU core */
-       shmobile_smp_apmu_cpu_shutdown(cpu);
-
-       /* jump to shared mach-shmobile sleep / reset code */
-       shmobile_smp_sleep();
-}
-
-int shmobile_smp_apmu_cpu_kill(unsigned int cpu)
-{
-       return apmu_wrap(cpu, apmu_power_off_poll);
-}
-#endif
-
-#if defined(CONFIG_SUSPEND)
-static int shmobile_smp_apmu_do_suspend(unsigned long cpu)
-{
-       shmobile_smp_hook(cpu, __pa_symbol(cpu_resume), 0);
-       shmobile_smp_apmu_cpu_shutdown(cpu);
-       cpu_do_idle(); /* WFI selects Core Standby */
-       return 1;
-}
-
-static int shmobile_smp_apmu_enter_suspend(suspend_state_t state)
-{
-       cpu_suspend(smp_processor_id(), shmobile_smp_apmu_do_suspend);
-       cpu_leave_lowpower();
-       return 0;
-}
-
-void __init shmobile_smp_apmu_suspend_init(void)
-{
-       shmobile_suspend_ops.enter = shmobile_smp_apmu_enter_suspend;
-}
-#endif
diff --git a/arch/arm/mach-shmobile/platsmp-apmu.h b/arch/arm/mach-shmobile/platsmp-apmu.h
deleted file mode 100644 (file)
index 76512c9..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * rmobile apmu definition
- *
- * Copyright (C) 2014  Renesas Electronics 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; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#ifndef PLATSMP_APMU_H
-#define PLATSMP_APMU_H
-
-struct rcar_apmu_config {
-       struct resource iomem;
-       int cpus[4];
-};
-
-extern void shmobile_smp_apmu_prepare_cpus(unsigned int max_cpus,
-                                          struct rcar_apmu_config *apmu_config,
-                                          int num);
-extern int shmobile_smp_apmu_boot_secondary(unsigned int cpu,
-                                           struct task_struct *idle);
-extern void shmobile_smp_apmu_cpu_die(unsigned int cpu);
-extern int shmobile_smp_apmu_cpu_kill(unsigned int cpu);
-
-#endif /* PLATSMP_APMU_H */
index 02e21bc..b23378f 100644 (file)
@@ -36,12 +36,3 @@ bool shmobile_smp_cpu_can_disable(unsigned int cpu)
        return true; /* Hotplug of any CPU is supported */
 }
 #endif
-
-bool __init shmobile_smp_init_fallback_ops(void)
-{
-       /* fallback on PSCI/smp_ops if no other DT based method is detected */
-       if (!IS_ENABLED(CONFIG_SMP))
-               return false;
-
-       return platform_can_secondary_boot() ? true : false;
-}
diff --git a/arch/arm/mach-shmobile/pm-r8a7779.c b/arch/arm/mach-shmobile/pm-r8a7779.c
deleted file mode 100644 (file)
index 5c9a93f..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * r8a7779 Power management support
- *
- * Copyright (C) 2011  Renesas Solutions Corp.
- * Copyright (C) 2011  Magnus Damm
- *
- * 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.
- */
-
-#include <linux/soc/renesas/rcar-sysc.h>
-
-#include <asm/io.h>
-
-#include "r8a7779.h"
-
-/* SYSC */
-#define SYSCIER 0x0c
-#define SYSCIMR 0x10
-
-#if defined(CONFIG_PM) || defined(CONFIG_SMP)
-
-static void __init r8a7779_sysc_init(void)
-{
-       rcar_sysc_init(0xffd85000, 0x0131000e);
-}
-
-#else /* CONFIG_PM || CONFIG_SMP */
-
-static inline void r8a7779_sysc_init(void) {}
-
-#endif /* CONFIG_PM || CONFIG_SMP */
-
-void __init r8a7779_pm_init(void)
-{
-       static int once;
-
-       if (!once++)
-               r8a7779_sysc_init();
-}
index 5a798b4..345af3e 100644 (file)
@@ -15,7 +15,6 @@
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/smp.h>
-#include <linux/soc/renesas/rcar-sysc.h>
 #include <asm/io.h>
 #include <asm/cputype.h>
 #include "common.h"
@@ -46,23 +45,6 @@ static inline u32 phys_to_sbar(phys_addr_t addr)
        return (addr >> 8) & 0xfffffc00;
 }
 
-/* SYSC */
-#define SYSCIER 0x0c
-#define SYSCIMR 0x10
-
-#if defined(CONFIG_SMP)
-
-static void __init rcar_gen2_sysc_init(u32 syscier)
-{
-       rcar_sysc_init(0xe6180000, syscier);
-}
-
-#else /* CONFIG_SMP */
-
-static inline void rcar_gen2_sysc_init(u32 syscier) {}
-
-#endif /* CONFIG_SMP */
-
 void __init rcar_gen2_pm_init(void)
 {
        void __iomem *p;
@@ -72,7 +54,6 @@ void __init rcar_gen2_pm_init(void)
        bool has_a7 = false;
        bool has_a15 = false;
        struct resource res;
-       u32 syscier = 0;
        int error;
 
        if (once++)
@@ -89,11 +70,6 @@ void __init rcar_gen2_pm_init(void)
                        has_a7 = true;
        }
 
-       if (of_machine_is_compatible("renesas,r8a7790"))
-               syscier = 0x013111ef;
-       else if (of_machine_is_compatible("renesas,r8a7791"))
-               syscier = 0x00111003;
-
        np = of_find_compatible_node(NULL, NULL, "renesas,smp-sram");
        if (!np) {
                /* No smp-sram in DT, fall back to hardcoded address */
@@ -155,6 +131,5 @@ map:
        }
        iounmap(p);
 
-       rcar_gen2_sysc_init(syscier);
        shmobile_smp_apmu_suspend_init();
 }
index 30668aa..ca9db8f 100644 (file)
@@ -2,8 +2,6 @@
 #ifndef __ASM_R8A7779_H__
 #define __ASM_R8A7779_H__
 
-extern void r8a7779_pm_init(void);
-
 extern const struct smp_operations r8a7779_smp_ops;
 
 #endif /* __ASM_R8A7779_H__ */
diff --git a/arch/arm/mach-shmobile/r8a7790.h b/arch/arm/mach-shmobile/r8a7790.h
deleted file mode 100644 (file)
index 669c8cd..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef __ASM_R8A7790_H__
-#define __ASM_R8A7790_H__
-
-extern const struct smp_operations r8a7790_smp_ops;
-
-#endif /* __ASM_R8A7790_H__ */
diff --git a/arch/arm/mach-shmobile/r8a7791.h b/arch/arm/mach-shmobile/r8a7791.h
deleted file mode 100644 (file)
index 8c794aa..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef __ASM_R8A7791_H__
-#define __ASM_R8A7791_H__
-
-extern const struct smp_operations r8a7791_smp_ops;
-
-#endif /* __ASM_R8A7791_H__ */
index 93f628a..21ebc76 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * R-Car Generation 2 da9063/da9210 regulator quirk
  *
  * been initialized, but before the i2c slave drivers are initialized.
  *
  * Copyright (C) 2015 Glider bvba
- *
- * 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.
- *
- * 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/device.h>
index 3c99aaf..a328d2f 100644 (file)
@@ -1,16 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Emma Mobile EV2 processor support
  *
  * Copyright (C) 2012  Magnus Damm
- *
- * 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.
- *
- * 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>
index 319ca95..1486722 100644 (file)
@@ -1,17 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * r7s72100 processor support
  *
  * Copyright (C) 2013  Renesas Solutions Corp.
  * Copyright (C) 2013  Magnus Damm
- *
- * 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.
- *
- * 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>
index 20173c4..23a29a0 100644 (file)
@@ -1,17 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * r8a73a4 processor support
  *
  * Copyright (C) 2013  Renesas Solutions Corp.
  * Copyright (C) 2013  Magnus Damm
- *
- * 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.
- *
- * 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>
@@ -26,7 +18,6 @@ static const char *const r8a73a4_boards_compat_dt[] __initconst = {
 };
 
 DT_MACHINE_START(R8A73A4_DT, "Generic R8A73A4 (Flattened Device Tree)")
-       .init_early     = shmobile_init_delay,
        .init_late      = shmobile_init_late,
        .dt_compat      = r8a73a4_boards_compat_dt,
 MACHINE_END
index 3849eef..787d039 100644 (file)
@@ -1,17 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * R8A7740 processor support
  *
  * Copyright (C) 2011  Renesas Solutions Corp.
  * Copyright (C) 2011  Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * 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>
index 7fa4a0b..ce51794 100644 (file)
@@ -1,18 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * r8a7778 processor support
  *
  * Copyright (C) 2013  Renesas Solutions Corp.
  * Copyright (C) 2013  Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
  * Copyright (C) 2013  Cogent Embedded, 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; version 2 of the License.
- *
- * 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/io.h>
index 0686112..d589326 100644 (file)
@@ -1,18 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * r8a7779 processor support
  *
  * Copyright (C) 2011, 2013  Renesas Solutions Corp.
  * Copyright (C) 2011  Magnus Damm
  * Copyright (C) 2013  Cogent Embedded, 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; version 2 of the License.
- *
- * 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/irq.h>
diff --git a/arch/arm/mach-shmobile/setup-r8a7790.c b/arch/arm/mach-shmobile/setup-r8a7790.c
deleted file mode 100644 (file)
index 78d3e85..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * r8a7790 processor support
- *
- * Copyright (C) 2013  Renesas Solutions Corp.
- * Copyright (C) 2013  Magnus Damm
- *
- * 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.
- *
- * 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 <asm/mach/arch.h>
-
-#include "common.h"
-#include "r8a7790.h"
-#include "rcar-gen2.h"
-
-static const char * const r8a7790_boards_compat_dt[] __initconst = {
-       "renesas,r8a7790",
-       NULL,
-};
-
-DT_MACHINE_START(R8A7790_DT, "Generic R8A7790 (Flattened Device Tree)")
-       .smp_init       = smp_init_ops(shmobile_smp_init_fallback_ops),
-       .smp            = smp_ops(r8a7790_smp_ops),
-       .init_early     = shmobile_init_delay,
-       .init_time      = rcar_gen2_timer_init,
-       .init_late      = shmobile_init_late,
-       .reserve        = rcar_gen2_reserve,
-       .dt_compat      = r8a7790_boards_compat_dt,
-MACHINE_END
diff --git a/arch/arm/mach-shmobile/setup-r8a7791.c b/arch/arm/mach-shmobile/setup-r8a7791.c
deleted file mode 100644 (file)
index 26e2d18..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * r8a7791 processor support
- *
- * Copyright (C) 2013  Renesas Electronics Corporation
- * Copyright (C) 2013  Renesas Solutions Corp.
- * Copyright (C) 2013  Magnus Damm
- *
- * 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.
- *
- * 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 <asm/mach/arch.h>
-
-#include "common.h"
-#include "r8a7791.h"
-#include "rcar-gen2.h"
-
-static const char *const r8a7791_boards_compat_dt[] __initconst = {
-       "renesas,r8a7791",
-       NULL,
-};
-
-DT_MACHINE_START(R8A7791_DT, "Generic R8A7791 (Flattened Device Tree)")
-       .smp_init       = smp_init_ops(shmobile_smp_init_fallback_ops),
-       .smp            = smp_ops(r8a7791_smp_ops),
-       .init_early     = shmobile_init_delay,
-       .init_time      = rcar_gen2_timer_init,
-       .init_late      = shmobile_init_late,
-       .reserve        = rcar_gen2_reserve,
-       .dt_compat      = r8a7791_boards_compat_dt,
-MACHINE_END
index 88fdc18..013acc9 100644 (file)
@@ -1,18 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * R-Car Generation 2 support
  *
  * Copyright (C) 2013  Renesas Solutions Corp.
  * Copyright (C) 2013  Magnus Damm
  * Copyright (C) 2014  Ulrich Hecht
- *
- * 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.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 #include <linux/clk-provider.h>
@@ -67,7 +59,6 @@ static unsigned int __init get_extal_freq(void)
 
 void __init rcar_gen2_timer_init(void)
 {
-#ifdef CONFIG_ARM_ARCH_TIMER
        void __iomem *base;
        u32 freq;
 
@@ -109,7 +100,6 @@ void __init rcar_gen2_timer_init(void)
        }
 
        iounmap(base);
-#endif /* CONFIG_ARM_ARCH_TIMER */
 
        of_clk_init(NULL);
        timer_probe();
@@ -186,10 +176,8 @@ void __init rcar_gen2_reserve(void)
 }
 
 static const char * const rcar_gen2_boards_compat_dt[] __initconst = {
-       /*
-        * R8A7790 and R8A7791 can't be handled here as long as they need SMP
-        * initialization fallback.
-        */
+       "renesas,r8a7790",
+       "renesas,r8a7791",
        "renesas,r8a7792",
        "renesas,r8a7793",
        "renesas,r8a7794",
@@ -197,7 +185,6 @@ static const char * const rcar_gen2_boards_compat_dt[] __initconst = {
 };
 
 DT_MACHINE_START(RCAR_GEN2_DT, "Generic R-Car Gen2 (Flattened Device Tree)")
-       .init_early     = shmobile_init_delay,
        .init_late      = shmobile_init_late,
        .init_time      = rcar_gen2_timer_init,
        .reserve        = rcar_gen2_reserve,
@@ -212,7 +199,6 @@ static const char * const rz_g1_boards_compat_dt[] __initconst = {
 };
 
 DT_MACHINE_START(RZ_G1_DT, "Generic RZ/G1 (Flattened Device Tree)")
-       .init_early     = shmobile_init_delay,
        .init_late      = shmobile_init_late,
        .init_time      = rcar_gen2_timer_init,
        .reserve        = rcar_gen2_reserve,
index a25ff18..cc08aa7 100644 (file)
@@ -1,18 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * sh73a0 processor support
  *
  * Copyright (C) 2010  Takashi Yoshii
  * Copyright (C) 2010  Magnus Damm
  * Copyright (C) 2008  Yoshihiro Shimoda
- *
- * 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.
- *
- * 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>
index 3a73219..3853ece 100644 (file)
@@ -1,17 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * SMP support for Emma Mobile EV2
  *
  * Copyright (C) 2012  Renesas Solutions Corp.
  * Copyright (C) 2012  Magnus Damm
- *
- * 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.
- *
- * 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>
index c6951ee..0ed73b6 100644 (file)
@@ -1,17 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * SMP support for R-Mobile / SH-Mobile - r8a7779 portion
  *
  * Copyright (C) 2011  Renesas Solutions Corp.
  * Copyright (C) 2011  Magnus Damm
- *
- * 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.
- *
- * 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>
 #define AVECR IOMEM(0xfe700040)
 #define R8A7779_SCU_BASE 0xf0000000
 
-static const struct rcar_sysc_ch r8a7779_ch_cpu1 = {
-       .chan_offs = 0x40, /* PWRSR0 .. PWRER0 */
-       .chan_bit = 1, /* ARM1 */
-       .isr_bit = 1, /* ARM1 */
-};
-
-static const struct rcar_sysc_ch r8a7779_ch_cpu2 = {
-       .chan_offs = 0x40, /* PWRSR0 .. PWRER0 */
-       .chan_bit = 2, /* ARM2 */
-       .isr_bit = 2, /* ARM2 */
-};
-
-static const struct rcar_sysc_ch r8a7779_ch_cpu3 = {
-       .chan_offs = 0x40, /* PWRSR0 .. PWRER0 */
-       .chan_bit = 3, /* ARM3 */
-       .isr_bit = 3, /* ARM3 */
-};
-
-static const struct rcar_sysc_ch * const r8a7779_ch_cpu[4] = {
-       [1] = &r8a7779_ch_cpu1,
-       [2] = &r8a7779_ch_cpu2,
-       [3] = &r8a7779_ch_cpu3,
-};
-
-static int r8a7779_platform_cpu_kill(unsigned int cpu)
+static int r8a7779_boot_secondary(unsigned int cpu, struct task_struct *idle)
 {
-       const struct rcar_sysc_ch *ch = NULL;
        int ret = -EIO;
 
        cpu = cpu_logical_map(cpu);
-
-       if (cpu < ARRAY_SIZE(r8a7779_ch_cpu))
-               ch = r8a7779_ch_cpu[cpu];
-
-       if (ch)
-               ret = rcar_sysc_power_down(ch);
-
-       return ret ? ret : 1;
-}
-
-static int r8a7779_boot_secondary(unsigned int cpu, struct task_struct *idle)
-{
-       const struct rcar_sysc_ch *ch = NULL;
-       unsigned int lcpu = cpu_logical_map(cpu);
-       int ret;
-
-       if (lcpu < ARRAY_SIZE(r8a7779_ch_cpu))
-               ch = r8a7779_ch_cpu[lcpu];
-
-       if (ch)
-               ret = rcar_sysc_power_up(ch);
-       else
-               ret = -EIO;
+       if (cpu)
+               ret = rcar_sysc_power_up_cpu(cpu);
 
        return ret;
 }
@@ -95,16 +41,20 @@ static void __init r8a7779_smp_prepare_cpus(unsigned int max_cpus)
 
        /* setup r8a7779 specific SCU bits */
        shmobile_smp_scu_prepare_cpus(R8A7779_SCU_BASE, max_cpus);
+}
 
-       r8a7779_pm_init();
+#ifdef CONFIG_HOTPLUG_CPU
+static int r8a7779_platform_cpu_kill(unsigned int cpu)
+{
+       int ret = -EIO;
 
-       /* power off secondary CPUs */
-       r8a7779_platform_cpu_kill(1);
-       r8a7779_platform_cpu_kill(2);
-       r8a7779_platform_cpu_kill(3);
+       cpu = cpu_logical_map(cpu);
+       if (cpu)
+               ret = rcar_sysc_power_down_cpu(cpu);
+
+       return ret ? ret : 1;
 }
 
-#ifdef CONFIG_HOTPLUG_CPU
 static int r8a7779_cpu_kill(unsigned int cpu)
 {
        if (shmobile_smp_scu_cpu_kill(cpu))
diff --git a/arch/arm/mach-shmobile/smp-r8a7790.c b/arch/arm/mach-shmobile/smp-r8a7790.c
deleted file mode 100644 (file)
index 28f26d5..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * SMP support for r8a7790
- *
- * Copyright (C) 2012-2013 Renesas Solutions Corp.
- * Copyright (C) 2012 Takashi Yoshii <takashi.yoshii.ze@renesas.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * 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/smp.h>
-#include <linux/io.h>
-#include <linux/soc/renesas/rcar-sysc.h>
-
-#include <asm/smp_plat.h>
-
-#include "common.h"
-#include "platsmp-apmu.h"
-#include "rcar-gen2.h"
-#include "r8a7790.h"
-
-static const struct rcar_sysc_ch r8a7790_ca15_scu = {
-       .chan_offs = 0x180, /* PWRSR5 .. PWRER5 */
-       .isr_bit = 12, /* CA15-SCU */
-};
-
-static const struct rcar_sysc_ch r8a7790_ca7_scu = {
-       .chan_offs = 0x100, /* PWRSR3 .. PWRER3 */
-       .isr_bit = 21, /* CA7-SCU */
-};
-
-static struct rcar_apmu_config r8a7790_apmu_config[] = {
-       {
-               .iomem = DEFINE_RES_MEM(0xe6152000, 0x188),
-               .cpus = { 0, 1, 2, 3 },
-       },
-       {
-               .iomem = DEFINE_RES_MEM(0xe6151000, 0x188),
-               .cpus = { 0x100, 0x0101, 0x102, 0x103 },
-       }
-};
-
-static void __init r8a7790_smp_prepare_cpus(unsigned int max_cpus)
-{
-       /* let APMU code install data related to shmobile_boot_vector */
-       shmobile_smp_apmu_prepare_cpus(max_cpus,
-                                      r8a7790_apmu_config,
-                                      ARRAY_SIZE(r8a7790_apmu_config));
-
-       /* turn on power to SCU */
-       rcar_gen2_pm_init();
-       rcar_sysc_power_up(&r8a7790_ca15_scu);
-       rcar_sysc_power_up(&r8a7790_ca7_scu);
-}
-
-const struct smp_operations r8a7790_smp_ops __initconst = {
-       .smp_prepare_cpus       = r8a7790_smp_prepare_cpus,
-       .smp_boot_secondary     = shmobile_smp_apmu_boot_secondary,
-#ifdef CONFIG_HOTPLUG_CPU
-       .cpu_can_disable        = shmobile_smp_cpu_can_disable,
-       .cpu_die                = shmobile_smp_apmu_cpu_die,
-       .cpu_kill               = shmobile_smp_apmu_cpu_kill,
-#endif
-};
diff --git a/arch/arm/mach-shmobile/smp-r8a7791.c b/arch/arm/mach-shmobile/smp-r8a7791.c
deleted file mode 100644 (file)
index 2948c22..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * SMP support for r8a7791
- *
- * Copyright (C) 2013 Renesas Solutions Corp.
- * Copyright (C) 2013 Magnus Damm
- *
- * 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.
- *
- * 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/smp.h>
-#include <linux/io.h>
-
-#include <asm/smp_plat.h>
-
-#include "common.h"
-#include "platsmp-apmu.h"
-#include "r8a7791.h"
-#include "rcar-gen2.h"
-
-static struct rcar_apmu_config r8a7791_apmu_config[] = {
-       {
-               .iomem = DEFINE_RES_MEM(0xe6152000, 0x188),
-               .cpus = { 0, 1 },
-       }
-};
-
-static void __init r8a7791_smp_prepare_cpus(unsigned int max_cpus)
-{
-       /* let APMU code install data related to shmobile_boot_vector */
-       shmobile_smp_apmu_prepare_cpus(max_cpus,
-                                      r8a7791_apmu_config,
-                                      ARRAY_SIZE(r8a7791_apmu_config));
-
-       rcar_gen2_pm_init();
-}
-
-const struct smp_operations r8a7791_smp_ops __initconst = {
-       .smp_prepare_cpus       = r8a7791_smp_prepare_cpus,
-       .smp_boot_secondary     = shmobile_smp_apmu_boot_secondary,
-#ifdef CONFIG_HOTPLUG_CPU
-       .cpu_can_disable        = shmobile_smp_cpu_can_disable,
-       .cpu_die                = shmobile_smp_apmu_cpu_die,
-       .cpu_kill               = shmobile_smp_apmu_cpu_kill,
-#endif
-};
index 6196a63..828e8ae 100644 (file)
@@ -32,14 +32,6 @@ void __init shmobile_init_delay(void)
        for_each_child_of_node(cpus, np) {
                u32 freq;
 
-               if (IS_ENABLED(CONFIG_ARM_ARCH_TIMER) &&
-                   (of_device_is_compatible(np, "arm,cortex-a7") ||
-                    of_device_is_compatible(np, "arm,cortex-a15"))) {
-                       of_node_put(np);
-                       of_node_put(cpus);
-                       return;
-               }
-
                if (!of_property_read_u32(np, "clock-frequency", &freq))
                        max_freq = max(max_freq, freq);
        }
index 779235a..e661d26 100644 (file)
@@ -9,6 +9,7 @@ config ARCH_UNIPHIER
        select HAVE_ARM_SCU
        select HAVE_ARM_TWD if SMP
        select PINCTRL
+       select RESET_CONTROLLER
        help
          Support for UniPhier SoC family developed by Socionext Inc.
          (formerly, System LSI Business Division of Panasonic Corporation)
diff --git a/arch/arm/mach-uniphier/Makefile b/arch/arm/mach-uniphier/Makefile
deleted file mode 100644 (file)
index e69de29..0000000
index d1329f1..bf99226 100644 (file)
@@ -32,7 +32,7 @@ bool is_swbp_insn(uprobe_opcode_t *insn)
 int set_swbp(struct arch_uprobe *auprobe, struct mm_struct *mm,
             unsigned long vaddr)
 {
-       return uprobe_write_opcode(mm, vaddr,
+       return uprobe_write_opcode(auprobe, mm, vaddr,
                   __opcode_to_mem_arm(auprobe->bpinsn));
 }
 
index d0a53cc..29e75b4 100644 (file)
@@ -108,6 +108,7 @@ config ARM64
        select HAVE_ARCH_KGDB
        select HAVE_ARCH_MMAP_RND_BITS
        select HAVE_ARCH_MMAP_RND_COMPAT_BITS if COMPAT
+       select HAVE_ARCH_PREL32_RELOCATIONS
        select HAVE_ARCH_SECCOMP_FILTER
        select HAVE_ARCH_STACKLEAK
        select HAVE_ARCH_THREAD_STRUCT_WHITELIST
index d5aeac3..393d2b5 100644 (file)
@@ -71,6 +71,13 @@ config ARCH_EXYNOS
        help
          This enables support for ARMv8 based Samsung Exynos SoC family.
 
+config ARCH_K3
+       bool "Texas Instruments Inc. K3 multicore SoC architecture"
+       select PM_GENERIC_DOMAINS if PM
+       help
+         This enables support for Texas Instruments' K3 multicore SoC
+         architecture.
+
 config ARCH_LAYERSCAPE
        bool "ARMv8 based Freescale Layerscape SoC family"
        select EDAC_SUPPORT
@@ -151,6 +158,7 @@ config ARCH_ROCKCHIP
        select GPIOLIB
        select PINCTRL
        select PINCTRL_ROCKCHIP
+       select PM
        select ROCKCHIP_TIMER
        help
          This enables support for the ARMv8 based Rockchip chipsets,
@@ -261,6 +269,7 @@ config ARCH_UNIPHIER
        bool "Socionext UniPhier SoC Family"
        select ARCH_HAS_RESET_CONTROLLER
        select PINCTRL
+       select RESET_CONTROLLER
        help
          This enables support for Socionext UniPhier SoC family.
 
index efe61a2..106039d 100644 (file)
@@ -62,14 +62,14 @@ CHECKFLAGS  += -D__AARCH64EB__
 AS             += -EB
 # Prefer the baremetal ELF build target, but not all toolchains include
 # it so fall back to the standard linux version if needed.
-LDFLAGS                += -EB $(call ld-option, -maarch64elfb, -maarch64linuxb)
+KBUILD_LDFLAGS += -EB $(call ld-option, -maarch64elfb, -maarch64linuxb)
 UTS_MACHINE    := aarch64_be
 else
 KBUILD_CPPFLAGS        += -mlittle-endian
 CHECKFLAGS     += -D__AARCH64EL__
 AS             += -EL
 # Same as above, prefer ELF but fall back to linux target if needed.
-LDFLAGS                += -EL $(call ld-option, -maarch64elf, -maarch64linux)
+KBUILD_LDFLAGS += -EL $(call ld-option, -maarch64elf, -maarch64linux)
 UTS_MACHINE    := aarch64
 endif
 
index 3543bc3..4690364 100644 (file)
@@ -23,5 +23,6 @@ subdir-y += rockchip
 subdir-y += socionext
 subdir-y += sprd
 subdir-y += synaptics
+subdir-y += ti
 subdir-y += xilinx
 subdir-y += zte
index c31f90a..9ffa7a0 100644 (file)
@@ -1,9 +1,11 @@
 # SPDX-License-Identifier: GPL-2.0
+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-olinuxino.dtb
 dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-orangepi-win.dtb
 dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-pine64-plus.dtb sun50i-a64-pine64.dtb
+dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-pinebook.dtb
 dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-sopine-baseboard.dtb
 dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-teres-i.dtb
 dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h5-libretech-all-h3-cc.dtb
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-amarula-relic.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-amarula-relic.dts
new file mode 100644 (file)
index 0000000..eac4793
--- /dev/null
@@ -0,0 +1,219 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (C) 2018 Amarula Solutions B.V.
+ * Author: Jagan Teki <jagan@amarulasolutions.com>
+ */
+
+/dts-v1/;
+
+#include "sun50i-a64.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+       model = "Amarula A64-Relic";
+       compatible = "amarula,a64-relic", "allwinner,sun50i-a64";
+
+       aliases {
+               serial0 = &uart0;
+       };
+
+       chosen {
+               stdout-path = "serial0:115200n8";
+       };
+
+       wifi_pwrseq: wifi-pwrseq {
+               compatible = "mmc-pwrseq-simple";
+               clocks = <&rtc 1>;
+               clock-names = "ext_clock";
+               reset-gpios = <&r_pio 0 2 GPIO_ACTIVE_LOW>; /* WL-PMU-EN: PL2 */
+       };
+};
+
+&ehci0 {
+       status = "okay";
+};
+
+&mmc1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&mmc1_pins>;
+       vmmc-supply = <&reg_dcdc1>;
+       /*
+        * Schematic shows both dldo4 and eldo1 connected for vcc-io-wifi, but
+        * dldo4 connection shows DNP(Do Not Populate) and eldo1 connected with
+        * 0Ohm register to vcc-io-wifi so eldo1 is used.
+        */
+       vqmmc-supply = <&reg_eldo1>;
+       mmc-pwrseq = <&wifi_pwrseq>;
+       bus-width = <4>;
+       non-removable;
+       status = "okay";
+
+       brcmf: wifi@1 {
+               reg = <1>;
+               compatible = "brcm,bcm4329-fmac";
+               interrupt-parent = <&r_pio>;
+               interrupts = <0 3 IRQ_TYPE_LEVEL_LOW>;  /* WL-WAKE-AP: PL3 */
+               interrupt-names = "host-wake";
+       };
+};
+
+&mmc2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&mmc2_pins>;
+       vmmc-supply = <&reg_dcdc1>;
+       bus-width = <8>;
+       non-removable;
+       cap-mmc-hw-reset;
+       status = "okay";
+};
+
+&ohci0 {
+       status = "okay";
+};
+
+&r_rsb {
+       status = "okay";
+
+       axp803: pmic@3a3 {
+               compatible = "x-powers,axp803";
+               reg = <0x3a3>;
+               interrupt-parent = <&r_intc>;
+               interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
+               x-powers,drive-vbus-en; /* set N_VBUSEN as output pin */
+       };
+};
+
+#include "axp803.dtsi"
+
+&reg_aldo1 {
+       regulator-always-on;
+       regulator-min-microvolt = <2800000>;
+       regulator-max-microvolt = <2800000>;
+       regulator-name = "avdd-csi";
+};
+
+&reg_aldo2 {
+       regulator-always-on;
+       regulator-min-microvolt = <1800000>;
+       regulator-max-microvolt = <3300000>;
+       regulator-name = "vcc-pl";
+};
+
+&reg_aldo3 {
+       regulator-always-on;
+       regulator-min-microvolt = <3000000>;
+       regulator-max-microvolt = <3000000>;
+       regulator-name = "vcc-pll-avcc";
+};
+
+&reg_dcdc1 {
+       regulator-always-on;
+       regulator-min-microvolt = <3300000>;
+       regulator-max-microvolt = <3300000>;
+       regulator-name = "vcc-3v3";
+};
+
+&reg_dcdc2 {
+       regulator-always-on;
+       regulator-min-microvolt = <1040000>;
+       regulator-max-microvolt = <1300000>;
+       regulator-name = "vdd-cpux";
+};
+
+/* DCDC3 is polyphased with DCDC2 */
+
+&reg_dcdc5 {
+       regulator-always-on;
+       regulator-min-microvolt = <1500000>;
+       regulator-max-microvolt = <1500000>;
+       regulator-name = "vcc-dram";
+};
+
+&reg_dcdc6 {
+       regulator-always-on;
+       regulator-min-microvolt = <1100000>;
+       regulator-max-microvolt = <1100000>;
+       regulator-name = "vdd-sys";
+};
+
+&reg_dldo1 {
+       regulator-min-microvolt = <3300000>;
+       regulator-max-microvolt = <3300000>;
+       regulator-name = "vcc-hdmi-dsi-sensor";
+};
+
+&reg_dldo2 {
+       regulator-min-microvolt = <3300000>;
+       regulator-max-microvolt = <3300000>;
+       regulator-name = "vcc-mipi";
+};
+
+&reg_dldo3 {
+       regulator-min-microvolt = <2800000>;
+       regulator-max-microvolt = <2800000>;
+       regulator-name = "dovdd-csi";
+};
+
+&reg_dldo4 {
+       regulator-min-microvolt = <3300000>;
+       regulator-max-microvolt = <3300000>;
+       regulator-name = "vcc-wifi-io";
+};
+
+&reg_drivevbus {
+       regulator-name = "usb0-vbus";
+       status = "okay";
+};
+
+&reg_eldo1 {
+       regulator-always-on;
+       regulator-min-microvolt = <1800000>;
+       regulator-max-microvolt = <1800000>;
+       regulator-name = "cpvdd";
+};
+
+&reg_eldo3 {
+       regulator-min-microvolt = <1800000>;
+       regulator-max-microvolt = <1800000>;
+       regulator-name = "dvdd-csi";
+};
+
+&reg_fldo1 {
+       regulator-min-microvolt = <1200000>;
+       regulator-max-microvolt = <1200000>;
+       regulator-name = "vcc-1v2-hsic";
+};
+
+/*
+ * The A64 chip cannot work without this regulator off, although
+ * it seems to be only driving the AR100 core.
+ * Maybe we don't still know well about CPUs domain.
+ */
+&reg_fldo2 {
+       regulator-always-on;
+       regulator-min-microvolt = <1100000>;
+       regulator-max-microvolt = <1100000>;
+       regulator-name = "vdd-cpus";
+};
+
+&reg_rtc_ldo {
+       regulator-name = "vcc-rtc";
+};
+
+&uart0 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&uart0_pins_a>;
+       status = "okay";
+};
+
+&usb_otg {
+       dr_mode = "otg";
+       status = "okay";
+};
+
+&usbphy {
+       usb0_id_det-gpios = <&pio 7 9 GPIO_ACTIVE_HIGH>; /* PH9 */
+       usb0_vbus-supply = <&reg_drivevbus>;
+       status = "okay";
+};
index 0716b14..094cfed 100644 (file)
        regulator-name = "vcc-rtc";
 };
 
+&simplefb_hdmi {
+       vcc-hdmi-supply = <&reg_dldo1>;
+};
+
 &uart0 {
        pinctrl-names = "default";
        pinctrl-0 = <&uart0_pins_a>;
index e2dce48..98dbff1 100644 (file)
        regulator-name = "vcc-rtc";
 };
 
+&simplefb_hdmi {
+       vcc-hdmi-supply = <&reg_dldo1>;
+};
+
 &uart0 {
        pinctrl-names = "default";
        pinctrl-0 = <&uart0_pins_a>;
index 3b3081b..3f53139 100644 (file)
        regulator-name = "vcc-rtc";
 };
 
+&simplefb_hdmi {
+       vcc-hdmi-supply = <&reg_dldo1>;
+};
+
 &uart0 {
        pinctrl-names = "default";
        pinctrl-0 = <&uart0_pins_a>;
index bf42690..1221764 100644 (file)
        regulator-name = "vcc-rtc";
 };
 
+&simplefb_hdmi {
+       vcc-hdmi-supply = <&reg_dldo1>;
+};
+
 &uart0 {
        pinctrl-names = "default";
        pinctrl-0 = <&uart0_pins_a>;
index a758257..1b9b92e 100644 (file)
        regulator-name = "vcc-rtc";
 };
 
+&simplefb_hdmi {
+       vcc-hdmi-supply = <&reg_dldo1>;
+};
+
 /* On Euler connector */
 &spdif {
        status = "disabled";
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts
new file mode 100644 (file)
index 0000000..897e60c
--- /dev/null
@@ -0,0 +1,285 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (C) 2017 Icenowy Zheng <icenowy@aosc.xyz>
+ * Copyright (C) 2018 Vasily Khoruzhick <anarsoul@gmail.com>
+ *
+ */
+
+/dts-v1/;
+
+#include "sun50i-a64.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/pwm/pwm.h>
+
+/ {
+       model = "Pinebook";
+       compatible = "pine64,pinebook", "allwinner,sun50i-a64";
+
+       aliases {
+               serial0 = &uart0;
+               ethernet0 = &rtl8723cs;
+       };
+
+       backlight: backlight {
+               compatible = "pwm-backlight";
+               pwms = <&pwm 0 50000 0>;
+               brightness-levels = <0 5 10 15 20 30 40 55 70 85 100>;
+               default-brightness-level = <2>;
+               enable-gpios = <&pio 3 23 GPIO_ACTIVE_HIGH>; /* PD23 */
+       };
+
+       chosen {
+               stdout-path = "serial0:115200n8";
+
+               framebuffer-lcd {
+                       panel-supply = <&reg_dc1sw>;
+                       dvdd25-supply = <&reg_dldo2>;
+                       dvdd12-supply = <&reg_fldo1>;
+               };
+       };
+
+       gpio_keys {
+               compatible = "gpio-keys";
+
+               lid_switch {
+                       label = "Lid Switch";
+                       gpios = <&r_pio 0 12 GPIO_ACTIVE_LOW>; /* PL12 */
+                       linux,input-type = <EV_SW>;
+                       linux,code = <SW_LID>;
+                       linux,can-disable;
+                       wakeup-source;
+               };
+       };
+
+       reg_vcc3v3: vcc3v3 {
+               compatible = "regulator-fixed";
+               regulator-name = "vcc3v3";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+       };
+
+       wifi_pwrseq: wifi_pwrseq {
+               compatible = "mmc-pwrseq-simple";
+               reset-gpios = <&r_pio 0 2 GPIO_ACTIVE_LOW>; /* PL2 */
+       };
+};
+
+&ehci0 {
+       phys = <&usbphy 0>;
+       phy-names = "usb";
+       status = "okay";
+};
+
+&ehci1 {
+       status = "okay";
+};
+
+&mmc0 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&mmc0_pins>;
+       vmmc-supply = <&reg_dcdc1>;
+       cd-gpios = <&pio 5 6 GPIO_ACTIVE_HIGH>;
+       cd-inverted;
+       disable-wp;
+       bus-width = <4>;
+       status = "okay";
+};
+
+&mmc1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&mmc1_pins>;
+       vmmc-supply = <&reg_dldo4>;
+       vqmmc-supply = <&reg_eldo1>;
+       mmc-pwrseq = <&wifi_pwrseq>;
+       bus-width = <4>;
+       non-removable;
+       status = "okay";
+
+       rtl8723cs: wifi@1 {
+               reg = <1>;
+       };
+};
+
+&mmc2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&mmc2_pins>;
+       vmmc-supply = <&reg_dcdc1>;
+       vqmmc-supply = <&reg_eldo1>;
+       bus-width = <8>;
+       non-removable;
+       cap-mmc-hw-reset;
+       mmc-hs200-1_8v;
+       status = "okay";
+};
+
+&ohci0 {
+       phys = <&usbphy 0>;
+       phy-names = "usb";
+       status = "okay";
+};
+
+&ohci1 {
+       status = "okay";
+};
+
+&pwm {
+       status = "okay";
+};
+
+&r_rsb {
+       status = "okay";
+
+       axp803: pmic@3a3 {
+               compatible = "x-powers,axp803";
+               reg = <0x3a3>;
+               interrupt-parent = <&r_intc>;
+               interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
+       };
+};
+
+/* The ANX6345 eDP-bridge is on r_i2c */
+&r_i2c {
+       clock-frequency = <100000>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&r_i2c_pins_a>;
+       status = "okay";
+};
+
+#include "axp803.dtsi"
+
+&reg_aldo1 {
+       regulator-min-microvolt = <2800000>;
+       regulator-max-microvolt = <2800000>;
+       regulator-name = "vcc-csi";
+};
+
+&reg_aldo2 {
+       regulator-always-on;
+       regulator-min-microvolt = <1800000>;
+       regulator-max-microvolt = <3300000>;
+       regulator-name = "vcc-pl";
+};
+
+&reg_aldo3 {
+       regulator-always-on;
+       regulator-min-microvolt = <2700000>;
+       regulator-max-microvolt = <3300000>;
+       regulator-name = "vcc-pll-avcc";
+};
+
+&reg_dc1sw {
+       regulator-name = "vcc-lcd";
+};
+
+&reg_dcdc1 {
+       regulator-always-on;
+       regulator-min-microvolt = <3300000>;
+       regulator-max-microvolt = <3300000>;
+       regulator-name = "vcc-3v3";
+};
+
+&reg_dcdc2 {
+       regulator-always-on;
+       regulator-min-microvolt = <1000000>;
+       regulator-max-microvolt = <1300000>;
+       regulator-name = "vdd-cpux";
+};
+
+/* DCDC3 is polyphased with DCDC2 */
+
+&reg_dcdc5 {
+       regulator-always-on;
+       regulator-min-microvolt = <1200000>;
+       regulator-max-microvolt = <1200000>;
+       regulator-name = "vcc-dram";
+};
+
+&reg_dcdc6 {
+       regulator-always-on;
+       regulator-min-microvolt = <1100000>;
+       regulator-max-microvolt = <1100000>;
+       regulator-name = "vdd-sys";
+};
+
+&reg_dldo1 {
+       regulator-min-microvolt = <3300000>;
+       regulator-max-microvolt = <3300000>;
+       regulator-name = "vcc-hdmi";
+};
+
+&reg_dldo2 {
+       regulator-min-microvolt = <2500000>;
+       regulator-max-microvolt = <2500000>;
+       regulator-name = "vcc-edp";
+};
+
+&reg_dldo3 {
+       regulator-min-microvolt = <3300000>;
+       regulator-max-microvolt = <3300000>;
+       regulator-name = "avdd-csi";
+};
+
+&reg_dldo4 {
+       regulator-min-microvolt = <3300000>;
+       regulator-max-microvolt = <3300000>;
+       regulator-name = "vcc-wifi";
+};
+
+&reg_eldo1 {
+       regulator-always-on;
+       regulator-min-microvolt = <1800000>;
+       regulator-max-microvolt = <1800000>;
+       regulator-name = "cpvdd";
+};
+
+&reg_eldo3 {
+       regulator-min-microvolt = <1800000>;
+       regulator-max-microvolt = <1800000>;
+       regulator-name = "vdd-1v8-csi";
+};
+
+&reg_fldo1 {
+       regulator-min-microvolt = <1200000>;
+       regulator-max-microvolt = <1200000>;
+       regulator-name = "vcc-1v2-hsic";
+};
+
+&reg_fldo2 {
+       regulator-always-on;
+       regulator-min-microvolt = <1100000>;
+       regulator-max-microvolt = <1100000>;
+       regulator-name = "vdd-cpus";
+};
+
+&reg_ldo_io0 {
+       regulator-min-microvolt = <3300000>;
+       regulator-max-microvolt = <3300000>;
+       regulator-name = "vcc-usb";
+       status = "okay";
+};
+
+&reg_rtc_ldo {
+       regulator-name = "vcc-rtc";
+};
+
+&simplefb_hdmi {
+       vcc-hdmi-supply = <&reg_dldo1>;
+};
+
+&uart0 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&uart0_pins_a>;
+       status = "okay";
+};
+
+&usb_otg {
+       dr_mode = "host";
+};
+
+&usbphy {
+       usb0_vbus-supply = <&reg_ldo_io0>;
+       usb1_vbus-supply = <&reg_ldo_io0>;
+       status = "okay";
+};
index abe179d..c21f233 100644 (file)
        regulator-name = "vcc-wifi";
 };
 
+&simplefb_hdmi {
+       vcc-hdmi-supply = <&reg_dldo1>;
+};
+
 &uart0 {
        pinctrl-names = "default";
        pinctrl-0 = <&uart0_pins_a>;
index 43418bd..6723b86 100644 (file)
@@ -45,6 +45,8 @@
 
 #include "sun50i-a64.dtsi"
 
+#include <dt-bindings/gpio/gpio.h>
+
 &mmc0 {
        pinctrl-names = "default";
        pinctrl-0 = <&mmc0_pins>;
@@ -52,6 +54,7 @@
        non-removable;
        disable-wp;
        bus-width = <4>;
+       cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>; /* PF6 */
        status = "okay";
 };
 
        };
 };
 
+&spi0  {
+       status = "okay";
+
+       flash@0 {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "jedec,spi-nor";
+               reg = <0>;
+               spi-max-frequency = <40000000>;
+       };
+};
+
 #include "axp803.dtsi"
 
 &reg_aldo2 {
index d9baab3..81f8e00 100644 (file)
@@ -38,6 +38,7 @@
                        gpios = <&r_pio 0 8 GPIO_ACTIVE_LOW>; /* PL8 */
                        linux,input-type = <EV_SW>;
                        linux,code = <SW_LID>;
+                       wakeup-source;
                };
        };
 
 &reg_dldo3 {
        regulator-min-microvolt = <1200000>;
        regulator-max-microvolt = <1200000>;
-       regulator-name = "eDP12";
+       regulator-name = "vdd-edp";
 };
 
 &reg_dldo4 {
        regulator-name = "vcc-rtc";
 };
 
+&simplefb_hdmi {
+       vcc-hdmi-supply = <&reg_dldo1>;
+};
+
 &uart0 {
        pinctrl-names = "default";
        pinctrl-0 = <&uart0_pins_a>;
index 1b2ef28..d3daf90 100644 (file)
  */
 
 #include <dt-bindings/clock/sun50i-a64-ccu.h>
+#include <dt-bindings/clock/sun8i-de2.h>
 #include <dt-bindings/clock/sun8i-r-ccu.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 #include <dt-bindings/reset/sun50i-a64-ccu.h>
+#include <dt-bindings/reset/sun8i-de2.h>
+#include <dt-bindings/reset/sun8i-r-ccu.h>
 
 / {
        interrupt-parent = <&gic>;
                #size-cells = <1>;
                ranges;
 
-/*
- * The pipeline mixer0-lcd0 depends on clock CLK_MIXER0 from DE2 CCU.
- * However there is no support for this clock on A64 yet, so we depend
- * on the upstream clocks here to keep them (and thus CLK_MIXER0) up.
- */
                simplefb_lcd: framebuffer-lcd {
                        compatible = "allwinner,simple-framebuffer",
                                     "simple-framebuffer";
                        allwinner,pipeline = "mixer0-lcd0";
                        clocks = <&ccu CLK_TCON0>,
-                                <&ccu CLK_DE>, <&ccu CLK_BUS_DE>;
+                                <&display_clocks CLK_MIXER0>;
+                       status = "disabled";
+               };
+
+               simplefb_hdmi: framebuffer-hdmi {
+                       compatible = "allwinner,simple-framebuffer",
+                                    "simple-framebuffer";
+                       allwinner,pipeline = "mixer1-lcd1-hdmi";
+                       clocks = <&display_clocks CLK_MIXER1>,
+                                <&ccu CLK_TCON1>, <&ccu CLK_HDMI>;
                        status = "disabled";
                };
        };
                #size-cells = <1>;
                ranges;
 
+               de2@1000000 {
+                       compatible = "allwinner,sun50i-a64-de2";
+                       reg = <0x1000000 0x400000>;
+                       allwinner,sram = <&de2_sram 1>;
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0 0x1000000 0x400000>;
+
+                       display_clocks: clock@0 {
+                               compatible = "allwinner,sun50i-a64-de2-clk";
+                               reg = <0x0 0x100000>;
+                               clocks = <&ccu CLK_DE>,
+                                        <&ccu CLK_BUS_DE>;
+                               clock-names = "mod",
+                                             "bus";
+                               resets = <&ccu RST_BUS_DE>;
+                               #clock-cells = <1>;
+                               #reset-cells = <1>;
+                       };
+               };
+
                syscon: syscon@1c00000 {
-                       compatible = "allwinner,sun50i-a64-system-controller",
-                               "syscon";
+                       compatible = "allwinner,sun50i-a64-system-control";
                        reg = <0x01c00000 0x1000>;
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges;
+
+                       sram_c: sram@18000 {
+                               compatible = "mmio-sram";
+                               reg = <0x00018000 0x28000>;
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+                               ranges = <0 0x00018000 0x28000>;
+
+                               de2_sram: sram-section@0 {
+                                       compatible = "allwinner,sun50i-a64-sram-c";
+                                       reg = <0x0000 0x28000>;
+                               };
+                       };
                };
 
                dma: dma-controller@1c02000 {
                                bias-pull-up;
                        };
 
+                       pwm_pin: pwm_pin {
+                               pins = "PD22";
+                               function = "pwm";
+                       };
+
                        rmii_pins: rmii_pins {
                                pins = "PD10", "PD11", "PD13", "PD14", "PD17",
                                       "PD18", "PD19", "PD20", "PD22", "PD23";
                        clocks = <&ccu CLK_BUS_EMAC>;
                        clock-names = "stmmaceth";
                        status = "disabled";
-                       #address-cells = <1>;
-                       #size-cells = <0>;
 
                        mdio: mdio {
                                compatible = "snps,dwmac-mdio";
                        #interrupt-cells = <3>;
                };
 
+               pwm: pwm@1c21400 {
+                       compatible = "allwinner,sun50i-a64-pwm",
+                                    "allwinner,sun5i-a13-pwm";
+                       reg = <0x01c21400 0x400>;
+                       clocks = <&osc24M>;
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&pwm_pin>;
+                       #pwm-cells = <3>;
+                       status = "disabled";
+               };
+
                rtc: rtc@1f00000 {
                        compatible = "allwinner,sun6i-a31-rtc";
                        reg = <0x01f00000 0x54>;
                        interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>,
                                     <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>;
+                       clock-output-names = "rtc-osc32k", "rtc-osc32k-out";
+                       clocks = <&osc32k>;
+                       #clock-cells = <1>;
                };
 
                r_intc: interrupt-controller@1f00c00 {
                        #reset-cells = <1>;
                };
 
+               r_i2c: i2c@1f02400 {
+                       compatible = "allwinner,sun50i-a64-i2c",
+                                    "allwinner,sun6i-a31-i2c";
+                       reg = <0x01f02400 0x400>;
+                       interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&r_ccu CLK_APB0_I2C>;
+                       resets = <&r_ccu RST_APB0_I2C>;
+                       status = "disabled";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+               };
+
+               r_pwm: pwm@1f03800 {
+                       compatible = "allwinner,sun50i-a64-pwm",
+                                    "allwinner,sun5i-a13-pwm";
+                       reg = <0x01f03800 0x400>;
+                       clocks = <&osc24M>;
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&r_pwm_pin>;
+                       #pwm-cells = <3>;
+                       status = "disabled";
+               };
+
                r_pio: pinctrl@1f02c00 {
                        compatible = "allwinner,sun50i-a64-r-pinctrl";
                        reg = <0x01f02c00 0x400>;
                        interrupt-controller;
                        #interrupt-cells = <3>;
 
+                       r_i2c_pins_a: i2c-a {
+                               pins = "PL8", "PL9";
+                               function = "s_i2c";
+                       };
+
+                       r_pwm_pin: pwm {
+                               pins = "PL10";
+                               function = "s_pwm";
+                       };
+
                        r_rsb_pins: rsb {
                                pins = "PL0", "PL1";
                                function = "s_rsb";
index 98862c7..3e0d5a9 100644 (file)
        status = "okay";
 };
 
+&spi0  {
+       status = "okay";
+
+       flash@0 {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "jedec,spi-nor";
+               reg = <0>;
+               spi-max-frequency = <40000000>;
+       };
+};
+
 &uart0 {
        pinctrl-names = "default";
        pinctrl-0 = <&uart0_pins_a>;
index b6f2d6b..ceffc40 100644 (file)
        chosen {
                stdout-path = "serial0:115200n8";
        };
+
+       leds {
+               compatible = "gpio-leds";
+
+               heartbeat {
+                       label = "pine-h64:green:heartbeat";
+                       gpios = <&r_pio 0 4 GPIO_ACTIVE_HIGH>; /* PL4 */
+               };
+
+               link {
+                       label = "pine-h64:white:link";
+                       gpios = <&r_pio 0 3 GPIO_ACTIVE_HIGH>; /* PL3 */
+               };
+
+               status {
+                       label = "pine-h64:blue:status";
+                       gpios = <&r_pio 0 7 GPIO_ACTIVE_HIGH>; /* PL7 */
+               };
+       };
+};
+
+&mmc0 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&mmc0_pins>;
+       vmmc-supply = <&reg_cldo1>;
+       cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>;
+       status = "okay";
+};
+
+&mmc2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&mmc2_pins>;
+       vmmc-supply = <&reg_cldo1>;
+       vqmmc-supply = <&reg_bldo2>;
+       non-removable;
+       cap-mmc-hw-reset;
+       status = "okay";
 };
 
 &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;
+
+               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";
+                       };
+
+                       reg_aldo3: aldo3 {
+                               /* This regulator is connected with CLDO1 */
+                               regulator-always-on;
+                               regulator-min-microvolt = <3300000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-name = "vcc-3v3-1";
+                       };
+
+                       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 {
+                               /* This regulator is connected with ALDO3 */
+                               regulator-always-on;
+                               regulator-min-microvolt = <3300000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-name = "vcc-3v3-2";
+                       };
+
+                       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 */
+                       };
+               };
+       };
+
        pcf8563: rtc@51 {
                compatible = "nxp,pcf8563";
                reg = <0x51>;
index c72da8c..cfa5fff 100644 (file)
@@ -5,7 +5,9 @@
 
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 #include <dt-bindings/clock/sun50i-h6-ccu.h>
+#include <dt-bindings/clock/sun50i-h6-r-ccu.h>
 #include <dt-bindings/reset/sun50i-h6-ccu.h>
+#include <dt-bindings/reset/sun50i-h6-r-ccu.h>
 
 / {
        interrupt-parent = <&gic>;
                        interrupt-controller;
                        #interrupt-cells = <3>;
 
+                       mmc0_pins: mmc0-pins {
+                               pins = "PF0", "PF1", "PF2", "PF3",
+                                      "PF4", "PF5";
+                               function = "mmc0";
+                               drive-strength = <30>;
+                               bias-pull-up;
+                       };
+
+                       mmc2_pins: mmc2-pins {
+                               pins = "PC1", "PC4", "PC5", "PC6",
+                                      "PC7", "PC8", "PC9", "PC10",
+                                      "PC11", "PC12", "PC13", "PC14";
+                               function = "mmc2";
+                               drive-strength = <30>;
+                               bias-pull-up;
+                       };
+
                        uart0_ph_pins: uart0-ph {
                                pins = "PH0", "PH1";
                                function = "uart0";
                        };
                };
 
+               mmc0: mmc@4020000 {
+                       compatible = "allwinner,sun50i-h6-mmc",
+                                    "allwinner,sun50i-a64-mmc";
+                       reg = <0x04020000 0x1000>;
+                       clocks = <&ccu CLK_BUS_MMC0>, <&ccu CLK_MMC0>;
+                       clock-names = "ahb", "mmc";
+                       resets = <&ccu RST_BUS_MMC0>;
+                       reset-names = "ahb";
+                       interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
+                       status = "disabled";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+               };
+
+               mmc1: mmc@4021000 {
+                       compatible = "allwinner,sun50i-h6-mmc",
+                                    "allwinner,sun50i-a64-mmc";
+                       reg = <0x04021000 0x1000>;
+                       clocks = <&ccu CLK_BUS_MMC1>, <&ccu CLK_MMC1>;
+                       clock-names = "ahb", "mmc";
+                       resets = <&ccu RST_BUS_MMC1>;
+                       reset-names = "ahb";
+                       interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
+                       status = "disabled";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+               };
+
+               mmc2: mmc@4022000 {
+                       compatible = "allwinner,sun50i-h6-emmc",
+                                    "allwinner,sun50i-a64-emmc";
+                       reg = <0x04022000 0x1000>;
+                       clocks = <&ccu CLK_BUS_MMC2>, <&ccu CLK_MMC2>;
+                       clock-names = "ahb", "mmc";
+                       resets = <&ccu RST_BUS_MMC2>;
+                       reset-names = "ahb";
+                       interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
+                       status = "disabled";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+               };
+
                uart0: serial@5000000 {
                        compatible = "snps,dw-apb-uart";
                        reg = <0x05000000 0x400>;
                        reg = <0x07022000 0x400>;
                        interrupts = <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>,
                                     <GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>;
-                       clocks = <&r_ccu 2>, <&osc24M>, <&osc32k>;
+                       clocks = <&r_ccu CLK_R_APB1>, <&osc24M>, <&osc32k>;
                        clock-names = "apb", "hosc", "losc";
                        gpio-controller;
                        #gpio-cells = <3>;
                        compatible = "allwinner,sun6i-a31-i2c";
                        reg = <0x07081400 0x400>;
                        interrupts = <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>;
-                       clocks = <&r_ccu 8>;
-                       resets = <&r_ccu 4>;
+                       clocks = <&r_ccu CLK_R_APB2_I2C>;
+                       resets = <&r_ccu RST_R_APB2_I2C>;
                        pinctrl-names = "default";
                        pinctrl-0 = <&r_i2c_pins>;
                        status = "disabled";
index 67dac59..d033da4 100644 (file)
                                #clock-cells = <0>;
                                compatible = "fixed-clock";
                        };
+
+                       qspi_clk: qspi-clk {
+                               #clock-cells = <0>;
+                               compatible = "fixed-clock";
+                               clock-frequency = <200000000>;
+                       };
                };
 
                gmac0: ethernet@ff800000 {
                        interrupts = <0 90 4>;
                        interrupt-names = "macirq";
                        mac-address = [00 00 00 00 00 00];
-                       resets = <&rst EMAC0_RESET>;
-                       reset-names = "stmmaceth";
+                       resets = <&rst EMAC0_RESET>, <&rst EMAC0_OCP_RESET>;
+                       reset-names = "stmmaceth", "stmmaceth-ocp";
                        clocks = <&clkmgr STRATIX10_EMAC0_CLK>;
                        clock-names = "stmmaceth";
                        status = "disabled";
                        interrupts = <0 91 4>;
                        interrupt-names = "macirq";
                        mac-address = [00 00 00 00 00 00];
-                       resets = <&rst EMAC1_RESET>;
-                       reset-names = "stmmaceth";
+                       resets = <&rst EMAC1_RESET>, <&rst EMAC1_OCP_RESET>;
+                       reset-names = "stmmaceth", "stmmaceth-ocp";
                        clocks = <&clkmgr STRATIX10_EMAC1_CLK>;
                        clock-names = "stmmaceth";
                        status = "disabled";
                        interrupts = <0 92 4>;
                        interrupt-names = "macirq";
                        mac-address = [00 00 00 00 00 00];
-                       resets = <&rst EMAC2_RESET>;
-                       reset-names = "stmmaceth";
+                       resets = <&rst EMAC2_RESET>, <&rst EMAC2_OCP_RESET>;
+                       reset-names = "stmmaceth", "stmmaceth-ocp";
                        clocks = <&clkmgr STRATIX10_EMAC2_CLK>;
                        clock-names = "stmmaceth";
                        status = "disabled";
                        resets = <&rst SPIM0_RESET>;
                        reg-io-width = <4>;
                        num-cs = <4>;
+                       clocks = <&clkmgr STRATIX10_L4_MAIN_CLK>;
                        status = "disabled";
                };
 
                        resets = <&rst SPIM1_RESET>;
                        reg-io-width = <4>;
                        num-cs = <4>;
+                       clocks = <&clkmgr STRATIX10_L4_MAIN_CLK>;
                        status = "disabled";
                };
 
                        phy-names = "usb2-phy";
                        resets = <&rst USB0_RESET>, <&rst USB0_OCP_RESET>;
                        reset-names = "dwc2", "dwc2-ecc";
+                       clocks = <&clkmgr STRATIX10_USB_CLK>;
                        status = "disabled";
                };
 
                        phy-names = "usb2-phy";
                        resets = <&rst USB1_RESET>, <&rst USB1_OCP_RESET>;
                        reset-names = "dwc2", "dwc2-ecc";
+                       clocks = <&clkmgr STRATIX10_USB_CLK>;
                        status = "disabled";
                };
 
                        reg = <0xffd00200 0x100>;
                        interrupts = <0 117 4>;
                        resets = <&rst WATCHDOG0_RESET>;
+                       clocks = <&clkmgr STRATIX10_L4_SYS_FREE_CLK>;
                        status = "disabled";
                };
 
                        reg = <0xffd00300 0x100>;
                        interrupts = <0 118 4>;
                        resets = <&rst WATCHDOG1_RESET>;
+                       clocks = <&clkmgr STRATIX10_L4_SYS_FREE_CLK>;
                        status = "disabled";
                };
 
                        reg = <0xffd00400 0x100>;
                        interrupts = <0 125 4>;
                        resets = <&rst WATCHDOG2_RESET>;
+                       clocks = <&clkmgr STRATIX10_L4_SYS_FREE_CLK>;
                        status = "disabled";
                };
 
                        reg = <0xffd00500 0x100>;
                        interrupts = <0 126 4>;
                        resets = <&rst WATCHDOG3_RESET>;
+                       clocks = <&clkmgr STRATIX10_L4_SYS_FREE_CLK>;
                        status = "disabled";
                };
 
                                interrupts = <16 4>, <48 4>;
                        };
                };
+
+               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>;
+                       clocks = <&qspi_clk>;
+
+                       status = "disabled";
+               };
        };
 };
index f9b1ef1..6edc4fa 100644 (file)
                reg = <0x68>;
        };
 };
+
+&qspi {
+       flash@0 {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "n25q00a";
+               reg = <0>;
+               spi-max-frequency = <50000000>;
+
+               m25p,fast-read;
+               cdns,page-size = <256>;
+               cdns,block-size = <16>;
+               cdns,read-delay = <1>;
+               cdns,tshsl-ns = <50>;
+               cdns,tsd2d-ns = <50>;
+               cdns,tchsh-ns = <4>;
+               cdns,tslch-ns = <4>;
+
+               partitions {
+                       compatible = "fixed-partitions";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+
+                       qspi_boot: partition@0 {
+                               label = "Boot and fpga data";
+                               reg = <0x0 0x4000000>;
+                       };
+
+                       qspi_rootfs: partition@4000000 {
+                               label = "Root Filesystem - JFFS2";
+                               reg = <0x4000000 0x4000000>;
+                       };
+               };
+       };
+};
index 34dd0e9..a97c0e2 100644 (file)
@@ -17,6 +17,9 @@ dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905x-nexbox-a95x.dtb
 dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905x-p212.dtb
 dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905d-p230.dtb
 dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905d-p231.dtb
+dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s805x-p241.dtb
+dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905w-p281.dtb
+dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905w-tx3-mini.dtb
 dtb-$(CONFIG_ARCH_MESON) += meson-gxm-khadas-vim2.dtb
 dtb-$(CONFIG_ARCH_MESON) += meson-gxm-nexbox-a1.dtb
 dtb-$(CONFIG_ARCH_MESON) += meson-gxm-q200.dtb
index dff9b15..d5c0142 100644 (file)
@@ -6,21 +6,75 @@
 /dts-v1/;
 
 #include "meson-axg.dtsi"
+#include <dt-bindings/input/input.h>
 
 / {
        compatible = "amlogic,s400", "amlogic,a113d", "amlogic,meson-axg";
        model = "Amlogic Meson AXG S400 Development Board";
 
+       adc_keys {
+               compatible = "adc-keys";
+               io-channels = <&saradc 0>;
+               io-channel-names = "buttons";
+               keyup-threshold-microvolt = <1800000>;
+
+               button-next {
+                       label = "Next";
+                       linux,code = <KEY_NEXT>;
+                       press-threshold-microvolt = <1116000>; /* 62% */
+               };
+
+               button-prev {
+                       label = "Previous";
+                       linux,code = <KEY_PREVIOUS>;
+                       press-threshold-microvolt = <900000>; /* 50% */
+               };
+
+               button-wifi {
+                       label = "Wifi";
+                       linux,code = <KEY_WLAN>;
+                       press-threshold-microvolt = <684000>; /* 38% */
+               };
+
+               button-up {
+                       label = "Volume Up";
+                       linux,code = <KEY_VOLUMEUP>;
+                       press-threshold-microvolt = <468000>; /* 26% */
+               };
+
+               button-down {
+                       label = "Volume Down";
+                       linux,code = <KEY_VOLUMEDOWN>;
+                       press-threshold-microvolt = <252000>; /* 14% */
+               };
+
+               button-voice {
+                       label = "Voice";
+                       linux,code = <KEY_VOICECOMMAND>;
+                       press-threshold-microvolt = <0>; /* 0% */
+               };
+       };
+
        aliases {
                serial0 = &uart_AO;
                serial1 = &uart_A;
        };
 
+       main_12v: regulator-main_12v {
+               compatible = "regulator-fixed";
+               regulator-name = "12V";
+               regulator-min-microvolt = <12000000>;
+               regulator-max-microvolt = <12000000>;
+               regulator-always-on;
+       };
+
        vddio_boot: regulator-vddio_boot {
                compatible = "regulator-fixed";
                regulator-name = "VDDIO_BOOT";
                regulator-min-microvolt = <1800000>;
                regulator-max-microvolt = <1800000>;
+               vin-supply = <&vddao_3v3>;
+               regulator-always-on;
        };
 
        vddao_3v3: regulator-vddao_3v3 {
@@ -28,6 +82,8 @@
                regulator-name = "VDDAO_3V3";
                regulator-min-microvolt = <3300000>;
                regulator-max-microvolt = <3300000>;
+               vin-supply = <&main_12v>;
+               regulator-always-on;
        };
 
        vddio_ao18: regulator-vddio_ao18 {
@@ -35,6 +91,8 @@
                regulator-name = "VDDIO_AO18";
                regulator-min-microvolt = <1800000>;
                regulator-max-microvolt = <1800000>;
+               vin-supply = <&vddao_3v3>;
+               regulator-always-on;
        };
 
        vcc_3v3: regulator-vcc_3v3 {
                regulator-name = "VCC_3V3";
                regulator-min-microvolt = <3300000>;
                regulator-max-microvolt = <3300000>;
+               vin-supply = <&vddao_3v3>;
+               regulator-always-on;
+       };
+
+       vcc_5v: regulator-vcc_5v {
+               compatible = "regulator-fixed";
+               regulator-name = "VCC5V";
+               regulator-min-microvolt = <5000000>;
+               regulator-max-microvolt = <5000000>;
+               vin-supply = <&main_12v>;
+
+               gpio = <&gpio_ao GPIOAO_13 GPIO_ACTIVE_HIGH>;
+               enable-active-high;
+       };
+
+       usb_pwr: regulator-usb_pwr {
+               compatible = "regulator-fixed";
+               regulator-name = "USB_PWR";
+               regulator-min-microvolt = <5000000>;
+               regulator-max-microvolt = <5000000>;
+               vin-supply = <&vcc_5v>;
+
+               gpio = <&gpio_ao GPIOAO_5 GPIO_ACTIVE_HIGH>;
+               enable-active-high;
        };
 
        emmc_pwrseq: emmc-pwrseq {
                clock-frequency = <32768>;
                pwms = <&pwm_ab 0 30518 0>; /* PWM_A at 32.768KHz */
        };
+
+       speaker-leds {
+               compatible = "gpio-leds";
+
+               aled1 {
+                       label = "speaker:aled1";
+                       gpios = <&gpio_speaker 7 0>;
+               };
+
+               aled2 {
+                       label = "speaker:aled2";
+                       gpios = <&gpio_speaker 6 0>;
+               };
+
+               aled3 {
+                       label = "speaker:aled3";
+                       gpios = <&gpio_speaker 5 0>;
+               };
+
+               aled4 {
+                       label = "speaker:aled4";
+                       gpios = <&gpio_speaker 4 0>;
+               };
+
+               aled5 {
+                       label = "speaker:aled5";
+                       gpios = <&gpio_speaker 3 0>;
+               };
+
+               aled6 {
+                       label = "speaker:aled6";
+                       gpios = <&gpio_speaker 2 0>;
+               };
+       };
+
+       linein: audio-codec@0 {
+               #sound-dai-cells = <0>;
+               compatible = "everest,es7241";
+               VDDA-supply = <&vcc_3v3>;
+               VDDP-supply = <&vcc_3v3>;
+               VDDD-supply = <&vcc_3v3>;
+               status = "okay";
+               sound-name-prefix = "Linein";
+       };
+
+       lineout: audio-codec@1 {
+               #sound-dai-cells = <0>;
+               compatible = "everest,es7154";
+               VDD-supply = <&vcc_3v3>;
+               PVDD-supply = <&vcc_5v>;
+               status = "okay";
+               sound-name-prefix = "Lineout";
+       };
+
+       spdif_dit: audio-codec@2 {
+               #sound-dai-cells = <0>;
+               compatible = "linux,spdif-dit";
+               status = "okay";
+               sound-name-prefix = "DIT";
+       };
 };
 
 &ethmac {
        status = "okay";
        pinctrl-0 = <&i2c1_z_pins>;
        pinctrl-names = "default";
+
+       speaker_amp1: audio-codec@1b {
+               compatible = "ti,tas5707";
+               reg = <0x1b>;
+               reset-gpios = <&gpio_ao GPIOAO_4 GPIO_ACTIVE_LOW>;
+               #sound-dai-cells = <0>;
+               AVDD-supply = <&vcc_3v3>;
+               DVDD-supply = <&vcc_3v3>;
+               PVDD_A-supply = <&main_12v>;
+               PVDD_B-supply = <&main_12v>;
+               PVDD_C-supply = <&main_12v>;
+               PVDD_D-supply = <&main_12v>;
+       };
 };
 
 &i2c_AO {
        status = "okay";
        pinctrl-0 = <&i2c_ao_sck_10_pins>, <&i2c_ao_sda_11_pins>;
        pinctrl-names = "default";
+
+       gpio_speaker: gpio-controller@1f {
+               compatible = "nxp,pca9557";
+               reg = <0x1f>;
+               gpio-controller;
+               #gpio-cells = <2>;
+               vcc-supply = <&vddao_3v3>;
+       };
 };
 
 &pwm_ab {
                compatible = "brcm,bcm4329-fmac";
        };
 };
+
+&saradc {
+       status = "okay";
+       vref-supply = <&vddio_ao18>;
+};
index 67d7115..c518130 100644 (file)
@@ -6,6 +6,7 @@
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/interrupt-controller/irq.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/clock/axg-audio-clkc.h>
 #include <dt-bindings/clock/axg-clkc.h>
 #include <dt-bindings/clock/axg-aoclkc.h>
 #include <dt-bindings/gpio/meson-axg-gpio.h>
                method = "smc";
        };
 
+       tdmif_a: audio-controller@0 {
+               compatible = "amlogic,axg-tdm-iface";
+               #sound-dai-cells = <0>;
+               sound-name-prefix = "TDM_A";
+               clocks = <&clkc_audio AUD_CLKID_MST_A_MCLK>,
+                        <&clkc_audio AUD_CLKID_MST_A_SCLK>,
+                        <&clkc_audio AUD_CLKID_MST_A_LRCLK>;
+               clock-names = "mclk", "sclk", "lrclk";
+               status = "disabled";
+       };
+
+       tdmif_b: audio-controller@1 {
+               compatible = "amlogic,axg-tdm-iface";
+               #sound-dai-cells = <0>;
+               sound-name-prefix = "TDM_B";
+               clocks = <&clkc_audio AUD_CLKID_MST_B_MCLK>,
+                        <&clkc_audio AUD_CLKID_MST_B_SCLK>,
+                        <&clkc_audio AUD_CLKID_MST_B_LRCLK>;
+               clock-names = "mclk", "sclk", "lrclk";
+               status = "disabled";
+       };
+
+       tdmif_c: audio-controller@2 {
+               compatible = "amlogic,axg-tdm-iface";
+               #sound-dai-cells = <0>;
+               sound-name-prefix = "TDM_C";
+               clocks = <&clkc_audio AUD_CLKID_MST_C_MCLK>,
+                        <&clkc_audio AUD_CLKID_MST_C_SCLK>,
+                        <&clkc_audio AUD_CLKID_MST_C_LRCLK>;
+               clock-names = "mclk", "sclk", "lrclk";
+               status = "disabled";
+       };
+
        timer {
                compatible = "arm,armv8-timer";
                interrupts = <GIC_PPI 13
                        };
                };
 
+               audio: bus@ff642000 {
+                       compatible = "simple-bus";
+                       reg = <0x0 0xff642000 0x0 0x2000>;
+                       #address-cells = <2>;
+                       #size-cells = <2>;
+                       ranges = <0x0 0x0 0x0 0xff642000 0x0 0x2000>;
+
+                       clkc_audio: clock-controller@0 {
+                               compatible = "amlogic,axg-audio-clkc";
+                               reg = <0x0 0x0 0x0 0xb4>;
+                               #clock-cells = <1>;
+
+                               clocks = <&clkc CLKID_AUDIO>,
+                                        <&clkc CLKID_MPLL0>,
+                                        <&clkc CLKID_MPLL1>,
+                                        <&clkc CLKID_MPLL2>,
+                                        <&clkc CLKID_MPLL3>,
+                                        <&clkc CLKID_HIFI_PLL>,
+                                        <&clkc CLKID_FCLK_DIV3>,
+                                        <&clkc CLKID_FCLK_DIV4>,
+                                        <&clkc CLKID_GP0_PLL>;
+                               clock-names = "pclk",
+                                             "mst_in0",
+                                             "mst_in1",
+                                             "mst_in2",
+                                             "mst_in3",
+                                             "mst_in4",
+                                             "mst_in5",
+                                             "mst_in6",
+                                             "mst_in7";
+
+                               resets = <&reset RESET_AUDIO>;
+                       };
+
+                       arb: reset-controller@280 {
+                               compatible = "amlogic,meson-axg-audio-arb";
+                               reg = <0x0 0x280 0x0 0x4>;
+                               #reset-cells = <1>;
+                               clocks = <&clkc_audio AUD_CLKID_DDR_ARB>;
+                       };
+
+                       tdmin_a: audio-controller@300 {
+                               compatible = "amlogic,axg-tdmin";
+                               reg = <0x0 0x300 0x0 0x40>;
+                               sound-name-prefix = "TDMIN_A";
+                               clocks = <&clkc_audio AUD_CLKID_TDMIN_A>,
+                                        <&clkc_audio AUD_CLKID_TDMIN_A_SCLK>,
+                                        <&clkc_audio AUD_CLKID_TDMIN_A_SCLK_SEL>,
+                                        <&clkc_audio AUD_CLKID_TDMIN_A_LRCLK>,
+                                        <&clkc_audio AUD_CLKID_TDMIN_A_LRCLK>;
+                               clock-names = "pclk", "sclk", "sclk_sel",
+                                             "lrclk", "lrclk_sel";
+                               status = "disabled";
+                       };
+
+                       tdmin_b: audio-controller@340 {
+                               compatible = "amlogic,axg-tdmin";
+                               reg = <0x0 0x340 0x0 0x40>;
+                               sound-name-prefix = "TDMIN_B";
+                               clocks = <&clkc_audio AUD_CLKID_TDMIN_B>,
+                                        <&clkc_audio AUD_CLKID_TDMIN_B_SCLK>,
+                                        <&clkc_audio AUD_CLKID_TDMIN_B_SCLK_SEL>,
+                                        <&clkc_audio AUD_CLKID_TDMIN_B_LRCLK>,
+                                        <&clkc_audio AUD_CLKID_TDMIN_B_LRCLK>;
+                               clock-names = "pclk", "sclk", "sclk_sel",
+                                             "lrclk", "lrclk_sel";
+                               status = "disabled";
+                       };
+
+                       tdmin_c: audio-controller@380 {
+                               compatible = "amlogic,axg-tdmin";
+                               reg = <0x0 0x380 0x0 0x40>;
+                               sound-name-prefix = "TDMIN_C";
+                               clocks = <&clkc_audio AUD_CLKID_TDMIN_C>,
+                                        <&clkc_audio AUD_CLKID_TDMIN_C_SCLK>,
+                                        <&clkc_audio AUD_CLKID_TDMIN_C_SCLK_SEL>,
+                                        <&clkc_audio AUD_CLKID_TDMIN_C_LRCLK>,
+                                        <&clkc_audio AUD_CLKID_TDMIN_C_LRCLK>;
+                               clock-names = "pclk", "sclk", "sclk_sel",
+                                             "lrclk", "lrclk_sel";
+                               status = "disabled";
+                       };
+
+                       tdmin_lb: audio-controller@3c0 {
+                               compatible = "amlogic,axg-tdmin";
+                               reg = <0x0 0x3c0 0x0 0x40>;
+                               sound-name-prefix = "TDMIN_LB";
+                               clocks = <&clkc_audio AUD_CLKID_TDMIN_LB>,
+                                        <&clkc_audio AUD_CLKID_TDMIN_LB_SCLK>,
+                                        <&clkc_audio AUD_CLKID_TDMIN_LB_SCLK_SEL>,
+                                        <&clkc_audio AUD_CLKID_TDMIN_LB_LRCLK>,
+                                        <&clkc_audio AUD_CLKID_TDMIN_LB_LRCLK>;
+                               clock-names = "pclk", "sclk", "sclk_sel",
+                                             "lrclk", "lrclk_sel";
+                               status = "disabled";
+                       };
+
+                       spdifout: audio-controller@480 {
+                               compatible = "amlogic,axg-spdifout";
+                               reg = <0x0 0x480 0x0 0x50>;
+                               #sound-dai-cells = <0>;
+                               sound-name-prefix = "SPDIFOUT";
+                               clocks = <&clkc_audio AUD_CLKID_SPDIFOUT>,
+                                        <&clkc_audio AUD_CLKID_SPDIFOUT_CLK>;
+                               clock-names = "pclk", "mclk";
+                               status = "disabled";
+                       };
+
+                       tdmout_a: audio-controller@500 {
+                               compatible = "amlogic,axg-tdmout";
+                               reg = <0x0 0x500 0x0 0x40>;
+                               sound-name-prefix = "TDMOUT_A";
+                               clocks = <&clkc_audio AUD_CLKID_TDMOUT_A>,
+                                        <&clkc_audio AUD_CLKID_TDMOUT_A_SCLK>,
+                                        <&clkc_audio AUD_CLKID_TDMOUT_A_SCLK_SEL>,
+                                        <&clkc_audio AUD_CLKID_TDMOUT_A_LRCLK>,
+                                        <&clkc_audio AUD_CLKID_TDMOUT_A_LRCLK>;
+                               clock-names = "pclk", "sclk", "sclk_sel",
+                                             "lrclk", "lrclk_sel";
+                               status = "disabled";
+                       };
+
+                       tdmout_b: audio-controller@540 {
+                               compatible = "amlogic,axg-tdmout";
+                               reg = <0x0 0x540 0x0 0x40>;
+                               sound-name-prefix = "TDMOUT_B";
+                               clocks = <&clkc_audio AUD_CLKID_TDMOUT_B>,
+                                        <&clkc_audio AUD_CLKID_TDMOUT_B_SCLK>,
+                                        <&clkc_audio AUD_CLKID_TDMOUT_B_SCLK_SEL>,
+                                        <&clkc_audio AUD_CLKID_TDMOUT_B_LRCLK>,
+                                        <&clkc_audio AUD_CLKID_TDMOUT_B_LRCLK>;
+                               clock-names = "pclk", "sclk", "sclk_sel",
+                                             "lrclk", "lrclk_sel";
+                               status = "disabled";
+                       };
+
+                       tdmout_c: audio-controller@580 {
+                               compatible = "amlogic,axg-tdmout";
+                               reg = <0x0 0x580 0x0 0x40>;
+                               sound-name-prefix = "TDMOUT_C";
+                               clocks = <&clkc_audio AUD_CLKID_TDMOUT_C>,
+                                        <&clkc_audio AUD_CLKID_TDMOUT_C_SCLK>,
+                                        <&clkc_audio AUD_CLKID_TDMOUT_C_SCLK_SEL>,
+                                        <&clkc_audio AUD_CLKID_TDMOUT_C_LRCLK>,
+                                        <&clkc_audio AUD_CLKID_TDMOUT_C_LRCLK>;
+                               clock-names = "pclk", "sclk", "sclk_sel",
+                                             "lrclk", "lrclk_sel";
+                               status = "disabled";
+                       };
+               };
+
                cbus: bus@ffd00000 {
                        compatible = "simple-bus";
                        reg = <0x0 0xffd00000 0x0 0x25000>;
                                        };
                                };
 
+                               pdm_dclk_a14_pins: pdm_dclk_a14 {
+                                       mux {
+                                               groups = "pdm_dclk_a14";
+                                               function = "pdm";
+                                       };
+                               };
+
+                               pdm_dclk_a19_pins: pdm_dclk_a19 {
+                                       mux {
+                                               groups = "pdm_dclk_a19";
+                                               function = "pdm";
+                                       };
+                               };
+
+                               pdm_din0_pins: pdm_din0 {
+                                       mux {
+                                               groups = "pdm_din0";
+                                               function = "pdm";
+                                       };
+                               };
+
+                               pdm_din1_pins: pdm_din1 {
+                                       mux {
+                                               groups = "pdm_din1";
+                                               function = "pdm";
+                                       };
+                               };
+
+                               pdm_din2_pins: pdm_din2 {
+                                       mux {
+                                               groups = "pdm_din2";
+                                               function = "pdm";
+                                       };
+                               };
+
+                               pdm_din3_pins: pdm_din3 {
+                                       mux {
+                                               groups = "pdm_din3";
+                                               function = "pdm";
+                                       };
+                               };
+
                                pwm_a_a_pins: pwm_a_a {
                                        mux {
                                                groups = "pwm_a_a";
                                        };
                                };
 
+                               spdif_in_z_pins: spdif_in_z {
+                                       mux {
+                                               groups = "spdif_in_z";
+                                               function = "spdif_in";
+                                       };
+                               };
+
+                               spdif_in_a1_pins: spdif_in_a1 {
+                                       mux {
+                                               groups = "spdif_in_a1";
+                                               function = "spdif_in";
+                                       };
+                               };
+
+                               spdif_in_a7_pins: spdif_in_a7 {
+                                       mux {
+                                               groups = "spdif_in_a7";
+                                               function = "spdif_in";
+                                       };
+                               };
+
+                               spdif_in_a19_pins: spdif_in_a19 {
+                                       mux {
+                                               groups = "spdif_in_a19";
+                                               function = "spdif_in";
+                                       };
+                               };
+
+                               spdif_in_a20_pins: spdif_in_a20 {
+                                       mux {
+                                               groups = "spdif_in_a20";
+                                               function = "spdif_in";
+                                       };
+                               };
+
+                               spdif_out_z_pins: spdif_out_z {
+                                       mux {
+                                               groups = "spdif_out_z";
+                                               function = "spdif_out";
+                                       };
+                               };
+
+                               spdif_out_a1_pins: spdif_out_a1 {
+                                       mux {
+                                               groups = "spdif_out_a1";
+                                               function = "spdif_out";
+                                       };
+                               };
+
+                               spdif_out_a11_pins: spdif_out_a11 {
+                                       mux {
+                                               groups = "spdif_out_a11";
+                                               function = "spdif_out";
+                                       };
+                               };
+
+                               spdif_out_a19_pins: spdif_out_a19 {
+                                       mux {
+                                               groups = "spdif_out_a19";
+                                               function = "spdif_out";
+                                       };
+                               };
+
+                               spdif_out_a20_pins: spdif_out_a20 {
+                                       mux {
+                                               groups = "spdif_out_a20";
+                                               function = "spdif_out";
+                                       };
+                               };
+
                                spi0_pins: spi0 {
                                        mux {
                                                groups = "spi0_miso",
                                interrupts = <GIC_SPI 196 IRQ_TYPE_EDGE_RISING>;
                                status = "disabled";
                        };
+
+                       saradc: adc@9000 {
+                               compatible = "amlogic,meson-axg-saradc",
+                                       "amlogic,meson-saradc";
+                               reg = <0x0 0x9000 0x0 0x38>;
+                               #io-channel-cells = <1>;
+                               interrupts = <GIC_SPI 73 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";
+                       };
                };
        };
 };
index 88e712e..765247b 100644 (file)
                regulator-always-on;
        };
 
+       vddio_ao18: regulator-vddio_ao18 {
+               compatible = "regulator-fixed";
+               regulator-name = "VDDIO_AO18";
+               regulator-min-microvolt = <1800000>;
+               regulator-max-microvolt = <1800000>;
+       };
+
        vddio_boot: regulator-vddio_boot {
                compatible = "regulator-fixed";
                regulator-name = "VDDIO_BOOT";
        clock-names = "clkin0";
 };
 
+&saradc {
+       status = "okay";
+       vref-supply = <&vddio_ao18>;
+};
+
 /* Wireless SDIO Module */
 &sd_emmc_a {
        status = "okay";
 
        vmmc-supply = <&vddao_3v3>;
        vqmmc-supply = <&vddio_boot>;
-
-       brcmf: wifi@1 {
-               reg = <1>;
-               compatible = "brcm,bcm4329-fmac";
-       };
 };
 
 /* SD card */
index 7d5709c..cbe99bd 100644 (file)
                compatible = "mmc-pwrseq-emmc";
                reset-gpios = <&gpio BOOT_9 GPIO_ACTIVE_LOW>;
        };
+
+       /* CVBS is available on CON1 pin 36, disabled by default */
+       cvbs-connector {
+               compatible = "composite-video-connector";
+               status = "disabled";
+
+               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>;
+                       };
+               };
+       };
+};
+
+&cec_AO {
+       status = "okay";
+       pinctrl-0 = <&ao_cec_pins>;
+       pinctrl-names = "default";
+       hdmi-phandle = <&hdmi_tx>;
+};
+
+&cvbs_vdac_port {
+       cvbs_vdac_out: endpoint {
+               remote-endpoint = <&cvbs_connector_in>;
+       };
 };
 
 &ethmac {
        };
 };
 
+&hdmi_tx {
+       status = "okay";
+       pinctrl-0 = <&hdmi_hpd_pins>, <&hdmi_i2c_pins>;
+       pinctrl-names = "default";
+};
+
+&hdmi_tx_tmds_port {
+       hdmi_tx_tmds_out: endpoint {
+               remote-endpoint = <&hdmi_connector_in>;
+       };
+};
+
 &ir {
        status = "okay";
        pinctrl-0 = <&remote_input_ao_pins>;
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl-s805x-p241.dts b/arch/arm64/boot/dts/amlogic/meson-gxl-s805x-p241.dts
new file mode 100644 (file)
index 0000000..70433e0
--- /dev/null
@@ -0,0 +1,218 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2018 BayLibre, SAS.
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ * Author: Jerome Brunet <jbrunet@baylibre.com>
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/input/input.h>
+
+#include "meson-gxl-s905x.dtsi"
+
+/ {
+       compatible = "amlogic,p241", "amlogic,s805x", "amlogic,meson-gxl";
+       model = "Amlogic Meson GXL (S805X) P241 Development Board";
+
+       aliases {
+               serial0 = &uart_AO;
+               serial1 = &uart_A;
+               ethernet0 = &ethmac;
+       };
+
+       chosen {
+               stdout-path = "serial0:115200n8";
+       };
+
+       cvbs-connector {
+               compatible = "composite-video-connector";
+
+               port {
+                       cvbs_connector_in: endpoint {
+                               remote-endpoint = <&cvbs_vdac_out>;
+                       };
+               };
+       };
+
+       emmc_pwrseq: emmc-pwrseq {
+               compatible = "mmc-pwrseq-emmc";
+               reset-gpios = <&gpio BOOT_9 GPIO_ACTIVE_LOW>;
+       };
+
+       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 0x20000000>;
+       };
+
+       vddio_boot: regulator-vddio_boot {
+               compatible = "regulator-fixed";
+               regulator-name = "VDDIO_BOOT";
+               regulator-min-microvolt = <1800000>;
+               regulator-max-microvolt = <1800000>;
+       };
+
+       vddao_3v3: regulator-vddao_3v3 {
+               compatible = "regulator-fixed";
+               regulator-name = "VDDAO_3V3";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+       };
+
+       vddio_ao18: regulator-vddio_ao18 {
+               compatible = "regulator-fixed";
+               regulator-name = "VDDIO_AO18";
+               regulator-min-microvolt = <1800000>;
+               regulator-max-microvolt = <1800000>;
+       };
+
+       vcc_3v3: regulator-vcc_3v3 {
+               compatible = "regulator-fixed";
+               regulator-name = "VCC_3V3";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+       };
+
+       emmc_pwrseq: emmc-pwrseq {
+               compatible = "mmc-pwrseq-emmc";
+               reset-gpios = <&gpio BOOT_9 GPIO_ACTIVE_LOW>;
+       };
+
+       wifi32k: wifi32k {
+               compatible = "pwm-clock";
+               #clock-cells = <0>;
+               clock-frequency = <32768>;
+               pwms = <&pwm_ef 0 30518 0>; /* PWM_E at 32.768KHz */
+       };
+
+       sdio_pwrseq: sdio-pwrseq {
+               compatible = "mmc-pwrseq-simple";
+               reset-gpios = <&gpio GPIOX_6 GPIO_ACTIVE_LOW>;
+               clocks = <&wifi32k>;
+               clock-names = "ext_clock";
+       };
+};
+
+&cec_AO {
+       status = "okay";
+       pinctrl-0 = <&ao_cec_pins>;
+       pinctrl-names = "default";
+       hdmi-phandle = <&hdmi_tx>;
+};
+
+&cvbs_vdac_port {
+       cvbs_vdac_out: endpoint {
+               remote-endpoint = <&cvbs_connector_in>;
+       };
+};
+
+&ethmac {
+       status = "okay";
+};
+
+&internal_phy {
+       pinctrl-0 = <&eth_link_led_pins>, <&eth_act_led_pins>;
+       pinctrl-names = "default";
+};
+
+&ir {
+       status = "okay";
+       pinctrl-0 = <&remote_input_ao_pins>;
+       pinctrl-names = "default";
+};
+
+&hdmi_tx {
+       status = "okay";
+       pinctrl-0 = <&hdmi_hpd_pins>, <&hdmi_i2c_pins>;
+       pinctrl-names = "default";
+};
+
+&hdmi_tx_tmds_port {
+       hdmi_tx_tmds_out: endpoint {
+               remote-endpoint = <&hdmi_connector_in>;
+       };
+};
+
+&saradc {
+       status = "okay";
+       vref-supply = <&vddio_ao18>;
+};
+
+/* Wireless SDIO Module */
+&sd_emmc_a {
+       status = "okay";
+       pinctrl-0 = <&sdio_pins>;
+       pinctrl-1 = <&sdio_clk_gate_pins>;
+       pinctrl-names = "default", "clk-gate";
+       #address-cells = <1>;
+       #size-cells = <0>;
+
+       bus-width = <4>;
+       cap-sd-highspeed;
+       max-frequency = <100000000>;
+
+       non-removable;
+       disable-wp;
+
+       mmc-pwrseq = <&sdio_pwrseq>;
+
+       vmmc-supply = <&vddao_3v3>;
+       vqmmc-supply = <&vddio_boot>;
+};
+
+/* eMMC */
+&sd_emmc_c {
+       status = "okay";
+       pinctrl-0 = <&emmc_pins>, <&emmc_ds_pins>;
+       pinctrl-1 = <&emmc_clk_gate_pins>;
+       pinctrl-names = "default", "clk-gate";
+
+       bus-width = <8>;
+       cap-mmc-highspeed;
+       max-frequency = <200000000>;
+       non-removable;
+       disable-wp;
+       mmc-ddr-1_8v;
+       mmc-hs200-1_8v;
+
+       mmc-pwrseq = <&emmc_pwrseq>;
+       vmmc-supply = <&vcc_3v3>;
+       vqmmc-supply = <&vddio_boot>;
+};
+
+&pwm_ef {
+       status = "okay";
+       pinctrl-0 = <&pwm_e_pins>;
+       pinctrl-names = "default";
+       clocks = <&clkc CLKID_FCLK_DIV4>;
+       clock-names = "clkin0";
+};
+
+/* This is connected to the Bluetooth module: */
+&uart_A {
+       status = "okay";
+       pinctrl-0 = <&uart_a_pins>, <&uart_a_cts_rts_pins>;
+       pinctrl-names = "default";
+       uart-has-rtscts;
+};
+
+&uart_AO {
+       status = "okay";
+       pinctrl-0 = <&uart_ao_a_pins>;
+       pinctrl-names = "default";
+};
+
+&usb0 {
+       status = "okay";
+};
index a9f9bb9..15014fa 100644 (file)
                };
        };
 
-       vddio_ao18: regulator-vddio_ao18 {
-               compatible = "regulator-fixed";
-               regulator-name = "VDDIO_AO18";
-               regulator-min-microvolt = <1800000>;
-               regulator-max-microvolt = <1800000>;
-       };
-
        hdmi-connector {
                compatible = "hdmi-connector";
                type = "a";
        };
 };
 
-&saradc {
-       status = "okay";
-       vref-supply = <&vddio_ao18>;
+&sd_emmc_a {
+       brcmf: wifi@1 {
+               reg = <1>;
+               compatible = "brcm,bcm4329-fmac";
+       };
 };
index 80a2314..92c425d 100644 (file)
        phy-mode = "rmii";
        phy-handle = <&internal_phy>;
 };
+
+&sd_emmc_a {
+       brcmf: wifi@1 {
+               reg = <1>;
+               compatible = "brcm,bcm4329-fmac";
+       };
+};
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl-s905w-p281.dts b/arch/arm64/boot/dts/amlogic/meson-gxl-s905w-p281.dts
new file mode 100644 (file)
index 0000000..6509c49
--- /dev/null
@@ -0,0 +1,22 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2018 Martin Blumenstingl <martin.blumenstingl@googlemail.com>.
+ * Based on meson-gxl-s905d-p231.dts:
+ * - Copyright (c) 2016 Endless Computers, Inc.
+ *   Author: Carlo Caione <carlo@endlessm.com>
+ */
+
+/dts-v1/;
+
+#include "meson-gxl-s905x.dtsi"
+#include "meson-gx-p23x-q20x.dtsi"
+
+/ {
+       compatible = "amlogic,p281", "amlogic,s905w", "amlogic,meson-gxl";
+       model = "Amlogic Meson GXL (S905W) P281 Development Board";
+
+       memory@0 {
+               device_type = "memory";
+               reg = <0x0 0x0 0x0 0x40000000>;
+       };
+};
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl-s905w-tx3-mini.dts b/arch/arm64/boot/dts/amlogic/meson-gxl-s905w-tx3-mini.dts
new file mode 100644 (file)
index 0000000..789c819
--- /dev/null
@@ -0,0 +1,22 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2018 Martin Blumenstingl <martin.blumenstingl@googlemail.com>.
+ * Based on meson-gxl-s905d-p231.dts:
+ * - Copyright (c) 2016 Endless Computers, Inc.
+ *   Author: Carlo Caione <carlo@endlessm.com>
+ */
+
+/dts-v1/;
+
+#include "meson-gxl-s905x.dtsi"
+#include "meson-gx-p23x-q20x.dtsi"
+
+/ {
+       compatible = "oranth,tx3-mini", "amlogic,s905w", "amlogic,meson-gxl";
+       model = "Oranth Tanix TX3 Mini";
+
+       memory@0 {
+               device_type = "memory";
+               reg = <0x0 0x0 0x0 0x40000000>; /* 1 GiB or 2 GiB */
+       };
+};
index 0868da4..313f88f 100644 (file)
        #cooling-cells = <2>;
 };
 
+&cpu1 {
+       #cooling-cells = <2>;
+};
+
+&cpu2 {
+       #cooling-cells = <2>;
+};
+
+&cpu3 {
+       #cooling-cells = <2>;
+};
+
 &cpu4 {
        #cooling-cells = <2>;
 };
 
+&cpu5 {
+       #cooling-cells = <2>;
+};
+
+&cpu6 {
+       #cooling-cells = <2>;
+};
+
+&cpu7 {
+       #cooling-cells = <2>;
+};
+
 &ethmac {
        pinctrl-0 = <&eth_pins>;
        pinctrl-names = "default";
index 1014172..73d656e 100644 (file)
                        gpios = <&gpio_ao GPIOAO_2 GPIO_ACTIVE_LOW>;
                };
        };
-
-       vddio_ao18: regulator-vddio_ao18 {
-               compatible = "regulator-fixed";
-               regulator-name = "VDDIO_AO18";
-               regulator-min-microvolt = <1800000>;
-               regulator-max-microvolt = <1800000>;
-       };
 };
 
 /* Q200 has exclusive choice between internal or external PHY */
@@ -79,7 +72,9 @@
        };
 };
 
-&saradc {
-       status = "okay";
-       vref-supply = <&vddio_ao18>;
+&sd_emmc_a {
+       brcmf: wifi@1 {
+               reg = <1>;
+               compatible = "brcm,bcm4329-fmac";
+       };
 };
index 8d132b1..d02b80d 100644 (file)
        phy-mode = "rmii";
        phy-handle = <&internal_phy>;
 };
+
+&sd_emmc_a {
+       brcmf: wifi@1 {
+               reg = <1>;
+               compatible = "brcm,bcm4329-fmac";
+       };
+};
index 2c5db03..b2b7ced 100644 (file)
@@ -63,7 +63,7 @@
                };
 
                idle-states {
-                       entry-method = "arm,psci";
+                       entry-method = "psci";
 
                        CPU_SLEEP_0: cpu-sleep-0 {
                                compatible = "arm,idle-state";
index c51950f..ab77adb 100644 (file)
@@ -63,7 +63,7 @@
                };
 
                idle-states {
-                       entry-method = "arm,psci";
+                       entry-method = "psci";
 
                        CPU_SLEEP_0: cpu-sleep-0 {
                                compatible = "arm,idle-state";
index 2b2bf39..1fb5c5a 100644 (file)
@@ -62,7 +62,7 @@
                };
 
                idle-states {
-                       entry-method = "arm,psci";
+                       entry-method = "psci";
 
                        CPU_SLEEP_0: cpu-sleep-0 {
                                compatible = "arm,idle-state";
index c4d06cf..20c7d0a 100644 (file)
@@ -1,3 +1,5 @@
 # SPDX-License-Identifier: GPL-2.0
 dtb-$(CONFIG_ARCH_BCM_IPROC) += bcm958742k.dtb
 dtb-$(CONFIG_ARCH_BCM_IPROC) += bcm958742t.dtb
+
+dtb-$(CONFIG_ARCH_BCM_IPROC) += bcm958802a802x.dtb
index 8862ec9..bc299c3 100644 (file)
  *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include "stingray.dtsi"
+#include "stingray-board-base.dtsi"
 
 / {
-       chosen {
-               stdout-path = "serial0:115200n8";
-       };
-
-       aliases {
-               serial0 = &uart1;
-               serial1 = &uart0;
-               serial2 = &uart2;
-               serial3 = &uart3;
-       };
-
        sdio0_vddo_ctrl_reg: sdio0_vddo_ctrl {
                compatible = "regulator-gpio";
                regulator-name = "sdio0_vddo_ctrl_reg";
        };
 };
 
-&memory { /* Default DRAM banks */
-       reg = <0x00000000 0x80000000 0x0 0x80000000>, /* 2G @ 2G */
-             <0x00000008 0x80000000 0x1 0x80000000>; /* 6G @ 34G */
-};
-
 &sata0 {
        status = "okay";
 };
        status = "okay";
 };
 
-&mdio_mux_iproc {
-       mdio@10 {
-               gphy0: eth-phy@10 {
-                       reg = <0x10>;
-               };
-       };
-};
-
-&uart1 {
-       status = "okay";
-};
-
 &pwm {
        status = "okay";
 };
 };
 
 &enet {
-       phy-mode = "rgmii-id";
-       phy-handle = <&gphy0>;
        status = "okay";
 };
 
 
 &sdio0 {
        vqmmc-supply = <&sdio0_vddo_ctrl_reg>;
-       non-removable;
-       full-pwr-cycle;
        status = "okay";
 };
 
 &sdio1 {
        vqmmc-supply = <&sdio1_vddo_ctrl_reg>;
-       full-pwr-cycle;
        status = "okay";
 };
diff --git a/arch/arm64/boot/dts/broadcom/stingray/bcm958802a802x.dts b/arch/arm64/boot/dts/broadcom/stingray/bcm958802a802x.dts
new file mode 100644 (file)
index 0000000..a41facd
--- /dev/null
@@ -0,0 +1,26 @@
+// SPDX-License-Identifier: (GPL-2.0 or BSD-3-Clause)
+/*
+ *Copyright(c) 2018 Broadcom
+ */
+
+/dts-v1/;
+
+#include "stingray-board-base.dtsi"
+
+/ {
+       compatible = "brcm,bcm958802a802x", "brcm,stingray";
+       model = "Stingray PS225xx (BCM958802A802x)";
+};
+
+&enet {
+       status = "disabled";
+};
+
+&sdio0 {
+       no-1-8-v;
+       status = "okay";
+};
+
+&uart0 {
+       status = "okay";
+};
diff --git a/arch/arm64/boot/dts/broadcom/stingray/stingray-board-base.dtsi b/arch/arm64/boot/dts/broadcom/stingray/stingray-board-base.dtsi
new file mode 100644 (file)
index 0000000..82a2471
--- /dev/null
@@ -0,0 +1,51 @@
+// SPDX-License-Identifier: (GPL-2.0 or BSD-3-Clause)
+/*
+ *  Copyright(c) 2016-2018 Broadcom
+ */
+
+#include "stingray.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+       aliases {
+               serial0 = &uart1;
+               serial1 = &uart0;
+               serial2 = &uart2;
+               serial3 = &uart3;
+       };
+
+       chosen {
+               stdout-path = "serial0:115200n8";
+       };
+};
+
+&memory { /* Default DRAM banks */
+       reg = <0x00000000 0x80000000 0x0 0x80000000>, /* 2G @ 2G */
+             <0x00000008 0x80000000 0x1 0x80000000>; /* 6G @ 34G */
+};
+
+&enet {
+       phy-mode = "rgmii-id";
+       phy-handle = <&gphy0>;
+};
+
+&uart1 {
+       status = "okay";
+};
+
+&sdio0 {
+       non-removable;
+       full-pwr-cycle;
+};
+
+&sdio1 {
+       full-pwr-cycle;
+};
+
+&mdio_mux_iproc {
+       mdio@10 {
+               gphy0: eth-phy@10 {
+                       reg = <0x10>;
+               };
+       };
+};
index 3a4d452..10a106a 100644 (file)
                        reg = <0x0001d104 0x32>,
                              <0x0001c854 0x4>;
                        clocks = <&osc>;
-                       clock-output-names = "genpll0", "clk_125", "clk_scr",
+                       clock-output-names = "genpll0", "clk_125m", "clk_scr",
                                             "clk_250", "clk_pcie_axi",
                                             "clk_paxc_axi_x2",
                                             "clk_paxc_axi";
                };
 
+               genpll2: genpll2@1d1ac {
+                       #clock-cells = <1>;
+                       compatible = "brcm,sr-genpll2";
+                       reg = <0x0001d1ac 0x32>,
+                             <0x0001c854 0x4>;
+                       clocks = <&osc>;
+                       clock-output-names = "genpll2", "clk_nic",
+                                            "clk_ts_500_ref", "clk_125_nitro",
+                                            "clk_chimp", "clk_nic_flash",
+                                            "clk_fs";
+               };
+
                genpll3: genpll3@1d1e0 {
                        #clock-cells = <1>;
                        compatible = "brcm,sr-genpll3";
@@ -75,8 +87,8 @@
                              <0x0001c854 0x4>;
                        clocks = <&osc>;
                        clock-output-names = "genpll4", "clk_ccn",
-                                            "clk_tpiu_pll", "noc_clk",
-                                            "pll_chclk_fs4",
+                                            "clk_tpiu_pll", "clk_noc",
+                                            "clk_chclk_fs4",
                                             "clk_bridge_fscpu";
                };
 
@@ -86,8 +98,8 @@
                        reg = <0x0001d248 0x32>,
                              <0x0001c870 0x4>;
                        clocks = <&osc>;
-                       clock-output-names = "genpll5", "fs4_hf_clk",
-                                            "crypto_ae_clk", "raid_ae_clk";
+                       clock-output-names = "genpll5", "clk_fs4_hf",
+                                            "clk_crypto_ae", "clk_raid_ae";
                };
 
                lcpll0: lcpll0@1d0c4 {
                        reg = <0x0001d138 0x3c>,
                              <0x0001c870 0x4>;
                        clocks = <&osc>;
-                       clock-output-names = "lcpll1", "clk_wanpn",
+                       clock-output-names = "lcpll1", "clk_wan",
                                             "clk_usb_ref",
-                                            "timesync_evt_clk";
+                                            "clk_crmu_ts";
                };
 
                hsls_clk: hsls_clk {
diff --git a/arch/arm64/boot/dts/broadcom/stingray/stingray-pcie.dtsi b/arch/arm64/boot/dts/broadcom/stingray/stingray-pcie.dtsi
new file mode 100644 (file)
index 0000000..33a472a
--- /dev/null
@@ -0,0 +1,54 @@
+// SPDX-License-Identifier: (GPL-2.0 or BSD-3-Clause)
+/*
+ *Copyright(c) 2018 Broadcom
+ */
+
+pcie8: pcie@60400000 {
+       compatible = "brcm,iproc-pcie-paxc-v2";
+       reg = <0 0x60400000 0 0x1000>;
+       linux,pci-domain = <8>;
+
+       bus-range = <0x0 0x1>;
+
+       #address-cells = <3>;
+       #size-cells = <2>;
+       device_type = "pci";
+       ranges = <0x83000000 0 0x10000000 0 0x10000000 0 0x20000000>;
+
+       dma-coherent;
+
+       msi-map = <0x100 &gic_its 0x2000 0x1>, /* PF0 */
+                 <0x108 &gic_its 0x2040 0x8>, /* PF0-VF0-7 */
+                 <0x101 &gic_its 0x2080 0x1>, /* PF1 */
+                 <0x110 &gic_its 0x20c8 0x8>, /* PF1-VF8-15 */
+                 <0x102 &gic_its 0x2100 0x1>, /* PF2 */
+                 <0x118 &gic_its 0x2150 0x8>, /* PF2-VF16-23 */
+                 <0x103 &gic_its 0x2180 0x1>, /* PF3 */
+                 <0x120 &gic_its 0x21d8 0x8>, /* PF3-VF24-31 */
+                 <0x104 &gic_its 0x2200 0x1>, /* PF4 */
+                 <0x128 &gic_its 0x2260 0x8>, /* PF4-VF32-39 */
+                 <0x105 &gic_its 0x2280 0x1>, /* PF5 */
+                 <0x130 &gic_its 0x22e8 0x8>, /* PF5-VF40-47 */
+                 <0x106 &gic_its 0x2300 0x1>, /* PF6 */
+                 <0x138 &gic_its 0x2370 0x8>, /* PF6-VF48-55 */
+                 <0x107 &gic_its 0x2380 0x1>, /* PF7 */
+                 <0x140 &gic_its 0x23f8 0x8>; /* PF7-VF56-63 */
+
+       phys = <&pcie_phy 8>;
+       phy-names = "pcie-phy";
+};
+
+pcie-ss {
+       compatible = "simple-bus";
+       #address-cells = <1>;
+       #size-cells = <1>;
+       ranges = <0x0 0x0 0x40000000 0x800>;
+
+       pcie_phy: phy@0 {
+               compatible = "brcm,sr-pcie-phy";
+               reg = <0x0 0x200>;
+               brcm,sr-cdru = <&cdru>;
+               brcm,sr-mhb = <&mhb>;
+               #phy-cells = <1>;
+       };
+};
index a70e8dd..e283480 100644 (file)
                             <GIC_PPI 10 IRQ_TYPE_LEVEL_LOW>;
        };
 
+       mhb: syscon@60401000 {
+               compatible = "brcm,sr-mhb", "syscon";
+               reg = <0 0x60401000 0 0x38c>;
+       };
+
        scr {
                compatible = "simple-bus";
                #address-cells = <1>;
 
                #include "stingray-clock.dtsi"
 
+               otp: otp@1c400 {
+                       compatible = "brcm,ocotp-v2";
+                       reg = <0x0001c400 0x68>;
+                       brcm,ocotp-size = <2048>;
+                       status = "okay";
+               };
+
+               cdru: syscon@1d000 {
+                       compatible = "brcm,sr-cdru", "syscon";
+                       reg = <0x0001d000 0x400>;
+               };
+
                gpio_crmu: gpio@24800 {
                        compatible = "brcm,iproc-gpio";
                        reg = <0x00024800 0x4c>;
 
        #include "stingray-fs4.dtsi"
        #include "stingray-sata.dtsi"
+       #include "stingray-pcie.dtsi"
 
        hsls {
                compatible = "simple-bus";
                        interrupts = <GIC_SPI 189 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&hsls_25m_div2_clk>, <&hsls_div4_clk>;
                        clock-names = "wdogclk", "apb_pclk";
+                       timeout-sec = <60>;
                };
 
                gpio_hsls: gpio@d0000 {
diff --git a/arch/arm64/boot/dts/exynos/exynos5433-tmu-g3d-sensor-conf.dtsi b/arch/arm64/boot/dts/exynos/exynos5433-tmu-g3d-sensor-conf.dtsi
deleted file mode 100644 (file)
index f080357..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Device tree sources for Exynos5433 TMU sensor configuration
- *
- * Copyright (c) 2016 Jonghwa Lee <jonghwa3.lee@samsung.com>
- */
-
-#include <dt-bindings/thermal/thermal_exynos.h>
-
-#thermal-sensor-cells = <0>;
-samsung,tmu_gain = <8>;
-samsung,tmu_reference_voltage = <23>;
-samsung,tmu_noise_cancel_mode = <4>;
-samsung,tmu_efuse_value = <75>;
-samsung,tmu_min_efuse_value = <40>;
-samsung,tmu_max_efuse_value = <150>;
-samsung,tmu_first_point_trim = <25>;
-samsung,tmu_second_point_trim = <85>;
-samsung,tmu_default_temp_offset = <50>;
-samsung,tmu_mux_addr = <6>;
diff --git a/arch/arm64/boot/dts/exynos/exynos5433-tmu-sensor-conf.dtsi b/arch/arm64/boot/dts/exynos/exynos5433-tmu-sensor-conf.dtsi
deleted file mode 100644 (file)
index cccae66..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Device tree sources for Exynos5433 TMU sensor configuration
- *
- * Copyright (c) 2016 Chanwoo Choi <cw00.choi@samsung.com>
- */
-
-#include <dt-bindings/thermal/thermal_exynos.h>
-
-#thermal-sensor-cells = <0>;
-samsung,tmu_gain = <8>;
-samsung,tmu_reference_voltage = <16>;
-samsung,tmu_noise_cancel_mode = <4>;
-samsung,tmu_efuse_value = <75>;
-samsung,tmu_min_efuse_value = <40>;
-samsung,tmu_max_efuse_value = <150>;
-samsung,tmu_first_point_trim = <25>;
-samsung,tmu_second_point_trim = <85>;
-samsung,tmu_default_temp_offset = <50>;
index 038c997..2131f12 100644 (file)
                        clocks = <&cmu_peris CLK_PCLK_TMU0_APBIF>,
                                <&cmu_peris CLK_SCLK_TMU0>;
                        clock-names = "tmu_apbif", "tmu_sclk";
-                       #include "exynos5433-tmu-sensor-conf.dtsi"
+                       #thermal-sensor-cells = <0>;
                        status = "disabled";
                };
 
                        clocks = <&cmu_peris CLK_PCLK_TMU0_APBIF>,
                                <&cmu_peris CLK_SCLK_TMU0>;
                        clock-names = "tmu_apbif", "tmu_sclk";
-                       #include "exynos5433-tmu-sensor-conf.dtsi"
+                       #thermal-sensor-cells = <0>;
                        status = "disabled";
                };
 
                        clocks = <&cmu_peris CLK_PCLK_TMU1_APBIF>,
                                <&cmu_peris CLK_SCLK_TMU1>;
                        clock-names = "tmu_apbif", "tmu_sclk";
-                       #include "exynos5433-tmu-g3d-sensor-conf.dtsi"
+                       #thermal-sensor-cells = <0>;
                        status = "disabled";
                };
 
                        clocks = <&cmu_peris CLK_PCLK_TMU1_APBIF>,
                                <&cmu_peris CLK_SCLK_TMU1>;
                        clock-names = "tmu_apbif", "tmu_sclk";
-                       #include "exynos5433-tmu-sensor-conf.dtsi"
+                       #thermal-sensor-cells = <0>;
                        status = "disabled";
                };
 
                        clocks = <&cmu_peris CLK_PCLK_TMU1_APBIF>,
                                <&cmu_peris CLK_SCLK_TMU1>;
                        clock-names = "tmu_apbif", "tmu_sclk";
-                       #include "exynos5433-tmu-sensor-conf.dtsi"
+                       #thermal-sensor-cells = <0>;
                        status = "disabled";
                };
 
                        power-domains = <&pd_gscl>;
                };
 
-               sysmmu_scaler_0: sysmmu@0x15040000 {
+               sysmmu_scaler_0: sysmmu@15040000 {
                        compatible = "samsung,exynos-sysmmu";
                        reg = <0x15040000 0x1000>;
                        interrupts = <GIC_SPI 404 IRQ_TYPE_LEVEL_HIGH>;
                        power-domains = <&pd_mscl>;
                };
 
-               sysmmu_scaler_1: sysmmu@0x15050000 {
+               sysmmu_scaler_1: sysmmu@15050000 {
                        compatible = "samsung,exynos-sysmmu";
                        reg = <0x15050000 0x1000>;
                        interrupts = <GIC_SPI 406 IRQ_TYPE_LEVEL_HIGH>;
diff --git a/arch/arm64/boot/dts/exynos/exynos7-tmu-sensor-conf.dtsi b/arch/arm64/boot/dts/exynos/exynos7-tmu-sensor-conf.dtsi
deleted file mode 100644 (file)
index 4849471..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Device tree sources for Exynos7 TMU sensor configuration
- *
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com
- */
-
-#include <dt-bindings/thermal/thermal_exynos.h>
-
-#thermal-sensor-cells = <0>;
-samsung,tmu_gain = <9>;
-samsung,tmu_reference_voltage = <17>;
-samsung,tmu_noise_cancel_mode = <4>;
-samsung,tmu_efuse_value = <75>;
-samsung,tmu_min_efuse_value = <15>;
-samsung,tmu_max_efuse_value = <100>;
-samsung,tmu_first_point_trim = <25>;
-samsung,tmu_second_point_trim = <85>;
-samsung,tmu_default_temp_offset = <50>;
-samsung,tmu_cal_type = <TYPE_ONE_POINT_TRIMMING>;
index 93a8433..75ad724 100644 (file)
                        clocks = <&clock_peris PCLK_TMU>,
                                 <&clock_peris SCLK_TMU>;
                        clock-names = "tmu_apbif", "tmu_sclk";
-                       #include "exynos7-tmu-sensor-conf.dtsi"
+                       #thermal-sensor-cells = <0>;
                };
 
                thermal-zones {
index 7286b1e..f90c040 100644 (file)
@@ -1,45 +1,9 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * Device Tree file for Freescale LS1012A Freedom Board.
  *
  * Copyright 2016 Freescale Semiconductor, Inc.
  *
- * This file is dual-licensed: you can use it either under the terms
- * of the GPLv2 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 library is free software; 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 library is distributed in the hope that it will be useful,
- *     but WITHOUT 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/;
 
index cdc4aee..2fb1cb1 100644 (file)
@@ -1,45 +1,9 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * Device Tree file for Freescale LS1012A QDS Board.
  *
  * Copyright 2016 Freescale Semiconductor, Inc.
  *
- * This file is dual-licensed: you can use it either under the terms
- * of the GPLv2 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 library is free software; 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 library is distributed in the hope that it will be useful,
- *     but WITHOUT 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/;
 
index c1a119e..5edb1e1 100644 (file)
@@ -1,45 +1,9 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * Device Tree file for Freescale LS1012A RDB Board.
  *
  * Copyright 2016 Freescale Semiconductor, Inc.
  *
- * This file is dual-licensed: you can use it either under the terms
- * of the GPLv2 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 library is free software; 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 library is distributed in the hope that it will be useful,
- *     but WITHOUT 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/;
 
index 205f0f4..68ac78c 100644 (file)
@@ -1,45 +1,9 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * Device Tree Include file for Freescale Layerscape-1012A family SoC.
  *
  * Copyright 2016 Freescale Semiconductor, Inc.
  *
- * This file is dual-licensed: you can use it either under the terms
- * of the GPLv2 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 library is free software; 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 library is distributed in the hope that it will be useful,
- *     but WITHOUT 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/interrupt-controller/arm-gic.h>
@@ -79,7 +43,7 @@
                 * PSCI node is not added default, U-boot will add missing
                 * parts if it determines to use PSCI.
                 */
-               entry-method = "arm,psci";
+               entry-method = "psci";
 
                CPU_PH20: cpu-ph20 {
                        compatible = "arm,idle-state";
index 169e171..6082ae0 100644 (file)
@@ -1,9 +1,8 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
 /*
  * QorIQ FMan v3 device tree nodes for ls1043
  *
  * Copyright 2015-2016 Freescale Semiconductor Inc.
- *
- * SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
  */
 
 &soc {
index 6341281..c7b8d2c 100644 (file)
@@ -1,47 +1,10 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * Device Tree Include file for Freescale Layerscape-1043A family SoC.
  *
  * Copyright 2014-2015 Freescale Semiconductor, Inc.
  *
  * Mingkai Hu <Mingkai.hu@freescale.com>
- *
- * This file is dual-licensed: you can use it either under the terms
- * of the GPLv2 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 library is free software; 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 library is distributed in the hope that it will be useful,
- *     but WITHOUT 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/;
index 3dc0c8e..7b01ba8 100644 (file)
@@ -1,47 +1,10 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * Device Tree Include file for Freescale Layerscape-1043A family SoC.
  *
  * Copyright 2014-2015 Freescale Semiconductor, Inc.
  *
  * Mingkai Hu <Mingkai.hu@freescale.com>
- *
- * This file is dual-licensed: you can use it either under the terms
- * of the GPLv2 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 library is free software; 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 library is distributed in the hope that it will be useful,
- *     but WITHOUT 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/;
index 1109f22..7881e3d 100644 (file)
@@ -1,47 +1,10 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * Device Tree Include file for Freescale Layerscape-1043A family SoC.
  *
  * Copyright 2014-2015 Freescale Semiconductor, Inc.
  *
  * Mingkai Hu <Mingkai.hu@freescale.com>
- *
- * This file is dual-licensed: you can use it either under the terms
- * of the GPLv2 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 library is free software; 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 library is distributed in the hope that it will be useful,
- *     but WITHOUT 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/thermal/thermal.h>
@@ -80,8 +43,8 @@
                        reg = <0x0>;
                        clocks = <&clockgen 1 0>;
                        next-level-cache = <&l2>;
-                       #cooling-cells = <2>;
                        cpu-idle-states = <&CPU_PH20>;
+                       #cooling-cells = <2>;
                };
 
                cpu1: cpu@1 {
@@ -91,6 +54,7 @@
                        clocks = <&clockgen 1 0>;
                        next-level-cache = <&l2>;
                        cpu-idle-states = <&CPU_PH20>;
+                       #cooling-cells = <2>;
                };
 
                cpu2: cpu@2 {
                        clocks = <&clockgen 1 0>;
                        next-level-cache = <&l2>;
                        cpu-idle-states = <&CPU_PH20>;
+                       #cooling-cells = <2>;
                };
 
                cpu3: cpu@3 {
                        clocks = <&clockgen 1 0>;
                        next-level-cache = <&l2>;
                        cpu-idle-states = <&CPU_PH20>;
+                       #cooling-cells = <2>;
                };
 
                l2: l2-cache {
                 * PSCI node is not added default, U-boot will add missing
                 * parts if it determines to use PSCI.
                 */
-               entry-method = "arm,psci";
+               entry-method = "psci";
 
                CPU_PH20: cpu-ph20 {
                        compatible = "arm,idle-state";
index f5017db..d6caaea 100644 (file)
@@ -1,9 +1,9 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
 /*
  * QorIQ FMan v3 device tree nodes for ls1046
  *
  * Copyright 2015-2016 Freescale Semiconductor Inc.
  *
- * SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
  */
 
 &soc {
index 434383b..e69306e 100644 (file)
@@ -1,47 +1,10 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * Device Tree Include file for Freescale Layerscape-1046A family SoC.
  *
  * Copyright 2016 Freescale Semiconductor, Inc.
  *
  * Shaohui Xie <Shaohui.Xie@nxp.com>
- *
- * This file is dual-licensed: you can use it either under the terms
- * of the GPLv2 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 library is free software; 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 library is distributed in the hope that it will be useful,
- *     but WITHOUT 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/;
index 5dc2782..440e111 100644 (file)
@@ -1,47 +1,10 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * Device Tree Include file for Freescale Layerscape-1046A family SoC.
  *
  * Copyright 2016 Freescale Semiconductor, Inc.
  *
  * Mingkai Hu <mingkai.hu@nxp.com>
- *
- * This file is dual-licensed: you can use it either under the terms
- * of the GPLv2 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 library is free software; 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 library is distributed in the hope that it will be useful,
- *     but WITHOUT 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/;
index 136ebfa..ef83786 100644 (file)
@@ -1,47 +1,10 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * Device Tree Include file for Freescale Layerscape-1046A family SoC.
  *
  * Copyright 2016 Freescale Semiconductor, Inc.
  *
  * Mingkai Hu <mingkai.hu@nxp.com>
- *
- * This file is dual-licensed: you can use it either under the terms
- * of the GPLv2 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 library is free software; 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 library is distributed in the hope that it will be useful,
- *     but WITHOUT 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/interrupt-controller/arm-gic.h>
@@ -87,6 +50,7 @@
                        clocks = <&clockgen 1 0>;
                        next-level-cache = <&l2>;
                        cpu-idle-states = <&CPU_PH20>;
+                       #cooling-cells = <2>;
                };
 
                cpu2: cpu@2 {
@@ -96,6 +60,7 @@
                        clocks = <&clockgen 1 0>;
                        next-level-cache = <&l2>;
                        cpu-idle-states = <&CPU_PH20>;
+                       #cooling-cells = <2>;
                };
 
                cpu3: cpu@3 {
                        clocks = <&clockgen 1 0>;
                        next-level-cache = <&l2>;
                        cpu-idle-states = <&CPU_PH20>;
+                       #cooling-cells = <2>;
                };
 
                l2: l2-cache {
                 * PSCI node is not added default, U-boot will add missing
                 * parts if it determines to use PSCI.
                 */
-               entry-method = "arm,psci";
+               entry-method = "psci";
 
                CPU_PH20: cpu-ph20 {
                        compatible = "arm,idle-state";
index 3012805..6f48d21 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * Device Tree file for NXP LS1088A QDS Board.
  *
@@ -5,43 +6,6 @@
  *
  * Harninder Rai <harninder.rai@nxp.com>
  *
- * This file is dual-licensed: you can use it either under the terms
- * of the GPLv2 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 library is free software; 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 library is distributed in the hope that it will be useful,
- *     but WITHOUT 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/;
index 4f17601..8e925df 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * Device Tree file for NXP LS1088A RDB Board.
  *
@@ -5,43 +6,6 @@
  *
  * Harninder Rai <harninder.rai@nxp.com>
  *
- * This file is dual-licensed: you can use it either under the terms
- * of the GPLv2 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 library is free software; 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 library is distributed in the hope that it will be useful,
- *     but WITHOUT 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/;
index 1c6556b..a07f612 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * Device Tree Include file for NXP Layerscape-1088A family SoC.
  *
@@ -5,43 +6,6 @@
  *
  * Harninder Rai <harninder.rai@nxp.com>
  *
- * This file is dual-licensed: you can use it either under the terms
- * of the GPLv2 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 library is free software; 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 library is distributed in the hope that it will be useful,
- *     but WITHOUT 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/interrupt-controller/arm-gic.h>
 #include <dt-bindings/thermal/thermal.h>
@@ -76,6 +40,7 @@
                        reg = <0x1>;
                        clocks = <&clockgen 1 0>;
                        cpu-idle-states = <&CPU_PH20>;
+                       #cooling-cells = <2>;
                };
 
                cpu2: cpu@2 {
@@ -84,6 +49,7 @@
                        reg = <0x2>;
                        clocks = <&clockgen 1 0>;
                        cpu-idle-states = <&CPU_PH20>;
+                       #cooling-cells = <2>;
                };
 
                cpu3: cpu@3 {
@@ -92,6 +58,7 @@
                        reg = <0x3>;
                        clocks = <&clockgen 1 0>;
                        cpu-idle-states = <&CPU_PH20>;
+                       #cooling-cells = <2>;
                };
 
                cpu4: cpu@100 {
                        reg = <0x101>;
                        clocks = <&clockgen 1 1>;
                        cpu-idle-states = <&CPU_PH20>;
+                       #cooling-cells = <2>;
                };
 
                cpu6: cpu@102 {
                        reg = <0x102>;
                        clocks = <&clockgen 1 1>;
                        cpu-idle-states = <&CPU_PH20>;
+                       #cooling-cells = <2>;
                };
 
                cpu7: cpu@103 {
                        reg = <0x103>;
                        clocks = <&clockgen 1 1>;
                        cpu-idle-states = <&CPU_PH20>;
+                       #cooling-cells = <2>;
                };
 
                CPU_PH20: cpu-ph20 {
index 3c99608..f6c3ee7 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * Device Tree file for Freescale LS2080a QDS Board.
  *
@@ -7,43 +8,6 @@
  * Abhimanyu Saini <abhimanyu.saini@nxp.com>
  * Bhupesh Sharma <bhupesh.sharma@freescale.com>
  *
- * This file is dual-licensed: you can use it either under the terms
- * of the GPLv2 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 library is free software; 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 library is distributed in the hope that it will be useful,
- *     but WITHOUT 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/;
index a4e7de9..4489435 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * Device Tree file for Freescale LS2080a RDB Board.
  *
@@ -7,43 +8,6 @@
  * Abhimanyu Saini <abhimanyu.saini@nxp.com>
  * Bhupesh Sharma <bhupesh.sharma@freescale.com>
  *
- * This file is dual-licensed: you can use it either under the terms
- * of the GPLv2 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 library is free software; 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 library is distributed in the hope that it will be useful,
- *     but WITHOUT 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/;
index fbbb73e..5517305 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * Device Tree file for Freescale LS2080a software Simulator model
  *
@@ -5,43 +6,6 @@
  *
  * Bhupesh Sharma <bhupesh.sharma@freescale.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 library is free software; 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 library is distributed in the hope that it will be useful,
- *     but WITHOUT 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/;
index 8d73930..f9c1d30 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * Device Tree Include file for Freescale Layerscape-2080A family SoC.
  *
@@ -6,43 +7,6 @@
  * Abhimanyu Saini <abhimanyu.saini@nxp.com>
  * Bhupesh Sharma <bhupesh.sharma@freescale.com>
  *
- * This file is dual-licensed: you can use it either under the terms
- * of the GPLv2 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 library is free software; 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 library is distributed in the hope that it will be useful,
- *     but WITHOUT 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 "fsl-ls208xa.dtsi"
@@ -65,6 +29,7 @@
                clocks = <&clockgen 1 0>;
                cpu-idle-states = <&CPU_PW20>;
                next-level-cache = <&cluster0_l2>;
+               #cooling-cells = <2>;
        };
 
        cpu2: cpu@100 {
@@ -84,6 +49,7 @@
                clocks = <&clockgen 1 1>;
                cpu-idle-states = <&CPU_PW20>;
                next-level-cache = <&cluster1_l2>;
+               #cooling-cells = <2>;
        };
 
        cpu4: cpu@200 {
                clocks = <&clockgen 1 2>;
                cpu-idle-states = <&CPU_PW20>;
                next-level-cache = <&cluster2_l2>;
+               #cooling-cells = <2>;
        };
 
        cpu6: cpu@300 {
                clocks = <&clockgen 1 3>;
                cpu-idle-states = <&CPU_PW20>;
                next-level-cache = <&cluster3_l2>;
+               #cooling-cells = <2>;
        };
 
        cluster0_l2: l2-cache0 {
index eaee5b1..7c17b1b 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * Device Tree file for Freescale LS2088A QDS Board.
  *
@@ -6,43 +7,6 @@
  *
  * Abhimanyu Saini <abhimanyu.saini@nxp.com>
  *
- * This file is dual-licensed: you can use it either under the terms
- * of the GPLv2 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 library is free software; 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 library is distributed in the hope that it will be useful,
- *     but WITHOUT 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/;
index c411442..f6b4d75 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * Device Tree file for Freescale LS2088A RDB Board.
  *
@@ -6,43 +7,6 @@
  *
  * Abhimanyu Saini <abhimanyu.saini@nxp.com>
  *
- * This file is dual-licensed: you can use it either under the terms
- * of the GPLv2 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 library is free software; 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 library is distributed in the hope that it will be useful,
- *     but WITHOUT 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/;
index 0884e1a..7c882da 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * Device Tree Include file for Freescale Layerscape-2088A family SoC.
  *
@@ -6,43 +7,6 @@
  *
  * Abhimanyu Saini <abhimanyu.saini@nxp.com>
  *
- * This file is dual-licensed: you can use it either under the terms
- * of the GPLv2 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 library is free software; 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 library is distributed in the hope that it will be useful,
- *     but WITHOUT 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 "fsl-ls208xa.dtsi"
@@ -65,6 +29,7 @@
                clocks = <&clockgen 1 0>;
                cpu-idle-states = <&CPU_PW20>;
                next-level-cache = <&cluster0_l2>;
+               #cooling-cells = <2>;
        };
 
        cpu2: cpu@100 {
@@ -84,6 +49,7 @@
                clocks = <&clockgen 1 1>;
                cpu-idle-states = <&CPU_PW20>;
                next-level-cache = <&cluster1_l2>;
+               #cooling-cells = <2>;
        };
 
        cpu4: cpu@200 {
                clocks = <&clockgen 1 2>;
                cpu-idle-states = <&CPU_PW20>;
                next-level-cache = <&cluster2_l2>;
+               #cooling-cells = <2>;
        };
 
        cpu6: cpu@300 {
                clocks = <&clockgen 1 3>;
                cpu-idle-states = <&CPU_PW20>;
                next-level-cache = <&cluster3_l2>;
+               #cooling-cells = <2>;
        };
 
        cluster0_l2: l2-cache0 {
index 1de6188..c11f52e 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * Device Tree file for Freescale LS2080A QDS Board.
  *
@@ -6,43 +7,6 @@
  *
  * Abhimanyu Saini <abhimanyu.saini@nxp.com>
  *
- * This file is dual-licensed: you can use it either under the terms
- * of the GPLv2 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 library is free software; 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 library is distributed in the hope that it will be useful,
- *     but WITHOUT 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.
  */
 
 &esdhc {
index 061647b..6fd7f63 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * Device Tree file for Freescale LS2080A RDB Board.
  *
@@ -6,43 +7,6 @@
  *
  * Abhimanyu Saini <abhimanyu.saini@nxp.com>
  *
- * This file is dual-licensed: you can use it either under the terms
- * of the GPLv2 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 library is free software; 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 library is distributed in the hope that it will be useful,
- *     but WITHOUT 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.
  */
 
 &esdhc {
index 137ef4d..8cb78dd 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * Device Tree Include file for Freescale Layerscape-2080A family SoC.
  *
@@ -6,43 +7,6 @@
  *
  * Abhimanyu Saini <abhimanyu.saini@nxp.com>
  *
- * This file is dual-licensed: you can use it either under the terms
- * of the GPLv2 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 library is free software; 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 library is distributed in the hope that it will be useful,
- *     but WITHOUT 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/thermal/thermal.h>
index ae15307..ff1aba5 100644 (file)
@@ -1,9 +1,9 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
 /*
  * QorIQ BMan Portals device tree
  *
  * Copyright 2011-2016 Freescale Semiconductor Inc.
  *
- * SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
  */
 
 &bportals {
index ecdffe7..dbd2fc3 100644 (file)
@@ -1,9 +1,9 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
 /*
  * QorIQ FMan v3 10g port #0 device tree
  *
  * Copyright 2012-2015 Freescale Semiconductor Inc.
  *
- * SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
  */
 
 fman@1a00000 {
index a7f6af5..6fc5d25 100644 (file)
@@ -1,9 +1,9 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
 /*
  * QorIQ FMan v3 10g port #1 device tree
  *
  * Copyright 2012-2015 Freescale Semiconductor Inc.
  *
- * SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
  */
 
 fman@1a00000 {
index d600786..4e02276 100644 (file)
@@ -1,9 +1,9 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
 /*
  * QorIQ FMan v3 1g port #0 device tree
  *
  * Copyright 2012-2015 Freescale Semiconductor Inc.
  *
- * SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
  */
 
 fman@1a00000 {
index 3c0b76d..0312fa4 100644 (file)
@@ -1,9 +1,9 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
 /*
  * QorIQ FMan v3 1g port #1 device tree
  *
  * Copyright 2012-2015 Freescale Semiconductor Inc.
  *
- * SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
  */
 
 fman@1a00000 {
index 89633af..af2df07 100644 (file)
@@ -1,9 +1,9 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
 /*
  * QorIQ FMan v3 1g port #2 device tree
  *
  * Copyright 2012-2015 Freescale Semiconductor Inc.
  *
- * SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
  */
 
 fman@1a00000 {
index 87c2b70..4ac98dc 100644 (file)
@@ -1,9 +1,9 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
 /*
  * QorIQ FMan v3 1g port #3 device tree
  *
  * Copyright 2012-2015 Freescale Semiconductor Inc.
  *
- * SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
  */
 
 fman@1a00000 {
index 8f4d74b..bd932d8 100644 (file)
@@ -1,9 +1,9 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
 /*
  * QorIQ FMan v3 1g port #4 device tree
  *
  * Copyright 2012-2015 Freescale Semiconductor Inc.
  *
- * SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
  */
 
 fman@1a00000 {
index d534f77..7de1c52 100644 (file)
@@ -1,9 +1,9 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
 /*
  * QorIQ FMan v3 1g port #5 device tree
  *
  * Copyright 2012-2015 Freescale Semiconductor Inc.
  *
- * SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
  */
 
 fman@1a00000 {
index 4664c33..263b972 100644 (file)
@@ -1,9 +1,9 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
 /*
  * QorIQ FMan v3 device tree
  *
  * Copyright 2012-2015 Freescale Semiconductor Inc.
  *
- * SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
  */
 
 fman0: fman@1a00000 {
index 6a93a4a..e3bec08 100644 (file)
@@ -1,9 +1,9 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
 /*
  * QorIQ QMan Portals device tree
  *
  * Copyright 2011-2016 Freescale Semiconductor Inc.
  *
- * SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
  */
 
 &qportals {
index 68c5a6c..c98bcbc 100644 (file)
 };
 
 &dwmmc1 {
+       bus-width = <0x4>;
+       cap-sd-highspeed;
+       sd-uhs-sdr12;
+       sd-uhs-sdr25;
+       sd-uhs-sdr50;
+       sd-uhs-sdr104;
+       disable-wp;
+       cd-inverted;
+       cd-gpios = <&gpio25 3 0>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&sd_pmx_func
+                    &sd_clk_cfg_func
+                    &sd_cfg_func>;
        vmmc-supply = <&ldo16>;
        vqmmc-supply = <&ldo9>;
        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>;
-       ti,non-removable;
-       non-removable;
-       cap-power-off-card;
-       keep-power-in-suspend;
-       #address-cells = <0x1>;
-       #size-cells = <0x0>;
        status = "ok";
 
        wlcore: wlcore@2 {
index 851190a..f432b0a 100644 (file)
@@ -61,7 +61,7 @@
                        reg = <0x0 0x0>;
                        enable-method = "psci";
                        next-level-cache = <&A53_L2>;
-                       cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP_0>;
+                       cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
                        capacity-dmips-mhz = <592>;
                        clocks = <&stub_clock HI3660_CLK_STUB_CLUSTER0>;
                        operating-points-v2 = <&cluster0_opp>;
@@ -75,7 +75,7 @@
                        reg = <0x0 0x1>;
                        enable-method = "psci";
                        next-level-cache = <&A53_L2>;
-                       cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP_0>;
+                       cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
                        capacity-dmips-mhz = <592>;
                        clocks = <&stub_clock HI3660_CLK_STUB_CLUSTER0>;
                        operating-points-v2 = <&cluster0_opp>;
@@ -87,7 +87,7 @@
                        reg = <0x0 0x2>;
                        enable-method = "psci";
                        next-level-cache = <&A53_L2>;
-                       cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP_0>;
+                       cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
                        capacity-dmips-mhz = <592>;
                        clocks = <&stub_clock HI3660_CLK_STUB_CLUSTER0>;
                        operating-points-v2 = <&cluster0_opp>;
@@ -99,7 +99,7 @@
                        reg = <0x0 0x3>;
                        enable-method = "psci";
                        next-level-cache = <&A53_L2>;
-                       cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP_0>;
+                       cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
                        capacity-dmips-mhz = <592>;
                        clocks = <&stub_clock HI3660_CLK_STUB_CLUSTER0>;
                        operating-points-v2 = <&cluster0_opp>;
                        reg = <0x0 0x100>;
                        enable-method = "psci";
                        next-level-cache = <&A73_L2>;
-                       cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP_1>;
+                       cpu-idle-states = <&CPU_SLEEP_1 &CLUSTER_SLEEP_1>;
                        capacity-dmips-mhz = <1024>;
                        clocks = <&stub_clock HI3660_CLK_STUB_CLUSTER1>;
                        operating-points-v2 = <&cluster1_opp>;
                        reg = <0x0 0x101>;
                        enable-method = "psci";
                        next-level-cache = <&A73_L2>;
-                       cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP_1>;
+                       cpu-idle-states = <&CPU_SLEEP_1 &CLUSTER_SLEEP_1>;
                        capacity-dmips-mhz = <1024>;
                        clocks = <&stub_clock HI3660_CLK_STUB_CLUSTER1>;
                        operating-points-v2 = <&cluster1_opp>;
                        reg = <0x0 0x102>;
                        enable-method = "psci";
                        next-level-cache = <&A73_L2>;
-                       cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP_1>;
+                       cpu-idle-states = <&CPU_SLEEP_1 &CLUSTER_SLEEP_1>;
                        capacity-dmips-mhz = <1024>;
                        clocks = <&stub_clock HI3660_CLK_STUB_CLUSTER1>;
                        operating-points-v2 = <&cluster1_opp>;
                        reg = <0x0 0x103>;
                        enable-method = "psci";
                        next-level-cache = <&A73_L2>;
-                       cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP_1>;
+                       cpu-idle-states = <&CPU_SLEEP_1 &CLUSTER_SLEEP_1>;
                        capacity-dmips-mhz = <1024>;
                        clocks = <&stub_clock HI3660_CLK_STUB_CLUSTER1>;
                        operating-points-v2 = <&cluster1_opp>;
                idle-states {
                        entry-method = "psci";
 
-                       CPU_SLEEP: cpu-sleep {
+                       CPU_SLEEP_0: cpu-sleep-0 {
                                compatible = "arm,idle-state";
                                local-timer-stop;
                                arm,psci-suspend-param = <0x0010000>;
-                               entry-latency-us = <40>;
-                               exit-latency-us = <70>;
-                               min-residency-us = <3000>;
+                               entry-latency-us = <400>;
+                               exit-latency-us = <650>;
+                               min-residency-us = <1500>;
                        };
-
                        CLUSTER_SLEEP_0: cluster-sleep-0 {
                                compatible = "arm,idle-state";
                                local-timer-stop;
                                arm,psci-suspend-param = <0x1010000>;
                                entry-latency-us = <500>;
-                               exit-latency-us = <5000>;
-                               min-residency-us = <20000>;
+                               exit-latency-us = <1600>;
+                               min-residency-us = <3500>;
+                       };
+
+
+                       CPU_SLEEP_1: cpu-sleep-1 {
+                               compatible = "arm,idle-state";
+                               local-timer-stop;
+                               arm,psci-suspend-param = <0x0010000>;
+                               entry-latency-us = <400>;
+                               exit-latency-us = <550>;
+                               min-residency-us = <1500>;
                        };
 
                        CLUSTER_SLEEP_1: cluster-sleep-1 {
                                compatible = "arm,idle-state";
                                local-timer-stop;
                                arm,psci-suspend-param = <0x1010000>;
-                               entry-latency-us = <1000>;
-                               exit-latency-us = <5000>;
-                               min-residency-us = <20000>;
+                               entry-latency-us = <800>;
+                               exit-latency-us = <2900>;
+                               min-residency-us = <3500>;
                        };
                };
 
 
                /* SD */
                dwmmc1: dwmmc1@ff37f000 {
-                       #address-cells = <1>;
-                       #size-cells = <0>;
-                       cd-inverted;
                        compatible = "hisilicon,hi3660-dw-mshc";
-                       bus-width = <0x4>;
-                       disable-wp;
-                       cap-sd-highspeed;
-                       supports-highspeed;
-                       card-detect-delay = <200>;
                        reg = <0x0 0xff37f000 0x0 0x1000>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
                        interrupts = <GIC_SPI 139 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&crg_ctrl HI3660_CLK_GATE_SD>,
                                <&crg_ctrl HI3660_HCLK_GATE_SD>;
                        clock-frequency = <3200000>;
                        resets = <&crg_rst 0x94 18>;
                        reset-names = "reset";
-                       cd-gpios = <&gpio25 3 0>;
                        hisilicon,peripheral-syscon = <&sctrl>;
-                       pinctrl-names = "default";
-                       pinctrl-0 = <&sd_pmx_func
-                                    &sd_clk_cfg_func
-                                    &sd_cfg_func>;
-                       sd-uhs-sdr12;
-                       sd-uhs-sdr25;
-                       sd-uhs-sdr50;
-                       sd-uhs-sdr104;
+                       card-detect-delay = <200>;
                        status = "disabled";
-
-                       slot@0 {
-                               reg = <0x0>;
-                               bus-width = <4>;
-                               disable-wp;
-                       };
                };
 
                /* SDIO */
                dwmmc2: dwmmc2@ff3ff000 {
                        compatible = "hisilicon,hi3660-dw-mshc";
                        reg = <0x0 0xff3ff000 0x0 0x1000>;
+                       #address-cells = <0x1>;
+                       #size-cells = <0x0>;
                        interrupts = <GIC_SPI 140 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&crg_ctrl HI3660_CLK_GATE_SDIO0>,
                                 <&crg_ctrl HI3660_HCLK_GATE_SDIO0>;
                        resets = <&crg_rst 0x94 20>;
                        reset-names = "reset";
                        card-detect-delay = <200>;
-                       supports-highspeed;
-                       keep-power-in-suspend;
-                       pinctrl-names = "default";
-                       pinctrl-0 = <&sdio_pmx_func
-                                    &sdio_clk_cfg_func
-                                    &sdio_cfg_func>;
                        status = "disabled";
                };
 
index 7f12624..f4964be 100644 (file)
                        bus-width = <0x4>;
                        non-removable;
                        cap-power-off-card;
-                       keep-power-in-suspend;
                        vmmc-supply = <&reg_vdd_3v3>;
                        mmc-pwrseq = <&wl1835_pwrseq>;
 
index 586b281..247024d 100644 (file)
@@ -88,8 +88,8 @@
                        next-level-cache = <&CLUSTER0_L2>;
                        clocks = <&stub_clock 0>;
                        operating-points-v2 = <&cpu_opp_table>;
-                       #cooling-cells = <2>; /* min followed by max */
                        cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>;
+                       #cooling-cells = <2>; /* min followed by max */
                        dynamic-power-coefficient = <311>;
                };
 
                        next-level-cache = <&CLUSTER0_L2>;
                        operating-points-v2 = <&cpu_opp_table>;
                        cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>;
+                       #cooling-cells = <2>; /* min followed by max */
+                       dynamic-power-coefficient = <311>;
                };
 
                cpu2: cpu@2 {
                        next-level-cache = <&CLUSTER0_L2>;
                        operating-points-v2 = <&cpu_opp_table>;
                        cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>;
+                       #cooling-cells = <2>; /* min followed by max */
+                       dynamic-power-coefficient = <311>;
                };
 
                cpu3: cpu@3 {
                        next-level-cache = <&CLUSTER0_L2>;
                        operating-points-v2 = <&cpu_opp_table>;
                        cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>;
+                       #cooling-cells = <2>; /* min followed by max */
+                       dynamic-power-coefficient = <311>;
                };
 
                cpu4: cpu@100 {
                        next-level-cache = <&CLUSTER1_L2>;
                        operating-points-v2 = <&cpu_opp_table>;
                        cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>;
+                       #cooling-cells = <2>; /* min followed by max */
+                       dynamic-power-coefficient = <311>;
                };
 
                cpu5: cpu@101 {
                        next-level-cache = <&CLUSTER1_L2>;
                        operating-points-v2 = <&cpu_opp_table>;
                        cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>;
+                       #cooling-cells = <2>; /* min followed by max */
+                       dynamic-power-coefficient = <311>;
                };
 
                cpu6: cpu@102 {
                        next-level-cache = <&CLUSTER1_L2>;
                        operating-points-v2 = <&cpu_opp_table>;
                        cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>;
+                       #cooling-cells = <2>; /* min followed by max */
+                       dynamic-power-coefficient = <311>;
                };
 
                cpu7: cpu@103 {
                        next-level-cache = <&CLUSTER1_L2>;
                        operating-points-v2 = <&cpu_opp_table>;
                        cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP>;
+                       #cooling-cells = <2>; /* min followed by max */
+                       dynamic-power-coefficient = <311>;
                };
 
                CLUSTER0_L2: l2-cache0 {
index 3353252..d9531e2 100644 (file)
                serial1 = &uart1;
        };
 
+       reserved-memory {
+               #address-cells = <2>;
+               #size-cells = <2>;
+               ranges;
+
+               /*
+                * The PSCI firmware region depicted below is the default one
+                * and should be updated by the bootloader.
+                */
+               psci-area@4000000 {
+                       reg = <0 0x4000000 0 0x200000>;
+                       no-map;
+               };
+       };
+
        cpus {
                #address-cells = <1>;
                #size-cells = <0>;
                                status = "disabled";
                        };
 
+                       avs: avs@11500 {
+                               compatible = "marvell,armada-3700-avs",
+                                            "syscon";
+                               reg = <0x11500 0x40>;
+                       };
+
                        uart0: serial@12000 {
                                compatible = "marvell,armada-3700-uart";
                                reg = <0x12000 0x200>;
                        };
 
                        crypto: crypto@90000 {
-                               compatible = "inside-secure,safexcel-eip97";
+                               compatible = "inside-secure,safexcel-eip97ies";
                                reg = <0x90000 0x20000>;
                                interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>,
                                             <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>,
index a66958f..56fa448 100644 (file)
@@ -91,7 +91,7 @@
        };
 
        sfp_eth3: sfp-eth3 {
-               /* CON3,4 - CPS lane 5 */
+               /* CON13,14 - CPS lane 5 */
                compatible = "sff,sfp";
                i2c-bus = <&sfp_1g_i2c>;
                los-gpio = <&cp0_gpio2 22 GPIO_ACTIVE_HIGH>;
index 1c6ff81..840c845 100644 (file)
                };
 
                CP110_LABEL(crypto): crypto@800000 {
-                       compatible = "inside-secure,safexcel-eip197";
+                       compatible = "inside-secure,safexcel-eip197b";
                        reg = <0x800000 0x200000>;
                        interrupts = <ICU_GRP_NSR 87 IRQ_TYPE_LEVEL_HIGH>,
                                <ICU_GRP_NSR 88 IRQ_TYPE_LEVEL_HIGH>,
index ac17f60..5b7fd6a 100644 (file)
@@ -3,5 +3,6 @@ dtb-$(CONFIG_ARCH_MEDIATEK) += mt2712-evb.dtb
 dtb-$(CONFIG_ARCH_MEDIATEK) += mt6755-evb.dtb
 dtb-$(CONFIG_ARCH_MEDIATEK) += mt6795-evb.dtb
 dtb-$(CONFIG_ARCH_MEDIATEK) += mt6797-evb.dtb
+dtb-$(CONFIG_ARCH_MEDIATEK) += mt6797-x20-dev.dtb
 dtb-$(CONFIG_ARCH_MEDIATEK) += mt7622-rfb1.dtb
 dtb-$(CONFIG_ARCH_MEDIATEK) += mt8173-evb.dtb
index 6d8532a..75cc0f7 100644 (file)
                };
 
                idle-states {
-                       entry-method = "arm,psci";
+                       entry-method = "psci";
 
                        CPU_SLEEP_0: cpu-sleep-0 {
                                compatible = "arm,idle-state";
diff --git a/arch/arm64/boot/dts/mediatek/mt6797-x20-dev.dts b/arch/arm64/boot/dts/mediatek/mt6797-x20-dev.dts
new file mode 100644 (file)
index 0000000..742938a
--- /dev/null
@@ -0,0 +1,33 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Device Tree Source for MediaTek X20 Development Board
+ *
+ * Copyright (C) 2018, Linaro Ltd.
+ *
+ */
+
+/dts-v1/;
+
+#include "mt6797.dtsi"
+
+/ {
+       model = "Mediatek X20 Development Board";
+       compatible = "archermind,mt6797-x20-dev", "mediatek,mt6797";
+
+       aliases {
+               serial0 = &uart1;
+       };
+
+       memory@40000000 {
+               device_type = "memory";
+               reg = <0 0x40000000 0 0x80000000>;
+       };
+
+       chosen {
+               stdout-path = "serial0:115200n8";
+       };
+};
+
+&uart1 {
+       status = "okay";
+};
index b783764..a747b7b 100644 (file)
@@ -18,7 +18,7 @@
        compatible = "mediatek,mt7622-rfb1", "mediatek,mt7622";
 
        chosen {
-               bootargs = "console=ttyS0,115200n1 swiotlb=512";
+               bootargs = "earlycon=uart8250,mmio32,0x11002000 console=ttyS0,115200n1 swiotlb=512";
        };
 
        cpus {
@@ -34,7 +34,7 @@
        };
 
        gpio-keys {
-               compatible = "gpio-keys-polled";
+               compatible = "gpio-keys";
                poll-interval = <100>;
 
                factory {
index 9213c96..de2c47b 100644 (file)
@@ -89,6 +89,7 @@
                                 <&apmixedsys CLK_APMIXED_MAIN_CORE_EN>;
                        clock-names = "cpu", "intermediate";
                        operating-points-v2 = <&cpu_opp_table>;
+                       #cooling-cells = <2>;
                        enable-method = "psci";
                        clock-frequency = <1300000000>;
                };
 
        pio: pinctrl@10211000 {
                compatible = "mediatek,mt7622-pinctrl";
-               reg = <0 0x10211000 0 0x1000>;
+               reg = <0 0x10211000 0 0x1000>,
+                     <0 0x10005000 0 0x1000>;
+               reg-names = "base", "eint";
                gpio-controller;
                #gpio-cells = <2>;
+               gpio-ranges = <&pio 0 0 103>;
+               interrupt-controller;
+               interrupts = <GIC_SPI 153 IRQ_TYPE_LEVEL_HIGH>;
+               interrupt-parent = <&gic>;
+               #interrupt-cells = <2>;
        };
 
        watchdog: watchdog@10212000 {
                reg = <0 0x11002000 0 0x400>;
                interrupts = <GIC_SPI 91 IRQ_TYPE_LEVEL_LOW>;
                clocks = <&topckgen CLK_TOP_UART_SEL>,
-                        <&pericfg CLK_PERI_UART1_PD>;
+                        <&pericfg CLK_PERI_UART0_PD>;
                clock-names = "baud", "bus";
                status = "disabled";
        };
index 94597e3..abd2f15 100644 (file)
                        reg = <0x001>;
                        enable-method = "psci";
                        cpu-idle-states = <&CPU_SLEEP_0>;
+                       #cooling-cells = <2>;
                        clocks = <&infracfg CLK_INFRA_CA53SEL>,
                                 <&apmixedsys CLK_APMIXED_MAINPLL>;
                        clock-names = "cpu", "intermediate";
                        reg = <0x101>;
                        enable-method = "psci";
                        cpu-idle-states = <&CPU_SLEEP_0>;
+                       #cooling-cells = <2>;
                        clocks = <&infracfg CLK_INFRA_CA57SEL>,
                                 <&apmixedsys CLK_APMIXED_MAINPLL>;
                        clock-names = "cpu", "intermediate";
index ecb0341..57d3f00 100644 (file)
        };
 
        cbb {
+               ethernet@2490000 {
+                       status = "okay";
+
+                       phy-reset-gpios = <&gpio TEGRA194_MAIN_GPIO(G, 5) GPIO_ACTIVE_LOW>;
+                       phy-handle = <&phy>;
+                       phy-mode = "rgmii";
+
+                       mdio {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+
+                               phy: phy@0 {
+                                       compatible = "ethernet-phy-ieee802.3-c22";
+                                       reg = <0x0>;
+                                       interrupt-parent = <&gpio>;
+                                       interrupts = <TEGRA194_MAIN_GPIO(G, 4) IRQ_TYPE_LEVEL_LOW>;
+                               };
+                       };
+               };
+
                serial@3110000 {
                        status = "okay";
                };
 
                /* SDMMC1 (SD/MMC) */
                sdhci@3400000 {
-/*
                        cd-gpios = <&gpio TEGRA194_MAIN_GPIO(A, 0) GPIO_ACTIVE_LOW>;
-*/
                };
 
                /* SDMMC4 (eMMC) */
index 6322ef2..a4dfcd1 100644 (file)
                #size-cells = <1>;
                ranges = <0x0 0x0 0x0 0x40000000>;
 
+               gpio: gpio@2200000 {
+                       compatible = "nvidia,tegra194-gpio";
+                       reg-names = "security", "gpio";
+                       reg = <0x2200000 0x10000>,
+                             <0x2210000 0x10000>;
+                       interrupts = <GIC_SPI 288 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 296 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 304 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 312 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 320 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 328 IRQ_TYPE_LEVEL_HIGH>;
+                       #interrupt-cells = <2>;
+                       interrupt-controller;
+                       #gpio-cells = <2>;
+                       gpio-controller;
+               };
+
+               ethernet@2490000 {
+                       compatible = "nvidia,tegra186-eqos",
+                                    "snps,dwc-qos-ethernet-4.10";
+                       reg = <0x02490000 0x10000>;
+                       interrupts = <GIC_SPI 194 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&bpmp TEGRA194_CLK_AXI_CBB>,
+                                <&bpmp TEGRA194_CLK_EQOS_AXI>,
+                                <&bpmp TEGRA194_CLK_EQOS_RX>,
+                                <&bpmp TEGRA194_CLK_EQOS_TX>,
+                                <&bpmp TEGRA194_CLK_EQOS_PTP_REF>;
+                       clock-names = "master_bus", "slave_bus", "rx", "tx", "ptp_ref";
+                       resets = <&bpmp TEGRA194_RESET_EQOS>;
+                       reset-names = "eqos";
+                       status = "disabled";
+
+                       snps,write-requests = <1>;
+                       snps,read-requests = <3>;
+                       snps,burst-map = <0x7>;
+                       snps,txpbl = <16>;
+                       snps,rxpbl = <8>;
+               };
+
                uarta: serial@3100000 {
                        compatible = "nvidia,tegra194-uart", "nvidia,tegra20-uart";
                        reg = <0x03100000 0x40>;
                };
        };
 
+       cpus {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               cpu@0 {
+                       compatible = "nvidia,tegra194-carmel", "arm,armv8";
+                       device_type = "cpu";
+                       reg = <0x10000>;
+                       enable-method = "psci";
+               };
+
+               cpu@1 {
+                       compatible = "nvidia,tegra194-carmel", "arm,armv8";
+                       device_type = "cpu";
+                       reg = <0x10001>;
+                       enable-method = "psci";
+               };
+
+               cpu@2 {
+                       compatible = "nvidia,tegra194-carmel", "arm,armv8";
+                       device_type = "cpu";
+                       reg = <0x100>;
+                       enable-method = "psci";
+               };
+
+               cpu@3 {
+                       compatible = "nvidia,tegra194-carmel", "arm,armv8";
+                       device_type = "cpu";
+                       reg = <0x101>;
+                       enable-method = "psci";
+               };
+
+               cpu@4 {
+                       compatible = "nvidia,tegra194-carmel", "arm,armv8";
+                       device_type = "cpu";
+                       reg = <0x200>;
+                       enable-method = "psci";
+               };
+
+               cpu@5 {
+                       compatible = "nvidia,tegra194-carmel", "arm,armv8";
+                       device_type = "cpu";
+                       reg = <0x201>;
+                       enable-method = "psci";
+               };
+
+               cpu@6 {
+                       compatible = "nvidia,tegra194-carmel", "arm,armv8";
+                       device_type = "cpu";
+                       reg = <0x10300>;
+                       enable-method = "psci";
+               };
+
+               cpu@7 {
+                       compatible = "nvidia,tegra194-carmel", "arm,armv8";
+                       device_type = "cpu";
+                       reg = <0x10301>;
+                       enable-method = "psci";
+               };
+       };
+
+       psci {
+               compatible = "arm,psci-1.0";
+               status = "okay";
+               method = "smc";
+       };
+
        timer {
                compatible = "arm,armv8-timer";
                interrupts = <GIC_PPI 13
index 9ff8487..78ce397 100644 (file)
                        led@6 {
                                label = "apq8016-sbc:blue:bt";
                                gpios = <&pm8916_mpps 3 GPIO_ACTIVE_HIGH>;
-                               linux,default-trigger = "bt";
+                               linux,default-trigger = "bluetooth-power";
                                default-state = "off";
                        };
                };
index 4d5ef01..0ef90c6 100644 (file)
 #include <dt-bindings/input/input.h>
 #include <dt-bindings/gpio/gpio.h>
 
+/*
+ * 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
+ *         P HSEC  = Primary High Speed External Connector
+ *         S HSEC  = Secondary High Speed External Connector
+ *         J14     = Camera Connector
+ *         TP      = Test Points
+ *
+ * Line names are taken from the schematic "DragonBoard 820c",
+ * drawing no: LM25-P2751-1
+ *
+ * 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, which means that the external UART on the
+ * LSEC is named UART0 while the schematic and SoC names this
+ * UART3. 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.
+ */
+
 / {
        aliases {
                serial0 = &blsp2_uart1;
                        status = "okay";
                };
 
+               pinctrl@1010000 {
+                       gpio-line-names =
+                               "[SPI0_DOUT]", /* GPIO_0, BLSP1_SPI_MOSI, LSEC pin 14 */
+                               "[SPI0_DIN]", /* GPIO_1, BLSP1_SPI_MISO, LSEC pin 10 */
+                               "[SPI0_CS]", /* GPIO_2, BLSP1_SPI_CS_N, LSEC pin 12 */
+                               "[SPI0_SCLK]", /* GPIO_3, BLSP1_SPI_CLK, LSEC pin 8 */
+                               "[UART1_TxD]", /* GPIO_4, BLSP8_UART_TX, LSEC pin 11 */
+                               "[UART1_RxD]", /* GPIO_5, BLSP8_UART_RX, LSEC pin 13 */
+                               "[I2C1_SDA]", /* GPIO_6, BLSP8_I2C_SDA, LSEC pin 21 */
+                               "[I2C1_SCL]", /* GPIO_7, BLSP8_I2C_SCL, LSEC pin 19 */
+                               "GPIO-H", /* GPIO_8, LCD0_RESET_N, LSEC pin 30 */
+                               "TP93", /* GPIO_9 */
+                               "GPIO-G", /* GPIO_10, MDP_VSYNC_P, LSEC pin 29 */
+                               "[MDP_VSYNC_S]", /* GPIO_11, S HSEC pin 55 */
+                               "NC", /* GPIO_12 */
+                               "[CSI0_MCLK]", /* GPIO_13, CAM_MCLK0, P HSEC pin 15 */
+                               "[CAM_MCLK1]", /* GPIO_14, J14 pin 11 */
+                               "[CSI1_MCLK]", /* GPIO_15, CAM_MCLK2, P HSEC pin 17 */
+                               "TP99", /* GPIO_16 */
+                               "[I2C2_SDA]", /* GPIO_17, CCI_I2C_SDA0, P HSEC pin 34 */
+                               "[I2C2_SCL]", /* GPIO_18, CCI_I2C_SCL0, P HSEC pin 32 */
+                               "[CCI_I2C_SDA1]", /* GPIO_19, S HSEC pin 38 */
+                               "[CCI_I2C_SCL1]", /* GPIO_20, S HSEC pin 36 */
+                               "FLASH_STROBE_EN", /* GPIO_21, S HSEC pin 5 */
+                               "FLASH_STROBE_TRIG", /* GPIO_22, S HSEC pin 1 */
+                               "GPIO-K", /* GPIO_23, CAM2_RST_N, LSEC pin 33 */
+                               "GPIO-D", /* GPIO_24, LSEC pin 26 */
+                               "GPIO-I", /* GPIO_25, CAM0_RST_N, LSEC pin 31 */
+                               "GPIO-J", /* GPIO_26, CAM0_STANDBY_N, LSEC pin 32 */
+                               "BLSP6_I2C_SDA", /* GPIO_27 */
+                               "BLSP6_I2C_SCL", /* GPIO_28 */
+                               "GPIO-B", /* GPIO_29, TS0_RESET_N, LSEC pin 24 */
+                               "GPIO30", /* GPIO_30, S HSEC pin 4 */
+                               "HDMI_CEC", /* GPIO_31 */
+                               "HDMI_DDC_CLOCK", /* GPIO_32 */
+                               "HDMI_DDC_DATA", /* GPIO_33 */
+                               "HDMI_HOT_PLUG_DETECT", /* GPIO_34 */
+                               "PCIE0_RST_N", /* GPIO_35 */
+                               "PCIE0_CLKREQ_N", /* GPIO_36 */
+                               "PCIE0_WAKE", /* GPIO_37 */
+                               "SD_CARD_DET_N", /* GPIO_38 */
+                               "TSIF1_SYNC", /* GPIO_39, S HSEC pin 48 */
+                               "W_DISABLE_N", /* GPIO_40 */
+                               "[BLSP9_UART_TX]", /* GPIO_41 */
+                               "[BLSP9_UART_RX]", /* GPIO_42 */
+                               "[BLSP2_UART_CTS_N]", /* GPIO_43 */
+                               "[BLSP2_UART_RFR_N]", /* GPIO_44 */
+                               "[BLSP3_UART_TX]", /* GPIO_45 */
+                               "[BLSP3_UART_RX]", /* GPIO_46 */
+                               "[I2C0_SDA]", /* GPIO_47, LS_I2C0_SDA, LSEC pin 17 */
+                               "[I2C0_SCL]", /* GPIO_48, LS_I2C0_SCL, LSEC pin 15 */
+                               "[UART0_TxD]", /* GPIO_49, BLSP9_UART_TX, LSEC pin 5 */
+                               "[UART0_RxD]", /* GPIO_50, BLSP9_UART_RX, LSEC pin 7 */
+                               "[UART0_CTS]", /* GPIO_51, BLSP9_UART_CTS_N, LSEC pin 3 */
+                               "[UART0_RTS]", /* GPIO_52, BLSP9_UART_RFR_N, LSEC pin 9 */
+                               "[CODEC_INT1_N]", /* GPIO_53 */
+                               "[CODEC_INT2_N]", /* GPIO_54 */
+                               "[BLSP7_I2C_SDA]", /* GPIO_55 */
+                               "[BLSP7_I2C_SCL]", /* GPIO_56 */
+                               "MI2S_MCLK", /* GPIO_57, S HSEC pin 3 */
+                               "[PCM_CLK]", /* GPIO_58, QUA_MI2S_SCK, LSEC pin 18 */
+                               "[PCM_FS]", /* GPIO_59, QUA_MI2S_WS, LSEC pin 16 */
+                               "[PCM_DO]", /* GPIO_60, QUA_MI2S_DATA0, LSEC pin 20 */
+                               "[PCM_DI]", /* GPIO_61, QUA_MI2S_DATA1, LSEC pin 22 */
+                               "GPIO-E", /* GPIO_62, LSEC pin 27 */
+                               "TP87", /* GPIO_63 */
+                               "[CODEC_RST_N]", /* GPIO_64 */
+                               "[PCM1_CLK]", /* GPIO_65 */
+                               "[PCM1_SYNC]", /* GPIO_66 */
+                               "[PCM1_DIN]", /* GPIO_67 */
+                               "[PCM1_DOUT]", /* GPIO_68 */
+                               "AUDIO_REF_CLK", /* GPIO_69 */
+                               "SLIMBUS_CLK", /* GPIO_70 */
+                               "SLIMBUS_DATA0", /* GPIO_71 */
+                               "SLIMBUS_DATA1", /* GPIO_72 */
+                               "NC", /* GPIO_73 */
+                               "NC", /* GPIO_74 */
+                               "NC", /* GPIO_75 */
+                               "NC", /* GPIO_76 */
+                               "TP94", /* GPIO_77 */
+                               "NC", /* GPIO_78 */
+                               "TP95", /* GPIO_79 */
+                               "GPIO-A", /* GPIO_80, MEMS_RESET_N, LSEC pin 23 */
+                               "TP88", /* GPIO_81 */
+                               "TP89", /* GPIO_82 */
+                               "TP90", /* GPIO_83 */
+                               "TP91", /* GPIO_84 */
+                               "[SD_DAT0]", /* GPIO_85, BLSP12_SPI_MOSI, P HSEC pin 1 */
+                               "[SD_CMD]", /* GPIO_86, BLSP12_SPI_MISO, P HSEC pin 11 */
+                               "[SD_DAT3]", /* GPIO_87, BLSP12_SPI_CS_N, P HSEC pin 7 */
+                               "[SD_SCLK]", /* GPIO_88, BLSP12_SPI_CLK, P HSEC pin 9 */
+                               "TSIF1_CLK", /* GPIO_89, S HSEC pin 42 */
+                               "TSIF1_EN", /* GPIO_90, S HSEC pin 46 */
+                               "TSIF1_DATA", /* GPIO_91, S HSEC pin 44 */
+                               "NC", /* GPIO_92 */
+                               "TSIF2_CLK", /* GPIO_93, S HSEC pin 52 */
+                               "TSIF2_EN", /* GPIO_94, S HSEC pin 56 */
+                               "TSIF2_DATA", /* GPIO_95, S HSEC pin 54 */
+                               "TSIF2_SYNC", /* GPIO_96, S HSEC pin 58 */
+                               "NC", /* GPIO_97 */
+                               "CAM1_STANDBY_N", /* GPIO_98 */
+                               "NC", /* GPIO_99 */
+                               "NC", /* GPIO_100 */
+                               "[LCD1_RESET_N]", /* GPIO_101, S HSEC pin 51 */
+                               "BOOT_CONFIG1", /* GPIO_102 */
+                               "USB_HUB_RESET", /* GPIO_103 */
+                               "CAM1_RST_N", /* GPIO_104 */
+                               "NC", /* GPIO_105 */
+                               "NC", /* GPIO_106 */
+                               "NC", /* GPIO_107 */
+                               "NC", /* GPIO_108 */
+                               "NC", /* GPIO_109 */
+                               "NC", /* GPIO_110 */
+                               "NC", /* GPIO_111 */
+                               "NC", /* GPIO_112 */
+                               "PMI8994_BUA", /* GPIO_113 */
+                               "PCIE2_RST_N", /* GPIO_114 */
+                               "PCIE2_CLKREQ_N", /* GPIO_115 */
+                               "PCIE2_WAKE", /* GPIO_116 */
+                               "SSC_IRQ_0", /* GPIO_117 */
+                               "SSC_IRQ_1", /* GPIO_118 */
+                               "SSC_IRQ_2", /* GPIO_119 */
+                               "NC", /* GPIO_120 */
+                               "GPIO121", /* GPIO_121, S HSEC pin 2 */
+                               "NC", /* GPIO_122 */
+                               "SSC_IRQ_6", /* GPIO_123 */
+                               "SSC_IRQ_7", /* GPIO_124 */
+                               "GPIO-C", /* GPIO_125, TS_INT0, LSEC pin 25 */
+                               "BOOT_CONFIG5", /* GPIO_126 */
+                               "NC", /* GPIO_127 */
+                               "NC", /* GPIO_128 */
+                               "BOOT_CONFIG7", /* GPIO_129 */
+                               "PCIE1_RST_N", /* GPIO_130 */
+                               "PCIE1_CLKREQ_N", /* GPIO_131 */
+                               "PCIE1_WAKE", /* GPIO_132 */
+                               "GPIO-L", /* GPIO_133, CAM2_STANDBY_N, LSEC pin 34 */
+                               "NC", /* GPIO_134 */
+                               "NC", /* GPIO_135 */
+                               "BOOT_CONFIG8", /* GPIO_136 */
+                               "NC", /* GPIO_137 */
+                               "NC", /* GPIO_138 */
+                               "GPS_SSBI2", /* GPIO_139 */
+                               "GPS_SSBI1", /* GPIO_140 */
+                               "NC", /* GPIO_141 */
+                               "NC", /* GPIO_142 */
+                               "NC", /* GPIO_143 */
+                               "BOOT_CONFIG6", /* GPIO_144 */
+                               "NC", /* GPIO_145 */
+                               "NC", /* GPIO_146 */
+                               "NC", /* GPIO_147 */
+                               "NC", /* GPIO_148 */
+                               "NC"; /* GPIO_149 */
+               };
+
+               qcom,spmi@400f000 {
+                       pmic@0 {
+                               gpios@c000 {
+                                       gpio-line-names =
+                                               "NC",
+                                               "KEY_VOLP_N",
+                                               "NC",
+                                               "BL1_PWM",
+                                               "GPIO-F", /* BL0_PWM, LSEC pin 28 */
+                                               "BL1_EN",
+                                               "NC",
+                                               "WLAN_EN",
+                                               "NC",
+                                               "NC",
+                                               "NC",
+                                               "NC",
+                                               "NC",
+                                               "NC",
+                                               "DIVCLK1",
+                                               "DIVCLK2",
+                                               "DIVCLK3",
+                                               "DIVCLK4",
+                                               "BT_EN",
+                                               "PMIC_SLB",
+                                               "PMIC_BUA",
+                                               "USB_VBUS_DET";
+                               };
+
+                               mpps@a000 {
+                                       gpio-line-names =
+                                               "VDDPX_BIAS",
+                                               "WIFI_LED",
+                                               "NC",
+                                               "BT_LED",
+                                               "PM_MPP05",
+                                               "PM_MPP06",
+                                               "PM_MPP07",
+                                               "NC";
+                               };
+                       };
+
+                       pmic@2 {
+                               gpios@c000 {
+                                       gpio-line-names =
+                                               "NC",
+                                               "SPKR_AMP_EN1",
+                                               "SPKR_AMP_EN2",
+                                               "TP61",
+                                               "NC",
+                                               "USB2_VBUS_DET",
+                                               "NC",
+                                               "NC",
+                                               "NC",
+                                               "NC";
+                               };
+                       };
+               };
+
                phy@34000 {
                        status = "okay";
                };
index c2625d1..7b32b89 100644 (file)
                        clocks = <&gcc GCC_MDSS_AHB_CLK>,
                                 <&gcc GCC_MDSS_AXI_CLK>,
                                 <&gcc GCC_MDSS_VSYNC_CLK>;
-                       clock-names = "iface_clk",
-                                     "bus_clk",
-                                     "vsync_clk";
+                       clock-names = "iface",
+                                     "bus",
+                                     "vsync";
 
                        interrupts = <0 72 IRQ_TYPE_LEVEL_HIGH>;
 
                                         <&gcc GCC_MDSS_AXI_CLK>,
                                         <&gcc GCC_MDSS_MDP_CLK>,
                                         <&gcc GCC_MDSS_VSYNC_CLK>;
-                               clock-names = "iface_clk",
-                                             "bus_clk",
-                                             "core_clk",
-                                             "vsync_clk";
+                               clock-names = "iface",
+                                             "bus",
+                                             "core",
+                                             "vsync";
 
                                iommus = <&apps_iommu 4>;
 
                                         <&gcc GCC_MDSS_BYTE0_CLK>,
                                         <&gcc GCC_MDSS_PCLK0_CLK>,
                                         <&gcc GCC_MDSS_ESC0_CLK>;
-                               clock-names = "mdp_core_clk",
-                                             "iface_clk",
-                                             "bus_clk",
-                                             "byte_clk",
-                                             "pixel_clk",
-                                             "core_clk";
+                               clock-names = "mdp_core",
+                                             "iface",
+                                             "bus",
+                                             "byte",
+                                             "pixel",
+                                             "core";
                                phys = <&dsi_phy0>;
                                phy-names = "dsi-phy";
 
                                #phy-cells = <0>;
 
                                clocks = <&gcc GCC_MDSS_AHB_CLK>;
-                               clock-names = "iface_clk";
+                               clock-names = "iface";
                        };
                };
 
index 8c7f9ca..cd3865e 100644 (file)
                        reg = <0x740000 0x20000>;
                };
 
+               tsens0: thermal-sensor@4a9000 {
+                       compatible = "qcom,msm8996-tsens";
+                       reg = <0x4a9000 0x1000>, /* TM */
+                             <0x4a8000 0x1000>; /* SROT */
+                       #qcom,sensors = <13>;
+                       #thermal-sensor-cells = <1>;
+               };
+
+               tsens1: thermal-sensor@4ad000 {
+                       compatible = "qcom,msm8996-tsens";
+                       reg = <0x4ad000 0x1000>, /* TM */
+                             <0x4ac000 0x1000>; /* SROT */
+                       #qcom,sensors = <8>;
+                       #thermal-sensor-cells = <1>;
+               };
+
                tcsr: syscon@7a0000 {
                        compatible = "qcom,tcsr-msm8996", "syscon";
                        reg = <0x7a0000 0x18000>;
                        status = "disabled";
                };
 
-               tsens0: thermal-sensor@4a8000 {
-                       compatible = "qcom,msm8996-tsens";
-                       reg = <0x4a8000 0x2000>;
-                       #thermal-sensor-cells = <1>;
-               };
-
                blsp2_uart1: serial@75b0000 {
                        compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm";
                        reg = <0x75b0000 0x1000>;
diff --git a/arch/arm64/boot/dts/qcom/pm8005.dtsi b/arch/arm64/boot/dts/qcom/pm8005.dtsi
new file mode 100644 (file)
index 0000000..4d5aca3
--- /dev/null
@@ -0,0 +1,33 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/* Copyright 2018 Google LLC. */
+
+#include <dt-bindings/spmi/spmi.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
+&spmi_bus {
+       pm8005_lsid0: pmic@4 {
+               compatible = "qcom,pm8005", "qcom,spmi-pmic";
+               reg = <0x4 SPMI_USID>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               pm8005_gpio: gpios@c000 {
+                       compatible = "qcom,pm8005-gpio", "qcom,spmi-gpio";
+                       reg = <0xc000>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+                       interrupts = <0 0xc0 0 IRQ_TYPE_NONE>,
+                                    <0 0xc1 0 IRQ_TYPE_NONE>,
+                                    <0 0xc2 0 IRQ_TYPE_NONE>,
+                                    <0 0xc3 0 IRQ_TYPE_NONE>;
+               };
+
+       };
+
+       pm8005_lsid1: pmic@5 {
+               compatible = "qcom,pm8005", "qcom,spmi-pmic";
+               reg = <0x5 SPMI_USID>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+       };
+};
diff --git a/arch/arm64/boot/dts/qcom/pm8998.dtsi b/arch/arm64/boot/dts/qcom/pm8998.dtsi
new file mode 100644 (file)
index 0000000..92bed1e
--- /dev/null
@@ -0,0 +1,55 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/* Copyright 2018 Google LLC. */
+
+#include <dt-bindings/spmi/spmi.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
+&spmi_bus {
+       pm8998_lsid0: pmic@0 {
+               compatible = "qcom,pm8998", "qcom,spmi-pmic";
+               reg = <0x0 SPMI_USID>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               pm8998_gpio: gpios@c000 {
+                       compatible = "qcom,pm8998-gpio", "qcom,spmi-gpio";
+                       reg = <0xc000>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+                       interrupts = <0 0xc0 0 IRQ_TYPE_NONE>,
+                                    <0 0xc1 0 IRQ_TYPE_NONE>,
+                                    <0 0xc2 0 IRQ_TYPE_NONE>,
+                                    <0 0xc3 0 IRQ_TYPE_NONE>,
+                                    <0 0xc4 0 IRQ_TYPE_NONE>,
+                                    <0 0xc5 0 IRQ_TYPE_NONE>,
+                                    <0 0xc6 0 IRQ_TYPE_NONE>,
+                                    <0 0xc7 0 IRQ_TYPE_NONE>,
+                                    <0 0xc8 0 IRQ_TYPE_NONE>,
+                                    <0 0xc9 0 IRQ_TYPE_NONE>,
+                                    <0 0xca 0 IRQ_TYPE_NONE>,
+                                    <0 0xcb 0 IRQ_TYPE_NONE>,
+                                    <0 0xcc 0 IRQ_TYPE_NONE>,
+                                    <0 0xcd 0 IRQ_TYPE_NONE>,
+                                    <0 0xce 0 IRQ_TYPE_NONE>,
+                                    <0 0xcf 0 IRQ_TYPE_NONE>,
+                                    <0 0xd0 0 IRQ_TYPE_NONE>,
+                                    <0 0xd1 0 IRQ_TYPE_NONE>,
+                                    <0 0xd2 0 IRQ_TYPE_NONE>,
+                                    <0 0xd3 0 IRQ_TYPE_NONE>,
+                                    <0 0xd4 0 IRQ_TYPE_NONE>,
+                                    <0 0xd5 0 IRQ_TYPE_NONE>,
+                                    <0 0xd6 0 IRQ_TYPE_NONE>,
+                                    <0 0xd7 0 IRQ_TYPE_NONE>,
+                                    <0 0xd8 0 IRQ_TYPE_NONE>,
+                                    <0 0xd9 0 IRQ_TYPE_NONE>;
+               };
+
+       };
+
+       pm8998_lsid1: pmic@1 {
+               compatible = "qcom,pm8998", "qcom,spmi-pmic";
+               reg = <0x1 SPMI_USID>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+       };
+};
index 979ab49..6d651f3 100644 (file)
 / {
        model = "Qualcomm Technologies, Inc. SDM845 MTP";
        compatible = "qcom,sdm845-mtp";
+
+       aliases {
+               serial0 = &uart9;
+       };
+
+       chosen {
+               stdout-path = "serial0:115200n8";
+       };
+};
+
+&i2c10 {
+       status = "okay";
+       clock-frequency = <400000>;
+};
+
+&qupv3_id_1 {
+       status = "okay";
+};
+
+&uart9 {
+       status = "okay";
+};
+
+/* PINCTRL - additions to nodes defined in sdm845.dtsi */
+
+&qup_i2c10_default {
+       pinconf {
+               pins = "gpio55", "gpio56";
+               drive-strength = <2>;
+               bias-disable;
+       };
+};
+
+&qup_uart9_default {
+       pinconf-tx {
+               pins = "gpio4";
+               drive-strength = <2>;
+               bias-disable;
+       };
+
+       pinconf-rx {
+               pins = "gpio5";
+               drive-strength = <2>;
+               bias-pull-up;
+       };
 };
index cdaabeb..0c9a2aa 100644 (file)
@@ -5,7 +5,10 @@
  * Copyright (c) 2018, The Linux Foundation. All rights reserved.
  */
 
+#include <dt-bindings/clock/qcom,gcc-sdm845.h>
+#include <dt-bindings/clock/qcom,rpmh.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/soc/qcom,rpmh-rsc.h>
 
 / {
        interrupt-parent = <&intc>;
        #address-cells = <2>;
        #size-cells = <2>;
 
+       aliases {
+               i2c0 = &i2c0;
+               i2c1 = &i2c1;
+               i2c2 = &i2c2;
+               i2c3 = &i2c3;
+               i2c4 = &i2c4;
+               i2c5 = &i2c5;
+               i2c6 = &i2c6;
+               i2c7 = &i2c7;
+               i2c8 = &i2c8;
+               i2c9 = &i2c9;
+               i2c10 = &i2c10;
+               i2c11 = &i2c11;
+               i2c12 = &i2c12;
+               i2c13 = &i2c13;
+               i2c14 = &i2c14;
+               i2c15 = &i2c15;
+               spi0 = &spi0;
+               spi1 = &spi1;
+               spi2 = &spi2;
+               spi3 = &spi3;
+               spi4 = &spi4;
+               spi5 = &spi5;
+               spi6 = &spi6;
+               spi7 = &spi7;
+               spi8 = &spi8;
+               spi9 = &spi9;
+               spi10 = &spi10;
+               spi11 = &spi11;
+               spi12 = &spi12;
+               spi13 = &spi13;
+               spi14 = &spi14;
+               spi15 = &spi15;
+       };
+
        chosen { };
 
        memory@80000000 {
                };
        };
 
+       pmu {
+               compatible = "arm,armv8-pmuv3";
+               interrupts = <GIC_PPI 5 IRQ_TYPE_LEVEL_HIGH>;
+       };
+
        timer {
                compatible = "arm,armv8-timer";
                interrupts = <GIC_PPI 1 IRQ_TYPE_LEVEL_LOW>,
                        #power-domain-cells = <1>;
                };
 
+               qupv3_id_0: geniqup@8c0000 {
+                       compatible = "qcom,geni-se-qup";
+                       reg = <0x8c0000 0x6000>;
+                       clock-names = "m-ahb", "s-ahb";
+                       clocks = <&gcc GCC_QUPV3_WRAP_0_M_AHB_CLK>,
+                                <&gcc GCC_QUPV3_WRAP_0_S_AHB_CLK>;
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges;
+                       status = "disabled";
+
+                       i2c0: i2c@880000 {
+                               compatible = "qcom,geni-i2c";
+                               reg = <0x880000 0x4000>;
+                               clock-names = "se";
+                               clocks = <&gcc GCC_QUPV3_WRAP0_S0_CLK>;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&qup_i2c0_default>;
+                               interrupts = <GIC_SPI 601 IRQ_TYPE_LEVEL_HIGH>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               status = "disabled";
+                       };
+
+                       spi0: spi@880000 {
+                               compatible = "qcom,geni-spi";
+                               reg = <0x880000 0x4000>;
+                               clock-names = "se";
+                               clocks = <&gcc GCC_QUPV3_WRAP0_S0_CLK>;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&qup_spi0_default>;
+                               interrupts = <GIC_SPI 601 IRQ_TYPE_LEVEL_HIGH>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               status = "disabled";
+                       };
+
+                       i2c1: i2c@884000 {
+                               compatible = "qcom,geni-i2c";
+                               reg = <0x884000 0x4000>;
+                               clock-names = "se";
+                               clocks = <&gcc GCC_QUPV3_WRAP0_S1_CLK>;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&qup_i2c1_default>;
+                               interrupts = <GIC_SPI 602 IRQ_TYPE_LEVEL_HIGH>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               status = "disabled";
+                       };
+
+                       spi1: spi@884000 {
+                               compatible = "qcom,geni-spi";
+                               reg = <0x884000 0x4000>;
+                               clock-names = "se";
+                               clocks = <&gcc GCC_QUPV3_WRAP0_S1_CLK>;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&qup_spi1_default>;
+                               interrupts = <GIC_SPI 602 IRQ_TYPE_LEVEL_HIGH>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               status = "disabled";
+                       };
+
+                       i2c2: i2c@888000 {
+                               compatible = "qcom,geni-i2c";
+                               reg = <0x888000 0x4000>;
+                               clock-names = "se";
+                               clocks = <&gcc GCC_QUPV3_WRAP0_S2_CLK>;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&qup_i2c2_default>;
+                               interrupts = <GIC_SPI 603 IRQ_TYPE_LEVEL_HIGH>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               status = "disabled";
+                       };
+
+                       spi2: spi@888000 {
+                               compatible = "qcom,geni-spi";
+                               reg = <0x888000 0x4000>;
+                               clock-names = "se";
+                               clocks = <&gcc GCC_QUPV3_WRAP0_S2_CLK>;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&qup_spi2_default>;
+                               interrupts = <GIC_SPI 603 IRQ_TYPE_LEVEL_HIGH>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               status = "disabled";
+                       };
+
+                       i2c3: i2c@88c000 {
+                               compatible = "qcom,geni-i2c";
+                               reg = <0x88c000 0x4000>;
+                               clock-names = "se";
+                               clocks = <&gcc GCC_QUPV3_WRAP0_S3_CLK>;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&qup_i2c3_default>;
+                               interrupts = <GIC_SPI 604 IRQ_TYPE_LEVEL_HIGH>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               status = "disabled";
+                       };
+
+                       spi3: spi@88c000 {
+                               compatible = "qcom,geni-spi";
+                               reg = <0x88c000 0x4000>;
+                               clock-names = "se";
+                               clocks = <&gcc GCC_QUPV3_WRAP0_S3_CLK>;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&qup_spi3_default>;
+                               interrupts = <GIC_SPI 604 IRQ_TYPE_LEVEL_HIGH>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               status = "disabled";
+                       };
+
+                       i2c4: i2c@890000 {
+                               compatible = "qcom,geni-i2c";
+                               reg = <0x890000 0x4000>;
+                               clock-names = "se";
+                               clocks = <&gcc GCC_QUPV3_WRAP0_S4_CLK>;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&qup_i2c4_default>;
+                               interrupts = <GIC_SPI 605 IRQ_TYPE_LEVEL_HIGH>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               status = "disabled";
+                       };
+
+                       spi4: spi@890000 {
+                               compatible = "qcom,geni-spi";
+                               reg = <0x890000 0x4000>;
+                               clock-names = "se";
+                               clocks = <&gcc GCC_QUPV3_WRAP0_S4_CLK>;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&qup_spi4_default>;
+                               interrupts = <GIC_SPI 605 IRQ_TYPE_LEVEL_HIGH>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               status = "disabled";
+                       };
+
+                       i2c5: i2c@894000 {
+                               compatible = "qcom,geni-i2c";
+                               reg = <0x894000 0x4000>;
+                               clock-names = "se";
+                               clocks = <&gcc GCC_QUPV3_WRAP0_S5_CLK>;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&qup_i2c5_default>;
+                               interrupts = <GIC_SPI 606 IRQ_TYPE_LEVEL_HIGH>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               status = "disabled";
+                       };
+
+                       spi5: spi@894000 {
+                               compatible = "qcom,geni-spi";
+                               reg = <0x894000 0x4000>;
+                               clock-names = "se";
+                               clocks = <&gcc GCC_QUPV3_WRAP0_S5_CLK>;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&qup_spi5_default>;
+                               interrupts = <GIC_SPI 606 IRQ_TYPE_LEVEL_HIGH>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               status = "disabled";
+                       };
+
+                       i2c6: i2c@898000 {
+                               compatible = "qcom,geni-i2c";
+                               reg = <0x898000 0x4000>;
+                               clock-names = "se";
+                               clocks = <&gcc GCC_QUPV3_WRAP0_S6_CLK>;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&qup_i2c6_default>;
+                               interrupts = <GIC_SPI 607 IRQ_TYPE_LEVEL_HIGH>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               status = "disabled";
+                       };
+
+                       spi6: spi@898000 {
+                               compatible = "qcom,geni-spi";
+                               reg = <0x898000 0x4000>;
+                               clock-names = "se";
+                               clocks = <&gcc GCC_QUPV3_WRAP0_S6_CLK>;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&qup_spi6_default>;
+                               interrupts = <GIC_SPI 607 IRQ_TYPE_LEVEL_HIGH>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               status = "disabled";
+                       };
+
+                       i2c7: i2c@89c000 {
+                               compatible = "qcom,geni-i2c";
+                               reg = <0x89c000 0x4000>;
+                               clock-names = "se";
+                               clocks = <&gcc GCC_QUPV3_WRAP0_S7_CLK>;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&qup_i2c7_default>;
+                               interrupts = <GIC_SPI 608 IRQ_TYPE_LEVEL_HIGH>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               status = "disabled";
+                       };
+
+                       spi7: spi@89c000 {
+                               compatible = "qcom,geni-spi";
+                               reg = <0x89c000 0x4000>;
+                               clock-names = "se";
+                               clocks = <&gcc GCC_QUPV3_WRAP0_S7_CLK>;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&qup_spi7_default>;
+                               interrupts = <GIC_SPI 608 IRQ_TYPE_LEVEL_HIGH>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               status = "disabled";
+                       };
+               };
+
+               qupv3_id_1: geniqup@ac0000 {
+                       compatible = "qcom,geni-se-qup";
+                       reg = <0xac0000 0x6000>;
+                       clock-names = "m-ahb", "s-ahb";
+                       clocks = <&gcc GCC_QUPV3_WRAP_1_M_AHB_CLK>,
+                                <&gcc GCC_QUPV3_WRAP_1_S_AHB_CLK>;
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges;
+                       status = "disabled";
+
+                       i2c8: i2c@a80000 {
+                               compatible = "qcom,geni-i2c";
+                               reg = <0xa80000 0x4000>;
+                               clock-names = "se";
+                               clocks = <&gcc GCC_QUPV3_WRAP1_S0_CLK>;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&qup_i2c8_default>;
+                               interrupts = <GIC_SPI 353 IRQ_TYPE_LEVEL_HIGH>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               status = "disabled";
+                       };
+
+                       spi8: spi@a80000 {
+                               compatible = "qcom,geni-spi";
+                               reg = <0xa80000 0x4000>;
+                               clock-names = "se";
+                               clocks = <&gcc GCC_QUPV3_WRAP1_S0_CLK>;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&qup_spi8_default>;
+                               interrupts = <GIC_SPI 353 IRQ_TYPE_LEVEL_HIGH>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               status = "disabled";
+                       };
+
+                       i2c9: i2c@a84000 {
+                               compatible = "qcom,geni-i2c";
+                               reg = <0xa84000 0x4000>;
+                               clock-names = "se";
+                               clocks = <&gcc GCC_QUPV3_WRAP1_S1_CLK>;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&qup_i2c9_default>;
+                               interrupts = <GIC_SPI 354 IRQ_TYPE_LEVEL_HIGH>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               status = "disabled";
+                       };
+
+                       spi9: spi@a84000 {
+                               compatible = "qcom,geni-spi";
+                               reg = <0xa84000 0x4000>;
+                               clock-names = "se";
+                               clocks = <&gcc GCC_QUPV3_WRAP1_S1_CLK>;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&qup_spi9_default>;
+                               interrupts = <GIC_SPI 354 IRQ_TYPE_LEVEL_HIGH>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               status = "disabled";
+                       };
+
+                       uart9: serial@a84000 {
+                               compatible = "qcom,geni-debug-uart";
+                               reg = <0xa84000 0x4000>;
+                               clock-names = "se";
+                               clocks = <&gcc GCC_QUPV3_WRAP1_S1_CLK>;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&qup_uart9_default>;
+                               interrupts = <GIC_SPI 354 IRQ_TYPE_LEVEL_HIGH>;
+                               status = "disabled";
+                       };
+
+                       i2c10: i2c@a88000 {
+                               compatible = "qcom,geni-i2c";
+                               reg = <0xa88000 0x4000>;
+                               clock-names = "se";
+                               clocks = <&gcc GCC_QUPV3_WRAP1_S2_CLK>;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&qup_i2c10_default>;
+                               interrupts = <GIC_SPI 355 IRQ_TYPE_LEVEL_HIGH>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               status = "disabled";
+                       };
+
+                       spi10: spi@a88000 {
+                               compatible = "qcom,geni-spi";
+                               reg = <0xa88000 0x4000>;
+                               clock-names = "se";
+                               clocks = <&gcc GCC_QUPV3_WRAP1_S2_CLK>;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&qup_spi10_default>;
+                               interrupts = <GIC_SPI 355 IRQ_TYPE_LEVEL_HIGH>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               status = "disabled";
+                       };
+
+                       i2c11: i2c@a8c000 {
+                               compatible = "qcom,geni-i2c";
+                               reg = <0xa8c000 0x4000>;
+                               clock-names = "se";
+                               clocks = <&gcc GCC_QUPV3_WRAP1_S3_CLK>;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&qup_i2c11_default>;
+                               interrupts = <GIC_SPI 356 IRQ_TYPE_LEVEL_HIGH>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               status = "disabled";
+                       };
+
+                       spi11: spi@a8c000 {
+                               compatible = "qcom,geni-spi";
+                               reg = <0xa8c000 0x4000>;
+                               clock-names = "se";
+                               clocks = <&gcc GCC_QUPV3_WRAP1_S3_CLK>;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&qup_spi11_default>;
+                               interrupts = <GIC_SPI 356 IRQ_TYPE_LEVEL_HIGH>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               status = "disabled";
+                       };
+
+                       i2c12: i2c@a90000 {
+                               compatible = "qcom,geni-i2c";
+                               reg = <0xa90000 0x4000>;
+                               clock-names = "se";
+                               clocks = <&gcc GCC_QUPV3_WRAP1_S4_CLK>;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&qup_i2c12_default>;
+                               interrupts = <GIC_SPI 357 IRQ_TYPE_LEVEL_HIGH>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               status = "disabled";
+                       };
+
+                       spi12: spi@a90000 {
+                               compatible = "qcom,geni-spi";
+                               reg = <0xa90000 0x4000>;
+                               clock-names = "se";
+                               clocks = <&gcc GCC_QUPV3_WRAP1_S4_CLK>;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&qup_spi12_default>;
+                               interrupts = <GIC_SPI 357 IRQ_TYPE_LEVEL_HIGH>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               status = "disabled";
+                       };
+
+                       i2c13: i2c@a94000 {
+                               compatible = "qcom,geni-i2c";
+                               reg = <0xa94000 0x4000>;
+                               clock-names = "se";
+                               clocks = <&gcc GCC_QUPV3_WRAP1_S5_CLK>;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&qup_i2c13_default>;
+                               interrupts = <GIC_SPI 358 IRQ_TYPE_LEVEL_HIGH>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               status = "disabled";
+                       };
+
+                       spi13: spi@a94000 {
+                               compatible = "qcom,geni-spi";
+                               reg = <0xa94000 0x4000>;
+                               clock-names = "se";
+                               clocks = <&gcc GCC_QUPV3_WRAP1_S5_CLK>;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&qup_spi13_default>;
+                               interrupts = <GIC_SPI 358 IRQ_TYPE_LEVEL_HIGH>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               status = "disabled";
+                       };
+
+                       i2c14: i2c@a98000 {
+                               compatible = "qcom,geni-i2c";
+                               reg = <0xa98000 0x4000>;
+                               clock-names = "se";
+                               clocks = <&gcc GCC_QUPV3_WRAP1_S6_CLK>;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&qup_i2c14_default>;
+                               interrupts = <GIC_SPI 359 IRQ_TYPE_LEVEL_HIGH>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               status = "disabled";
+                       };
+
+                       spi14: spi@a98000 {
+                               compatible = "qcom,geni-spi";
+                               reg = <0xa98000 0x4000>;
+                               clock-names = "se";
+                               clocks = <&gcc GCC_QUPV3_WRAP1_S6_CLK>;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&qup_spi14_default>;
+                               interrupts = <GIC_SPI 359 IRQ_TYPE_LEVEL_HIGH>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               status = "disabled";
+                       };
+
+                       i2c15: i2c@a9c000 {
+                               compatible = "qcom,geni-i2c";
+                               reg = <0xa9c000 0x4000>;
+                               clock-names = "se";
+                               clocks = <&gcc GCC_QUPV3_WRAP1_S7_CLK>;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&qup_i2c15_default>;
+                               interrupts = <GIC_SPI 360 IRQ_TYPE_LEVEL_HIGH>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               status = "disabled";
+                       };
+
+                       spi15: spi@a9c000 {
+                               compatible = "qcom,geni-spi";
+                               reg = <0xa9c000 0x4000>;
+                               clock-names = "se";
+                               clocks = <&gcc GCC_QUPV3_WRAP1_S7_CLK>;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&qup_spi15_default>;
+                               interrupts = <GIC_SPI 360 IRQ_TYPE_LEVEL_HIGH>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               status = "disabled";
+                       };
+               };
+
                tcsr_mutex_regs: syscon@1f40000 {
                        compatible = "syscon";
                        reg = <0x1f40000 0x40000>;
                        #gpio-cells = <2>;
                        interrupt-controller;
                        #interrupt-cells = <2>;
+
+                       qup_i2c0_default: qup-i2c0-default {
+                               pinmux {
+                                       pins = "gpio0", "gpio1";
+                                       function = "qup0";
+                               };
+                       };
+
+                       qup_i2c1_default: qup-i2c1-default {
+                               pinmux {
+                                       pins = "gpio17", "gpio18";
+                                       function = "qup1";
+                               };
+                       };
+
+                       qup_i2c2_default: qup-i2c2-default {
+                               pinmux {
+                                       pins = "gpio27", "gpio28";
+                                       function = "qup2";
+                               };
+                       };
+
+                       qup_i2c3_default: qup-i2c3-default {
+                               pinmux {
+                                       pins = "gpio41", "gpio42";
+                                       function = "qup3";
+                               };
+                       };
+
+                       qup_i2c4_default: qup-i2c4-default {
+                               pinmux {
+                                       pins = "gpio89", "gpio90";
+                                       function = "qup4";
+                               };
+                       };
+
+                       qup_i2c5_default: qup-i2c5-default {
+                               pinmux {
+                                       pins = "gpio85", "gpio86";
+                                       function = "qup5";
+                               };
+                       };
+
+                       qup_i2c6_default: qup-i2c6-default {
+                               pinmux {
+                                       pins = "gpio45", "gpio46";
+                                       function = "qup6";
+                               };
+                       };
+
+                       qup_i2c7_default: qup-i2c7-default {
+                               pinmux {
+                                       pins = "gpio93", "gpio94";
+                                       function = "qup7";
+                               };
+                       };
+
+                       qup_i2c8_default: qup-i2c8-default {
+                               pinmux {
+                                       pins = "gpio65", "gpio66";
+                                       function = "qup8";
+                               };
+                       };
+
+                       qup_i2c9_default: qup-i2c9-default {
+                               pinmux {
+                                       pins = "gpio6", "gpio7";
+                                       function = "qup9";
+                               };
+                       };
+
+                       qup_i2c10_default: qup-i2c10-default {
+                               pinmux {
+                                       pins = "gpio55", "gpio56";
+                                       function = "qup10";
+                               };
+                       };
+
+                       qup_i2c11_default: qup-i2c11-default {
+                               pinmux {
+                                       pins = "gpio31", "gpio32";
+                                       function = "qup11";
+                               };
+                       };
+
+                       qup_i2c12_default: qup-i2c12-default {
+                               pinmux {
+                                       pins = "gpio49", "gpio50";
+                                       function = "qup12";
+                               };
+                       };
+
+                       qup_i2c13_default: qup-i2c13-default {
+                               pinmux {
+                                       pins = "gpio105", "gpio106";
+                                       function = "qup13";
+                               };
+                       };
+
+                       qup_i2c14_default: qup-i2c14-default {
+                               pinmux {
+                                       pins = "gpio33", "gpio34";
+                                       function = "qup14";
+                               };
+                       };
+
+                       qup_i2c15_default: qup-i2c15-default {
+                               pinmux {
+                                       pins = "gpio81", "gpio82";
+                                       function = "qup15";
+                               };
+                       };
+
+                       qup_spi0_default: qup-spi0-default {
+                               pinmux {
+                                       pins = "gpio0", "gpio1",
+                                              "gpio2", "gpio3";
+                                       function = "qup0";
+                               };
+                       };
+
+                       qup_spi1_default: qup-spi1-default {
+                               pinmux {
+                                       pins = "gpio17", "gpio18",
+                                              "gpio19", "gpio20";
+                                       function = "qup1";
+                               };
+                       };
+
+                       qup_spi2_default: qup-spi2-default {
+                               pinmux {
+                                       pins = "gpio27", "gpio28",
+                                              "gpio29", "gpio30";
+                                       function = "qup2";
+                               };
+                       };
+
+                       qup_spi3_default: qup-spi3-default {
+                               pinmux {
+                                       pins = "gpio41", "gpio42",
+                                              "gpio43", "gpio44";
+                                       function = "qup3";
+                               };
+                       };
+
+                       qup_spi4_default: qup-spi4-default {
+                               pinmux {
+                                       pins = "gpio89", "gpio90",
+                                              "gpio91", "gpio92";
+                                       function = "qup4";
+                               };
+                       };
+
+                       qup_spi5_default: qup-spi5-default {
+                               pinmux {
+                                       pins = "gpio85", "gpio86",
+                                              "gpio87", "gpio88";
+                                       function = "qup5";
+                               };
+                       };
+
+                       qup_spi6_default: qup-spi6-default {
+                               pinmux {
+                                       pins = "gpio45", "gpio46",
+                                              "gpio47", "gpio48";
+                                       function = "qup6";
+                               };
+                       };
+
+                       qup_spi7_default: qup-spi7-default {
+                               pinmux {
+                                       pins = "gpio93", "gpio94",
+                                              "gpio95", "gpio96";
+                                       function = "qup7";
+                               };
+                       };
+
+                       qup_spi8_default: qup-spi8-default {
+                               pinmux {
+                                       pins = "gpio65", "gpio66",
+                                              "gpio67", "gpio68";
+                                       function = "qup8";
+                               };
+                       };
+
+                       qup_spi9_default: qup-spi9-default {
+                               pinmux {
+                                       pins = "gpio6", "gpio7",
+                                              "gpio4", "gpio5";
+                                       function = "qup9";
+                               };
+                       };
+
+                       qup_spi10_default: qup-spi10-default {
+                               pinmux {
+                                       pins = "gpio55", "gpio56",
+                                              "gpio53", "gpio54";
+                                       function = "qup10";
+                               };
+                       };
+
+                       qup_spi11_default: qup-spi11-default {
+                               pinmux {
+                                       pins = "gpio31", "gpio32",
+                                              "gpio33", "gpio34";
+                                       function = "qup11";
+                               };
+                       };
+
+                       qup_spi12_default: qup-spi12-default {
+                               pinmux {
+                                       pins = "gpio49", "gpio50",
+                                              "gpio51", "gpio52";
+                                       function = "qup12";
+                               };
+                       };
+
+                       qup_spi13_default: qup-spi13-default {
+                               pinmux {
+                                       pins = "gpio105", "gpio106",
+                                              "gpio107", "gpio108";
+                                       function = "qup13";
+                               };
+                       };
+
+                       qup_spi14_default: qup-spi14-default {
+                               pinmux {
+                                       pins = "gpio33", "gpio34",
+                                              "gpio31", "gpio32";
+                                       function = "qup14";
+                               };
+                       };
+
+                       qup_spi15_default: qup-spi15-default {
+                               pinmux {
+                                       pins = "gpio81", "gpio82",
+                                              "gpio83", "gpio84";
+                                       function = "qup15";
+                               };
+                       };
+
+                       qup_uart9_default: qup-uart9-default {
+                               pinmux {
+                                       pins = "gpio4", "gpio5";
+                                       function = "qup9";
+                               };
+                       };
+               };
+
+               tsens0: thermal-sensor@c263000 {
+                       compatible = "qcom,sdm845-tsens", "qcom,tsens-v2";
+                       reg = <0xc263000 0x1ff>, /* TM */
+                             <0xc222000 0x1ff>; /* SROT */
+                       #qcom,sensors = <13>;
+                       #thermal-sensor-cells = <1>;
+               };
+
+               tsens1: thermal-sensor@c265000 {
+                       compatible = "qcom,sdm845-tsens", "qcom,tsens-v2";
+                       reg = <0xc265000 0x1ff>, /* TM */
+                             <0xc223000 0x1ff>; /* SROT */
+                       #qcom,sensors = <8>;
+                       #thermal-sensor-cells = <1>;
                };
 
                spmi_bus: spmi@c440000 {
                        #mbox-cells = <1>;
                };
 
+               apps_rsc: rsc@179c0000 {
+                       label = "apps_rsc";
+                       compatible = "qcom,rpmh-rsc";
+                       reg = <0x179c0000 0x10000>,
+                             <0x179d0000 0x10000>,
+                             <0x179e0000 0x10000>;
+                       reg-names = "drv-0", "drv-1", "drv-2";
+                       interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>;
+                       qcom,tcs-offset = <0xd00>;
+                       qcom,drv-id = <2>;
+                       qcom,tcs-config = <ACTIVE_TCS  2>,
+                                         <SLEEP_TCS   3>,
+                                         <WAKE_TCS    3>,
+                                         <CONTROL_TCS 1>;
+
+                       rpmhcc: clock-controller {
+                               compatible = "qcom,sdm845-rpmh-clk";
+                               #clock-cells = <1>;
+                       };
+               };
+
                intc: interrupt-controller@17a00000 {
                        compatible = "arm,gic-v3";
                        #address-cells = <1>;
index 009cb1c..2f24dfc 100644 (file)
@@ -1,12 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Device Tree Source for the H3ULCB Kingfisher board
  *
  * Copyright (C) 2017 Renesas Electronics Corp.
  * Copyright (C) 2017 Cogent Embedded, Inc.
- *
- * This file is licensed under the terms of the GNU General Public License
- * version 2.  This program is licensed "as is" without any warranty of any
- * kind, whether express or implied.
  */
 
 #include "r8a7795-es1-h3ulcb.dts"
index dd4f9b6..598b981 100644 (file)
@@ -1,12 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Device Tree Source for the H3ULCB (R-Car Starter Kit Premier) board
  *
  * Copyright (C) 2016 Renesas Electronics Corp.
  * Copyright (C) 2016 Cogent Embedded, Inc.
- *
- * This file is licensed under the terms of the GNU General Public License
- * version 2.  This program is licensed "as is" without any warranty of any
- * kind, whether express or implied.
  */
 
 /dts-v1/;
index 3f46345..6b5fa91 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Device Tree Source for the Salvator-X board with R-Car H3 ES1.x
  *
  * Copyright (C) 2015 Renesas Electronics Corp.
- *
- * 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.
  */
 
 /dts-v1/;
index e19dcd6..7b2fbae 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Device Tree Source for the r8a7795 ES1.x SoC
  *
  * Copyright (C) 2015 Renesas Electronics Corp.
- *
- * 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 "r8a7795.dtsi"
@@ -80,7 +77,7 @@
 
        vspd3: vsp@fea38000 {
                compatible = "renesas,vsp2";
-               reg = <0 0xfea38000 0 0x8000>;
+               reg = <0 0xfea38000 0 0x5000>;
                interrupts = <GIC_SPI 469 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&cpg CPG_MOD 620>;
                power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
index 4403227..80791ed 100644 (file)
@@ -1,12 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Device Tree Source for the H3ULCB Kingfisher board
  *
  * Copyright (C) 2017 Renesas Electronics Corp.
  * Copyright (C) 2017 Cogent Embedded, Inc.
- *
- * This file is licensed under the terms of the GNU General Public License
- * version 2.  This program is licensed "as is" without any warranty of any
- * kind, whether express or implied.
  */
 
 #include "r8a7795-h3ulcb.dts"
index 0afe777..df50bf4 100644 (file)
@@ -1,12 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Device Tree Source for the H3ULCB (R-Car Starter Kit Premier) board
  *
  * Copyright (C) 2016 Renesas Electronics Corp.
  * Copyright (C) 2016 Cogent Embedded, Inc.
- *
- * This file is licensed under the terms of the GNU General Public License
- * version 2.  This program is licensed "as is" without any warranty of any
- * kind, whether express or implied.
  */
 
 /dts-v1/;
index 0efbef5..446822f 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Device Tree Source for the Salvator-X board with R-Car H3 ES2.0
  *
  * Copyright (C) 2015 Renesas Electronics Corp.
- *
- * 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.
  */
 
 /dts-v1/;
index e231b5a..8ded64d 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Device Tree Source for the Salvator-X 2nd version board with R-Car H3 ES2.0
  *
  * Copyright (C) 2015-2017 Renesas Electronics Corp.
- *
- * 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.
  */
 
 /dts-v1/;
index d842940..fb9d08a 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Device Tree Source for the r8a7795 SoC
  *
  * Copyright (C) 2015 Renesas Electronics Corp.
- *
- * 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 <dt-bindings/clock/r8a7795-cpg-mssr.h>
                #size-cells = <2>;
                ranges;
 
-               wdt0: watchdog@e6020000 {
+               rwdt: watchdog@e6020000 {
                        compatible = "renesas,r8a7795-wdt", "renesas,rcar-gen3-wdt";
                        reg = <0 0xe6020000 0 0x0c>;
                        clocks = <&cpg CPG_MOD 402>;
                        status = "disabled";
                };
 
+               arm_cc630p: crypto@e6601000 {
+                       compatible = "arm,cryptocell-630p-ree";
+                       interrupts = <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
+                       reg = <0x0 0xe6601000 0 0x1000>;
+                       clocks = <&cpg CPG_MOD 229>;
+                       resets = <&cpg 229>;
+                       power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+               };
+
                i2c3: i2c@e66d0000 {
                        #address-cells = <1>;
                        #size-cells = <0>;
 
                vspd0: vsp@fea20000 {
                        compatible = "renesas,vsp2";
-                       reg = <0 0xfea20000 0 0x8000>;
+                       reg = <0 0xfea20000 0 0x5000>;
                        interrupts = <GIC_SPI 466 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&cpg CPG_MOD 623>;
                        power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
 
                vspd1: vsp@fea28000 {
                        compatible = "renesas,vsp2";
-                       reg = <0 0xfea28000 0 0x8000>;
+                       reg = <0 0xfea28000 0 0x5000>;
                        interrupts = <GIC_SPI 467 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&cpg CPG_MOD 622>;
                        power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
 
                vspd2: vsp@fea30000 {
                        compatible = "renesas,vsp2";
-                       reg = <0 0xfea30000 0 0x8000>;
+                       reg = <0 0xfea30000 0 0x5000>;
                        interrupts = <GIC_SPI 468 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&cpg CPG_MOD 621>;
                        power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
index de2390f..2df50eb 100644 (file)
@@ -1,12 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Device Tree Source for the M3ULCB Kingfisher board
  *
  * Copyright (C) 2017 Renesas Electronics Corp.
  * Copyright (C) 2017 Cogent Embedded, Inc.
- *
- * This file is licensed under the terms of the GNU General Public License
- * version 2.  This program is licensed "as is" without any warranty of any
- * kind, whether express or implied.
  */
 
 #include "r8a7796-m3ulcb.dts"
index daee1f1..cbd8acb 100644 (file)
@@ -1,12 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Device Tree Source for the M3ULCB (R-Car Starter Kit Pro) board
  *
  * Copyright (C) 2016 Renesas Electronics Corp.
  * Copyright (C) 2016 Cogent Embedded, Inc.
- *
- * This file is licensed under the terms of the GNU General Public License
- * version 2.  This program is licensed "as is" without any warranty of any
- * kind, whether express or implied.
  */
 
 /dts-v1/;
index 90cca09..052d72a 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Device Tree Source for the Salvator-X board with R-Car M3-W
  *
  * Copyright (C) 2016 Renesas Electronics Corp.
- *
- * 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.
  */
 
 /dts-v1/;
index ddf35d4..8860be6 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Device Tree Source for the Salvator-X 2nd version board with R-Car M3-W
  *
  * Copyright (C) 2015-2017 Renesas Electronics Corp.
- *
- * 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.
  */
 
 /dts-v1/;
index 7c25be6..cbd35c0 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Device Tree Source for the r8a7796 SoC
  *
- * Copyright (C) 2016 Renesas Electronics Corp.
- *
- * 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.
+ * Copyright (C) 2016-2017 Renesas Electronics Corp.
  */
 
 #include <dt-bindings/clock/r8a7796-cpg-mssr.h>
                #size-cells = <2>;
                ranges;
 
-               wdt0: watchdog@e6020000 {
+               rwdt: watchdog@e6020000 {
                        compatible = "renesas,r8a7796-wdt",
                                     "renesas,rcar-gen3-wdt";
                        reg = <0 0xe6020000 0 0x0c>;
                };
 
                pciec0: pcie@fe000000 {
+                       compatible = "renesas,pcie-r8a7796",
+                                    "renesas,pcie-rcar-gen3";
                        reg = <0 0xfe000000 0 0x80000>;
-                       /* placeholder */
+                       #address-cells = <3>;
+                       #size-cells = <2>;
+                       bus-range = <0x00 0xff>;
+                       device_type = "pci";
+                       ranges = <0x01000000 0 0x00000000 0 0xfe100000 0 0x00100000
+                               0x02000000 0 0xfe200000 0 0xfe200000 0 0x00200000
+                               0x02000000 0 0x30000000 0 0x30000000 0 0x08000000
+                               0x42000000 0 0x38000000 0 0x38000000 0 0x08000000>;
+                       /* Map all possible DDR as inbound ranges */
+                       dma-ranges = <0x42000000 0 0x40000000 0 0x40000000 0 0x80000000>;
+                       interrupts = <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>,
+                               <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>,
+                               <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>;
+                       #interrupt-cells = <1>;
+                       interrupt-map-mask = <0 0 0 0>;
+                       interrupt-map = <0 0 0 0 &gic GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&cpg CPG_MOD 319>, <&pcie_bus_clk>;
+                       clock-names = "pcie", "pcie_bus";
+                       power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+                       resets = <&cpg 319>;
+                       status = "disabled";
                };
 
                pciec1: pcie@ee800000 {
+                       compatible = "renesas,pcie-r8a7796",
+                                    "renesas,pcie-rcar-gen3";
                        reg = <0 0xee800000 0 0x80000>;
-                       /* placeholder */
+                       #address-cells = <3>;
+                       #size-cells = <2>;
+                       bus-range = <0x00 0xff>;
+                       device_type = "pci";
+                       ranges = <0x01000000 0 0x00000000 0 0xee900000 0 0x00100000
+                               0x02000000 0 0xeea00000 0 0xeea00000 0 0x00200000
+                               0x02000000 0 0xc0000000 0 0xc0000000 0 0x08000000
+                               0x42000000 0 0xc8000000 0 0xc8000000 0 0x08000000>;
+                       /* Map all possible DDR as inbound ranges */
+                       dma-ranges = <0x42000000 0 0x40000000 0 0x40000000 0 0x80000000>;
+                       interrupts = <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>,
+                               <GIC_SPI 149 IRQ_TYPE_LEVEL_HIGH>,
+                               <GIC_SPI 150 IRQ_TYPE_LEVEL_HIGH>;
+                       #interrupt-cells = <1>;
+                       interrupt-map-mask = <0 0 0 0>;
+                       interrupt-map = <0 0 0 0 &gic GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&cpg CPG_MOD 318>, <&pcie_bus_clk>;
+                       clock-names = "pcie", "pcie_bus";
+                       power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+                       resets = <&cpg 318>;
+                       status = "disabled";
                };
 
                imr-lx4@fe860000 {
 
                vspd0: vsp@fea20000 {
                        compatible = "renesas,vsp2";
-                       reg = <0 0xfea20000 0 0x8000>;
+                       reg = <0 0xfea20000 0 0x5000>;
                        interrupts = <GIC_SPI 466 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&cpg CPG_MOD 623>;
                        power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
 
                vspd1: vsp@fea28000 {
                        compatible = "renesas,vsp2";
-                       reg = <0 0xfea28000 0 0x8000>;
+                       reg = <0 0xfea28000 0 0x5000>;
                        interrupts = <GIC_SPI 467 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&cpg CPG_MOD 622>;
                        power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
 
                vspd2: vsp@fea30000 {
                        compatible = "renesas,vsp2";
-                       reg = <0 0xfea30000 0 0x8000>;
+                       reg = <0 0xfea30000 0 0x5000>;
                        interrupts = <GIC_SPI 468 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&cpg CPG_MOD 621>;
                        power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
index 486aeca..0cd4446 100644 (file)
                #size-cells = <2>;
                ranges;
 
-               wdt0: watchdog@e6020000 {
+               rwdt: watchdog@e6020000 {
+                       compatible = "renesas,r8a77965-wdt",
+                                    "renesas,rcar-gen3-wdt";
                        reg = <0 0xe6020000 0 0x0c>;
-                       /* placeholder */
+                       clocks = <&cpg CPG_MOD 402>;
+                       power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
+                       resets = <&cpg 402>;
+                       status = "disabled";
                };
 
                gpio0: gpio@e6050000 {
                        status = "disabled";
                };
 
+               hscif0: serial@e6540000 {
+                       compatible = "renesas,hscif-r8a77965",
+                                    "renesas,rcar-gen3-hscif",
+                                    "renesas,hscif";
+                       reg = <0 0xe6540000 0 0x60>;
+                       interrupts = <GIC_SPI 154 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&cpg CPG_MOD 520>,
+                                <&cpg CPG_CORE R8A77965_CLK_S3D1>,
+                                <&scif_clk>;
+                       clock-names = "fck", "brg_int", "scif_clk";
+                       dmas = <&dmac1 0x31>, <&dmac1 0x30>,
+                              <&dmac2 0x31>, <&dmac2 0x30>;
+                       dma-names = "tx", "rx", "tx", "rx";
+                       power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
+                       resets = <&cpg 520>;
+                       status = "disabled";
+               };
+
+               hscif1: serial@e6550000 {
+                       compatible = "renesas,hscif-r8a77965",
+                                    "renesas,rcar-gen3-hscif",
+                                    "renesas,hscif";
+                       reg = <0 0xe6550000 0 0x60>;
+                       interrupts = <GIC_SPI 155 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&cpg CPG_MOD 519>,
+                                <&cpg CPG_CORE R8A77965_CLK_S3D1>,
+                                <&scif_clk>;
+                       clock-names = "fck", "brg_int", "scif_clk";
+                       dmas = <&dmac1 0x33>, <&dmac1 0x32>,
+                              <&dmac2 0x33>, <&dmac2 0x32>;
+                       dma-names = "tx", "rx", "tx", "rx";
+                       power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
+                       resets = <&cpg 519>;
+                       status = "disabled";
+               };
+
+               hscif2: serial@e6560000 {
+                       compatible = "renesas,hscif-r8a77965",
+                                    "renesas,rcar-gen3-hscif",
+                                    "renesas,hscif";
+                       reg = <0 0xe6560000 0 0x60>;
+                       interrupts = <GIC_SPI 144 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&cpg CPG_MOD 518>,
+                                <&cpg CPG_CORE R8A77965_CLK_S3D1>,
+                                <&scif_clk>;
+                       clock-names = "fck", "brg_int", "scif_clk";
+                       dmas = <&dmac1 0x35>, <&dmac1 0x34>,
+                              <&dmac2 0x35>, <&dmac2 0x34>;
+                       dma-names = "tx", "rx", "tx", "rx";
+                       power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
+                       resets = <&cpg 518>;
+                       status = "disabled";
+               };
+
+               hscif3: serial@e66a0000 {
+                       compatible = "renesas,hscif-r8a77965",
+                                    "renesas,rcar-gen3-hscif",
+                                    "renesas,hscif";
+                       reg = <0 0xe66a0000 0 0x60>;
+                       interrupts = <GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&cpg CPG_MOD 517>,
+                                <&cpg CPG_CORE R8A77965_CLK_S3D1>,
+                                <&scif_clk>;
+                       clock-names = "fck", "brg_int", "scif_clk";
+                       dmas = <&dmac0 0x37>, <&dmac0 0x36>;
+                       dma-names = "tx", "rx";
+                       power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
+                       resets = <&cpg 517>;
+                       status = "disabled";
+               };
+
+               hscif4: serial@e66b0000 {
+                       compatible = "renesas,hscif-r8a77965",
+                                    "renesas,rcar-gen3-hscif",
+                                    "renesas,hscif";
+                       reg = <0 0xe66b0000 0 0x60>;
+                       interrupts = <GIC_SPI 146 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&cpg CPG_MOD 516>,
+                                <&cpg CPG_CORE R8A77965_CLK_S3D1>,
+                                <&scif_clk>;
+                       clock-names = "fck", "brg_int", "scif_clk";
+                       dmas = <&dmac0 0x39>, <&dmac0 0x38>;
+                       dma-names = "tx", "rx";
+                       power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
+                       resets = <&cpg 516>;
+                       status = "disabled";
+               };
+
                hsusb: usb@e6590000 {
                        compatible = "renesas,usbhs-r8a7796",
                                     "renesas,rcar-gen3-usbhs";
                        dma-channels = <16>;
                };
 
+               ipmmu_ds0: mmu@e6740000 {
+                       compatible = "renesas,ipmmu-r8a77965";
+                       reg = <0 0xe6740000 0 0x1000>;
+                       renesas,ipmmu-main = <&ipmmu_mm 0>;
+                       power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
+                       #iommu-cells = <1>;
+               };
+
+               ipmmu_ds1: mmu@e7740000 {
+                       compatible = "renesas,ipmmu-r8a77965";
+                       reg = <0 0xe7740000 0 0x1000>;
+                       renesas,ipmmu-main = <&ipmmu_mm 1>;
+                       power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
+                       #iommu-cells = <1>;
+               };
+
+               ipmmu_hc: mmu@e6570000 {
+                       compatible = "renesas,ipmmu-r8a77965";
+                       reg = <0 0xe6570000 0 0x1000>;
+                       renesas,ipmmu-main = <&ipmmu_mm 2>;
+                       power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
+                       #iommu-cells = <1>;
+               };
+
+               ipmmu_ir: mmu@ff8b0000 {
+                       compatible = "renesas,ipmmu-r8a77965";
+                       reg = <0 0xff8b0000 0 0x1000>;
+                       renesas,ipmmu-main = <&ipmmu_mm 3>;
+                       power-domains = <&sysc R8A77965_PD_A3IR>;
+                       #iommu-cells = <1>;
+               };
+
+               ipmmu_mm: mmu@e67b0000 {
+                       compatible = "renesas,ipmmu-r8a77965";
+                       reg = <0 0xe67b0000 0 0x1000>;
+                       interrupts = <GIC_SPI 196 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 197 IRQ_TYPE_LEVEL_HIGH>;
+                       power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
+                       #iommu-cells = <1>;
+               };
+
+               ipmmu_mp: mmu@ec670000 {
+                       compatible = "renesas,ipmmu-r8a77965";
+                       reg = <0 0xec670000 0 0x1000>;
+                       renesas,ipmmu-main = <&ipmmu_mm 4>;
+                       power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
+                       #iommu-cells = <1>;
+               };
+
+               ipmmu_pv0: mmu@fd800000 {
+                       compatible = "renesas,ipmmu-r8a77965";
+                       reg = <0 0xfd800000 0 0x1000>;
+                       renesas,ipmmu-main = <&ipmmu_mm 6>;
+                       power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
+                       #iommu-cells = <1>;
+               };
+
+               ipmmu_rt: mmu@ffc80000 {
+                       compatible = "renesas,ipmmu-r8a77965";
+                       reg = <0 0xffc80000 0 0x1000>;
+                       renesas,ipmmu-main = <&ipmmu_mm 10>;
+                       power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
+                       #iommu-cells = <1>;
+               };
+
+               ipmmu_vc0: mmu@fe6b0000 {
+                       compatible = "renesas,ipmmu-r8a77965";
+                       reg = <0 0xfe6b0000 0 0x1000>;
+                       renesas,ipmmu-main = <&ipmmu_mm 12>;
+                       power-domains = <&sysc R8A77965_PD_A3VC>;
+                       #iommu-cells = <1>;
+               };
+
+               ipmmu_vi0: mmu@febd0000 {
+                       compatible = "renesas,ipmmu-r8a77965";
+                       reg = <0 0xfebd0000 0 0x1000>;
+                       renesas,ipmmu-main = <&ipmmu_mm 14>;
+                       power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
+                       #iommu-cells = <1>;
+               };
+
+               ipmmu_vp0: mmu@fe990000 {
+                       compatible = "renesas,ipmmu-r8a77965";
+                       reg = <0 0xfe990000 0 0x1000>;
+                       renesas,ipmmu-main = <&ipmmu_mm 16>;
+                       power-domains = <&sysc R8A77965_PD_A3VP>;
+                       #iommu-cells = <1>;
+               };
+
                avb: ethernet@e6800000 {
                        compatible = "renesas,etheravb-r8a77965",
                                     "renesas,etheravb-rcar-gen3";
                        reg = <0 0xe6e60000 0 64>;
                        interrupts = <GIC_SPI 152 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&cpg CPG_MOD 207>,
-                                <&cpg CPG_CORE 20>,
+                                <&cpg CPG_CORE R8A77965_CLK_S3D1>,
                                 <&scif_clk>;
                        clock-names = "fck", "brg_int", "scif_clk";
                        dmas = <&dmac1 0x51>, <&dmac1 0x50>,
                        reg = <0 0xe6e68000 0 64>;
                        interrupts = <GIC_SPI 153 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&cpg CPG_MOD 206>,
-                                <&cpg CPG_CORE 20>,
+                                <&cpg CPG_CORE R8A77965_CLK_S3D1>,
                                 <&scif_clk>;
                        clock-names = "fck", "brg_int", "scif_clk";
                        dmas = <&dmac1 0x53>, <&dmac1 0x52>,
                        reg = <0 0xe6e88000 0 64>;
                        interrupts = <GIC_SPI 164 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&cpg CPG_MOD 310>,
-                                <&cpg CPG_CORE 20>,
+                                <&cpg CPG_CORE R8A77965_CLK_S3D1>,
                                 <&scif_clk>;
                        clock-names = "fck", "brg_int", "scif_clk";
                        power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
                        reg = <0 0xe6c50000 0 64>;
                        interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&cpg CPG_MOD 204>,
-                                <&cpg CPG_CORE 20>,
+                                <&cpg CPG_CORE R8A77965_CLK_S3D1>,
                                 <&scif_clk>;
                        clock-names = "fck", "brg_int", "scif_clk";
                        dmas = <&dmac0 0x57>, <&dmac0 0x56>;
                        reg = <0 0xe6c40000 0 64>;
                        interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&cpg CPG_MOD 203>,
-                                <&cpg CPG_CORE 20>,
+                                <&cpg CPG_CORE R8A77965_CLK_S3D1>,
                                 <&scif_clk>;
                        clock-names = "fck", "brg_int", "scif_clk";
                        dmas = <&dmac0 0x59>, <&dmac0 0x58>;
                        reg = <0 0xe6f30000 0 64>;
                        interrupts = <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&cpg CPG_MOD 202>,
-                                <&cpg CPG_CORE 20>,
+                                <&cpg CPG_CORE R8A77965_CLK_S3D1>,
                                 <&scif_clk>;
                        clock-names = "fck", "brg_int", "scif_clk";
                        dmas = <&dmac1 0x5b>, <&dmac1 0x5a>,
                                port@0 {
                                        reg = <0>;
                                };
+                               port@1 {
+                                       reg = <1>;
+                               };
                        };
                };
 
                };
 
                pciec0: pcie@fe000000 {
+                       compatible = "renesas,pcie-r8a77965",
+                                    "renesas,pcie-rcar-gen3";
                        reg = <0 0xfe000000 0 0x80000>;
-                       /* placeholder */
+                       #address-cells = <3>;
+                       #size-cells = <2>;
+                       bus-range = <0x00 0xff>;
+                       device_type = "pci";
+                       ranges = <0x01000000 0 0x00000000 0 0xfe100000 0 0x00100000
+                               0x02000000 0 0xfe200000 0 0xfe200000 0 0x00200000
+                               0x02000000 0 0x30000000 0 0x30000000 0 0x08000000
+                               0x42000000 0 0x38000000 0 0x38000000 0 0x08000000>;
+                       /* Map all possible DDR as inbound ranges */
+                       dma-ranges = <0x42000000 0 0x40000000 0 0x40000000 0 0x80000000>;
+                       interrupts = <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>,
+                               <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>,
+                               <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>;
+                       #interrupt-cells = <1>;
+                       interrupt-map-mask = <0 0 0 0>;
+                       interrupt-map = <0 0 0 0 &gic GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&cpg CPG_MOD 319>, <&pcie_bus_clk>;
+                       clock-names = "pcie", "pcie_bus";
+                       power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
+                       resets = <&cpg 319>;
+                       status = "disabled";
                };
 
                pciec1: pcie@ee800000 {
+                       compatible = "renesas,pcie-r8a77965",
+                                    "renesas,pcie-rcar-gen3";
                        reg = <0 0xee800000 0 0x80000>;
-                       /* placeholder */
+                       #address-cells = <3>;
+                       #size-cells = <2>;
+                       bus-range = <0x00 0xff>;
+                       device_type = "pci";
+                       ranges = <0x01000000 0 0x00000000 0 0xee900000 0 0x00100000
+                               0x02000000 0 0xeea00000 0 0xeea00000 0 0x00200000
+                               0x02000000 0 0xc0000000 0 0xc0000000 0 0x08000000
+                               0x42000000 0 0xc8000000 0 0xc8000000 0 0x08000000>;
+                       /* Map all possible DDR as inbound ranges */
+                       dma-ranges = <0x42000000 0 0x40000000 0 0x40000000 0 0x80000000>;
+                       interrupts = <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>,
+                               <GIC_SPI 149 IRQ_TYPE_LEVEL_HIGH>,
+                               <GIC_SPI 150 IRQ_TYPE_LEVEL_HIGH>;
+                       #interrupt-cells = <1>;
+                       interrupt-map-mask = <0 0 0 0>;
+                       interrupt-map = <0 0 0 0 &gic GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&cpg CPG_MOD 318>, <&pcie_bus_clk>;
+                       clock-names = "pcie", "pcie_bus";
+                       power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
+                       resets = <&cpg 318>;
+                       status = "disabled";
                };
 
                fcpf0: fcp@fe950000 {
 
                vspd0: vsp@fea20000 {
                        compatible = "renesas,vsp2";
-                       reg = <0 0xfea20000 0 0x8000>;
+                       reg = <0 0xfea20000 0 0x5000>;
                        interrupts = <GIC_SPI 466 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&cpg CPG_MOD 623>;
                        power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
 
                vspd1: vsp@fea28000 {
                        compatible = "renesas,vsp2";
-                       reg = <0 0xfea28000 0 0x8000>;
+                       reg = <0 0xfea28000 0 0x5000>;
                        interrupts = <GIC_SPI 467 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&cpg CPG_MOD 622>;
                        power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
index 21f9cf5..b6d5332 100644 (file)
@@ -1,12 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Device Tree Source for the Eagle board
  *
  * Copyright (C) 2016-2017 Renesas Electronics Corp.
  * Copyright (C) 2017 Cogent Embedded, Inc.
- *
- * This file is licensed under the terms of the GNU General Public License
- * version 2.  This program is licensed "as is" without any warranty of any
- * kind, whether express or implied.
  */
 
 /dts-v1/;
index 9fce031..8eac8ca 100644 (file)
@@ -1,12 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Device Tree Source for the V3M Starter Kit board
  *
  * Copyright (C) 2017 Renesas Electronics Corp.
  * Copyright (C) 2017 Cogent Embedded, Inc.
- *
- * This file is licensed under the terms of the GNU General Public License
- * version 2.  This program is licensed "as is" without any warranty of any
- * kind, whether express or implied.
  */
 
 /dts-v1/;
index 98a2317..9541688 100644 (file)
@@ -1,12 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Device Tree Source for the r8a77970 SoC
  *
  * Copyright (C) 2016-2017 Renesas Electronics Corp.
  * Copyright (C) 2017 Cogent Embedded, Inc.
- *
- * This file is licensed under the terms of the GNU General Public License
- * version 2.  This program is licensed "as is" without any warranty of any
- * kind, whether express or implied.
  */
 
 #include <dt-bindings/clock/r8a77970-cpg-mssr.h>
 
                vspd0: vsp@fea20000 {
                        compatible = "renesas,vsp2";
-                       reg = <0 0xfea20000 0 0x8000>;
+                       reg = <0 0xfea20000 0 0x5000>;
                        interrupts = <GIC_SPI 169 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&cpg CPG_MOD 623>;
                        power-domains = <&sysc R8A77970_PD_ALWAYS_ON>;
index 0b93a7d..9f25c40 100644 (file)
@@ -59,6 +59,8 @@
        phy0: ethernet-phy@0 {
                rxc-skew-ps = <1500>;
                reg = <0>;
+               interrupt-parent = <&gpio1>;
+               interrupts = <17 IRQ_TYPE_LEVEL_LOW>;
        };
 };
 
        clock-frequency = <32768>;
 };
 
+&i2c0 {
+       pinctrl-0 = <&i2c0_pins>;
+       pinctrl-names = "default";
+
+       status = "okay";
+       clock-frequency = <400000>;
+
+       io_expander0: gpio@20 {
+               compatible = "onnn,pca9654";
+               reg = <0x20>;
+               gpio-controller;
+               #gpio-cells = <2>;
+       };
+
+       io_expander1: gpio@21 {
+               compatible = "onnn,pca9654";
+               reg = <0x21>;
+               gpio-controller;
+               #gpio-cells = <2>;
+       };
+};
+
 &mmc0 {
        pinctrl-0 = <&mmc_pins>;
        pinctrl-1 = <&mmc_pins_uhs>;
                function = "canfd0";
        };
 
+       i2c0_pins: i2c0 {
+               groups = "i2c0";
+               function = "i2c0";
+       };
+
        mmc_pins: mmc {
                groups = "mmc_data8", "mmc_ctrl", "mmc_ds";
                function = "mmc";
index c968099..9dac42f 100644 (file)
@@ -15,6 +15,7 @@
 
        aliases {
                serial0 = &scif0;
+               ethernet0 = &gether;
        };
 
        chosen {
        clock-frequency = <32768>;
 };
 
+&gether {
+       pinctrl-0 = <&gether_pins>;
+       pinctrl-names = "default";
+
+       phy-mode = "rgmii";
+       phy-handle = <&phy0>;
+       renesas,no-ether-link;
+       status = "okay";
+
+       phy0: ethernet-phy@0 {
+               reg = <0>;
+               interrupt-parent = <&gpio4>;
+               interrupts = <23 IRQ_TYPE_LEVEL_LOW>;
+       };
+};
+
 &pfc {
+       gether_pins: gether {
+               groups = "gether_mdio_a", "gether_rgmii",
+                        "gether_txcrefclk", "gether_txcrefclk_mega";
+               function = "gether";
+       };
+
        scif0_pins: scif0 {
                groups = "scif0_data";
                function = "scif0";
index 4c40f9f..b8c9a56 100644 (file)
        #address-cells = <2>;
        #size-cells = <2>;
 
+       aliases {
+               i2c0 = &i2c0;
+               i2c1 = &i2c1;
+               i2c2 = &i2c2;
+               i2c3 = &i2c3;
+               i2c4 = &i2c4;
+               i2c5 = &i2c5;
+       };
+
        cpus {
                #address-cells = <1>;
                #size-cells = <0>;
                        enable-method = "psci";
                };
 
+               a53_1: cpu@1 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a53", "arm,armv8";
+                       reg = <1>;
+                       clocks = <&cpg CPG_CORE R8A77980_CLK_Z2>;
+                       power-domains = <&sysc R8A77980_PD_CA53_CPU1>;
+                       next-level-cache = <&L2_CA53>;
+                       enable-method = "psci";
+               };
+
+               a53_2: cpu@2 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a53", "arm,armv8";
+                       reg = <2>;
+                       clocks = <&cpg CPG_CORE R8A77980_CLK_Z2>;
+                       power-domains = <&sysc R8A77980_PD_CA53_CPU2>;
+                       next-level-cache = <&L2_CA53>;
+                       enable-method = "psci";
+               };
+
+               a53_3: cpu@3 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a53", "arm,armv8";
+                       reg = <3>;
+                       clocks = <&cpg CPG_CORE R8A77980_CLK_Z2>;
+                       power-domains = <&sysc R8A77980_PD_CA53_CPU3>;
+                       next-level-cache = <&L2_CA53>;
+                       enable-method = "psci";
+               };
+
                L2_CA53: cache-controller {
                        compatible = "cache";
                        power-domains = <&sysc R8A77980_PD_CA53_SCU>;
                #size-cells = <2>;
                ranges;
 
+               gpio0: gpio@e6050000 {
+                       compatible = "renesas,gpio-r8a77980",
+                                    "renesas,rcar-gen3-gpio";
+                       reg = <0 0xe6050000 0 0x50>;
+                       interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>;
+                       #gpio-cells = <2>;
+                       gpio-controller;
+                       gpio-ranges = <&pfc 0 0 22>;
+                       #interrupt-cells = <2>;
+                       interrupt-controller;
+                       clocks = <&cpg CPG_MOD 912>;
+                       power-domains = <&sysc R8A77980_PD_ALWAYS_ON>;
+                       resets = <&cpg 912>;
+               };
+
+               gpio1: gpio@e6051000 {
+                       compatible = "renesas,gpio-r8a77980",
+                                    "renesas,rcar-gen3-gpio";
+                       reg = <0 0xe6051000 0 0x50>;
+                       interrupts = <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>;
+                       #gpio-cells = <2>;
+                       gpio-controller;
+                       gpio-ranges = <&pfc 0 32 28>;
+                       #interrupt-cells = <2>;
+                       interrupt-controller;
+                       clocks = <&cpg CPG_MOD 911>;
+                       power-domains = <&sysc R8A77980_PD_ALWAYS_ON>;
+                       resets = <&cpg 911>;
+               };
+
+               gpio2: gpio@e6052000 {
+                       compatible = "renesas,gpio-r8a77980",
+                                    "renesas,rcar-gen3-gpio";
+                       reg = <0 0xe6052000 0 0x50>;
+                       interrupts = <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>;
+                       #gpio-cells = <2>;
+                       gpio-controller;
+                       gpio-ranges = <&pfc 0 64 30>;
+                       #interrupt-cells = <2>;
+                       interrupt-controller;
+                       clocks = <&cpg CPG_MOD 910>;
+                       power-domains = <&sysc R8A77980_PD_ALWAYS_ON>;
+                       resets = <&cpg 910>;
+               };
+
+               gpio3: gpio@e6053000 {
+                       compatible = "renesas,gpio-r8a77980",
+                                    "renesas,rcar-gen3-gpio";
+                       reg = <0 0xe6053000 0 0x50>;
+                       interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
+                       #gpio-cells = <2>;
+                       gpio-controller;
+                       gpio-ranges = <&pfc 0 96 17>;
+                       #interrupt-cells = <2>;
+                       interrupt-controller;
+                       clocks = <&cpg CPG_MOD 909>;
+                       power-domains = <&sysc R8A77980_PD_ALWAYS_ON>;
+                       resets = <&cpg 909>;
+               };
+
+               gpio4: gpio@e6054000 {
+                       compatible = "renesas,gpio-r8a77980",
+                                    "renesas,rcar-gen3-gpio";
+                       reg = <0 0xe6054000 0 0x50>;
+                       interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>;
+                       #gpio-cells = <2>;
+                       gpio-controller;
+                       gpio-ranges = <&pfc 0 128 25>;
+                       #interrupt-cells = <2>;
+                       interrupt-controller;
+                       clocks = <&cpg CPG_MOD 908>;
+                       power-domains = <&sysc R8A77980_PD_ALWAYS_ON>;
+                       resets = <&cpg 908>;
+               };
+
+               gpio5: gpio@e6055000 {
+                       compatible = "renesas,gpio-r8a77980",
+                                    "renesas,rcar-gen3-gpio";
+                       reg = <0 0xe6055000 0 0x50>;
+                       interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>;
+                       #gpio-cells = <2>;
+                       gpio-controller;
+                       gpio-ranges = <&pfc 0 160 15>;
+                       #interrupt-cells = <2>;
+                       interrupt-controller;
+                       clocks = <&cpg CPG_MOD 907>;
+                       power-domains = <&sysc R8A77980_PD_ALWAYS_ON>;
+                       resets = <&cpg 907>;
+               };
+
                pfc: pin-controller@e6060000 {
                        compatible = "renesas,pfc-r8a77980";
                        reg = <0 0xe6060000 0 0x50c>;
                        #power-domain-cells = <1>;
                };
 
+               intc_ex: interrupt-controller@e61c0000 {
+                       compatible = "renesas,intc-ex-r8a77980", "renesas,irqc";
+                       #interrupt-cells = <2>;
+                       interrupt-controller;
+                       reg = <0 0xe61c0000 0 0x200>;
+                       interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH
+                                     GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH
+                                     GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH
+                                     GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH
+                                     GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH
+                                     GIC_SPI 161 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&cpg CPG_MOD 407>;
+                       power-domains = <&sysc R8A77980_PD_ALWAYS_ON>;
+                       resets = <&cpg 407>;
+               };
+
+               i2c0: i2c@e6500000 {
+                       compatible = "renesas,i2c-r8a77980",
+                                    "renesas,rcar-gen3-i2c";
+                       reg = <0 0xe6500000 0 0x40>;
+                       interrupts = <GIC_SPI 287 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&cpg CPG_MOD 931>;
+                       power-domains = <&sysc R8A77980_PD_ALWAYS_ON>;
+                       resets = <&cpg 931>;
+                       dmas = <&dmac1 0x91>, <&dmac1 0x90>,
+                              <&dmac2 0x91>, <&dmac2 0x90>;
+                       dma-names = "tx", "rx", "tx", "rx";
+                       i2c-scl-internal-delay-ns = <6>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       status = "disabled";
+               };
+
+               i2c1: i2c@e6508000 {
+                       compatible = "renesas,i2c-r8a77980",
+                                    "renesas,rcar-gen3-i2c";
+                       reg = <0 0xe6508000 0 0x40>;
+                       interrupts = <GIC_SPI 288 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&cpg CPG_MOD 930>;
+                       power-domains = <&sysc R8A77980_PD_ALWAYS_ON>;
+                       resets = <&cpg 930>;
+                       dmas = <&dmac1 0x93>, <&dmac1 0x92>,
+                              <&dmac2 0x93>, <&dmac2 0x92>;
+                       dma-names = "tx", "rx", "tx", "rx";
+                       i2c-scl-internal-delay-ns = <6>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       status = "disabled";
+               };
+
+               i2c2: i2c@e6510000 {
+                       compatible = "renesas,i2c-r8a77980",
+                                    "renesas,rcar-gen3-i2c";
+                       reg = <0 0xe6510000 0 0x40>;
+                       interrupts = <GIC_SPI 286 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&cpg CPG_MOD 929>;
+                       power-domains = <&sysc R8A77980_PD_ALWAYS_ON>;
+                       resets = <&cpg 929>;
+                       dmas = <&dmac1 0x95>, <&dmac1 0x94>,
+                              <&dmac2 0x95>, <&dmac2 0x94>;
+                       dma-names = "tx", "rx", "tx", "rx";
+                       i2c-scl-internal-delay-ns = <6>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       status = "disabled";
+               };
+
+               i2c3: i2c@e66d0000 {
+                       compatible = "renesas,i2c-r8a77980",
+                                    "renesas,rcar-gen3-i2c";
+                       reg = <0 0xe66d0000 0 0x40>;
+                       interrupts = <GIC_SPI 290 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&cpg CPG_MOD 928>;
+                       power-domains = <&sysc R8A77980_PD_ALWAYS_ON>;
+                       resets = <&cpg 928>;
+                       i2c-scl-internal-delay-ns = <6>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       status = "disabled";
+               };
+
+               i2c4: i2c@e66d8000 {
+                       compatible = "renesas,i2c-r8a77980",
+                                    "renesas,rcar-gen3-i2c";
+                       reg = <0 0xe66d8000 0 0x40>;
+                       interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&cpg CPG_MOD 927>;
+                       power-domains = <&sysc R8A77980_PD_ALWAYS_ON>;
+                       resets = <&cpg 927>;
+                       i2c-scl-internal-delay-ns = <6>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       status = "disabled";
+               };
+
+               i2c5: i2c@e66e0000 {
+                       compatible = "renesas,i2c-r8a77980",
+                                    "renesas,rcar-gen3-i2c";
+                       reg = <0 0xe66e0000 0 0x40>;
+                       interrupts = <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&cpg CPG_MOD 919>;
+                       power-domains = <&sysc R8A77980_PD_ALWAYS_ON>;
+                       resets = <&cpg 919>;
+                       dmas = <&dmac1 0x9b>, <&dmac1 0x9a>,
+                              <&dmac2 0x9b>, <&dmac2 0x9a>;
+                       dma-names = "tx", "rx", "tx", "rx";
+                       i2c-scl-internal-delay-ns = <6>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       status = "disabled";
+               };
+
                hscif0: serial@e6540000 {
                        compatible = "renesas,hscif-r8a77980",
                                     "renesas,rcar-gen3-hscif",
                        };
                };
 
+               ipmmu_ds1: mmu@e7740000 {
+                       compatible = "renesas,ipmmu-r8a77980";
+                       reg = <0 0xe7740000 0 0x1000>;
+                       renesas,ipmmu-main = <&ipmmu_mm 0>;
+                       power-domains = <&sysc R8A77980_PD_ALWAYS_ON>;
+                       #iommu-cells = <1>;
+               };
+
+               ipmmu_vip0: mmu@e7b00000 {
+                       compatible = "renesas,ipmmu-r8a77980";
+                       reg = <0 0xe7b00000 0 0x1000>;
+                       power-domains = <&sysc R8A77980_PD_ALWAYS_ON>;
+                       #iommu-cells = <1>;
+               };
+
+               ipmmu_vip1: mmu@e7960000 {
+                       compatible = "renesas,ipmmu-r8a77980";
+                       reg = <0 0xe7960000 0 0x1000>;
+                       power-domains = <&sysc R8A77980_PD_ALWAYS_ON>;
+                       #iommu-cells = <1>;
+               };
+
+               ipmmu_ir: mmu@ff8b0000 {
+                       compatible = "renesas,ipmmu-r8a77980";
+                       reg = <0 0xff8b0000 0 0x1000>;
+                       renesas,ipmmu-main = <&ipmmu_mm 3>;
+                       power-domains = <&sysc R8A77980_PD_A3IR>;
+                       #iommu-cells = <1>;
+               };
+
+               ipmmu_mm: mmu@e67b0000 {
+                       compatible = "renesas,ipmmu-r8a77980";
+                       reg = <0 0xe67b0000 0 0x1000>;
+                       interrupts = <GIC_SPI 196 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 197 IRQ_TYPE_LEVEL_HIGH>;
+                       power-domains = <&sysc R8A77980_PD_ALWAYS_ON>;
+                       #iommu-cells = <1>;
+               };
+
+               ipmmu_rt: mmu@ffc80000 {
+                       compatible = "renesas,ipmmu-r8a77980";
+                       reg = <0 0xffc80000 0 0x1000>;
+                       renesas,ipmmu-main = <&ipmmu_mm 10>;
+                       power-domains = <&sysc R8A77980_PD_ALWAYS_ON>;
+                       #iommu-cells = <1>;
+               };
+
+               ipmmu_vc0: mmu@fe6b0000 {
+                       compatible = "renesas,ipmmu-r8a77980";
+                       reg = <0 0xfe6b0000 0 0x1000>;
+                       renesas,ipmmu-main = <&ipmmu_mm 12>;
+                       power-domains = <&sysc R8A77980_PD_ALWAYS_ON>;
+                       #iommu-cells = <1>;
+               };
+
+               ipmmu_vi0: mmu@febd0000 {
+                       compatible = "renesas,ipmmu-r8a77980";
+                       reg = <0 0xfebd0000 0 0x1000>;
+                       renesas,ipmmu-main = <&ipmmu_mm 14>;
+                       power-domains = <&sysc R8A77980_PD_ALWAYS_ON>;
+                       #iommu-cells = <1>;
+               };
+
                avb: ethernet@e6800000 {
                        compatible = "renesas,etheravb-r8a77980",
                                     "renesas,etheravb-rcar-gen3";
                        dma-channels = <16>;
                };
 
+               gether: ethernet@e7400000 {
+                       compatible = "renesas,gether-r8a77980";
+                       reg = <0 0xe7400000 0 0x1000>;
+                       interrupts = <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&cpg CPG_MOD 813>;
+                       power-domains = <&sysc R8A77980_PD_ALWAYS_ON>;
+                       resets = <&cpg 813>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       status = "disabled";
+               };
+
                mmc0: mmc@ee140000 {
                        compatible = "renesas,sdhi-r8a77980",
                                     "renesas,rcar-gen3-sdhi";
                              <0x0 0xf1020000 0 0x20000>,
                              <0x0 0xf1040000 0 0x20000>,
                              <0x0 0xf1060000 0 0x20000>;
-                       interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(1) |
+                       interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(4) |
                                      IRQ_TYPE_LEVEL_HIGH)>;
                        clocks = <&cpg CPG_MOD 408>;
                        clock-names = "clk";
                        resets = <&cpg 408>;
                };
 
+               vspd0: vsp@fea20000 {
+                       compatible = "renesas,vsp2";
+                       reg = <0 0xfea20000 0 0x5000>;
+                       interrupts = <GIC_SPI 169 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&cpg CPG_MOD 623>;
+                       power-domains = <&sysc R8A77980_PD_ALWAYS_ON>;
+                       resets = <&cpg 623>;
+                       renesas,fcp = <&fcpvd0>;
+               };
+
+               fcpvd0: fcp@fea27000 {
+                       compatible = "renesas,fcpv";
+                       reg = <0 0xfea27000 0 0x200>;
+                       clocks = <&cpg CPG_MOD 603>;
+                       power-domains = <&sysc R8A77980_PD_ALWAYS_ON>;
+                       resets = <&cpg 603>;
+               };
+
+               du: display@feb00000 {
+                       compatible = "renesas,du-r8a77980",
+                                    "renesas,du-r8a77970";
+                       reg = <0 0xfeb00000 0 0x80000>;
+                       interrupts = <GIC_SPI 256 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&cpg CPG_MOD 724>;
+                       clock-names = "du.0";
+                       power-domains = <&sysc R8A77980_PD_ALWAYS_ON>;
+                       resets = <&cpg 724>;
+                       vsps = <&vspd0>;
+                       status = "disabled";
+
+                       ports {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+
+                               port@0 {
+                                       reg = <0>;
+                                       du_out_rgb: endpoint {
+                                       };
+                               };
+
+                               port@1 {
+                                       reg = <1>;
+                                       du_out_lvds0: endpoint {
+                                               remote-endpoint = <&lvds0_in>;
+                                       };
+                               };
+                       };
+               };
+
+               lvds0: lvds-encoder@feb90000 {
+                       compatible = "renesas,r8a77980-lvds";
+                       reg = <0 0xfeb90000 0 0x14>;
+                       clocks = <&cpg CPG_MOD 727>;
+                       power-domains = <&sysc R8A77980_PD_ALWAYS_ON>;
+                       resets = <&cpg 727>;
+                       status = "disabled";
+
+                       ports {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+
+                               port@0 {
+                                       reg = <0>;
+                                       lvds0_in: endpoint {
+                                               remote-endpoint =
+                                                       <&du_out_lvds0>;
+                                       };
+                               };
+
+                               port@1 {
+                                       reg = <1>;
+                                       lvds0_out: endpoint {
+                                       };
+                               };
+                       };
+               };
+
                prr: chipid@fff00044 {
                        compatible = "renesas,prr";
                        reg = <0 0xfff00044 0 4>;
 
        timer {
                compatible = "arm,armv8-timer";
-               interrupts-extended = <&gic GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(1) |
+               interrupts-extended = <&gic GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) |
                                       IRQ_TYPE_LEVEL_LOW)>,
-                                     <&gic GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(1) |
+                                     <&gic GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(4) |
                                       IRQ_TYPE_LEVEL_LOW)>,
-                                     <&gic GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(1) |
+                                     <&gic GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) |
                                       IRQ_TYPE_LEVEL_LOW)>,
-                                     <&gic GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(1) |
+                                     <&gic GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) |
                                       IRQ_TYPE_LEVEL_LOW)>;
        };
 };
index 7a09d05..2bc3a48 100644 (file)
        };
 };
 
+&ehci0 {
+       status = "okay";
+};
+
 &extal_clk {
        clock-frequency = <48000000>;
 };
 
+&ohci0 {
+       status = "okay";
+};
+
 &pfc {
        avb_pins: avb {
                mux {
                        function = "avb";
                };
        };
+
+       usb0_pins: usb {
+               groups = "usb0_b";
+               function = "usb0";
+       };
+
+       usb30_pins: usb30 {
+               groups = "usb30";
+               function = "usb30";
+       };
+};
+
+&rwdt {
+       timeout-sec = <60>;
+       status = "okay";
 };
 
 &scif2 {
        status = "okay";
 };
+
+&usb2_phy0 {
+       pinctrl-0 = <&usb0_pins>;
+       pinctrl-names = "default";
+
+       status = "okay";
+};
+
+&xhci0 {
+       pinctrl-0 = <&usb30_pins>;
+       pinctrl-names = "default";
+
+       status = "okay";
+};
index be4f519..ae89260 100644 (file)
@@ -7,6 +7,7 @@
 
 #include <dt-bindings/clock/renesas-cpg-mssr.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/power/r8a77990-sysc.h>
 
 / {
        compatible = "renesas,r8a77990";
                #address-cells = <1>;
                #size-cells = <0>;
 
-               /* 1 core only at this point */
                a53_0: cpu@0 {
                        compatible = "arm,cortex-a53", "arm,armv8";
-                       reg = <0x0>;
+                       reg = <0>;
                        device_type = "cpu";
                        power-domains = <&sysc 5>;
                        next-level-cache = <&L2_CA53>;
                        enable-method = "psci";
                };
 
+               a53_1: cpu@1 {
+                       compatible = "arm,cortex-a53", "arm,armv8";
+                       reg = <1>;
+                       device_type = "cpu";
+                       power-domains = <&sysc 6>;
+                       next-level-cache = <&L2_CA53>;
+                       enable-method = "psci";
+               };
+
                L2_CA53: cache-controller-0 {
                        compatible = "cache";
                        power-domains = <&sysc 21>;
@@ -44,8 +53,9 @@
 
        pmu_a53 {
                compatible = "arm,cortex-a53-pmu";
-               interrupts-extended = <&gic GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>;
-               interrupt-affinity = <&a53_0>;
+               interrupts-extended = <&gic GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>,
+                                     <&gic GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>;
+               interrupt-affinity = <&a53_0>, <&a53_1>;
        };
 
        psci {
                #size-cells = <2>;
                ranges;
 
+               rwdt: watchdog@e6020000 {
+                       compatible = "renesas,r8a77990-wdt",
+                                    "renesas,rcar-gen3-wdt";
+                       reg = <0 0xe6020000 0 0x0c>;
+                       clocks = <&cpg CPG_MOD 402>;
+                       power-domains = <&sysc 32>;
+                       resets = <&cpg 402>;
+                       status = "disabled";
+               };
+
                gpio0: gpio@e6050000 {
                        compatible = "renesas,gpio-r8a77990",
                                     "renesas,rcar-gen3-gpio";
                        #power-domain-cells = <1>;
                };
 
+               ipmmu_ds0: mmu@e6740000 {
+                       compatible = "renesas,ipmmu-r8a77990";
+                       reg = <0 0xe6740000 0 0x1000>;
+                       renesas,ipmmu-main = <&ipmmu_mm 0>;
+                       power-domains = <&sysc R8A77990_PD_ALWAYS_ON>;
+                       #iommu-cells = <1>;
+               };
+
+               ipmmu_ds1: mmu@e7740000 {
+                       compatible = "renesas,ipmmu-r8a77990";
+                       reg = <0 0xe7740000 0 0x1000>;
+                       renesas,ipmmu-main = <&ipmmu_mm 1>;
+                       power-domains = <&sysc R8A77990_PD_ALWAYS_ON>;
+                       #iommu-cells = <1>;
+               };
+
+               ipmmu_hc: mmu@e6570000 {
+                       compatible = "renesas,ipmmu-r8a77990";
+                       reg = <0 0xe6570000 0 0x1000>;
+                       renesas,ipmmu-main = <&ipmmu_mm 2>;
+                       power-domains = <&sysc R8A77990_PD_ALWAYS_ON>;
+                       #iommu-cells = <1>;
+               };
+
+               ipmmu_mm: mmu@e67b0000 {
+                       compatible = "renesas,ipmmu-r8a77990";
+                       reg = <0 0xe67b0000 0 0x1000>;
+                       interrupts = <GIC_SPI 196 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 197 IRQ_TYPE_LEVEL_HIGH>;
+                       power-domains = <&sysc R8A77990_PD_ALWAYS_ON>;
+                       #iommu-cells = <1>;
+               };
+
+               ipmmu_mp: mmu@ec670000 {
+                       compatible = "renesas,ipmmu-r8a77990";
+                       reg = <0 0xec670000 0 0x1000>;
+                       renesas,ipmmu-main = <&ipmmu_mm 4>;
+                       power-domains = <&sysc R8A77990_PD_ALWAYS_ON>;
+                       #iommu-cells = <1>;
+               };
+
+               ipmmu_pv0: mmu@fd800000 {
+                       compatible = "renesas,ipmmu-r8a77990";
+                       reg = <0 0xfd800000 0 0x1000>;
+                       renesas,ipmmu-main = <&ipmmu_mm 6>;
+                       power-domains = <&sysc R8A77990_PD_ALWAYS_ON>;
+                       #iommu-cells = <1>;
+               };
+
+               ipmmu_rt: mmu@ffc80000 {
+                       compatible = "renesas,ipmmu-r8a77990";
+                       reg = <0 0xffc80000 0 0x1000>;
+                       renesas,ipmmu-main = <&ipmmu_mm 10>;
+                       power-domains = <&sysc R8A77990_PD_ALWAYS_ON>;
+                       #iommu-cells = <1>;
+               };
+
+               ipmmu_vc0: mmu@fe6b0000 {
+                       compatible = "renesas,ipmmu-r8a77990";
+                       reg = <0 0xfe6b0000 0 0x1000>;
+                       renesas,ipmmu-main = <&ipmmu_mm 12>;
+                       power-domains = <&sysc R8A77990_PD_A3VC>;
+                       #iommu-cells = <1>;
+               };
+
+               ipmmu_vi0: mmu@febd0000 {
+                       compatible = "renesas,ipmmu-r8a77990";
+                       reg = <0 0xfebd0000 0 0x1000>;
+                       renesas,ipmmu-main = <&ipmmu_mm 14>;
+                       power-domains = <&sysc R8A77990_PD_ALWAYS_ON>;
+                       #iommu-cells = <1>;
+               };
+
+               ipmmu_vp0: mmu@fe990000 {
+                       compatible = "renesas,ipmmu-r8a77990";
+                       reg = <0 0xfe990000 0 0x1000>;
+                       renesas,ipmmu-main = <&ipmmu_mm 16>;
+                       power-domains = <&sysc R8A77990_PD_ALWAYS_ON>;
+                       #iommu-cells = <1>;
+               };
+
                avb: ethernet@e6800000 {
                        compatible = "renesas,etheravb-r8a77990",
                                     "renesas,etheravb-rcar-gen3";
-                       reg = <0 0xe6800000 0 0x800>, <0 0xe6a00000 0 0x10000>;
+                       reg = <0 0xe6800000 0 0x800>;
                        interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>,
                                     <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>,
                                     <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>,
                        status = "disabled";
                };
 
+               xhci0: usb@ee000000 {
+                       compatible = "renesas,xhci-r8a77990",
+                                    "renesas,rcar-gen3-xhci";
+                       reg = <0 0xee000000 0 0xc00>;
+                       interrupts = <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&cpg CPG_MOD 328>;
+                       power-domains = <&sysc R8A77990_PD_ALWAYS_ON>;
+                       resets = <&cpg 328>;
+                       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 = <&usb2_phy0>;
+                       phy-names = "usb";
+                       power-domains = <&sysc 32>;
+                       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 = <&usb2_phy0>;
+                       phy-names = "usb";
+                       companion = <&ohci0>;
+                       power-domains = <&sysc 32>;
+                       resets = <&cpg 703>;
+                       status = "disabled";
+               };
+
+               usb2_phy0: usb-phy@ee080200 {
+                       compatible = "renesas,usb2-phy-r8a77990",
+                                    "renesas,rcar-gen3-usb2-phy";
+                       reg = <0 0xee080200 0 0x700>;
+                       interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&cpg CPG_MOD 703>;
+                       power-domains = <&sysc 32>;
+                       resets = <&cpg 703>;
+                       #phy-cells = <0>;
+                       status = "disabled";
+               };
+
                gic: interrupt-controller@f1010000 {
                        compatible = "arm,gic-400";
                        #interrupt-cells = <3>;
                              <0x0 0xf1040000 0 0x20000>,
                              <0x0 0xf1060000 0 0x20000>;
                        interrupts = <GIC_PPI 9
-                                       (GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_HIGH)>;
+                                       (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>;
                        clocks = <&cpg CPG_MOD 408>;
                        clock-names = "clk";
                        power-domains = <&sysc 32>;
 
        timer {
                compatible = "arm,armv8-timer";
-               interrupts-extended = <&gic GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_LOW)>,
-                                     <&gic GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_LOW)>,
-                                     <&gic GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_LOW)>,
-                                     <&gic GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_LOW)>;
+               interrupts-extended = <&gic GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
+                                     <&gic GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
+                                     <&gic GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
+                                     <&gic GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>;
        };
 };
index 9d73de8..a8e8f26 100644 (file)
@@ -1,12 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Device Tree Source for the Draak board
  *
  * Copyright (C) 2016 Renesas Electronics Corp.
  * Copyright (C) 2017 Glider bvba
- *
- * 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.
  */
 
 /dts-v1/;
                };
        };
 
+       composite-in {
+               compatible = "composite-video-connector";
+
+               port {
+                       composite_con_in: endpoint {
+                               remote-endpoint = <&adv7180_in>;
+                       };
+               };
+       };
+
+       hdmi-in {
+               compatible = "hdmi-connector";
+               type = "a";
+
+               port {
+                       hdmi_con_in: endpoint {
+                               remote-endpoint = <&adv7612_in>;
+                       };
+               };
+       };
+
        memory@48000000 {
                device_type = "memory";
                /* first 128MB is reserved for secure area. */
                regulator-boot-on;
                regulator-always-on;
        };
+
+       x12_clk: x12 {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <74250000>;
+       };
 };
 
 &extal_clk {
                groups = "usb0";
                function = "usb0";
        };
+
+       vin4_pins_cvbs: vin4 {
+               groups = "vin4_data8", "vin4_sync", "vin4_clk";
+               function = "vin4";
+       };
 };
 
 &i2c0 {
                reg = <0x50>;
                pagesize = <8>;
        };
+
+       composite-in@20 {
+               compatible = "adi,adv7180cp";
+               reg = <0x20>;
+
+               port {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+
+                       port@0 {
+                               reg = <0>;
+                               adv7180_in: endpoint {
+                                       remote-endpoint = <&composite_con_in>;
+                               };
+                       };
+
+                       port@3 {
+                               reg = <3>;
+
+                               /*
+                                * The VIN4 video input path is shared between
+                                * CVBS and HDMI inputs through SW[49-53]
+                                * switches.
+                                *
+                                * CVBS is the default selection, link it to
+                                * VIN4 here.
+                                */
+                               adv7180_out: endpoint {
+                                       remote-endpoint = <&vin4_in>;
+                               };
+                       };
+               };
+
+       };
+
+       hdmi-decoder@4c {
+               compatible = "adi,adv7612";
+               reg = <0x4c>;
+               default-input = <0>;
+
+               ports {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+
+                       port@0 {
+                               reg = <0>;
+
+                               adv7612_in: endpoint {
+                                       remote-endpoint = <&hdmi_con_in>;
+                               };
+                       };
+
+                       port@2 {
+                               reg = <2>;
+
+                               /*
+                                * The VIN4 video input path is shared between
+                                * CVBS and HDMI inputs through SW[49-53]
+                                * switches.
+                                *
+                                * CVBS is the default selection, leave HDMI
+                                * not connected here.
+                                */
+                               adv7612_out: endpoint {
+                                       pclk-sample = <0>;
+                                       hsync-active = <0>;
+                                       vsync-active = <0>;
+                               };
+                       };
+               };
+       };
 };
 
 &i2c1 {
        pinctrl-names = "default";
        status = "okay";
 
+       clocks = <&cpg CPG_MOD 724>,
+                <&cpg CPG_MOD 723>,
+                <&x12_clk>;
+       clock-names = "du.0", "du.1", "dclkin.0";
+
        ports {
                port@0 {
                        endpoint {
        timeout-sec = <60>;
        status = "okay";
 };
+
+&vin4 {
+       pinctrl-0 = <&vin4_pins_cvbs>;
+       pinctrl-names = "default";
+
+       status = "okay";
+
+       ports {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               port@0 {
+                       reg = <0>;
+
+                       vin4_in: endpoint {
+                               remote-endpoint = <&adv7180_out>;
+                       };
+               };
+       };
+};
index 2506f46..fe77bc4 100644 (file)
@@ -1,12 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Device Tree Source for the r8a77995 SoC
  *
  * Copyright (C) 2016 Renesas Electronics Corp.
  * Copyright (C) 2017 Glider bvba
- *
- * 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 <dt-bindings/clock/r8a77995-cpg-mssr.h>
@@ -88,8 +85,7 @@
 
                gpio0: gpio@e6050000 {
                        compatible = "renesas,gpio-r8a77995",
-                                    "renesas,rcar-gen3-gpio",
-                                    "renesas,gpio-rcar";
+                                    "renesas,rcar-gen3-gpio";
                        reg = <0 0xe6050000 0 0x50>;
                        interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>;
                        #gpio-cells = <2>;
 
                gpio1: gpio@e6051000 {
                        compatible = "renesas,gpio-r8a77995",
-                                    "renesas,rcar-gen3-gpio",
-                                    "renesas,gpio-rcar";
+                                    "renesas,rcar-gen3-gpio";
                        reg = <0 0xe6051000 0 0x50>;
                        interrupts = <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>;
                        #gpio-cells = <2>;
 
                gpio2: gpio@e6052000 {
                        compatible = "renesas,gpio-r8a77995",
-                                    "renesas,rcar-gen3-gpio",
-                                    "renesas,gpio-rcar";
+                                    "renesas,rcar-gen3-gpio";
                        reg = <0 0xe6052000 0 0x50>;
                        interrupts = <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>;
                        #gpio-cells = <2>;
 
                gpio3: gpio@e6053000 {
                        compatible = "renesas,gpio-r8a77995",
-                                    "renesas,rcar-gen3-gpio",
-                                    "renesas,gpio-rcar";
+                                    "renesas,rcar-gen3-gpio";
                        reg = <0 0xe6053000 0 0x50>;
                        interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
                        #gpio-cells = <2>;
 
                gpio4: gpio@e6054000 {
                        compatible = "renesas,gpio-r8a77995",
-                                    "renesas,rcar-gen3-gpio",
-                                    "renesas,gpio-rcar";
+                                    "renesas,rcar-gen3-gpio";
                        reg = <0 0xe6054000 0 0x50>;
                        interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>;
                        #gpio-cells = <2>;
 
                gpio5: gpio@e6055000 {
                        compatible = "renesas,gpio-r8a77995",
-                                    "renesas,rcar-gen3-gpio",
-                                    "renesas,gpio-rcar";
+                                    "renesas,rcar-gen3-gpio";
                        reg = <0 0xe6055000 0 0x50>;
                        interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>;
                        #gpio-cells = <2>;
 
                gpio6: gpio@e6055400 {
                        compatible = "renesas,gpio-r8a77995",
-                                    "renesas,rcar-gen3-gpio",
-                                    "renesas,gpio-rcar";
+                                    "renesas,rcar-gen3-gpio";
                        reg = <0 0xe6055400 0 0x50>;
                        interrupts = <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>;
                        #gpio-cells = <2>;
                        #power-domain-cells = <1>;
                };
 
+               thermal: thermal@e6190000 {
+                       compatible = "renesas,thermal-r8a77995";
+                       reg = <0 0xe6190000 0 0x10>, <0 0xe6190100 0 0x38>;
+                       interrupts = <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&cpg CPG_MOD 522>;
+                       power-domains = <&sysc R8A77995_PD_ALWAYS_ON>;
+                       resets = <&cpg 522>;
+                       #thermal-sensor-cells = <0>;
+               };
+
                intc_ex: interrupt-controller@e61c0000 {
                        compatible = "renesas,intc-ex-r8a77995", "renesas,irqc";
                        #interrupt-cells = <2>;
                        resets = <&cpg 407>;
                };
 
+               hscif0: serial@e6540000 {
+                       compatible = "renesas,hscif-r8a77995",
+                                    "renesas,rcar-gen3-hscif",
+                                    "renesas,hscif";
+                       reg = <0 0xe6540000 0 0x60>;
+                       interrupts = <GIC_SPI 154 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&cpg CPG_MOD 520>,
+                                <&cpg CPG_CORE R8A77995_CLK_S3D1C>,
+                                <&scif_clk>;
+                       clock-names = "fck", "brg_int", "scif_clk";
+                       dmas = <&dmac1 0x31>, <&dmac1 0x30>,
+                              <&dmac2 0x31>, <&dmac2 0x30>;
+                       dma-names = "tx", "rx", "tx", "rx";
+                       power-domains = <&sysc R8A77995_PD_ALWAYS_ON>;
+                       resets = <&cpg 520>;
+                       status = "disabled";
+               };
+
+               hscif3: serial@e66a0000 {
+                       compatible = "renesas,hscif-r8a77995",
+                                    "renesas,rcar-gen3-hscif",
+                                    "renesas,hscif";
+                       reg = <0 0xe66a0000 0 0x60>;
+                       interrupts = <GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&cpg CPG_MOD 517>,
+                                <&cpg CPG_CORE R8A77995_CLK_S3D1C>,
+                                <&scif_clk>;
+                       clock-names = "fck", "brg_int", "scif_clk";
+                       dmas = <&dmac0 0x37>, <&dmac0 0x36>;
+                       dma-names = "tx", "rx";
+                       power-domains = <&sysc R8A77995_PD_ALWAYS_ON>;
+                       resets = <&cpg 517>;
+                       status = "disabled";
+               };
+
                i2c0: i2c@e6500000 {
                        #address-cells = <1>;
                        #size-cells = <0>;
                        compatible = "renesas,ipmmu-r8a77995";
                        reg = <0 0xe6740000 0 0x1000>;
                        renesas,ipmmu-main = <&ipmmu_mm 0>;
+                       power-domains = <&sysc R8A77995_PD_ALWAYS_ON>;
                        #iommu-cells = <1>;
                };
 
                        compatible = "renesas,ipmmu-r8a77995";
                        reg = <0 0xe7740000 0 0x1000>;
                        renesas,ipmmu-main = <&ipmmu_mm 1>;
+                       power-domains = <&sysc R8A77995_PD_ALWAYS_ON>;
                        #iommu-cells = <1>;
                };
 
                        compatible = "renesas,ipmmu-r8a77995";
                        reg = <0 0xe6570000 0 0x1000>;
                        renesas,ipmmu-main = <&ipmmu_mm 2>;
+                       power-domains = <&sysc R8A77995_PD_ALWAYS_ON>;
                        #iommu-cells = <1>;
                };
 
                        reg = <0 0xe67b0000 0 0x1000>;
                        interrupts = <GIC_SPI 196 IRQ_TYPE_LEVEL_HIGH>,
                                     <GIC_SPI 197 IRQ_TYPE_LEVEL_HIGH>;
+                       power-domains = <&sysc R8A77995_PD_ALWAYS_ON>;
                        #iommu-cells = <1>;
                };
 
                        compatible = "renesas,ipmmu-r8a77995";
                        reg = <0 0xec670000 0 0x1000>;
                        renesas,ipmmu-main = <&ipmmu_mm 4>;
+                       power-domains = <&sysc R8A77995_PD_ALWAYS_ON>;
                        #iommu-cells = <1>;
                };
 
                        compatible = "renesas,ipmmu-r8a77995";
                        reg = <0 0xfd800000 0 0x1000>;
                        renesas,ipmmu-main = <&ipmmu_mm 6>;
+                       power-domains = <&sysc R8A77995_PD_ALWAYS_ON>;
                        #iommu-cells = <1>;
                };
 
                        compatible = "renesas,ipmmu-r8a77995";
                        reg = <0 0xffc80000 0 0x1000>;
                        renesas,ipmmu-main = <&ipmmu_mm 10>;
+                       power-domains = <&sysc R8A77995_PD_ALWAYS_ON>;
                        #iommu-cells = <1>;
                };
 
                        compatible = "renesas,ipmmu-r8a77995";
                        reg = <0 0xfe6b0000 0 0x1000>;
                        renesas,ipmmu-main = <&ipmmu_mm 12>;
+                       power-domains = <&sysc R8A77995_PD_ALWAYS_ON>;
                        #iommu-cells = <1>;
                };
 
                        compatible = "renesas,ipmmu-r8a77995";
                        reg = <0 0xfebd0000 0 0x1000>;
                        renesas,ipmmu-main = <&ipmmu_mm 14>;
+                       power-domains = <&sysc R8A77995_PD_ALWAYS_ON>;
                        #iommu-cells = <1>;
                };
 
                        compatible = "renesas,ipmmu-r8a77995";
                        reg = <0 0xfe990000 0 0x1000>;
                        renesas,ipmmu-main = <&ipmmu_mm 16>;
+                       power-domains = <&sysc R8A77995_PD_ALWAYS_ON>;
                        #iommu-cells = <1>;
                };
 
                        status = "disabled";
                };
 
+               scif0: serial@e6e60000 {
+                       compatible = "renesas,scif-r8a77995",
+                                    "renesas,rcar-gen3-scif", "renesas,scif";
+                       reg = <0 0xe6e60000 0 64>;
+                       interrupts = <GIC_SPI 152 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&cpg CPG_MOD 207>,
+                                <&cpg CPG_CORE R8A77995_CLK_S3D1C>,
+                                <&scif_clk>;
+                       clock-names = "fck", "brg_int", "scif_clk";
+                       dmas = <&dmac1 0x51>, <&dmac1 0x50>,
+                              <&dmac2 0x51>, <&dmac2 0x50>;
+                       dma-names = "tx", "rx", "tx", "rx";
+                       power-domains = <&sysc R8A77995_PD_ALWAYS_ON>;
+                       resets = <&cpg 207>;
+                       status = "disabled";
+               };
+
+               scif1: serial@e6e68000 {
+                       compatible = "renesas,scif-r8a77995",
+                                    "renesas,rcar-gen3-scif", "renesas,scif";
+                       reg = <0 0xe6e68000 0 64>;
+                       interrupts = <GIC_SPI 153 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&cpg CPG_MOD 206>,
+                                <&cpg CPG_CORE R8A77995_CLK_S3D1C>,
+                                <&scif_clk>;
+                       clock-names = "fck", "brg_int", "scif_clk";
+                       dmas = <&dmac1 0x53>, <&dmac1 0x52>,
+                              <&dmac2 0x53>, <&dmac2 0x52>;
+                       dma-names = "tx", "rx", "tx", "rx";
+                       power-domains = <&sysc R8A77995_PD_ALWAYS_ON>;
+                       resets = <&cpg 206>;
+                       status = "disabled";
+               };
+
                scif2: serial@e6e88000 {
                        compatible = "renesas,scif-r8a77995",
                                     "renesas,rcar-gen3-scif", "renesas,scif";
                        status = "disabled";
                };
 
+               scif3: serial@e6c50000 {
+                       compatible = "renesas,scif-r8a77995",
+                                    "renesas,rcar-gen3-scif", "renesas,scif";
+                       reg = <0 0xe6c50000 0 64>;
+                       interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&cpg CPG_MOD 204>,
+                                <&cpg CPG_CORE R8A77995_CLK_S3D1C>,
+                                <&scif_clk>;
+                       clock-names = "fck", "brg_int", "scif_clk";
+                       dmas = <&dmac0 0x57>, <&dmac0 0x56>;
+                       dma-names = "tx", "rx";
+                       power-domains = <&sysc R8A77995_PD_ALWAYS_ON>;
+                       resets = <&cpg 204>;
+                       status = "disabled";
+               };
+
+               scif4: serial@e6c40000 {
+                       compatible = "renesas,scif-r8a77995",
+                                    "renesas,rcar-gen3-scif", "renesas,scif";
+                       reg = <0 0xe6c40000 0 64>;
+                       interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&cpg CPG_MOD 203>,
+                                <&cpg CPG_CORE R8A77995_CLK_S3D1C>,
+                                <&scif_clk>;
+                       clock-names = "fck", "brg_int", "scif_clk";
+                       dmas = <&dmac0 0x59>, <&dmac0 0x58>;
+                       dma-names = "tx", "rx";
+                       power-domains = <&sysc R8A77995_PD_ALWAYS_ON>;
+                       resets = <&cpg 203>;
+                       status = "disabled";
+               };
+
+               scif5: serial@e6f30000 {
+                       compatible = "renesas,scif-r8a77995",
+                                    "renesas,rcar-gen3-scif", "renesas,scif";
+                       reg = <0 0xe6f30000 0 64>;
+                       interrupts = <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&cpg CPG_MOD 202>,
+                                <&cpg CPG_CORE R8A77995_CLK_S3D1C>,
+                                <&scif_clk>;
+                       clock-names = "fck", "brg_int", "scif_clk";
+                       dmas = <&dmac1 0x5b>, <&dmac1 0x5a>,
+                              <&dmac2 0x5b>, <&dmac2 0x5a>;
+                       dma-names = "tx", "rx", "tx", "rx";
+                       power-domains = <&sysc R8A77995_PD_ALWAYS_ON>;
+                       resets = <&cpg 202>;
+                       status = "disabled";
+               };
+
+               msiof0: spi@e6e90000 {
+                       compatible = "renesas,msiof-r8a77995",
+                                    "renesas,rcar-gen3-msiof";
+                       reg = <0 0xe6e90000 0 0x64>;
+                       interrupts = <GIC_SPI 156 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&cpg CPG_MOD 211>;
+                       dmas = <&dmac1 0x41>, <&dmac1 0x40>,
+                              <&dmac2 0x41>, <&dmac2 0x40>;
+                       dma-names = "tx", "rx", "tx", "rx";
+                       power-domains = <&sysc R8A77995_PD_ALWAYS_ON>;
+                       resets = <&cpg 211>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       status = "disabled";
+               };
+
+               msiof1: spi@e6ea0000 {
+                       compatible = "renesas,msiof-r8a77995",
+                                    "renesas,rcar-gen3-msiof";
+                       reg = <0 0xe6ea0000 0 0x64>;
+                       interrupts = <GIC_SPI 157 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&cpg CPG_MOD 210>;
+                       dmas = <&dmac1 0x43>, <&dmac1 0x42>,
+                              <&dmac2 0x43>, <&dmac2 0x42>;
+                       dma-names = "tx", "rx", "tx", "rx";
+                       power-domains = <&sysc R8A77995_PD_ALWAYS_ON>;
+                       resets = <&cpg 210>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       status = "disabled";
+               };
+
+               msiof2: spi@e6c00000 {
+                       compatible = "renesas,msiof-r8a77995",
+                                    "renesas,rcar-gen3-msiof";
+                       reg = <0 0xe6c00000 0 0x64>;
+                       interrupts = <GIC_SPI 158 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&cpg CPG_MOD 209>;
+                       dmas = <&dmac0 0x45>, <&dmac0 0x44>;
+                       dma-names = "tx", "rx";
+                       power-domains = <&sysc R8A77995_PD_ALWAYS_ON>;
+                       resets = <&cpg 209>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       status = "disabled";
+               };
+
+               msiof3: spi@e6c10000 {
+                       compatible = "renesas,msiof-r8a77995",
+                                    "renesas,rcar-gen3-msiof";
+                       reg = <0 0xe6c10000 0 0x64>;
+                       interrupts = <GIC_SPI 159 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&cpg CPG_MOD 208>;
+                       dmas = <&dmac0 0x47>, <&dmac0 0x46>;
+                       dma-names = "tx", "rx";
+                       power-domains = <&sysc R8A77995_PD_ALWAYS_ON>;
+                       resets = <&cpg 208>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       status = "disabled";
+               };
+
                vin4: video@e6ef4000 {
                        compatible = "renesas,vin-r8a77995";
                        reg = <0 0xe6ef4000 0 0x1000>;
 
                vspd0: vsp@fea20000 {
                        compatible = "renesas,vsp2";
-                       reg = <0 0xfea20000 0 0x8000>;
+                       reg = <0 0xfea20000 0 0x5000>;
                        interrupts = <GIC_SPI 466 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&cpg CPG_MOD 623>;
                        power-domains = <&sysc R8A77995_PD_ALWAYS_ON>;
 
                vspd1: vsp@fea28000 {
                        compatible = "renesas,vsp2";
-                       reg = <0 0xfea28000 0 0x8000>;
+                       reg = <0 0xfea28000 0 0x5000>;
                        interrupts = <GIC_SPI 467 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&cpg CPG_MOD 622>;
                        power-domains = <&sysc R8A77995_PD_ALWAYS_ON>;
                };
        };
 
+       thermal-zones {
+               cpu_thermal: cpu-thermal {
+                       polling-delay-passive = <250>;
+                       polling-delay = <1000>;
+                       thermal-sensors = <&thermal>;
+
+                       trips {
+                               cpu-crit {
+                                       temperature = <120000>;
+                                       hysteresis = <2000>;
+                                       type = "critical";
+                               };
+                       };
+
+                       cooling-maps {
+                       };
+               };
+       };
+
        timer {
                compatible = "arm,armv8-timer";
                interrupts-extended = <&gic GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_LOW)>,
index 9256fba..7d3d866 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Device Tree Source for common parts of Salvator-X board variants
  *
  * Copyright (C) 2015-2016 Renesas Electronics Corp.
- *
- * 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.
  */
 
 /*
@@ -36,7 +33,7 @@
 / {
        aliases {
                serial0 = &scif2;
-               serial1 = &scif1;
+               serial1 = &hscif1;
                ethernet0 = &avb;
        };
 
        clock-frequency = <32768>;
 };
 
+&hscif1 {
+       pinctrl-0 = <&hscif1_pins>;
+       pinctrl-names = "default";
+
+       uart-has-rtscts;
+       /* Please only enable hscif1 or scif1 */
+       status = "okay";
+};
+
 &hsusb {
        dr_mode = "otg";
        status = "okay";
                        };
                };
 
-               port@10 {
+               port@a {
                        reg = <10>;
 
                        adv7482_txa: endpoint {
                        };
                };
 
-               port@11 {
+               port@b {
                        reg = <11>;
 
                        adv7482_txb: endpoint {
                function = "du";
        };
 
+       hscif1_pins: hscif1 {
+               groups = "hscif1_data_a", "hscif1_ctrl_a";
+               function = "hscif1";
+       };
+
        i2c2_pins: i2c2 {
                groups = "i2c2_a";
                function = "i2c2";
        };
 
        sdhi2_pins: sd2 {
-               groups = "sdhi2_data8", "sdhi2_ctrl";
+               groups = "sdhi2_data8", "sdhi2_ctrl", "sdhi2_ds";
                function = "sdhi2";
                power-source = <3300>;
        };
 
        sdhi2_pins_uhs: sd2_uhs {
-               groups = "sdhi2_data8", "sdhi2_ctrl";
+               groups = "sdhi2_data8", "sdhi2_ctrl", "sdhi2_ds";
                function = "sdhi2";
                power-source = <1800>;
        };
        pinctrl-names = "default";
 
        uart-has-rtscts;
-       status = "okay";
+       /* Please only enable hscif1 or scif1 */
+       /* status = "okay"; */
 };
 
 &scif2 {
        status = "okay";
 };
 
-&wdt0 {
+&rwdt {
        timeout-sec = <60>;
        status = "okay";
 };
index 468868c..ddee50e 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Device Tree Source for the Salvator-X board
  *
  * Copyright (C) 2015-2016 Renesas Electronics Corp.
- *
- * 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 "salvator-common.dtsi"
@@ -20,6 +17,8 @@
 };
 
 &i2c4 {
+       clock-frequency = <400000>;
+
        versaclock5: clock-generator@6a {
                compatible = "idt,5p49v5923";
                reg = <0x6a>;
index bf4d200..717d427 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Device Tree Source for the Salvator-X 2nd version board
  *
  * Copyright (C) 2015-2017 Renesas Electronics Corp.
- *
- * 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 "salvator-common.dtsi"
@@ -20,6 +17,8 @@
 };
 
 &i2c4 {
+       clock-frequency = <400000>;
+
        versaclock6: clock-generator@6a {
                compatible = "idt,5p49v6901";
                reg = <0x6a>;
index a4e715c..8bf3091 100644 (file)
@@ -1,12 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Device Tree Source for the Kingfisher (ULCB extension) board
  *
  * Copyright (C) 2017 Renesas Electronics Corp.
  * Copyright (C) 2017 Cogent Embedded, Inc.
- *
- * This file is licensed under the terms of the GNU General Public License
- * version 2.  This program is licensed "as is" without any warranty of any
- * kind, whether express or implied.
  */
 
 / {
index 0edb16e..0ead552 100644 (file)
@@ -1,12 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Device Tree Source for the R-Car Gen3 ULCB board
  *
  * Copyright (C) 2016 Renesas Electronics Corp.
  * Copyright (C) 2016 Cogent Embedded, Inc.
- *
- * This file is licensed under the terms of the GNU General Public License
- * version 2.  This program is licensed "as is" without any warranty of any
- * kind, whether express or implied.
  */
 
 #include <dt-bindings/gpio/gpio.h>
        };
 
        sdhi2_pins: sd2 {
-               groups = "sdhi2_data8", "sdhi2_ctrl";
+               groups = "sdhi2_data8", "sdhi2_ctrl", "sdhi2_ds";
                function = "sdhi2";
                power-source = <3300>;
        };
 
        sdhi2_pins_uhs: sd2_uhs {
-               groups = "sdhi2_data8", "sdhi2_ctrl";
+               groups = "sdhi2_data8", "sdhi2_ctrl", "sdhi2_ds";
                function = "sdhi2";
                power-source = <1800>;
        };
        status = "okay";
 };
 
-&wdt0 {
+&rwdt {
        timeout-sec = <60>;
        status = "okay";
 };
index 48a83f8..b0092d9 100644 (file)
@@ -9,7 +9,9 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3368-orion-r68-meta.dtb
 dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3368-px5-evb.dtb
 dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3368-r88.dtb
 dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-evb.dtb
+dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-ficus.dtb
 dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-firefly.dtb
+dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-gru-bob.dtb
 dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-gru-kevin.dtb
 dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-puma-haikou.dtb
 dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-sapphire.dtb
index 3d551e3..8302d86 100644 (file)
@@ -1,43 +1,6 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * Copyright (c) 2017 Fuzhou Rockchip Electronics Co., Ltd
- *
- * This file is dual-licensed: you can use it either under the terms
- * of the GPL or the X11 license, at your option. Note that this dual
- * licensing only applies to this file, and not this project as a
- * whole.
- *
- *  a) This library is free software; 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 library is distributed in the hope that it will be useful,
- *     but WITHOUT 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/;
index 2825772..5272e88 100644 (file)
@@ -1,43 +1,6 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * Copyright (c) 2017 PINE64
- *
- * 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 library is free software; 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 library is distributed in the hope that it will be useful,
- *     but WITHOUT 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/;
index b8e9da1..3f5a294 100644 (file)
@@ -1,43 +1,6 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * Copyright (c) 2017 Fuzhou Rockchip Electronics Co., Ltd
- *
- * This file is dual-licensed: you can use it either under the terms
- * of the GPL or the X11 license, at your option. Note that this dual
- * licensing only applies to this file, and not this project as a
- * whole.
- *
- *  a) This library is free software; 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 library is distributed in the hope that it will be useful,
- *     but WITHOUT 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/rk3328-cru.h>
@@ -89,6 +52,7 @@
                        compatible = "arm,cortex-a53", "arm,armv8";
                        reg = <0x0 0x1>;
                        clocks = <&cru ARMCLK>;
+                       #cooling-cells = <2>;
                        dynamic-power-coefficient = <120>;
                        enable-method = "psci";
                        next-level-cache = <&l2>;
                        compatible = "arm,cortex-a53", "arm,armv8";
                        reg = <0x0 0x2>;
                        clocks = <&cru ARMCLK>;
+                       #cooling-cells = <2>;
                        dynamic-power-coefficient = <120>;
                        enable-method = "psci";
                        next-level-cache = <&l2>;
                        compatible = "arm,cortex-a53", "arm,armv8";
                        reg = <0x0 0x3>;
                        clocks = <&cru ARMCLK>;
+                       #cooling-cells = <2>;
                        dynamic-power-coefficient = <120>;
                        enable-method = "psci";
                        next-level-cache = <&l2>;
                reg = <0x0 0xff120000 0x0 0x100>;
                interrupts = <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&cru SCLK_UART1>, <&cru PCLK_UART1>;
-               clock-names = "sclk_uart", "pclk_uart";
+               clock-names = "baudclk", "apb_pclk";
                dmas = <&dmac 4>, <&dmac 5>;
                dma-names = "tx", "rx";
                pinctrl-names = "default";
index 8a5275f..160f2c7 100644 (file)
@@ -1,43 +1,6 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * Copyright (c) 2015 Caesar Wang <wxt@rock-chips.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/;
index a37220a..4de0891 100644 (file)
@@ -1,43 +1,6 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * Copyright (c) 2015 Caesar Wang <wxt@rock-chips.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/input/input.h>
index 5e4d3a7..6b9b1ac 100644 (file)
@@ -1,43 +1,6 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * Copyright (c) 2016 Andreas Färber
- *
- * 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/;
index d3f6c8e..96147d9 100644 (file)
@@ -1,43 +1,6 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * Copyright (c) 2016 Matthias Brugger <mbrugger@suse.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/;
index 13a9e22..fc1bf07 100644 (file)
@@ -1,43 +1,6 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * Copyright (c) 2016 Fuzhou Rockchip Electronics Co., Ltd
- *
- * This file is dual-licensed: you can use it either under the terms
- * of the GPL or the X11 license, at your option. Note that this dual
- * licensing only applies to this file, and not this project as a
- * whole.
- *
- *  a) This file is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License 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/;
index b3510d5..7452bed 100644 (file)
@@ -1,43 +1,6 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * Copyright (c) 2015 Heiko Stuebner <heiko@sntech.de>
- *
- * 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/;
index ad91ced..9c24de1 100644 (file)
@@ -1,43 +1,6 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * Copyright (c) 2015 Heiko Stuebner <heiko@sntech.de>
- *
- * 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 library is free software; 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 library is distributed in the hope that it will be useful,
- *     but WITHOUT 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/rk3368-cru.h>
                        compatible = "arm,cortex-a53", "arm,armv8";
                        reg = <0x0 0x0>;
                        enable-method = "psci";
-
                        #cooling-cells = <2>; /* min followed by max */
                };
 
                        compatible = "arm,cortex-a53", "arm,armv8";
                        reg = <0x0 0x1>;
                        enable-method = "psci";
+                       #cooling-cells = <2>; /* min followed by max */
                };
 
                cpu_l2: cpu@2 {
                        compatible = "arm,cortex-a53", "arm,armv8";
                        reg = <0x0 0x2>;
                        enable-method = "psci";
+                       #cooling-cells = <2>; /* min followed by max */
                };
 
                cpu_l3: cpu@3 {
                        compatible = "arm,cortex-a53", "arm,armv8";
                        reg = <0x0 0x3>;
                        enable-method = "psci";
+                       #cooling-cells = <2>; /* min followed by max */
                };
 
                cpu_b0: cpu@100 {
                        compatible = "arm,cortex-a53", "arm,armv8";
                        reg = <0x0 0x100>;
                        enable-method = "psci";
-
                        #cooling-cells = <2>; /* min followed by max */
                };
 
                        compatible = "arm,cortex-a53", "arm,armv8";
                        reg = <0x0 0x101>;
                        enable-method = "psci";
+                       #cooling-cells = <2>; /* min followed by max */
                };
 
                cpu_b2: cpu@102 {
                        compatible = "arm,cortex-a53", "arm,armv8";
                        reg = <0x0 0x102>;
                        enable-method = "psci";
+                       #cooling-cells = <2>; /* min followed by max */
                };
 
                cpu_b3: cpu@103 {
                        compatible = "arm,cortex-a53", "arm,armv8";
                        reg = <0x0 0x103>;
                        enable-method = "psci";
+                       #cooling-cells = <2>; /* min followed by max */
                };
        };
 
index 56533c3..959ddc3 100644 (file)
@@ -1,43 +1,6 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * Copyright (c) 2016 Fuzhou Rockchip Electronics Co., Ltd
- *
- * This file is dual-licensed: you can use it either under the terms
- * of the GPL or the X11 license, at your option. Note that this dual
- * licensing only applies to this file, and not this project as a
- * whole.
- *
- *  a) This file is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License 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/;
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-ficus.dts b/arch/arm64/boot/dts/rockchip/rk3399-ficus.dts
new file mode 100644 (file)
index 0000000..8978d92
--- /dev/null
@@ -0,0 +1,599 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2018 Collabora Ltd.
+ * Copyright (c) 2018 Fuzhou Rockchip Electronics Co., Ltd.
+ *
+ * Schematics available at https://dl.vamrs.com/products/ficus/docs/hw
+ */
+
+/dts-v1/;
+#include "rk3399.dtsi"
+#include "rk3399-opp.dtsi"
+
+/ {
+       model = "96boards RK3399 Ficus";
+       compatible = "vamrs,ficus", "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>;
+       };
+
+       vcc1v8_s0: vcc1v8-s0 {
+               compatible = "regulator-fixed";
+               regulator-name = "vcc1v8_s0";
+               regulator-min-microvolt = <1800000>;
+               regulator-max-microvolt = <1800000>;
+               regulator-always-on;
+       };
+
+       vcc_sys: vcc-sys {
+               compatible = "regulator-fixed";
+               regulator-name = "vcc_sys";
+               regulator-min-microvolt = <5000000>;
+               regulator-max-microvolt = <5000000>;
+               regulator-always-on;
+       };
+
+       vcc3v3_sys: vcc3v3-sys {
+               compatible = "regulator-fixed";
+               regulator-name = "vcc3v3_sys";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               regulator-always-on;
+               vin-supply = <&vcc_sys>;
+       };
+
+       vcc3v3_pcie: vcc3v3-pcie-regulator {
+               compatible = "regulator-fixed";
+               enable-active-high;
+               gpio = <&gpio1 24 GPIO_ACTIVE_HIGH>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&pcie_drv>;
+               regulator-boot-on;
+               regulator-name = "vcc3v3_pcie";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               vin-supply = <&vcc3v3_sys>;
+       };
+
+       vcc5v0_host: vcc5v0-host-regulator {
+               compatible = "regulator-fixed";
+               enable-active-high;
+               gpio = <&gpio4 27 GPIO_ACTIVE_HIGH>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&host_vbus_drv>;
+               regulator-name = "vcc5v0_host";
+               regulator-min-microvolt = <5000000>;
+               regulator-max-microvolt = <5000000>;
+               regulator-always-on;
+               vin-supply = <&vcc_sys>;
+       };
+
+       vdd_log: vdd-log {
+               compatible = "pwm-regulator";
+               pwms = <&pwm2 0 25000 0>;
+               regulator-name = "vdd_log";
+               regulator-min-microvolt = <800000>;
+               regulator-max-microvolt = <1400000>;
+               regulator-always-on;
+               regulator-boot-on;
+               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_sys>;
+       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";
+};
+
+&hdmi {
+       ddc-i2c-bus = <&i2c3>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&hdmi_cec>;
+       status = "okay";
+};
+
+&i2c0 {
+       clock-frequency = <400000>;
+       i2c-scl-rising-time-ns = <168>;
+       i2c-scl-falling-time-ns = <4>;
+       status = "okay";
+
+       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 = <&vcc_sys>;
+               status = "okay";
+
+               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 = <&vcc_sys>;
+               regulator-state-mem {
+                       regulator-off-in-suspend;
+               };
+       };
+
+       rk808: pmic@1b {
+               compatible = "rockchip,rk808";
+               reg = <0x1b>;
+               interrupt-parent = <&gpio1>;
+               interrupts = <21 IRQ_TYPE_LEVEL_LOW>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&pmic_int_l>;
+               rockchip,system-power-controller;
+               wakeup-source;
+               #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>;
+               vcc8-supply = <&vcc3v3_sys>;
+               vcc9-supply = <&vcc_sys>;
+               vcc10-supply = <&vcc_sys>;
+               vcc11-supply = <&vcc_sys>;
+               vcc12-supply = <&vcc3v3_sys>;
+               vddio-supply = <&vcc_1v8>;
+
+               regulators {
+                       vdd_center: DCDC_REG1 {
+                               regulator-name = "vdd_center";
+                               regulator-min-microvolt = <750000>;
+                               regulator-max-microvolt = <1350000>;
+                               regulator-always-on;
+                               regulator-boot-on;
+                               regulator-state-mem {
+                                       regulator-off-in-suspend;
+                               };
+                       };
+
+                       vdd_cpu_l: DCDC_REG2 {
+                               regulator-name = "vdd_cpu_l";
+                               regulator-min-microvolt = <750000>;
+                               regulator-max-microvolt = <1350000>;
+                               regulator-always-on;
+                               regulator-boot-on;
+                               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-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                               regulator-always-on;
+                               regulator-boot-on;
+                               regulator-state-mem {
+                                       regulator-on-in-suspend;
+                                       regulator-suspend-microvolt = <1800000>;
+                               };
+                       };
+
+                       vcc1v8_dvp: LDO_REG1 {
+                               regulator-name = "vcc1v8_dvp";
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                               regulator-always-on;
+                               regulator-boot-on;
+                               regulator-state-mem {
+                                       regulator-on-in-suspend;
+                                       regulator-suspend-microvolt = <1800000>;
+                               };
+                       };
+
+                       vcca1v8_hdmi: LDO_REG2 {
+                               regulator-name = "vcca1v8_hdmi";
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                               regulator-always-on;
+                               regulator-boot-on;
+                               regulator-state-mem {
+                                       regulator-on-in-suspend;
+                                       regulator-suspend-microvolt = <1800000>;
+                               };
+                       };
+
+                       vcca_1v8: LDO_REG3 {
+                               regulator-name = "vcca_1v8";
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                               regulator-always-on;
+                               regulator-boot-on;
+                               regulator-state-mem {
+                                       regulator-on-in-suspend;
+                                       regulator-suspend-microvolt = <1800000>;
+                               };
+                       };
+
+                       vcc_sd: LDO_REG4 {
+                               regulator-name = "vcc_sd";
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-always-on;
+                               regulator-boot-on;
+                               regulator-state-mem {
+                                       regulator-on-in-suspend;
+                                       regulator-suspend-microvolt = <3300000>;
+                               };
+                       };
+
+                       vcc3v0_sd: LDO_REG5 {
+                               regulator-name = "vcc3v0_sd";
+                               regulator-min-microvolt = <3000000>;
+                               regulator-max-microvolt = <3000000>;
+                               regulator-always-on;
+                               regulator-boot-on;
+                               regulator-state-mem {
+                                       regulator-on-in-suspend;
+                                       regulator-suspend-microvolt = <3000000>;
+                               };
+                       };
+
+                       vcc_1v5: LDO_REG6 {
+                               regulator-name = "vcc_1v5";
+                               regulator-min-microvolt = <1500000>;
+                               regulator-max-microvolt = <1500000>;
+                               regulator-always-on;
+                               regulator-boot-on;
+                               regulator-state-mem {
+                                       regulator-on-in-suspend;
+                                       regulator-suspend-microvolt = <1500000>;
+                               };
+                       };
+
+                       vcca0v9_hdmi: LDO_REG7 {
+                               regulator-name = "vcca0v9_hdmi";
+                               regulator-min-microvolt = <900000>;
+                               regulator-max-microvolt = <900000>;
+                               regulator-always-on;
+                               regulator-boot-on;
+                               regulator-state-mem {
+                                       regulator-on-in-suspend;
+                                       regulator-suspend-microvolt = <900000>;
+                               };
+                       };
+
+                       vcc_3v0: LDO_REG8 {
+                               regulator-name = "vcc_3v0";
+                               regulator-min-microvolt = <3000000>;
+                               regulator-max-microvolt = <3000000>;
+                               regulator-always-on;
+                               regulator-boot-on;
+                               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-on-in-suspend;
+                               };
+                       };
+
+                       vcc3v3_s0: SWITCH_REG2 {
+                               regulator-name = "vcc3v3_s0";
+                               regulator-always-on;
+                               regulator-boot-on;
+                               regulator-state-mem {
+                                       regulator-on-in-suspend;
+                               };
+                       };
+               };
+       };
+};
+
+&i2c1 {
+       status = "okay";
+};
+
+&i2c2 {
+       status = "okay";
+};
+
+&i2c3 {
+       status = "okay";
+};
+
+&i2c4 {
+       status = "okay";
+};
+
+&io_domains {
+       bt656-supply = <&vcc1v8_s0>; /* bt656_gpio2ab_ms */
+       audio-supply = <&vcc1v8_s0>; /* audio_gpio3d4a_ms */
+       sdmmc-supply = <&vcc_sd>; /* sdmmc_gpio4b_ms */
+       gpio1830-supply = <&vcc_3v0>; /* gpio1833_gpio4cd_ms */
+       status = "okay";
+};
+
+&pcie_phy {
+       status = "okay";
+};
+
+&pcie0 {
+       ep-gpios = <&gpio4 RK_PD4 GPIO_ACTIVE_HIGH>;
+       num-lanes = <4>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&pcie_clkreqn_cpm>;
+       vpcie3v3-supply = <&vcc3v3_pcie>;
+       status = "okay";
+};
+
+&pmu_io_domains {
+       pmu1830-supply = <&vcc_1v8>;
+       status = "okay";
+};
+
+&pinctrl {
+       gmac {
+               rgmii_sleep_pins: rgmii-sleep-pins {
+                       rockchip,pins =
+                               <3 15 RK_FUNC_GPIO &pcfg_output_low>;
+               };
+       };
+
+       sdmmc {
+               sdmmc_bus1: sdmmc-bus1 {
+                       rockchip,pins =
+                               <4 8 RK_FUNC_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>;
+               };
+
+               sdmmc_clk: sdmmc-clk {
+                       rockchip,pins =
+                               <4 12 RK_FUNC_1 &pcfg_pull_none_18ma>;
+               };
+
+               sdmmc_cmd: sdmmc-cmd {
+                       rockchip,pins =
+                               <4 13 RK_FUNC_1 &pcfg_pull_up_8ma>;
+               };
+       };
+
+       pcie {
+               pcie_drv: pcie-drv {
+                       rockchip,pins =
+                               <1 24 RK_FUNC_GPIO &pcfg_pull_none>;
+                       };
+       };
+
+       pmic {
+               pmic_int_l: pmic-int-l {
+                       rockchip,pins =
+                               <1 21 RK_FUNC_GPIO &pcfg_pull_up>;
+               };
+
+               vsel1_gpio: vsel1-gpio {
+                       rockchip,pins =
+                               <1 17 RK_FUNC_GPIO &pcfg_pull_down>;
+               };
+
+               vsel2_gpio: vsel2-gpio {
+                       rockchip,pins =
+                               <1 14 RK_FUNC_GPIO &pcfg_pull_down>;
+               };
+       };
+
+       usb2 {
+               host_vbus_drv: host-vbus-drv {
+                       rockchip,pins =
+                               <4 27 RK_FUNC_GPIO &pcfg_pull_none>;
+               };
+       };
+};
+
+&pwm2 {
+       status = "okay";
+};
+
+&pwm3 {
+       status = "okay";
+};
+
+&sdhci {
+       bus-width = <8>;
+       mmc-hs400-1_8v;
+       mmc-hs400-enhanced-strobe;
+       non-removable;
+       status = "okay";
+};
+
+&sdmmc {
+       bus-width = <4>;
+       cap-mmc-highspeed;
+       cap-sd-highspeed;
+       clock-frequency = <100000000>;
+       clock-freq-min-max = <100000 100000000>;
+       disable-wp;
+       sd-uhs-sdr104;
+       vqmmc-supply = <&vcc_sd>;
+       card-detect-delay = <800>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_cd &sdmmc_bus4>;
+       status = "okay";
+};
+
+&tcphy0 {
+       status = "okay";
+};
+
+&tcphy1 {
+       status = "okay";
+};
+
+&u2phy0 {
+       status = "okay";
+};
+
+&u2phy1 {
+       status = "okay";
+};
+
+&u2phy0_host {
+       phy-supply = <&vcc5v0_host>;
+       status = "okay";
+};
+
+&u2phy1_host {
+       phy-supply = <&vcc5v0_host>;
+       status = "okay";
+};
+
+&u2phy0_otg {
+       status = "okay";
+};
+
+&u2phy1_otg {
+       status = "okay";
+};
+
+&uart0 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&uart0_xfer &uart0_cts>;
+       status = "okay";
+};
+
+&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 = "host";
+};
+
+&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 2a35276..38336ab 100644 (file)
@@ -1,46 +1,10 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * Copyright (c) 2017 Fuzhou Rockchip Electronics Co., Ltd.
- *
- * This file is dual-licensed: you can use it either under the terms
- * of the GPL or the X11 license, at your option. Note that this dual
- * licensing only applies to this file, and not this project as a
- * whole.
- *
- *  a) This file is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License 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 <dt-bindings/input/linux-event-codes.h>
 #include <dt-bindings/pwm/pwm.h>
 #include "rk3399.dtsi"
 #include "rk3399-opp.dtsi"
                regulator-max-microvolt = <12000000>;
        };
 
+       gpio-keys {
+               compatible = "gpio-keys";
+               autorepeat;
+               pinctrl-names = "default";
+               pinctrl-0 = <&pwrbtn>;
+
+               power {
+                       debounce-interval = <100>;
+                       gpios = <&gpio0 RK_PA5 GPIO_ACTIVE_LOW>;
+                       label = "GPIO Key Power";
+                       linux,code = <KEY_POWER>;
+                       wakeup-source;
+               };
+       };
+
+       leds {
+               compatible = "gpio-leds";
+               pinctrl-names = "default";
+               pinctrl-0 = <&work_led_gpio>, <&diy_led_gpio>;
+
+               work-led {
+                       label = "work";
+                       default-state = "on";
+                       gpios = <&gpio2 RK_PD3 GPIO_ACTIVE_HIGH>;
+               };
+
+               diy-led {
+                       label = "diy";
+                       default-state = "off";
+                       gpios = <&gpio0 RK_PB5 GPIO_ACTIVE_HIGH>;
+               };
+       };
+
        rt5640-sound {
                compatible = "simple-audio-card";
                simple-audio-card,name = "rockchip,rt5640-codec";
 &i2s0 {
        rockchip,playback-channels = <8>;
        rockchip,capture-channels = <8>;
-       #sound-dai-cells = <0>;
        status = "okay";
 };
 
 &i2s1 {
        rockchip,playback-channels = <2>;
        rockchip,capture-channels = <2>;
-       #sound-dai-cells = <0>;
        status = "okay";
 };
 
 &i2s2 {
-       #sound-dai-cells = <0>;
        status = "okay";
 };
 
                        rockchip,pins = <1 RK_PA0 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
+
+       leds {
+               work_led_gpio: work_led-gpio {
+                       rockchip,pins = <2 RK_PD3 RK_FUNC_GPIO &pcfg_pull_none>;
+               };
+
+               diy_led_gpio: diy_led-gpio {
+                       rockchip,pins = <0 RK_PB5 RK_FUNC_GPIO &pcfg_pull_none>;
+               };
+       };
 };
 
 &pwm0 {
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-gru-bob.dts b/arch/arm64/boot/dts/rockchip/rk3399-gru-bob.dts
new file mode 100644 (file)
index 0000000..1ee0dc0
--- /dev/null
@@ -0,0 +1,79 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Google Gru-Bob Rev 4+ board device tree source
+ *
+ * Copyright 2018 Google, Inc
+ */
+
+/dts-v1/;
+#include "rk3399-gru-chromebook.dtsi"
+
+/ {
+       model = "Google Bob";
+       compatible = "google,bob-rev13", "google,bob-rev12",
+                    "google,bob-rev11", "google,bob-rev10",
+                    "google,bob-rev9", "google,bob-rev8",
+                    "google,bob-rev7", "google,bob-rev6",
+                    "google,bob-rev5", "google,bob-rev4",
+                    "google,bob", "google,gru", "rockchip,rk3399";
+
+       edp_panel: edp-panel {
+               compatible = "boe,nv101wxmn51", "simple-panel";
+               backlight = <&backlight>;
+               power-supply = <&pp3300_disp>;
+
+               ports {
+                       panel_in_edp: endpoint {
+                               remote-endpoint = <&edp_out_panel>;
+                       };
+               };
+       };
+};
+
+&ap_i2c_ts {
+       touchscreen: touchscreen@10 {
+               compatible = "elan,ekth3500";
+               reg = <0x10>;
+               interrupt-parent = <&gpio3>;
+               interrupts = <13 IRQ_TYPE_LEVEL_LOW>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&touch_int_l &touch_reset_l>;
+               reset-gpios = <&gpio4 26 GPIO_ACTIVE_LOW>;
+       };
+};
+
+&ap_i2c_tp {
+       trackpad: trackpad@15 {
+               compatible = "elan,ekth3000";
+               reg = <0x15>;
+               interrupt-parent = <&gpio1>;
+               interrupts = <4 IRQ_TYPE_LEVEL_LOW>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&trackpad_int_l>;
+               wakeup-source;
+       };
+};
+
+&backlight {
+       pwms = <&cros_ec_pwm 0>;
+};
+
+&cpu_alert0 {
+       temperature = <65000>;
+};
+
+&cpu_alert1 {
+       temperature = <70000>;
+};
+
+&spi0 {
+       status = "okay";
+};
+
+&pinctrl {
+       tpm {
+               h1_int_od_l: h1-int-od-l {
+                       rockchip,pins = <0 5 RK_FUNC_GPIO &pcfg_pull_up>;
+               };
+       };
+};
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-gru-chromebook.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-gru-chromebook.dtsi
new file mode 100644 (file)
index 0000000..ff81dfd
--- /dev/null
@@ -0,0 +1,397 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Google Gru-Chromebook shared properties
+ *
+ * Copyright 2018 Google, Inc
+ */
+
+#include "rk3399-gru.dtsi"
+
+/ {
+       pp900_ap: pp900-ap {
+               compatible = "regulator-fixed";
+               regulator-name = "pp900_ap";
+
+               /* EC turns on w/ pp900_ap_en; always on for AP */
+               regulator-always-on;
+               regulator-boot-on;
+               regulator-min-microvolt = <900000>;
+               regulator-max-microvolt = <900000>;
+
+               vin-supply = <&ppvar_sys>;
+       };
+
+       /* EC turns on w/ pp900_usb_en */
+       pp900_usb: pp900-ap {
+       };
+
+       /* EC turns on w/ pp900_pcie_en */
+       pp900_pcie: pp900-ap {
+       };
+
+       pp3000: pp3000 {
+               compatible = "regulator-fixed";
+               regulator-name = "pp3000";
+               pinctrl-names = "default";
+               pinctrl-0 = <&pp3000_en>;
+
+               enable-active-high;
+               gpio = <&gpio0 12 GPIO_ACTIVE_HIGH>;
+
+               regulator-always-on;
+               regulator-boot-on;
+               regulator-min-microvolt = <3000000>;
+               regulator-max-microvolt = <3000000>;
+
+               vin-supply = <&ppvar_sys>;
+       };
+
+       ppvar_centerlogic_pwm: ppvar-centerlogic-pwm {
+               compatible = "pwm-regulator";
+               regulator-name = "ppvar_centerlogic_pwm";
+
+               pwms = <&pwm3 0 3337 0>;
+               pwm-supply = <&ppvar_sys>;
+               pwm-dutycycle-range = <100 0>;
+               pwm-dutycycle-unit = <100>;
+
+               /* EC turns on w/ ppvar_centerlogic_en; always on for AP */
+               regulator-always-on;
+               regulator-boot-on;
+               regulator-min-microvolt = <799434>;
+               regulator-max-microvolt = <1049925>;
+       };
+
+       ppvar_centerlogic: ppvar-centerlogic {
+               compatible = "vctrl-regulator";
+               regulator-name = "ppvar_centerlogic";
+
+               regulator-min-microvolt = <799434>;
+               regulator-max-microvolt = <1049925>;
+
+               ctrl-supply = <&ppvar_centerlogic_pwm>;
+               ctrl-voltage-range = <799434 1049925>;
+
+               regulator-settling-time-up-us = <378>;
+               min-slew-down-rate = <225>;
+               ovp-threshold-percent = <16>;
+       };
+
+       /* Schematics call this PPVAR even though it's fixed */
+       ppvar_logic: ppvar-logic {
+               compatible = "regulator-fixed";
+               regulator-name = "ppvar_logic";
+
+               /* EC turns on w/ ppvar_logic_en; always on for AP */
+               regulator-always-on;
+               regulator-boot-on;
+               regulator-min-microvolt = <900000>;
+               regulator-max-microvolt = <900000>;
+
+               vin-supply = <&ppvar_sys>;
+       };
+
+       pp1800_audio: pp1800-audio {
+               compatible = "regulator-fixed";
+               regulator-name = "pp1800_audio";
+               pinctrl-names = "default";
+               pinctrl-0 = <&pp1800_audio_en>;
+
+               enable-active-high;
+               gpio = <&gpio0 2 GPIO_ACTIVE_HIGH>;
+
+               regulator-always-on;
+               regulator-boot-on;
+
+               vin-supply = <&pp1800>;
+       };
+
+       /* gpio is shared with pp3300_wifi_bt */
+       pp1800_pcie: pp1800-pcie {
+               compatible = "regulator-fixed";
+               regulator-name = "pp1800_pcie";
+               pinctrl-names = "default";
+               pinctrl-0 = <&wlan_module_pd_l>;
+
+               enable-active-high;
+               gpio = <&gpio0 4 GPIO_ACTIVE_HIGH>;
+
+               /*
+                * Need to wait 1ms + ramp-up time before we can power on WiFi.
+                * This has been approximated as 8ms total.
+                */
+               regulator-enable-ramp-delay = <8000>;
+
+               vin-supply = <&pp1800>;
+       };
+
+       /* Always on; plain and simple */
+       pp3000_ap: pp3000_emmc: pp3000 {
+       };
+
+       pp1500_ap_io: pp1500-ap-io {
+               compatible = "regulator-fixed";
+               regulator-name = "pp1500_ap_io";
+               pinctrl-names = "default";
+               pinctrl-0 = <&pp1500_en>;
+
+               enable-active-high;
+               gpio = <&gpio0 10 GPIO_ACTIVE_HIGH>;
+
+               regulator-always-on;
+               regulator-boot-on;
+               regulator-min-microvolt = <1500000>;
+               regulator-max-microvolt = <1500000>;
+
+               vin-supply = <&pp1800>;
+       };
+
+       pp3300_disp: pp3300-disp {
+               compatible = "regulator-fixed";
+               regulator-name = "pp3300_disp";
+               pinctrl-names = "default";
+               pinctrl-0 = <&pp3300_disp_en>;
+
+               enable-active-high;
+               gpio = <&gpio4 27 GPIO_ACTIVE_HIGH>;
+
+               startup-delay-us = <2000>;
+               vin-supply = <&pp3300>;
+       };
+
+       /* EC turns on w/ pp3300_usb_en_l */
+       pp3300_usb: pp3300 {
+       };
+
+       /* gpio is shared with pp1800_pcie and pinctrl is set there */
+       pp3300_wifi_bt: pp3300-wifi-bt {
+               compatible = "regulator-fixed";
+               regulator-name = "pp3300_wifi_bt";
+
+               enable-active-high;
+               gpio = <&gpio0 4 GPIO_ACTIVE_HIGH>;
+
+               vin-supply = <&pp3300>;
+       };
+
+       /*
+        * This is a bit of a hack. The WiFi module should be reset at least
+        * 1ms after its regulators have ramped up (max rampup time is ~7ms).
+        * With some stretching of the imagination, we can call the 1.8V
+        * regulator a supply.
+        */
+       wlan_pd_n: wlan-pd-n {
+               compatible = "regulator-fixed";
+               regulator-name = "wlan_pd_n";
+               pinctrl-names = "default";
+               pinctrl-0 = <&wlan_module_reset_l>;
+
+               enable-active-high;
+               gpio = <&gpio1 11 GPIO_ACTIVE_HIGH>;
+
+               vin-supply = <&pp1800_pcie>;
+       };
+
+       backlight: backlight {
+               compatible = "pwm-backlight";
+               brightness-levels = <0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
+                                    17 18 19 20 21 22 23 24 25 26 27 28 29 30
+                                    31 32 33 34 35 36 37 38 39 40 41 42 43 44
+                                    45 46 47 48 49 50 51 52 53 54 55 56 57 58
+                                    59 60 61 62 63 64 65 66 67 68 69 70 71 72
+                                    73 74 75 76 77 78 79 80 81 82 83 84 85 86
+                                    87 88 89 90 91 92 93 94 95 96 97 98 99 100>;
+               default-brightness-level = <51>;
+               enable-gpios = <&gpio1 17 GPIO_ACTIVE_HIGH>;
+               power-supply = <&pp3300_disp>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&bl_en>;
+               pwm-delay-us = <10000>;
+       };
+};
+
+&ppvar_bigcpu {
+       min-slew-down-rate = <225>;
+       ovp-threshold-percent = <16>;
+};
+
+&ppvar_litcpu {
+       min-slew-down-rate = <225>;
+       ovp-threshold-percent = <16>;
+};
+
+&ppvar_gpu {
+       min-slew-down-rate = <225>;
+       ovp-threshold-percent = <16>;
+};
+
+&cdn_dp {
+       extcon = <&usbc_extcon0>, <&usbc_extcon1>;
+};
+
+&edp {
+       status = "okay";
+
+       ports {
+               edp_out: port@1 {
+                       reg = <1>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+
+                       edp_out_panel: endpoint@0 {
+                               reg = <0>;
+                               remote-endpoint = <&panel_in_edp>;
+                       };
+               };
+       };
+};
+
+ap_i2c_mic: &i2c1 {
+       status = "okay";
+
+       clock-frequency = <400000>;
+
+       /* These are relatively safe rise/fall times */
+       i2c-scl-falling-time-ns = <50>;
+       i2c-scl-rising-time-ns = <300>;
+
+       headsetcodec: rt5514@57 {
+               compatible = "realtek,rt5514";
+               reg = <0x57>;
+               realtek,dmic-init-delay-ms = <20>;
+       };
+};
+
+ap_i2c_tp: &i2c5 {
+       status = "okay";
+
+       clock-frequency = <400000>;
+
+       /* These are relatively safe rise/fall times */
+       i2c-scl-falling-time-ns = <50>;
+       i2c-scl-rising-time-ns = <300>;
+
+       /*
+        * Note strange pullup enable.  Apparently this avoids leakage but
+        * still allows us to get nice 4.7K pullups for high speed i2c
+        * transfers.  Basically we want the pullup on whenever the ap is
+        * alive, so the "en" pin just gets set to output high.
+        */
+       pinctrl-0 = <&i2c5_xfer &ap_i2c_tp_pu_en>;
+};
+
+&cros_ec {
+       cros_ec_pwm: ec-pwm {
+               compatible = "google,cros-ec-pwm";
+               #pwm-cells = <1>;
+       };
+
+       usbc_extcon1: extcon@1 {
+               compatible = "google,extcon-usbc-cros-ec";
+               google,usb-port-id = <1>;
+
+               #extcon-cells = <0>;
+       };
+};
+
+&sound {
+       rockchip,codec = <&max98357a &headsetcodec
+                         &codec &wacky_spi_audio &cdn_dp>;
+};
+
+&spi2 {
+       wacky_spi_audio: spi2@0 {
+               compatible = "realtek,rt5514";
+               reg = <0>;
+               interrupt-parent = <&gpio1>;
+               interrupts = <13 IRQ_TYPE_LEVEL_HIGH>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&mic_int>;
+               /* May run faster once verified. */
+               spi-max-frequency = <10000000>;
+               wakeup-source;
+       };
+};
+
+&pci_rootport {
+       mvl_wifi: wifi@0,0 {
+               compatible = "pci1b4b,2b42";
+               reg = <0x83010000 0x0 0x00000000 0x0 0x00100000
+                      0x83010000 0x0 0x00100000 0x0 0x00100000>;
+               interrupt-parent = <&gpio0>;
+               interrupts = <8 IRQ_TYPE_LEVEL_LOW>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&wlan_host_wake_l>;
+               wakeup-source;
+       };
+};
+
+&tcphy1 {
+       status = "okay";
+       extcon = <&usbc_extcon1>;
+};
+
+&u2phy1 {
+       status = "okay";
+};
+
+&usb_host0_ehci {
+       status = "okay";
+};
+
+&usb_host1_ehci {
+       status = "okay";
+};
+
+&usb_host1_ohci {
+       status = "okay";
+};
+
+&usbdrd3_1 {
+       status = "okay";
+       extcon = <&usbc_extcon1>;
+};
+
+&usbdrd_dwc3_1 {
+       status = "okay";
+       dr_mode = "host";
+};
+
+&pinctrl {
+       discrete-regulators {
+               pp1500_en: pp1500-en {
+                       rockchip,pins = <RK_GPIO0 10 RK_FUNC_GPIO
+                                        &pcfg_pull_none>;
+               };
+
+               pp1800_audio_en: pp1800-audio-en {
+                       rockchip,pins = <RK_GPIO0 2 RK_FUNC_GPIO
+                                        &pcfg_pull_down>;
+               };
+
+               pp3000_en: pp3000-en {
+                       rockchip,pins = <RK_GPIO0 12 RK_FUNC_GPIO
+                                        &pcfg_pull_none>;
+               };
+
+               pp3300_disp_en: pp3300-disp-en {
+                       rockchip,pins = <RK_GPIO4 27 RK_FUNC_GPIO
+                                        &pcfg_pull_none>;
+               };
+
+               wlan_module_pd_l: wlan-module-pd-l {
+                       rockchip,pins = <RK_GPIO0 4 RK_FUNC_GPIO
+                                        &pcfg_pull_down>;
+               };
+       };
+};
+
+&wifi {
+       wifi_perst_l: wifi-perst-l {
+               rockchip,pins = <2 27 RK_FUNC_GPIO &pcfg_pull_none>;
+       };
+
+       wlan_host_wake_l: wlan-host-wake-l {
+               rockchip,pins = <0 8 RK_FUNC_GPIO &pcfg_pull_none>;
+       };
+};
index 8217912..2cc7c47 100644 (file)
@@ -1,49 +1,12 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * Google Gru-Kevin Rev 6+ board device tree source
  *
  * Copyright 2016-2017 Google, 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 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 "rk3399-gru.dtsi"
+#include "rk3399-gru-chromebook.dtsi"
 #include <dt-bindings/input/linux-event-codes.h>
 
 /*
                vin-supply = <&pp3300>;
        };
 
-       backlight: backlight {
-               compatible = "pwm-backlight";
-               pwms = <&cros_ec_pwm 1>;
-               brightness-levels = <0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
-                                    17 18 19 20 21 22 23 24 25 26 27 28 29 30
-                                    31 32 33 34 35 36 37 38 39 40 41 42 43 44
-                                    45 46 47 48 49 50 51 52 53 54 55 56 57 58
-                                    59 60 61 62 63 64 65 66 67 68 69 70 71 72
-                                    73 74 75 76 77 78 79 80 81 82 83 84 85 86
-                                    87 88 89 90 91 92 93 94 95 96 97 98 99 100>;
-               default-brightness-level = <51>;
-               enable-gpios = <&gpio1 17 GPIO_ACTIVE_HIGH>;
-               power-supply = <&pp3300_disp>;
-               pinctrl-names = "default";
-               pinctrl-0 = <&bl_en>;
-               pwm-delay-us = <10000>;
-       };
-
        edp_panel: edp-panel {
                compatible = "sharp,lq123p1jx31", "simple-panel";
                backlight = <&backlight>;
        };
 };
 
+&backlight {
+       pwms = <&cros_ec_pwm 1>;
+};
+
 &gpio_keys {
        pinctrl-names = "default";
        pinctrl-0 = <&bt_host_wake_l>, <&cpu1_pen_eject>;
@@ -280,23 +229,6 @@ ap_i2c_dig: &i2c2 {
        };
 };
 
-&edp {
-       status = "okay";
-
-       ports {
-               edp_out: port@1 {
-                       reg = <1>;
-                       #address-cells = <1>;
-                       #size-cells = <0>;
-
-                       edp_out_panel: endpoint@0 {
-                               reg = <0>;
-                               remote-endpoint = <&panel_in_edp>;
-                       };
-               };
-       };
-};
-
 &ppvar_bigcpu_pwm {
        regulator-min-microvolt = <798674>;
        regulator-max-microvolt = <1302172>;
@@ -374,10 +306,4 @@ ap_i2c_dig: &i2c2 {
                        rockchip,pins = <0 13 RK_FUNC_GPIO &pcfg_pull_up>;
                };
        };
-
-       wifi {
-               wlan_host_wake_l: wlan-host-wake-l {
-                       rockchip,pins = <0 8 RK_FUNC_GPIO &pcfg_pull_none>;
-               };
-       };
 };
index f49bfab..ca07f60 100644 (file)
@@ -1,45 +1,8 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * Google Gru (and derivatives) board device tree source
  *
  * Copyright 2016-2017 Google, 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 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/input/input.h>
                regulator-boot-on;
        };
 
-       pp900_ap: pp900-ap {
-               compatible = "regulator-fixed";
-               regulator-name = "pp900_ap";
-
-               /* EC turns on w/ pp900_ap_en; always on for AP */
-               regulator-always-on;
-               regulator-boot-on;
-               regulator-min-microvolt = <900000>;
-               regulator-max-microvolt = <900000>;
-
-               vin-supply = <&ppvar_sys>;
-       };
-
        pp1200_lpddr: pp1200-lpddr {
                compatible = "regulator-fixed";
                regulator-name = "pp1200_lpddr";
                vin-supply = <&ppvar_sys>;
        };
 
-       pp3000: pp3000 {
-               compatible = "regulator-fixed";
-               regulator-name = "pp3000";
-               pinctrl-names = "default";
-               pinctrl-0 = <&pp3000_en>;
-
-               enable-active-high;
-               gpio = <&gpio0 12 GPIO_ACTIVE_HIGH>;
-
-               regulator-always-on;
-               regulator-boot-on;
-               regulator-min-microvolt = <3000000>;
-               regulator-max-microvolt = <3000000>;
-
-               vin-supply = <&ppvar_sys>;
-       };
-
        pp3300: pp3300 {
                compatible = "regulator-fixed";
                regulator-name = "pp3300";
                ctrl-voltage-range = <800107 1302232>;
 
                regulator-settling-time-up-us = <322>;
-               min-slew-down-rate = <225>;
-               ovp-threshold-percent = <16>;
        };
 
        ppvar_litcpu_pwm: ppvar-litcpu-pwm {
                ctrl-voltage-range = <797743 1307837>;
 
                regulator-settling-time-up-us = <384>;
-               min-slew-down-rate = <225>;
-               ovp-threshold-percent = <16>;
        };
 
        ppvar_gpu_pwm: ppvar-gpu-pwm {
                ctrl-voltage-range = <786384 1217747>;
 
                regulator-settling-time-up-us = <390>;
-               min-slew-down-rate = <225>;
-               ovp-threshold-percent = <16>;
-       };
-
-       ppvar_centerlogic_pwm: ppvar-centerlogic-pwm {
-               compatible = "pwm-regulator";
-               regulator-name = "ppvar_centerlogic_pwm";
-
-               pwms = <&pwm3 0 3337 0>;
-               pwm-supply = <&ppvar_sys>;
-               pwm-dutycycle-range = <100 0>;
-               pwm-dutycycle-unit = <100>;
-
-               /* EC turns on w/ ppvar_centerlogic_en; always on for AP */
-               regulator-always-on;
-               regulator-boot-on;
-               regulator-min-microvolt = <799434>;
-               regulator-max-microvolt = <1049925>;
-       };
-
-       ppvar_centerlogic: ppvar-centerlogic {
-               compatible = "vctrl-regulator";
-               regulator-name = "ppvar_centerlogic";
-
-               regulator-min-microvolt = <799434>;
-               regulator-max-microvolt = <1049925>;
-
-               ctrl-supply = <&ppvar_centerlogic_pwm>;
-               ctrl-voltage-range = <799434 1049925>;
-
-               regulator-settling-time-up-us = <378>;
-               min-slew-down-rate = <225>;
-               ovp-threshold-percent = <16>;
-       };
-
-       /* Schematics call this PPVAR even though it's fixed */
-       ppvar_logic: ppvar-logic {
-               compatible = "regulator-fixed";
-               regulator-name = "ppvar_logic";
-
-               /* EC turns on w/ ppvar_logic_en; always on for AP */
-               regulator-always-on;
-               regulator-boot-on;
-               regulator-min-microvolt = <900000>;
-               regulator-max-microvolt = <900000>;
-
-               vin-supply = <&ppvar_sys>;
        };
 
        /* EC turns on w/ pp900_ddrpll_en */
        pp900_ddrpll: pp900-ap {
        };
 
-       /* EC turns on w/ pp900_pcie_en */
-       pp900_pcie: pp900-ap {
-       };
-
        /* EC turns on w/ pp900_pll_en */
        pp900_pll: pp900-ap {
        };
        pp900_pmu: pp900-ap {
        };
 
-       /* EC turns on w/ pp900_usb_en */
-       pp900_usb: pp900-ap {
-       };
-
        /* EC turns on w/ pp1800_s0_en_l */
        pp1800_ap_io: pp1800_emmc: pp1800_nfc: pp1800_s0: pp1800 {
        };
        pp1800_usb: pp1800 {
        };
 
-       pp1500_ap_io: pp1500-ap-io {
-               compatible = "regulator-fixed";
-               regulator-name = "pp1500_ap_io";
-               pinctrl-names = "default";
-               pinctrl-0 = <&pp1500_en>;
-
-               enable-active-high;
-               gpio = <&gpio0 10 GPIO_ACTIVE_HIGH>;
-
-               regulator-always-on;
-               regulator-boot-on;
-               regulator-min-microvolt = <1500000>;
-               regulator-max-microvolt = <1500000>;
-
-               vin-supply = <&pp1800>;
-       };
-
-       pp1800_audio: pp1800-audio {
-               compatible = "regulator-fixed";
-               regulator-name = "pp1800_audio";
-               pinctrl-names = "default";
-               pinctrl-0 = <&pp1800_audio_en>;
-
-               enable-active-high;
-               gpio = <&gpio0 2 GPIO_ACTIVE_HIGH>;
-
-               regulator-always-on;
-               regulator-boot-on;
-
-               vin-supply = <&pp1800>;
-       };
-
-       /* gpio is shared with pp3300_wifi_bt */
-       pp1800_pcie: pp1800-pcie {
-               compatible = "regulator-fixed";
-               regulator-name = "pp1800_pcie";
-               pinctrl-names = "default";
-               pinctrl-0 = <&wlan_module_pd_l>;
-
-               enable-active-high;
-               gpio = <&gpio0 4 GPIO_ACTIVE_HIGH>;
-
-               /*
-                * Need to wait 1ms + ramp-up time before we can power on WiFi.
-                * This has been approximated as 8ms total.
-                */
-               regulator-enable-ramp-delay = <8000>;
-
-               vin-supply = <&pp1800>;
-       };
-
-       /*
-        * This is a bit of a hack. The WiFi module should be reset at least
-        * 1ms after its regulators have ramped up (max rampup time is ~7ms).
-        * With some stretching of the imagination, we can call the 1.8V
-        * regulator a supply.
-        */
-       wlan_pd_n: wlan-pd-n {
-               compatible = "regulator-fixed";
-               regulator-name = "wlan_pd_n";
-               pinctrl-names = "default";
-               pinctrl-0 = <&wlan_module_reset_l>;
-
-               enable-active-high;
-               gpio = <&gpio1 11 GPIO_ACTIVE_HIGH>;
-
-               vin-supply = <&pp1800_pcie>;
-       };
-
-       /* Always on; plain and simple */
-       pp3000_ap: pp3000_emmc: pp3000 {
-       };
-
        pp3000_sd_slot: pp3000-sd-slot {
                compatible = "regulator-fixed";
                regulator-name = "pp3000_sd_slot";
        pp3300_trackpad: pp3300-trackpad {
        };
 
-       /* EC turns on w/ pp3300_usb_en_l */
-       pp3300_usb: pp3300 {
-       };
-
-       pp3300_disp: pp3300-disp {
-               compatible = "regulator-fixed";
-               regulator-name = "pp3300_disp";
-               pinctrl-names = "default";
-               pinctrl-0 = <&pp3300_disp_en>;
-
-               enable-active-high;
-               gpio = <&gpio4 27 GPIO_ACTIVE_HIGH>;
-
-               startup-delay-us = <2000>;
-               vin-supply = <&pp3300>;
-       };
-
-       /* gpio is shared with pp1800_pcie and pinctrl is set there */
-       pp3300_wifi_bt: pp3300-wifi-bt {
-               compatible = "regulator-fixed";
-               regulator-name = "pp3300_wifi_bt";
-
-               enable-active-high;
-               gpio = <&gpio0 4 GPIO_ACTIVE_HIGH>;
-
-               vin-supply = <&pp3300>;
-       };
-
        /* EC turns on w/ usb_a_en */
        pp5000_usb_a_vbus: pp5000 {
        };
                pinctrl-names = "default";
                pinctrl-0 = <&bt_host_wake_l>;
 
-               wake-on-bt {
+               wake_on_bt: wake-on-bt {
                        label = "Wake-on-Bluetooth";
                        gpios = <&gpio0 3 GPIO_ACTIVE_LOW>;
                        linux,code = <KEY_WAKEUP>;
                status = "okay";
        };
 
-       sound {
+       sound: sound {
                compatible = "rockchip,rk3399-gru-sound";
                rockchip,cpu = <&i2s0 &i2s2>;
-               rockchip,codec = <&max98357a &headsetcodec
-                                 &codec &wacky_spi_audio &cdn_dp>;
        };
 };
 
 &cdn_dp {
        status = "okay";
-       extcon = <&usbc_extcon0>, <&usbc_extcon1>;
 };
 
 /*
        status = "okay";
 };
 
-ap_i2c_mic: &i2c1 {
-       status = "okay";
-
-       clock-frequency = <400000>;
-
-       /* These are relatively safe rise/fall times */
-       i2c-scl-falling-time-ns = <50>;
-       i2c-scl-rising-time-ns = <300>;
-
-       headsetcodec: rt5514@57 {
-               compatible = "realtek,rt5514";
-               reg = <0x57>;
-               realtek,dmic-init-delay-ms = <20>;
-       };
-};
-
 ap_i2c_ts: &i2c3 {
        status = "okay";
 
@@ -639,24 +393,6 @@ ap_i2c_ts: &i2c3 {
        i2c-scl-rising-time-ns = <300>;
 };
 
-ap_i2c_tp: &i2c5 {
-       status = "okay";
-
-       clock-frequency = <400000>;
-
-       /* These are relatively safe rise/fall times */
-       i2c-scl-falling-time-ns = <50>;
-       i2c-scl-rising-time-ns = <300>;
-
-       /*
-        * Note strange pullup enable.  Apparently this avoids leakage but
-        * still allows us to get nice 4.7K pullups for high speed i2c
-        * transfers.  Basically we want the pullup on whenever the ap is
-        * alive, so the "en" pin just gets set to output high.
-        */
-       pinctrl-0 = <&i2c5_xfer &ap_i2c_tp_pu_en>;
-};
-
 ap_i2c_audio: &i2c8 {
        status = "okay";
 
@@ -730,17 +466,6 @@ ap_i2c_audio: &i2c8 {
                #address-cells = <3>;
                #size-cells = <2>;
                ranges;
-
-               mvl_wifi: wifi@0,0 {
-                       compatible = "pci1b4b,2b42";
-                       reg = <0x83010000 0x0 0x00000000 0x0 0x00100000
-                              0x83010000 0x0 0x00100000 0x0 0x00100000>;
-                       interrupt-parent = <&gpio0>;
-                       interrupts = <8 IRQ_TYPE_LEVEL_LOW>;
-                       pinctrl-names = "default";
-                       pinctrl-0 = <&wlan_host_wake_l>;
-                       wakeup-source;
-               };
        };
 };
 
@@ -830,18 +555,6 @@ ap_i2c_audio: &i2c8 {
 
 &spi2 {
        status = "okay";
-
-       wacky_spi_audio: spi2@0 {
-               compatible = "realtek,rt5514";
-               reg = <0>;
-               interrupt-parent = <&gpio1>;
-               interrupts = <13 IRQ_TYPE_LEVEL_HIGH>;
-               pinctrl-names = "default";
-               pinctrl-0 = <&mic_int>;
-               /* May run faster once verified. */
-               spi-max-frequency = <10000000>;
-               wakeup-source;
-       };
 };
 
 &spi5 {
@@ -863,24 +576,12 @@ ap_i2c_audio: &i2c8 {
                        #size-cells = <0>;
                };
 
-               cros_ec_pwm: ec-pwm {
-                       compatible = "google,cros-ec-pwm";
-                       #pwm-cells = <1>;
-               };
-
                usbc_extcon0: extcon@0 {
                        compatible = "google,extcon-usbc-cros-ec";
                        google,usb-port-id = <0>;
 
                        #extcon-cells = <0>;
                };
-
-               usbc_extcon1: extcon@1 {
-                       compatible = "google,extcon-usbc-cros-ec";
-                       google,usb-port-id = <1>;
-
-                       #extcon-cells = <0>;
-               };
        };
 };
 
@@ -896,19 +597,10 @@ ap_i2c_audio: &i2c8 {
        extcon = <&usbc_extcon0>;
 };
 
-&tcphy1 {
-       status = "okay";
-       extcon = <&usbc_extcon1>;
-};
-
 &u2phy0 {
        status = "okay";
 };
 
-&u2phy1 {
-       status = "okay";
-};
-
 &u2phy0_host {
        status = "okay";
 };
@@ -929,22 +621,10 @@ ap_i2c_audio: &i2c8 {
        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";
        extcon = <&usbc_extcon0>;
@@ -955,16 +635,6 @@ ap_i2c_audio: &i2c8 {
        dr_mode = "host";
 };
 
-&usbdrd3_1 {
-       status = "okay";
-       extcon = <&usbc_extcon1>;
-};
-
-&usbdrd_dwc3_1 {
-       status = "okay";
-       dr_mode = "host";
-};
-
 &vopb {
        status = "okay";
 };
@@ -1023,26 +693,6 @@ ap_i2c_audio: &i2c8 {
        };
 
        discrete-regulators {
-               pp1500_en: pp1500-en {
-                       rockchip,pins = <RK_GPIO0 10 RK_FUNC_GPIO
-                                        &pcfg_pull_none>;
-               };
-
-               pp1800_audio_en: pp1800-audio-en {
-                       rockchip,pins = <RK_GPIO0 2 RK_FUNC_GPIO
-                                        &pcfg_pull_down>;
-               };
-
-               pp3300_disp_en: pp3300-disp-en {
-                       rockchip,pins = <RK_GPIO4 27 RK_FUNC_GPIO
-                                        &pcfg_pull_none>;
-               };
-
-               pp3000_en: pp3000-en {
-                       rockchip,pins = <RK_GPIO0 12 RK_FUNC_GPIO
-                                        &pcfg_pull_none>;
-               };
-
                sd_io_pwr_en: sd-io-pwr-en {
                        rockchip,pins = <RK_GPIO2 2 RK_FUNC_GPIO
                                         &pcfg_pull_none>;
@@ -1057,11 +707,6 @@ ap_i2c_audio: &i2c8 {
                        rockchip,pins = <RK_GPIO4 29 RK_FUNC_GPIO
                                         &pcfg_pull_none>;
                };
-
-               wlan_module_pd_l: wlan-module-pd-l {
-                       rockchip,pins = <RK_GPIO0 4 RK_FUNC_GPIO
-                                        &pcfg_pull_down>;
-               };
        };
 
        codec {
@@ -1168,11 +813,7 @@ ap_i2c_audio: &i2c8 {
                };
        };
 
-       wifi {
-               wifi_perst_l: wifi-perst-l {
-                       rockchip,pins = <2 27 RK_FUNC_GPIO &pcfg_pull_none>;
-               };
-
+       wifi: wifi {
                wlan_module_reset_l: wlan-module-reset-l {
                        rockchip,pins = <1 11 RK_FUNC_GPIO &pcfg_pull_none>;
                };
index d8a120f..69cc9b0 100644 (file)
@@ -1,43 +1,6 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * Copyright (c) 2016-2017 Fuzhou Rockchip Electronics Co., Ltd
- *
- * This file is dual-licensed: you can use it either under the terms
- * of the GPL or the X11 license, at your option. Note that this dual
- * licensing only applies to this file, and not this project as a
- * whole.
- *
- *  a) This library is free software; 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 library is distributed in the hope that it will be useful,
- *     but WITHOUT 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 81617bc..d6f1095 100644 (file)
@@ -1,43 +1,6 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * Copyright (c) 2016-2017 Fuzhou Rockchip Electronics Co., Ltd
- *
- * This file is dual-licensed: you can use it either under the terms
- * of the GPL or the X11 license, at your option. Note that this dual
- * licensing only applies to this file, and not this project as a
- * whole.
- *
- *  a) This library is free software; 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 library is distributed in the hope that it will be useful,
- *     but WITHOUT 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 e0afdd8..e0d64f8 100644 (file)
@@ -1,43 +1,6 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * Copyright (c) 2017 Theobroma Systems Design und Consulting GmbH
- *
- * 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/;
index 14a0f19..0130b9f 100644 (file)
@@ -1,43 +1,6 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * Copyright (c) 2017 Theobroma Systems Design und Consulting GmbH
- *
- * 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/pwm/pwm.h>
        pinctrl-0 = <&i2s0_2ch_bus>;
        rockchip,playback-channels = <2>;
        rockchip,capture-channels = <2>;
-       #sound-dai-cells = <0>;
        status = "okay";
 };
 
index ad7548d..fef2c06 100644 (file)
@@ -1,43 +1,6 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * Copyright (c) 2017 Fuzhou Rockchip Electronics Co., Ltd.
- *
- * This file is dual-licensed: you can use it either under the terms
- * of the GPL or the X11 license, at your option. Note that this dual
- * licensing only applies to this file, and not this project as a
- * whole.
- *
- *  a) This file is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License 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/;
 &i2s0 {
        rockchip,playback-channels = <8>;
        rockchip,capture-channels = <8>;
-       #sound-dai-cells = <0>;
        status = "okay";
 };
 
 &spdif {
        i2c-scl-rising-time-ns = <450>;
        i2c-scl-falling-time-ns = <15>;
-       #sound-dai-cells = <0>;
        status = "okay";
 };
index 941b627..36b6079 100644 (file)
@@ -1,43 +1,6 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * Copyright (c) 2017 Fuzhou Rockchip Electronics Co., Ltd.
- *
- * This file is dual-licensed: you can use it either under the terms
- * of the GPL or the X11 license, at your option. Note that this dual
- * licensing only applies to this file, and not this project as a
- * whole.
- *
- *  a) This file is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License 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/pwm/pwm.h"
        status = "okay";
 };
 
+&hdmi_sound {
+       status = "okay";
+};
+
 &i2c0 {
        clock-frequency = <400000>;
        i2c-scl-rising-time-ns = <168>;
 };
 
 &i2s2 {
-       #sound-dai-cells = <0>;
        status = "okay";
 };
 
index e0040b6..c88e603 100644 (file)
@@ -1,43 +1,6 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 /*
  * Copyright (c) 2016 Fuzhou Rockchip Electronics Co., Ltd
- *
- * This file is dual-licensed: you can use it either under the terms
- * of the GPL or the X11 license, at your option. Note that this dual
- * licensing only applies to this file, and not this project as a
- * whole.
- *
- *  a) This library is free software; 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 library is distributed in the hope that it will be useful,
- *     but WITHOUT 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/rk3399-cru.h>
                        compatible = "arm,cortex-a53", "arm,armv8";
                        reg = <0x0 0x0>;
                        enable-method = "psci";
-                       #cooling-cells = <2>; /* min followed by max */
                        clocks = <&cru ARMCLKL>;
+                       #cooling-cells = <2>; /* min followed by max */
                        dynamic-power-coefficient = <100>;
                };
 
                        reg = <0x0 0x1>;
                        enable-method = "psci";
                        clocks = <&cru ARMCLKL>;
+                       #cooling-cells = <2>; /* min followed by max */
                        dynamic-power-coefficient = <100>;
                };
 
                        reg = <0x0 0x2>;
                        enable-method = "psci";
                        clocks = <&cru ARMCLKL>;
+                       #cooling-cells = <2>; /* min followed by max */
                        dynamic-power-coefficient = <100>;
                };
 
                        reg = <0x0 0x3>;
                        enable-method = "psci";
                        clocks = <&cru ARMCLKL>;
+                       #cooling-cells = <2>; /* min followed by max */
                        dynamic-power-coefficient = <100>;
                };
 
                        compatible = "arm,cortex-a72", "arm,armv8";
                        reg = <0x0 0x100>;
                        enable-method = "psci";
-                       #cooling-cells = <2>; /* min followed by max */
                        clocks = <&cru ARMCLKB>;
+                       #cooling-cells = <2>; /* min followed by max */
                        dynamic-power-coefficient = <436>;
                };
 
                        reg = <0x0 0x101>;
                        enable-method = "psci";
                        clocks = <&cru ARMCLKB>;
+                       #cooling-cells = <2>; /* min followed by max */
                        dynamic-power-coefficient = <436>;
                };
        };
                         <&cru SRST_P_UPHY0_TCPHY>;
                reset-names = "uphy", "uphy-pipe", "uphy-tcphy";
                rockchip,grf = <&grf>;
-               rockchip,typec-conn-dir = <0xe580 0 16>;
-               rockchip,usb3tousb2-en = <0xe580 3 19>;
-               rockchip,external-psm = <0xe588 14 30>;
-               rockchip,pipe-status = <0xe5c0 0 0>;
                status = "disabled";
 
                tcphy0_dp: dp-port {
                         <&cru SRST_P_UPHY1_TCPHY>;
                reset-names = "uphy", "uphy-pipe", "uphy-tcphy";
                rockchip,grf = <&grf>;
-               rockchip,typec-conn-dir = <0xe58c 0 16>;
-               rockchip,usb3tousb2-en = <0xe58c 3 19>;
-               rockchip,external-psm = <0xe594 14 30>;
-               rockchip,pipe-status = <0xe5c0 16 16>;
                status = "disabled";
 
                tcphy1_dp: dp-port {
                pinctrl-names = "default";
                pinctrl-0 = <&spdif_bus>;
                power-domains = <&power RK3399_PD_SDIOAUDIO>;
+               #sound-dai-cells = <0>;
                status = "disabled";
        };
 
                pinctrl-names = "default";
                pinctrl-0 = <&i2s0_8ch_bus>;
                power-domains = <&power RK3399_PD_SDIOAUDIO>;
+               #sound-dai-cells = <0>;
                status = "disabled";
        };
 
                pinctrl-names = "default";
                pinctrl-0 = <&i2s1_2ch_bus>;
                power-domains = <&power RK3399_PD_SDIOAUDIO>;
+               #sound-dai-cells = <0>;
                status = "disabled";
        };
 
                clock-names = "i2s_clk", "i2s_hclk";
                clocks = <&cru SCLK_I2S2_8CH>, <&cru HCLK_I2S2_8CH>;
                power-domains = <&power RK3399_PD_SDIOAUDIO>;
+               #sound-dai-cells = <0>;
                status = "disabled";
        };
 
                status = "disabled";
        };
 
+       hdmi_sound: hdmi-sound {
+               compatible = "simple-audio-card";
+               simple-audio-card,format = "i2s";
+               simple-audio-card,mclk-fs = <256>;
+               simple-audio-card,name = "hdmi-sound";
+               status = "disabled";
+
+               simple-audio-card,cpu {
+                       sound-dai = <&i2s2>;
+               };
+               simple-audio-card,codec {
+                       sound-dai = <&hdmi>;
+               };
+       };
+
        hdmi: hdmi@ff940000 {
                compatible = "rockchip,rk3399-dw-hdmi";
                reg = <0x0 0xff940000 0x0 0x20000>;
                power-domains = <&power RK3399_PD_HDCP>;
                reg-io-width = <4>;
                rockchip,grf = <&grf>;
+               #sound-dai-cells = <0>;
                status = "disabled";
 
                ports {
                        drive-strength = <12>;
                };
 
+               pcfg_pull_none_13ma: pcfg-pull-none-13ma {
+                       bias-disable;
+                       drive-strength = <13>;
+               };
+
+               pcfg_pull_none_18ma: pcfg-pull-none-18ma {
+                       bias-disable;
+                       drive-strength = <18>;
+               };
+
+               pcfg_pull_none_20ma: pcfg-pull-none-20ma {
+                       bias-disable;
+                       drive-strength = <20>;
+               };
+
+               pcfg_pull_up_2ma: pcfg-pull-up-2ma {
+                       bias-pull-up;
+                       drive-strength = <2>;
+               };
+
                pcfg_pull_up_8ma: pcfg-pull-up-8ma {
                        bias-pull-up;
                        drive-strength = <8>;
                };
 
+               pcfg_pull_up_18ma: pcfg-pull-up-18ma {
+                       bias-pull-up;
+                       drive-strength = <18>;
+               };
+
+               pcfg_pull_up_20ma: pcfg-pull-up-20ma {
+                       bias-pull-up;
+                       drive-strength = <20>;
+               };
+
                pcfg_pull_down_4ma: pcfg-pull-down-4ma {
                        bias-pull-down;
                        drive-strength = <4>;
                };
 
-               pcfg_pull_up_2ma: pcfg-pull-up-2ma {
-                       bias-pull-up;
-                       drive-strength = <2>;
+               pcfg_pull_down_8ma: pcfg-pull-down-8ma {
+                       bias-pull-down;
+                       drive-strength = <8>;
                };
 
                pcfg_pull_down_12ma: pcfg-pull-down-12ma {
                        drive-strength = <12>;
                };
 
-               pcfg_pull_none_13ma: pcfg-pull-none-13ma {
-                       bias-disable;
-                       drive-strength = <13>;
+               pcfg_pull_down_18ma: pcfg-pull-down-18ma {
+                       bias-pull-down;
+                       drive-strength = <18>;
+               };
+
+               pcfg_pull_down_20ma: pcfg-pull-down-20ma {
+                       bias-pull-down;
+                       drive-strength = <20>;
+               };
+
+               pcfg_output_high: pcfg-output-high {
+                       output-high;
+               };
+
+               pcfg_output_low: pcfg-output-low {
+                       output-low;
                };
 
                clock {
                pwm0 {
                        pwm0_pin: pwm0-pin {
                                rockchip,pins =
-                                       <4 18 RK_FUNC_1 &pcfg_pull_none>;
+                                       <4 RK_PC2 RK_FUNC_1 &pcfg_pull_none>;
+                       };
+
+                       pwm0_pin_pull_down: pwm0-pin-pull-down {
+                               rockchip,pins =
+                                       <4 RK_PC2 RK_FUNC_1 &pcfg_pull_down>;
                        };
 
                        vop0_pwm_pin: vop0-pwm-pin {
                                rockchip,pins =
-                                       <4 18 RK_FUNC_2 &pcfg_pull_none>;
+                                       <4 RK_PC2 RK_FUNC_2 &pcfg_pull_none>;
+                       };
+
+                       vop1_pwm_pin: vop1-pwm-pin {
+                               rockchip,pins =
+                                       <4 RK_PC2 RK_FUNC_3 &pcfg_pull_none>;
                        };
                };
 
                pwm1 {
                        pwm1_pin: pwm1-pin {
                                rockchip,pins =
-                                       <4 22 RK_FUNC_1 &pcfg_pull_none>;
+                                       <4 RK_PC6 RK_FUNC_1 &pcfg_pull_none>;
                        };
 
-                       vop1_pwm_pin: vop1-pwm-pin {
+                       pwm1_pin_pull_down: pwm1-pin-pull-down {
                                rockchip,pins =
-                                       <4 18 RK_FUNC_3 &pcfg_pull_none>;
+                                       <4 RK_PC6 RK_FUNC_1 &pcfg_pull_down>;
                        };
                };
 
                pwm2 {
                        pwm2_pin: pwm2-pin {
                                rockchip,pins =
-                                       <1 19 RK_FUNC_1 &pcfg_pull_none>;
+                                       <1 RK_PC3 RK_FUNC_1 &pcfg_pull_none>;
+                       };
+
+                       pwm2_pin_pull_down: pwm2-pin-pull-down {
+                               rockchip,pins =
+                                       <1 RK_PC3 RK_FUNC_1 &pcfg_pull_down>;
                        };
                };
 
                pwm3a {
                        pwm3a_pin: pwm3a-pin {
                                rockchip,pins =
-                                       <0 6 RK_FUNC_1 &pcfg_pull_none>;
+                                       <0 RK_PA6 RK_FUNC_1 &pcfg_pull_none>;
                        };
                };
 
                pwm3b {
                        pwm3b_pin: pwm3b-pin {
                                rockchip,pins =
-                                       <1 14 RK_FUNC_1 &pcfg_pull_none>;
+                                       <1 RK_PB6 RK_FUNC_1 &pcfg_pull_none>;
                        };
                };
 
index ae3b5ad..7968d52 100644 (file)
@@ -60,6 +60,7 @@
                        &i2s_port4
                        &spdif_port0
                        &comp_spdif_port0>;
+               hp-det-gpio = <&gpio UNIPHIER_GPIO_IRQ(0) GPIO_ACTIVE_LOW>;
        };
 
        spdif-out {
index 7919233..1a5e7c2 100644 (file)
@@ -60,6 +60,7 @@
                        &i2s_port4
                        &spdif_port0
                        &comp_spdif_port0>;
+               hp-det-gpio = <&gpio UNIPHIER_GPIO_IRQ(0) GPIO_ACTIVE_LOW>;
        };
 
        spdif-out {
index 0298bd0..caf1126 100644 (file)
@@ -58,6 +58,7 @@
                        clocks = <&sys_clk 32>;
                        enable-method = "psci";
                        operating-points-v2 = <&cluster0_opp>;
+                       #cooling-cells = <2>;
                };
 
                cpu2: cpu@100 {
@@ -77,6 +78,7 @@
                        clocks = <&sys_clk 33>;
                        enable-method = "psci";
                        operating-points-v2 = <&cluster1_opp>;
+                       #cooling-cells = <2>;
                };
        };
 
index 98d3b4f..82bd642 100644 (file)
                #address-cells = <1>;
                #size-cells = <0>;
 
+               led-controller@200 {
+                       compatible = "sprd,sc27xx-bltc", "sprd,sc2731-bltc";
+                       reg = <0x200>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+
+                       led@0 {
+                               label = "red";
+                               reg = <0x0>;
+                       };
+
+                       led@1 {
+                               label = "green";
+                               reg = <0x1>;
+                       };
+
+                       led@2 {
+                               label = "blue";
+                               reg = <0x2>;
+                       };
+               };
+
                rtc@280 {
                        compatible = "sprd,sc27xx-rtc", "sprd,sc2731-rtc";
                        reg = <0x280>;
                        #interrupt-cells = <2>;
                };
 
+               efuse@380 {
+                       compatible = "sprd,sc27xx-efuse", "sprd,sc2731-efuse";
+                       reg = <0x380>;
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       hwlocks = <&hwlock 12>;
+               };
+
+               pmic_adc: adc@480 {
+                       compatible = "sprd,sc27xx-adc", "sprd,sc2731-adc";
+                       reg = <0x480>;
+                       interrupt-parent = <&sc2731_pmic>;
+                       interrupts = <0 IRQ_TYPE_LEVEL_HIGH>;
+                       #io-channel-cells = <1>;
+                       hwlocks = <&hwlock 4>;
+               };
+
+               vibrator@ec8 {
+                       compatible = "sprd,sc27xx-vibrator", "sprd,sc2731-vibrator";
+                       reg = <0xec8>;
+               };
+
                regulators {
                        compatible = "sprd,sc27xx-regulator";
 
index 3f5160d..48f5928 100644 (file)
        };
 
        idle-states{
-               entry-method = "arm,psci";
+               entry-method = "psci";
 
                CORE_PD: core_pd {
                        compatible = "arm,idle-state";
index e9db910..eb6be56 100644 (file)
                                clocks = <&ext_32k>;
                        };
 
+                       timer@40050020 {
+                               compatible = "sprd,sc9860-suspend-timer";
+                               reg = <0 0x40050020 0 0x20>;
+                               clocks = <&ext_32k>;
+                       };
+
                        hwlock: hwspinlock@40500000 {
                                compatible = "sprd,hwspinlock-r3p0";
                                reg = <0 0x40500000 0 0x1000>;
diff --git a/arch/arm64/boot/dts/ti/Makefile b/arch/arm64/boot/dts/ti/Makefile
new file mode 100644 (file)
index 0000000..63e619d
--- /dev/null
@@ -0,0 +1,9 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Make file to build device tree binaries for boards based on
+# Texas Instruments Inc processors
+#
+# Copyright (C) 2016-2018 Texas Instruments Incorporated - http://www.ti.com/
+#
+
+dtb-$(CONFIG_ARCH_K3_AM6_SOC) += k3-am654-base-board.dtb
diff --git a/arch/arm64/boot/dts/ti/k3-am65-main.dtsi b/arch/arm64/boot/dts/ti/k3-am65-main.dtsi
new file mode 100644 (file)
index 0000000..2409344
--- /dev/null
@@ -0,0 +1,31 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Device Tree Source for AM6 SoC Family Main Domain peripherals
+ *
+ * Copyright (C) 2016-2018 Texas Instruments Incorporated - http://www.ti.com/
+ */
+
+&cbass_main {
+       gic500: interrupt-controller@1800000 {
+               compatible = "arm,gic-v3";
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges;
+               #interrupt-cells = <3>;
+               interrupt-controller;
+               reg = <0x01800000 0x10000>,     /* GICD */
+                     <0x01880000 0x90000>;     /* GICR */
+               /*
+                * vcpumntirq:
+                * virtual CPU interface maintenance interrupt
+                */
+               interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>;
+
+               gic_its: gic-its@18200000 {
+                       compatible = "arm,gic-v3-its";
+                       reg = <0x01820000 0x10000>;
+                       msi-controller;
+                       #msi-cells = <1>;
+               };
+       };
+};
diff --git a/arch/arm64/boot/dts/ti/k3-am65.dtsi b/arch/arm64/boot/dts/ti/k3-am65.dtsi
new file mode 100644 (file)
index 0000000..cede1fa
--- /dev/null
@@ -0,0 +1,87 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Device Tree Source for AM6 SoC Family
+ *
+ * Copyright (C) 2016-2018 Texas Instruments Incorporated - http://www.ti.com/
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+/ {
+       model = "Texas Instruments K3 AM654 SoC";
+       compatible = "ti,am654";
+       interrupt-parent = <&gic500>;
+       #address-cells = <2>;
+       #size-cells = <2>;
+
+       chosen { };
+
+       firmware {
+               optee {
+                       compatible = "linaro,optee-tz";
+                       method = "smc";
+               };
+
+               psci: psci {
+                       compatible = "arm,psci-1.0";
+                       method = "smc";
+               };
+       };
+
+       a53_timer0: timer-cl0-cpu0 {
+               compatible = "arm,armv8-timer";
+               interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_LOW>, /* cntpsirq */
+                            <GIC_PPI 14 IRQ_TYPE_LEVEL_LOW>, /* cntpnsirq */
+                            <GIC_PPI 11 IRQ_TYPE_LEVEL_LOW>, /* cntvirq */
+                            <GIC_PPI 10 IRQ_TYPE_LEVEL_LOW>; /* cnthpirq */
+       };
+
+       pmu: pmu {
+               compatible = "arm,armv8-pmuv3";
+               /* Recommendation from GIC500 TRM Table A.3 */
+               interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_HIGH>;
+       };
+
+       cbass_main: interconnect@100000 {
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges = <0x00100000 0x00 0x00100000 0x00020000>, /* ctrl mmr */
+                        <0x00600000 0x00 0x00600000 0x00001100>, /* GPIO */
+                        <0x00900000 0x00 0x00900000 0x00012000>, /* serdes */
+                        <0x01000000 0x00 0x01000000 0x0af02400>, /* Most peripherals */
+                        <0x30800000 0x00 0x30800000 0x0bc00000>, /* MAIN NAVSS */
+                        /* MCUSS Range */
+                        <0x28380000 0x00 0x28380000 0x03880000>,
+                        <0x40200000 0x00 0x40200000 0x00900100>,
+                        <0x42040000 0x00 0x42040000 0x03ac2400>,
+                        <0x45100000 0x00 0x45100000 0x00c24000>,
+                        <0x46000000 0x00 0x46000000 0x00200000>,
+                        <0x47000000 0x00 0x47000000 0x00068400>;
+
+               cbass_mcu: interconnect@28380000 {
+                       compatible = "simple-bus";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x28380000 0x28380000 0x03880000>, /* MCU NAVSS*/
+                                <0x40200000 0x40200000 0x00900100>, /* First peripheral window */
+                                <0x42040000 0x42040000 0x03ac2400>, /* WKUP */
+                                <0x45100000 0x45100000 0x00c24000>, /* MMRs, remaining NAVSS */
+                                <0x46000000 0x46000000 0x00200000>, /* CPSW */
+                                <0x47000000 0x47000000 0x00068400>; /* OSPI space 1 */
+
+                       cbass_wakeup: interconnect@42040000 {
+                               compatible = "simple-bus";
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+                               /* WKUP  Basic peripherals */
+                               ranges = <0x42040000 0x42040000 0x03ac2400>;
+                       };
+               };
+       };
+};
+
+/* Now include the peripherals for each bus segments */
+#include "k3-am65-main.dtsi"
diff --git a/arch/arm64/boot/dts/ti/k3-am654-base-board.dts b/arch/arm64/boot/dts/ti/k3-am654-base-board.dts
new file mode 100644 (file)
index 0000000..af6956f
--- /dev/null
@@ -0,0 +1,36 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2016-2018 Texas Instruments Incorporated - http://www.ti.com/
+ */
+
+/dts-v1/;
+
+#include "k3-am654.dtsi"
+
+/ {
+       compatible =  "ti,am654-evm", "ti,am654";
+       model = "Texas Instruments AM654 Base Board";
+
+       chosen {
+               stdout-path = "serial2:115200n8";
+               bootargs = "earlycon=ns16550a,mmio32,0x02800000";
+       };
+
+       memory@80000000 {
+               device_type = "memory";
+               /* 4G RAM */
+               reg = <0x00000000 0x80000000 0x00000000 0x80000000>,
+                     <0x00000008 0x80000000 0x00000000 0x80000000>;
+       };
+
+       reserved-memory {
+               #address-cells = <2>;
+               #size-cells = <2>;
+               ranges;
+               secure_ddr: secure_ddr@9e800000 {
+                       reg = <0 0x9e800000 0 0x01800000>; /* for OP-TEE */
+                       alignment = <0x1000>;
+                       no-map;
+               };
+       };
+};
diff --git a/arch/arm64/boot/dts/ti/k3-am654.dtsi b/arch/arm64/boot/dts/ti/k3-am654.dtsi
new file mode 100644 (file)
index 0000000..2affa6f
--- /dev/null
@@ -0,0 +1,115 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Device Tree Source for AM6 SoC family in Quad core configuration
+ *
+ * Copyright (C) 2016-2018 Texas Instruments Incorporated - http://www.ti.com/
+ */
+
+#include "k3-am65.dtsi"
+
+/ {
+       cpus {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               cpu-map {
+                       cluster0: cluster0 {
+                               core0 {
+                                       cpu = <&cpu0>;
+                               };
+
+                               core1 {
+                                       cpu = <&cpu1>;
+                               };
+                       };
+
+                       cluster1: cluster1 {
+                               core0 {
+                                       cpu = <&cpu2>;
+                               };
+
+                               core1 {
+                                       cpu = <&cpu3>;
+                               };
+                       };
+               };
+
+               cpu0: cpu@0 {
+                       compatible = "arm,cortex-a53", "arm,armv8";
+                       reg = <0x000>;
+                       device_type = "cpu";
+                       enable-method = "psci";
+                       i-cache-size = <0x8000>;
+                       i-cache-line-size = <64>;
+                       i-cache-sets = <256>;
+                       d-cache-size = <0x8000>;
+                       d-cache-line-size = <64>;
+                       d-cache-sets = <128>;
+                       next-level-cache = <&L2_0>;
+               };
+
+               cpu1: cpu@1 {
+                       compatible = "arm,cortex-a53", "arm,armv8";
+                       reg = <0x001>;
+                       device_type = "cpu";
+                       enable-method = "psci";
+                       i-cache-size = <0x8000>;
+                       i-cache-line-size = <64>;
+                       i-cache-sets = <256>;
+                       d-cache-size = <0x8000>;
+                       d-cache-line-size = <64>;
+                       d-cache-sets = <128>;
+                       next-level-cache = <&L2_0>;
+               };
+
+               cpu2: cpu@100 {
+                       compatible = "arm,cortex-a53", "arm,armv8";
+                       reg = <0x100>;
+                       device_type = "cpu";
+                       enable-method = "psci";
+                       i-cache-size = <0x8000>;
+                       i-cache-line-size = <64>;
+                       i-cache-sets = <256>;
+                       d-cache-size = <0x8000>;
+                       d-cache-line-size = <64>;
+                       d-cache-sets = <128>;
+                       next-level-cache = <&L2_1>;
+               };
+
+               cpu3: cpu@101 {
+                       compatible = "arm,cortex-a53", "arm,armv8";
+                       reg = <0x101>;
+                       device_type = "cpu";
+                       enable-method = "psci";
+                       i-cache-size = <0x8000>;
+                       i-cache-line-size = <64>;
+                       i-cache-sets = <256>;
+                       d-cache-size = <0x8000>;
+                       d-cache-line-size = <64>;
+                       d-cache-sets = <128>;
+                       next-level-cache = <&L2_1>;
+               };
+       };
+
+       L2_0: l2-cache0 {
+               compatible = "cache";
+               cache-level = <2>;
+               cache-size = <0x80000>;
+               cache-line-size = <64>;
+               cache-sets = <512>;
+               next-level-cache = <&msmc_l3>;
+       };
+
+       L2_1: l2-cache1 {
+               compatible = "cache";
+               cache-level = <2>;
+               cache-size = <0x80000>;
+               cache-line-size = <64>;
+               cache-sets = <512>;
+               next-level-cache = <&msmc_l3>;
+       };
+
+       msmc_l3: l3-cache0 {
+               compatible = "cache";
+               cache-level = <3>;
+       };
+};
index c2a0c00..60f5443 100644 (file)
@@ -1,5 +1,5 @@
 # SPDX-License-Identifier: GPL-2.0
-dtb-$(CONFIG_ARCH_ZYNQMP) += zynqmp-ep108.dtb
+dtb-$(CONFIG_ARCH_ZYNQMP) += avnet-ultra96-rev1.dtb
 dtb-$(CONFIG_ARCH_ZYNQMP) += zynqmp-zc1232-revA.dtb
 dtb-$(CONFIG_ARCH_ZYNQMP) += zynqmp-zc1254-revA.dtb
 dtb-$(CONFIG_ARCH_ZYNQMP) += zynqmp-zc1275-revA.dtb
diff --git a/arch/arm64/boot/dts/xilinx/avnet-ultra96-rev1.dts b/arch/arm64/boot/dts/xilinx/avnet-ultra96-rev1.dts
new file mode 100644 (file)
index 0000000..88aa06f
--- /dev/null
@@ -0,0 +1,19 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * dts file for Avnet Ultra96 rev1
+ *
+ * (C) Copyright 2018, Xilinx, Inc.
+ *
+ * Michal Simek <michal.simek@xilinx.com>
+ */
+
+/dts-v1/;
+
+#include "zynqmp-zcu100-revC.dts"
+
+/ {
+       model = "Avnet Ultra96 Rev1";
+       compatible = "avnet,ultra96-rev1", "avnet,ultra96",
+                    "xlnx,zynqmp-zcu100-revC", "xlnx,zynqmp-zcu100",
+                    "xlnx,zynqmp";
+};
diff --git a/arch/arm64/boot/dts/xilinx/zynqmp-ep108-clk.dtsi b/arch/arm64/boot/dts/xilinx/zynqmp-ep108-clk.dtsi
deleted file mode 100644 (file)
index 9f5eedb..0000000
+++ /dev/null
@@ -1,137 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * clock specification for Xilinx ZynqMP ep108 development board
- *
- * (C) Copyright 2015, Xilinx, Inc.
- *
- * Michal Simek <michal.simek@xilinx.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- */
-
-/ {
-       misc_clk: misc_clk {
-               compatible = "fixed-clock";
-               #clock-cells = <0>;
-               clock-frequency = <25000000>;
-       };
-
-       i2c_clk: i2c_clk {
-               compatible = "fixed-clock";
-               #clock-cells = <0x0>;
-               clock-frequency = <111111111>;
-       };
-
-       sata_clk: sata_clk {
-               compatible = "fixed-clock";
-               #clock-cells = <0>;
-               clock-frequency = <75000000>;
-       };
-
-       clk100: clk100 {
-               compatible = "fixed-clock";
-               #clock-cells = <0>;
-               clock-frequency = <100000000>;
-       };
-
-       clk600: clk600 {
-               compatible = "fixed-clock";
-               #clock-cells = <0>;
-               clock-frequency = <600000000>;
-       };
-};
-
-&can0 {
-       clocks = <&misc_clk &misc_clk>;
-};
-
-&can1 {
-       clocks = <&misc_clk &misc_clk>;
-};
-
-&fpd_dma_chan1 {
-       clocks = <&clk600>, <&clk100>;
-};
-
-&fpd_dma_chan2 {
-       clocks = <&clk600>, <&clk100>;
-};
-
-&fpd_dma_chan3 {
-       clocks = <&clk600>, <&clk100>;
-};
-
-&fpd_dma_chan4 {
-       clocks = <&clk600>, <&clk100>;
-};
-
-&fpd_dma_chan5 {
-       clocks = <&clk600>, <&clk100>;
-};
-
-&fpd_dma_chan6 {
-       clocks = <&clk600>, <&clk100>;
-};
-
-&fpd_dma_chan7 {
-       clocks = <&clk600>, <&clk100>;
-};
-
-&fpd_dma_chan8 {
-       clocks = <&clk600>, <&clk100>;
-};
-
-&gem0 {
-       clocks = <&misc_clk>, <&misc_clk>, <&misc_clk>;
-};
-
-&gpio {
-       clocks = <&misc_clk>;
-};
-
-&i2c0 {
-       clocks = <&i2c_clk>;
-};
-
-&i2c1 {
-       clocks = <&i2c_clk>;
-};
-
-&sata {
-       clocks = <&sata_clk>;
-};
-
-&sdhci0 {
-       clocks = <&misc_clk>, <&misc_clk>;
-};
-
-&sdhci1 {
-       clocks = <&misc_clk>, <&misc_clk>;
-};
-
-&spi0 {
-       clocks = <&misc_clk &misc_clk>;
-};
-
-&spi1 {
-       clocks = <&misc_clk &misc_clk>;
-};
-
-&uart0 {
-       clocks = <&misc_clk &misc_clk>;
-};
-
-&usb0 {
-       clocks = <&misc_clk>, <&misc_clk>;
-};
-
-&usb1 {
-       clocks = <&misc_clk>, <&misc_clk>;
-};
-
-&watchdog0 {
-       clocks= <&misc_clk>;
-};
diff --git a/arch/arm64/boot/dts/xilinx/zynqmp-ep108.dts b/arch/arm64/boot/dts/xilinx/zynqmp-ep108.dts
deleted file mode 100644 (file)
index 4b06849..0000000
+++ /dev/null
@@ -1,154 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * dts file for Xilinx ZynqMP ep108 development board
- *
- * (C) Copyright 2014 - 2015, Xilinx, Inc.
- *
- * Michal Simek <michal.simek@xilinx.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- */
-
-/dts-v1/;
-
-#include "zynqmp.dtsi"
-#include "zynqmp-ep108-clk.dtsi"
-
-/ {
-       model = "ZynqMP EP108";
-
-       aliases {
-               mmc0 = &sdhci0;
-               mmc1 = &sdhci1;
-               serial0 = &uart0;
-       };
-
-       chosen {
-               stdout-path = "serial0:115200n8";
-       };
-
-       memory@0 {
-               device_type = "memory";
-               reg = <0x0 0x0 0x0 0x40000000>;
-       };
-};
-
-&can0 {
-       status = "okay";
-};
-
-&can1 {
-       status = "okay";
-};
-
-&gem0 {
-       status = "okay";
-       phy-handle = <&phy0>;
-       phy-mode = "rgmii-id";
-       phy0: phy@0 {
-               reg = <0>;
-               max-speed = <100>;
-       };
-};
-
-&gpio {
-       status = "okay";
-};
-
-&i2c0 {
-       status = "okay";
-       clock-frequency = <400000>;
-       eeprom@54 {
-               compatible = "atmel,24c64";
-               reg = <0x54>;
-       };
-};
-
-&i2c1 {
-       status = "okay";
-       clock-frequency = <400000>;
-       eeprom@55 {
-               compatible = "atmel,24c64";
-               reg = <0x55>;
-       };
-};
-
-&sata {
-       status = "okay";
-       ceva,broken-gen2;
-       /* SATA Phy OOB timing settings */
-       ceva,p0-cominit-params = /bits/ 8 <0x0F 0x25 0x18 0x29>;
-       ceva,p0-comwake-params = /bits/ 8 <0x04 0x0B 0x08 0x0F>;
-       ceva,p0-burst-params = /bits/ 8 <0x0A 0x08 0x4A 0x06>;
-       ceva,p0-retry-params = /bits/ 16 <0x0216 0x7F06>;
-       ceva,p1-cominit-params = /bits/ 8 <0x0F 0x25 0x18 0x29>;
-       ceva,p1-comwake-params = /bits/ 8 <0x04 0x0B 0x08 0x0F>;
-       ceva,p1-burst-params = /bits/ 8 <0x0A 0x08 0x4A 0x06>;
-       ceva,p1-retry-params = /bits/ 16 <0x0216 0x7F06>;
-};
-
-&sdhci0 {
-       status = "okay";
-       bus-width = <8>;
-};
-
-&sdhci1 {
-       status = "okay";
-};
-
-&spi0 {
-       status = "okay";
-       num-cs = <1>;
-       spi0_flash0: spi0_flash0@0 {
-               compatible = "m25p80";
-               #address-cells = <1>;
-               #size-cells = <1>;
-               spi-max-frequency = <50000000>;
-               reg = <0>;
-
-               spi0_flash0@0 {
-                       label = "spi0_flash0";
-                       reg = <0x0 0x100000>;
-               };
-       };
-};
-
-&spi1 {
-       status = "okay";
-       num-cs = <1>;
-       spi1_flash0: spi1_flash0@0 {
-               compatible = "m25p80";
-               #address-cells = <1>;
-               #size-cells = <1>;
-               spi-max-frequency = <50000000>;
-               reg = <0>;
-
-               spi1_flash0@0 {
-                       label = "spi1_flash0";
-                       reg = <0x0 0x100000>;
-               };
-       };
-};
-
-&uart0 {
-       status = "okay";
-};
-
-&usb0 {
-       status = "okay";
-       dr_mode = "peripheral";
-       maximum-speed = "high-speed";
-};
-
-&usb1 {
-       status = "okay";
-       dr_mode = "host";
-       maximum-speed = "high-speed";
-};
-
-&watchdog0 {
-       status = "okay";
-};
index 3e862a9..eb5e8bd 100644 (file)
@@ -44,8 +44,6 @@
 
        gpio-keys {
                compatible = "gpio-keys";
-               #address-cells = <1>;
-               #size-cells = <0>;
                autorepeat;
                sw4 {
                        label = "sw4";
                        gpios = <&gpio 25 GPIO_ACTIVE_HIGH>;
                        default-state = "on";
                };
-
-               bt_power {
-                       label = "bt_power";
-                       gpios = <&gpio 8 GPIO_ACTIVE_HIGH>;
-                       default-state = "on";
-               };
        };
 
        wmmcsdio_fixed: fixedregulator-mmcsdio {
 
 &uart0 {
        status = "okay";
+       bluetooth {
+               compatible = "ti,wl1831-st";
+               enable-gpios = <&gpio 8 GPIO_ACTIVE_HIGH>;
+       };
 };
 
 &uart1 {
index 5b4ffe6..25dd574 100644 (file)
@@ -41,8 +41,6 @@
 
        gpio-keys {
                compatible = "gpio-keys";
-               #address-cells = <1>;
-               #size-cells = <0>;
                autorepeat;
                sw19 {
                        label = "sw19";
index 668f7f2..259f21b 100644 (file)
@@ -41,8 +41,6 @@
 
        gpio-keys {
                compatible = "gpio-keys";
-               #address-cells = <1>;
-               #size-cells = <0>;
                autorepeat;
                sw19 {
                        label = "sw19";
index 9a9dd6a..a61b3cc 100644 (file)
@@ -41,8 +41,6 @@
 
        gpio-keys {
                compatible = "gpio-keys";
-               #address-cells = <1>;
-               #size-cells = <0>;
                autorepeat;
                sw19 {
                        label = "sw19";
index a091e6f..29ce234 100644 (file)
@@ -58,7 +58,7 @@
                };
 
                idle-states {
-                       entry-method = "arm,psci";
+                       entry-method = "psci";
 
                        CPU_SLEEP_0: cpu-sleep-0 {
                                compatible = "arm,idle-state";
index 2c07e23..f67e8d5 100644 (file)
@@ -179,6 +179,7 @@ CONFIG_MTD_M25P80=y
 CONFIG_MTD_NAND=y
 CONFIG_MTD_NAND_DENALI_DT=y
 CONFIG_MTD_NAND_MARVELL=y
+CONFIG_MTD_NAND_QCOM=y
 CONFIG_MTD_SPI_NOR=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_NBD=m
@@ -295,6 +296,8 @@ CONFIG_SERIAL_XILINX_PS_UART_CONSOLE=y
 CONFIG_SERIAL_MVEBU_UART=y
 CONFIG_SERIAL_DEV_BUS=y
 CONFIG_VIRTIO_CONSOLE=y
+CONFIG_TCG_TPM=y
+CONFIG_TCG_TIS_I2C_INFINEON=y
 CONFIG_I2C_CHARDEV=y
 CONFIG_I2C_MUX=y
 CONFIG_I2C_MUX_PCA954x=y
@@ -349,10 +352,12 @@ CONFIG_POWER_RESET_MSM=y
 CONFIG_POWER_RESET_XGENE=y
 CONFIG_POWER_RESET_SYSCON=y
 CONFIG_SYSCON_REBOOT_MODE=y
+CONFIG_BATTERY_SBS=m
 CONFIG_BATTERY_BQ27XXX=y
 CONFIG_SENSORS_ARM_SCPI=y
 CONFIG_SENSORS_LM90=m
 CONFIG_SENSORS_INA2XX=m
+CONFIG_SENSORS_RASPBERRYPI_HWMON=m
 CONFIG_THERMAL_GOV_POWER_ALLOCATOR=y
 CONFIG_CPU_THERMAL=y
 CONFIG_THERMAL_EMULATION=y
@@ -365,16 +370,18 @@ CONFIG_TEGRA_BPMP_THERMAL=m
 CONFIG_QCOM_TSENS=y
 CONFIG_UNIPHIER_THERMAL=y
 CONFIG_WATCHDOG=y
+CONFIG_ARM_SP805_WATCHDOG=y
 CONFIG_S3C2410_WATCHDOG=y
 CONFIG_MESON_GXBB_WATCHDOG=m
 CONFIG_MESON_WATCHDOG=m
 CONFIG_RENESAS_WDT=y
 CONFIG_UNIPHIER_WATCHDOG=y
 CONFIG_BCM2835_WDT=y
+CONFIG_MFD_BD9571MWV=y
 CONFIG_MFD_AXP20X_RSB=y
 CONFIG_MFD_CROS_EC=y
-CONFIG_MFD_CROS_EC_I2C=y
-CONFIG_MFD_CROS_EC_SPI=y
+CONFIG_CROS_EC_I2C=y
+CONFIG_CROS_EC_SPI=y
 CONFIG_MFD_CROS_EC_CHARDEV=m
 CONFIG_MFD_EXYNOS_LPASS=m
 CONFIG_MFD_HI6421_PMIC=y
@@ -385,6 +392,7 @@ CONFIG_MFD_RK808=y
 CONFIG_MFD_SEC_CORE=y
 CONFIG_REGULATOR_FIXED_VOLTAGE=y
 CONFIG_REGULATOR_AXP20X=y
+CONFIG_REGULATOR_BD9571MWV=y
 CONFIG_REGULATOR_FAN53555=y
 CONFIG_REGULATOR_GPIO=y
 CONFIG_REGULATOR_HI6421V530=y
@@ -395,6 +403,7 @@ CONFIG_REGULATOR_QCOM_SMD_RPM=y
 CONFIG_REGULATOR_QCOM_SPMI=y
 CONFIG_REGULATOR_RK808=y
 CONFIG_REGULATOR_S2MPS11=y
+CONFIG_REGULATOR_VCTRL=m
 CONFIG_RC_CORE=m
 CONFIG_RC_DECODERS=y
 CONFIG_RC_DEVICES=y
@@ -407,6 +416,8 @@ CONFIG_MEDIA_CONTROLLER=y
 CONFIG_VIDEO_V4L2_SUBDEV_API=y
 # CONFIG_DVB_NET is not set
 CONFIG_V4L_MEM2MEM_DRIVERS=y
+CONFIG_MEDIA_USB_SUPPORT=y
+CONFIG_USB_VIDEO_CLASS=m
 CONFIG_VIDEO_SAMSUNG_S5P_JPEG=m
 CONFIG_VIDEO_SAMSUNG_S5P_MFC=m
 CONFIG_VIDEO_SAMSUNG_EXYNOS_GSC=m
@@ -448,9 +459,20 @@ CONFIG_SOUND=y
 CONFIG_SND=y
 CONFIG_SND_SOC=y
 CONFIG_SND_BCM2835_SOC_I2S=m
+CONFIG_SND_SOC_ROCKCHIP=m
+CONFIG_SND_SOC_ROCKCHIP_I2S=m
+CONFIG_SND_SOC_ROCKCHIP_SPDIF=m
+CONFIG_SND_SOC_ROCKCHIP_RT5645=m
+CONFIG_SND_SOC_RK3399_GRU_SOUND=m
 CONFIG_SND_SOC_SAMSUNG=y
 CONFIG_SND_SOC_RCAR=m
 CONFIG_SND_SOC_AK4613=m
+CONFIG_SND_SOC_DA7219=m
+CONFIG_SND_SOC_MAX98357A=m
+CONFIG_SND_SOC_RL6231=m
+CONFIG_SND_SOC_RT5514=m
+CONFIG_SND_SOC_RT5514_SPI=m
+CONFIG_SND_SOC_RT5645=m
 CONFIG_SND_SIMPLE_CARD=m
 CONFIG_SND_AUDIO_GRAPH_CARD=m
 CONFIG_I2C_HID=m
@@ -617,6 +639,7 @@ CONFIG_PHY_ROCKCHIP_INNO_USB2=y
 CONFIG_PHY_ROCKCHIP_PCIE=m
 CONFIG_PHY_ROCKCHIP_TYPEC=y
 CONFIG_PHY_TEGRA_XUSB=y
+CONFIG_HISI_PMU=y
 CONFIG_QCOM_L2_PMU=y
 CONFIG_QCOM_L3_PMU=y
 CONFIG_QCOM_QFPROM=y
index be3bf3d..ae1f704 100644 (file)
@@ -50,7 +50,8 @@
 #define ARM64_HW_DBM                           29
 #define ARM64_SSBD                             30
 #define ARM64_MISMATCHED_CACHE_TYPE            31
+#define ARM64_HAS_STAGE2_FWB                   32
 
-#define ARM64_NCAPS                            32
+#define ARM64_NCAPS                            33
 
 #endif /* __ASM_CPUCAPS_H */
index 6dd285e..aa45df7 100644 (file)
@@ -23,6 +23,7 @@
 #include <asm/types.h>
 
 /* Hyp Configuration Register (HCR) bits */
+#define HCR_FWB                (UL(1) << 46)
 #define HCR_TEA                (UL(1) << 37)
 #define HCR_TERR       (UL(1) << 36)
 #define HCR_TLOR       (UL(1) << 35)
index 0c97e45..6106a85 100644 (file)
@@ -63,6 +63,8 @@ static inline void vcpu_reset_hcr(struct kvm_vcpu *vcpu)
                /* trap error record accesses */
                vcpu->arch.hcr_el2 |= HCR_TERR;
        }
+       if (cpus_have_const_cap(ARM64_HAS_STAGE2_FWB))
+               vcpu->arch.hcr_el2 |= HCR_FWB;
 
        if (test_bit(KVM_ARM_VCPU_EL1_32BIT, vcpu->arch.features))
                vcpu->arch.hcr_el2 &= ~HCR_RW;
@@ -81,6 +83,21 @@ static inline unsigned long *vcpu_hcr(struct kvm_vcpu *vcpu)
        return (unsigned long *)&vcpu->arch.hcr_el2;
 }
 
+static inline void vcpu_clear_wfe_traps(struct kvm_vcpu *vcpu)
+{
+       vcpu->arch.hcr_el2 &= ~HCR_TWE;
+}
+
+static inline void vcpu_set_wfe_traps(struct kvm_vcpu *vcpu)
+{
+       vcpu->arch.hcr_el2 |= HCR_TWE;
+}
+
+static inline unsigned long vcpu_get_vsesr(struct kvm_vcpu *vcpu)
+{
+       return vcpu->arch.vsesr_el2;
+}
+
 static inline void vcpu_set_vsesr(struct kvm_vcpu *vcpu, u64 vsesr)
 {
        vcpu->arch.vsesr_el2 = vsesr;
index fe8777b..f26055f 100644 (file)
@@ -350,6 +350,11 @@ unsigned long kvm_arm_num_regs(struct kvm_vcpu *vcpu);
 int kvm_arm_copy_reg_indices(struct kvm_vcpu *vcpu, u64 __user *indices);
 int kvm_arm_get_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg);
 int kvm_arm_set_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg);
+int __kvm_arm_vcpu_get_events(struct kvm_vcpu *vcpu,
+                             struct kvm_vcpu_events *events);
+
+int __kvm_arm_vcpu_set_events(struct kvm_vcpu *vcpu,
+                             struct kvm_vcpu_events *events);
 
 #define KVM_ARCH_WANT_MMU_NOTIFIER
 int kvm_unmap_hva(struct kvm *kvm, unsigned long hva);
@@ -378,16 +383,23 @@ void handle_exit_early(struct kvm_vcpu *vcpu, struct kvm_run *run,
 int kvm_perf_init(void);
 int kvm_perf_teardown(void);
 
+void kvm_set_sei_esr(struct kvm_vcpu *vcpu, u64 syndrome);
+
 struct kvm_vcpu *kvm_mpidr_to_vcpu(struct kvm *kvm, unsigned long mpidr);
 
-void __kvm_set_tpidr_el2(u64 tpidr_el2);
 DECLARE_PER_CPU(kvm_cpu_context_t, kvm_host_cpu_state);
 
 static inline void __cpu_init_hyp_mode(phys_addr_t pgd_ptr,
                                       unsigned long hyp_stack_ptr,
                                       unsigned long vector_ptr)
 {
-       u64 tpidr_el2;
+       /*
+        * Calculate the raw per-cpu offset without a translation from the
+        * kernel's mapping to the linear mapping, and store it in tpidr_el2
+        * so that we can use adr_l to access per-cpu variables in EL2.
+        */
+       u64 tpidr_el2 = ((u64)this_cpu_ptr(&kvm_host_cpu_state) -
+                        (u64)kvm_ksym_ref(kvm_host_cpu_state));
 
        /*
         * Call initialization code, and switch to the full blown HYP code.
@@ -396,17 +408,7 @@ static inline void __cpu_init_hyp_mode(phys_addr_t pgd_ptr,
         * cpus_have_const_cap() wrapper.
         */
        BUG_ON(!static_branch_likely(&arm64_const_caps_ready));
-       __kvm_call_hyp((void *)pgd_ptr, hyp_stack_ptr, vector_ptr);
-
-       /*
-        * Calculate the raw per-cpu offset without a translation from the
-        * kernel's mapping to the linear mapping, and store it in tpidr_el2
-        * so that we can use adr_l to access per-cpu variables in EL2.
-        */
-       tpidr_el2 = (u64)this_cpu_ptr(&kvm_host_cpu_state)
-               - (u64)kvm_ksym_ref(kvm_host_cpu_state);
-
-       kvm_call_hyp(__kvm_set_tpidr_el2, tpidr_el2);
+       __kvm_call_hyp((void *)pgd_ptr, hyp_stack_ptr, vector_ptr, tpidr_el2);
 }
 
 static inline bool kvm_arch_check_sve_has_vhe(void)
index fb9a712..d6fff7d 100644 (file)
@@ -169,8 +169,12 @@ phys_addr_t kvm_get_idmap_vector(void);
 int kvm_mmu_init(void);
 void kvm_clear_hyp_idmap(void);
 
-#define        kvm_set_pte(ptep, pte)          set_pte(ptep, pte)
-#define        kvm_set_pmd(pmdp, pmd)          set_pmd(pmdp, pmd)
+#define kvm_mk_pmd(ptep)                                       \
+       __pmd(__phys_to_pmd_val(__pa(ptep)) | PMD_TYPE_TABLE)
+#define kvm_mk_pud(pmdp)                                       \
+       __pud(__phys_to_pud_val(__pa(pmdp)) | PMD_TYPE_TABLE)
+#define kvm_mk_pgd(pudp)                                       \
+       __pgd(__phys_to_pgd_val(__pa(pudp)) | PUD_TYPE_TABLE)
 
 static inline pte_t kvm_s2pte_mkwrite(pte_t pte)
 {
@@ -267,6 +271,15 @@ static inline void __clean_dcache_guest_page(kvm_pfn_t pfn, unsigned long size)
 {
        void *va = page_address(pfn_to_page(pfn));
 
+       /*
+        * With FWB, we ensure that the guest always accesses memory using
+        * cacheable attributes, and we don't have to clean to PoC when
+        * faulting in pages. Furthermore, FWB implies IDC, so cleaning to
+        * PoU is not required either in this case.
+        */
+       if (cpus_have_const_cap(ARM64_HAS_STAGE2_FWB))
+               return;
+
        kvm_flush_dcache_to_poc(va, size);
 }
 
@@ -287,20 +300,26 @@ static inline void __invalidate_icache_guest_page(kvm_pfn_t pfn,
 
 static inline void __kvm_flush_dcache_pte(pte_t pte)
 {
-       struct page *page = pte_page(pte);
-       kvm_flush_dcache_to_poc(page_address(page), PAGE_SIZE);
+       if (!cpus_have_const_cap(ARM64_HAS_STAGE2_FWB)) {
+               struct page *page = pte_page(pte);
+               kvm_flush_dcache_to_poc(page_address(page), PAGE_SIZE);
+       }
 }
 
 static inline void __kvm_flush_dcache_pmd(pmd_t pmd)
 {
-       struct page *page = pmd_page(pmd);
-       kvm_flush_dcache_to_poc(page_address(page), PMD_SIZE);
+       if (!cpus_have_const_cap(ARM64_HAS_STAGE2_FWB)) {
+               struct page *page = pmd_page(pmd);
+               kvm_flush_dcache_to_poc(page_address(page), PMD_SIZE);
+       }
 }
 
 static inline void __kvm_flush_dcache_pud(pud_t pud)
 {
-       struct page *page = pud_page(pud);
-       kvm_flush_dcache_to_poc(page_address(page), PUD_SIZE);
+       if (!cpus_have_const_cap(ARM64_HAS_STAGE2_FWB)) {
+               struct page *page = pud_page(pud);
+               kvm_flush_dcache_to_poc(page_address(page), PUD_SIZE);
+       }
 }
 
 #define kvm_virt_to_phys(x)            __pa_symbol(x)
index 49d9921..b964429 100644 (file)
 #define MT_S2_NORMAL           0xf
 #define MT_S2_DEVICE_nGnRE     0x1
 
+/*
+ * Memory types for Stage-2 translation when ID_AA64MMFR2_EL1.FWB is 0001
+ * Stage-2 enforces Normal-WB and Device-nGnRE
+ */
+#define MT_S2_FWB_NORMAL       6
+#define MT_S2_FWB_DEVICE_nGnRE 1
+
 #ifdef CONFIG_ARM64_4K_PAGES
 #define IOREMAP_MAX_ORDER      (PUD_SHIFT)
 #else
index 108ecad..78b942c 100644 (file)
 #define PAGE_HYP_RO            __pgprot(_HYP_PAGE_DEFAULT | PTE_HYP | PTE_RDONLY | PTE_HYP_XN)
 #define PAGE_HYP_DEVICE                __pgprot(PROT_DEVICE_nGnRE | PTE_HYP)
 
-#define PAGE_S2                        __pgprot(_PROT_DEFAULT | PTE_S2_MEMATTR(MT_S2_NORMAL) | PTE_S2_RDONLY | PTE_S2_XN)
-#define PAGE_S2_DEVICE         __pgprot(_PROT_DEFAULT | PTE_S2_MEMATTR(MT_S2_DEVICE_nGnRE) | PTE_S2_RDONLY | PTE_S2_XN)
+#define PAGE_S2_MEMATTR(attr)                                          \
+       ({                                                              \
+               u64 __val;                                              \
+               if (cpus_have_const_cap(ARM64_HAS_STAGE2_FWB))          \
+                       __val = PTE_S2_MEMATTR(MT_S2_FWB_ ## attr);     \
+               else                                                    \
+                       __val = PTE_S2_MEMATTR(MT_S2_ ## attr);         \
+               __val;                                                  \
+        })
+
+#define PAGE_S2_XN                                                     \
+       ({                                                              \
+               u64 __val;                                              \
+               if (cpus_have_const_cap(ARM64_HAS_CACHE_DIC))           \
+                       __val = 0;                                      \
+               else                                                    \
+                       __val = PTE_S2_XN;                              \
+               __val;                                                  \
+       })
+
+#define PAGE_S2                        __pgprot(_PROT_DEFAULT | PAGE_S2_MEMATTR(NORMAL) | PTE_S2_RDONLY | PAGE_S2_XN)
+#define PAGE_S2_DEVICE         __pgprot(_PROT_DEFAULT | PAGE_S2_MEMATTR(DEVICE_nGnRE) | PTE_S2_RDONLY | PAGE_S2_XN)
 
 #define PAGE_NONE              __pgprot(((_PAGE_DEFAULT) & ~PTE_VALID) | PTE_PROT_NONE | PTE_RDONLY | PTE_NG | PTE_PXN | PTE_UXN)
 #define PAGE_SHARED            __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_UXN | PTE_WRITE)
index e205ec8..c147093 100644 (file)
 #define SYS_ICC_DIR_EL1                        sys_reg(3, 0, 12, 11, 1)
 #define SYS_ICC_RPR_EL1                        sys_reg(3, 0, 12, 11, 3)
 #define SYS_ICC_SGI1R_EL1              sys_reg(3, 0, 12, 11, 5)
+#define SYS_ICC_ASGI1R_EL1             sys_reg(3, 0, 12, 11, 6)
+#define SYS_ICC_SGI0R_EL1              sys_reg(3, 0, 12, 11, 7)
 #define SYS_ICC_IAR1_EL1               sys_reg(3, 0, 12, 12, 0)
 #define SYS_ICC_EOIR1_EL1              sys_reg(3, 0, 12, 12, 1)
 #define SYS_ICC_HPPIR1_EL1             sys_reg(3, 0, 12, 12, 2)
 #define ID_AA64MMFR1_VMIDBITS_16       2
 
 /* id_aa64mmfr2 */
+#define ID_AA64MMFR2_FWB_SHIFT         40
 #define ID_AA64MMFR2_AT_SHIFT          32
 #define ID_AA64MMFR2_LVA_SHIFT         16
 #define ID_AA64MMFR2_IESB_SHIFT                12
index 0ad1cf2..a323316 100644 (file)
@@ -33,6 +33,8 @@ static inline void __tlb_remove_table(void *_table)
 #define tlb_remove_entry(tlb, entry)   tlb_remove_page(tlb, entry)
 #endif /* CONFIG_HAVE_RCU_TABLE_FREE */
 
+static void tlb_flush(struct mmu_gather *tlb);
+
 #include <asm-generic/tlb.h>
 
 static inline void tlb_flush(struct mmu_gather *tlb)
index 4e76630..97c3478 100644 (file)
@@ -39,6 +39,7 @@
 #define __KVM_HAVE_GUEST_DEBUG
 #define __KVM_HAVE_IRQ_LINE
 #define __KVM_HAVE_READONLY_MEM
+#define __KVM_HAVE_VCPU_EVENTS
 
 #define KVM_COALESCED_MMIO_PAGE_OFFSET 1
 
@@ -154,6 +155,18 @@ struct kvm_sync_regs {
 struct kvm_arch_memory_slot {
 };
 
+/* for KVM_GET/SET_VCPU_EVENTS */
+struct kvm_vcpu_events {
+       struct {
+               __u8 serror_pending;
+               __u8 serror_has_esr;
+               /* Align it to 8 bytes */
+               __u8 pad[6];
+               __u64 serror_esr;
+       } exception;
+       __u32 reserved[12];
+};
+
 /* If you need to interpret the index values, here is the key: */
 #define KVM_REG_ARM_COPROC_MASK                0x000000000FFF0000
 #define KVM_REG_ARM_COPROC_SHIFT       16
index 611e892..e238b79 100644 (file)
@@ -192,6 +192,7 @@ static const struct arm64_ftr_bits ftr_id_aa64mmfr1[] = {
 };
 
 static const struct arm64_ftr_bits ftr_id_aa64mmfr2[] = {
+       ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR2_FWB_SHIFT, 4, 0),
        ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR2_AT_SHIFT, 4, 0),
        ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR2_LVA_SHIFT, 4, 0),
        ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR2_IESB_SHIFT, 4, 0),
@@ -1026,6 +1027,14 @@ static void cpu_copy_el2regs(const struct arm64_cpu_capabilities *__unused)
 }
 #endif
 
+static void cpu_has_fwb(const struct arm64_cpu_capabilities *__unused)
+{
+       u64 val = read_sysreg_s(SYS_CLIDR_EL1);
+
+       /* Check that CLIDR_EL1.LOU{U,IS} are both 0 */
+       WARN_ON(val & (7 << 27 | 7 << 21));
+}
+
 static const struct arm64_cpu_capabilities arm64_features[] = {
        {
                .desc = "GIC system register CPU interface",
@@ -1182,6 +1191,17 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
                .type = ARM64_CPUCAP_SYSTEM_FEATURE,
                .matches = has_cache_dic,
        },
+       {
+               .desc = "Stage-2 Force Write-Back",
+               .type = ARM64_CPUCAP_SYSTEM_FEATURE,
+               .capability = ARM64_HAS_STAGE2_FWB,
+               .sys_reg = SYS_ID_AA64MMFR2_EL1,
+               .sign = FTR_UNSIGNED,
+               .field_pos = ID_AA64MMFR2_FWB_SHIFT,
+               .min_field_value = 1,
+               .matches = has_cpuid_feature,
+               .cpu_enable = cpu_has_fwb,
+       },
 #ifdef CONFIG_ARM64_HW_AFDBM
        {
                /*
index cdd4d9d..07256b0 100644 (file)
@@ -289,6 +289,39 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
        return -EINVAL;
 }
 
+int __kvm_arm_vcpu_get_events(struct kvm_vcpu *vcpu,
+                             struct kvm_vcpu_events *events)
+{
+       events->exception.serror_pending = !!(vcpu->arch.hcr_el2 & HCR_VSE);
+       events->exception.serror_has_esr = cpus_have_const_cap(ARM64_HAS_RAS_EXTN);
+
+       if (events->exception.serror_pending && events->exception.serror_has_esr)
+               events->exception.serror_esr = vcpu_get_vsesr(vcpu);
+
+       return 0;
+}
+
+int __kvm_arm_vcpu_set_events(struct kvm_vcpu *vcpu,
+                             struct kvm_vcpu_events *events)
+{
+       bool serror_pending = events->exception.serror_pending;
+       bool has_esr = events->exception.serror_has_esr;
+
+       if (serror_pending && has_esr) {
+               if (!cpus_have_const_cap(ARM64_HAS_RAS_EXTN))
+                       return -EINVAL;
+
+               if (!((events->exception.serror_esr) & ~ESR_ELx_ISS_MASK))
+                       kvm_set_sei_esr(vcpu, events->exception.serror_esr);
+               else
+                       return -EINVAL;
+       } else if (serror_pending) {
+               kvm_inject_vabt(vcpu);
+       }
+
+       return 0;
+}
+
 int __attribute_const__ kvm_target_cpu(void)
 {
        unsigned long implementor = read_cpuid_implementor();
index 6fd91b3..ea92251 100644 (file)
@@ -57,6 +57,7 @@ __invalid:
         * x0: HYP pgd
         * x1: HYP stack
         * x2: HYP vectors
+        * x3: per-CPU offset
         */
 __do_hyp_init:
        /* Check for a stub HVC call */
@@ -119,9 +120,8 @@ CPU_BE(     orr     x4, x4, #SCTLR_ELx_EE)
        mov     sp, x1
        msr     vbar_el2, x2
 
-       /* copy tpidr_el1 into tpidr_el2 for use by HYP */
-       mrs     x1, tpidr_el1
-       msr     tpidr_el2, x1
+       /* Set tpidr_el2 for use by HYP */
+       msr     tpidr_el2, x3
 
        /* Hello, World! */
        eret
index 35bc168..9ce2239 100644 (file)
@@ -288,8 +288,3 @@ void kvm_vcpu_put_sysregs(struct kvm_vcpu *vcpu)
 
        vcpu->arch.sysregs_loaded_on_cpu = false;
 }
-
-void __hyp_text __kvm_set_tpidr_el2(u64 tpidr_el2)
-{
-       asm("msr tpidr_el2, %0": : "r" (tpidr_el2));
-}
index d8e7165..a55e91d 100644 (file)
@@ -164,9 +164,9 @@ void kvm_inject_undefined(struct kvm_vcpu *vcpu)
                inject_undef64(vcpu);
 }
 
-static void pend_guest_serror(struct kvm_vcpu *vcpu, u64 esr)
+void kvm_set_sei_esr(struct kvm_vcpu *vcpu, u64 esr)
 {
-       vcpu_set_vsesr(vcpu, esr);
+       vcpu_set_vsesr(vcpu, esr & ESR_ELx_ISS_MASK);
        *vcpu_hcr(vcpu) |= HCR_VSE;
 }
 
@@ -184,5 +184,5 @@ static void pend_guest_serror(struct kvm_vcpu *vcpu, u64 esr)
  */
 void kvm_inject_vabt(struct kvm_vcpu *vcpu)
 {
-       pend_guest_serror(vcpu, ESR_ELx_ISV);
+       kvm_set_sei_esr(vcpu, ESR_ELx_ISV);
 }
index 4e4aeda..e37c78b 100644 (file)
@@ -77,8 +77,12 @@ int kvm_arch_dev_ioctl_check_extension(struct kvm *kvm, long ext)
        case KVM_CAP_ARM_PMU_V3:
                r = kvm_arm_support_pmu_v3();
                break;
+       case KVM_CAP_ARM_INJECT_SERROR_ESR:
+               r = cpus_have_const_cap(ARM64_HAS_RAS_EXTN);
+               break;
        case KVM_CAP_SET_GUEST_DEBUG:
        case KVM_CAP_VCPU_ATTRIBUTES:
+       case KVM_CAP_VCPU_EVENTS:
                r = 1;
                break;
        default:
index a436373..22fbbdb 100644 (file)
@@ -194,7 +194,16 @@ static bool access_dcsw(struct kvm_vcpu *vcpu,
        if (!p->is_write)
                return read_from_write_only(vcpu, p, r);
 
-       kvm_set_way_flush(vcpu);
+       /*
+        * Only track S/W ops if we don't have FWB. It still indicates
+        * that the guest is a bit broken (S/W operations should only
+        * be done by firmware, knowing that there is only a single
+        * CPU left in the system, and certainly not from non-secure
+        * software).
+        */
+       if (!cpus_have_const_cap(ARM64_HAS_STAGE2_FWB))
+               kvm_set_way_flush(vcpu);
+
        return true;
 }
 
@@ -243,10 +252,43 @@ static bool access_gic_sgi(struct kvm_vcpu *vcpu,
                           struct sys_reg_params *p,
                           const struct sys_reg_desc *r)
 {
+       bool g1;
+
        if (!p->is_write)
                return read_from_write_only(vcpu, p, r);
 
-       vgic_v3_dispatch_sgi(vcpu, p->regval);
+       /*
+        * In a system where GICD_CTLR.DS=1, a ICC_SGI0R_EL1 access generates
+        * Group0 SGIs only, while ICC_SGI1R_EL1 can generate either group,
+        * depending on the SGI configuration. ICC_ASGI1R_EL1 is effectively
+        * equivalent to ICC_SGI0R_EL1, as there is no "alternative" secure
+        * group.
+        */
+       if (p->is_aarch32) {
+               switch (p->Op1) {
+               default:                /* Keep GCC quiet */
+               case 0:                 /* ICC_SGI1R */
+                       g1 = true;
+                       break;
+               case 1:                 /* ICC_ASGI1R */
+               case 2:                 /* ICC_SGI0R */
+                       g1 = false;
+                       break;
+               }
+       } else {
+               switch (p->Op2) {
+               default:                /* Keep GCC quiet */
+               case 5:                 /* ICC_SGI1R_EL1 */
+                       g1 = true;
+                       break;
+               case 6:                 /* ICC_ASGI1R_EL1 */
+               case 7:                 /* ICC_SGI0R_EL1 */
+                       g1 = false;
+                       break;
+               }
+       }
+
+       vgic_v3_dispatch_sgi(vcpu, p->regval, g1);
 
        return true;
 }
@@ -1303,6 +1345,8 @@ static const struct sys_reg_desc sys_reg_descs[] = {
        { SYS_DESC(SYS_ICC_DIR_EL1), read_from_write_only },
        { SYS_DESC(SYS_ICC_RPR_EL1), write_to_read_only },
        { SYS_DESC(SYS_ICC_SGI1R_EL1), access_gic_sgi },
+       { SYS_DESC(SYS_ICC_ASGI1R_EL1), access_gic_sgi },
+       { SYS_DESC(SYS_ICC_SGI0R_EL1), access_gic_sgi },
        { SYS_DESC(SYS_ICC_IAR1_EL1), write_to_read_only },
        { SYS_DESC(SYS_ICC_EOIR1_EL1), read_from_write_only },
        { SYS_DESC(SYS_ICC_HPPIR1_EL1), write_to_read_only },
@@ -1613,8 +1657,6 @@ static const struct sys_reg_desc cp14_64_regs[] = {
  * register).
  */
 static const struct sys_reg_desc cp15_regs[] = {
-       { Op1( 0), CRn( 0), CRm(12), Op2( 0), access_gic_sgi },
-
        { Op1( 0), CRn( 1), CRm( 0), Op2( 0), access_vm_reg, NULL, c1_SCTLR },
        { Op1( 0), CRn( 2), CRm( 0), Op2( 0), access_vm_reg, NULL, c2_TTBR0 },
        { Op1( 0), CRn( 2), CRm( 0), Op2( 1), access_vm_reg, NULL, c2_TTBR1 },
@@ -1737,8 +1779,10 @@ static const struct sys_reg_desc cp15_regs[] = {
 static const struct sys_reg_desc cp15_64_regs[] = {
        { Op1( 0), CRn( 0), CRm( 2), Op2( 0), access_vm_reg, NULL, c2_TTBR0 },
        { Op1( 0), CRn( 0), CRm( 9), Op2( 0), access_pmu_evcntr },
-       { Op1( 0), CRn( 0), CRm(12), Op2( 0), access_gic_sgi },
+       { Op1( 0), CRn( 0), CRm(12), Op2( 0), access_gic_sgi }, /* ICC_SGI1R */
        { Op1( 1), CRn( 0), CRm( 2), Op2( 0), access_vm_reg, NULL, c2_TTBR1 },
+       { Op1( 1), CRn( 0), CRm(12), Op2( 0), access_gic_sgi }, /* ICC_ASGI1R */
+       { Op1( 2), CRn( 0), CRm(12), Op2( 0), access_gic_sgi }, /* ICC_SGI0R */
        { Op1( 2), CRn( 0), CRm(14), Op2( 0), access_cntp_cval },
 };
 
index 6ab942e..3fe8a94 100644 (file)
@@ -23,8 +23,7 @@ ifdef CONFIG_CPU_BIG_ENDIAN
 KBUILD_CFLAGS   += -mbig-endian
 KBUILD_AFLAGS   += -mbig-endian
 LINKFLAGS       += -mbig-endian
-KBUILD_LDFLAGS  += -mbig-endian
-LDFLAGS += -EB
+KBUILD_LDFLAGS  += -mbig-endian -EB
 CHECKFLAGS     += -D_BIG_ENDIAN
 endif
 
index 5e89d40..0b334b6 100644 (file)
@@ -16,6 +16,7 @@ config H8300
        select OF_IRQ
        select OF_EARLY_FLATTREE
        select HAVE_MEMBLOCK
+       select NO_BOOTMEM
        select TIMER_OF
        select H8300_TMR8
        select HAVE_KERNEL_GZIP
index e1c02ca..58634e6 100644 (file)
@@ -8,6 +8,8 @@
 # (C) Copyright 2002-2015 Yoshinori Sato <ysato@users.sourceforge.jp>
 #
 
+KBUILD_DEFCONFIG := edosk2674_defconfig
+
 cflags-$(CONFIG_CPU_H8300H)    := -mh
 aflags-$(CONFIG_CPU_H8300H)    := -mh -Wa,--mach=h8300h
 ldflags-$(CONFIG_CPU_H8300H)   := -mh8300helf_linux
@@ -20,7 +22,9 @@ KBUILD_CFLAGS += -mint32 -fno-builtin
 KBUILD_CFLAGS += -D__linux__
 KBUILD_CFLAGS += -DUTS_SYSNAME=\"uClinux\"
 KBUILD_AFLAGS += $(aflags-y)
-LDFLAGS += $(ldflags-y)
+KBUILD_LDFLAGS += $(ldflags-y)
+
+CHECKFLAGS += -msize-long
 
 ifeq ($(CROSS_COMPILE),)
 CROSS_COMPILE := h8300-unknown-linux-
index f1c31ce..595398b 100644 (file)
@@ -73,7 +73,7 @@
        timer16: timer@ffff68 {
                compatible = "renesas,16bit-timer";
                reg = <0xffff68 8>, <0xffff60 8>;
-               interrupts = <24 0>;
+               interrupts = <26 0>;
                renesas,channel = <0>;
                clocks = <&fclk>;
                clock-names = "fck";
index ea0cb0c..647a83b 100644 (file)
@@ -29,11 +29,11 @@ static inline unsigned long ffz(unsigned long word)
 
        result = -1;
        __asm__("1:\n\t"
-               "shlr.l %2\n\t"
+               "shlr.l %1\n\t"
                "adds #1,%0\n\t"
                "bcs 1b"
-               : "=r"(result)
-               : "0"(result), "r"(word));
+               : "=r"(result),"=r"(word)
+               : "0"(result), "1"(word));
        return result;
 }
 
@@ -66,7 +66,7 @@ H8300_GEN_BITOP(change_bit, "bnot")
 
 #undef H8300_GEN_BITOP
 
-static inline int test_bit(int nr, const unsigned long *addr)
+static inline int test_bit(int nr, const volatile unsigned long *addr)
 {
        int ret = 0;
        unsigned char *b_addr;
@@ -162,11 +162,11 @@ static inline unsigned long __ffs(unsigned long word)
 
        result = -1;
        __asm__("1:\n\t"
-               "shlr.l %2\n\t"
+               "shlr.l %1\n\t"
                "adds #1,%0\n\t"
                "bcc 1b"
-               : "=r" (result)
-               : "0"(result), "r"(word));
+               : "=r" (result),"=r"(word)
+               : "0"(result), "1"(word));
        return result;
 }
 
index 313cafa..66d3838 100644 (file)
@@ -4,6 +4,8 @@
 
 #include <uapi/asm/ptrace.h>
 
+struct task_struct;
+
 #ifndef __ASSEMBLY__
 #ifndef PS_S
 #define PS_S  (0x10)
index 602e478..1a1d30c 100644 (file)
@@ -129,7 +129,7 @@ void kgdb_arch_exit(void)
        /* Nothing to do */
 }
 
-const struct kgdb_arch arch_kgdb_ops = {
+struct kgdb_arch arch_kgdb_ops = {
        /* Breakpoint instruction: trapa #2 */
        .gdb_bpt_instr = { 0x57, 0x20 },
 };
index a4d0470..34e2df5 100644 (file)
@@ -23,7 +23,6 @@
 #include <linux/init.h>
 #include <linux/of.h>
 #include <linux/of_fdt.h>
-#include <linux/of_platform.h>
 #include <linux/of_address.h>
 #include <linux/clk-provider.h>
 #include <linux/memblock.h>
@@ -71,10 +70,6 @@ void __init h8300_fdt_init(void *fdt, char *bootargs)
 
 static void __init bootmem_init(void)
 {
-       int bootmap_size;
-       unsigned long ram_start_pfn;
-       unsigned long free_ram_start_pfn;
-       unsigned long ram_end_pfn;
        struct memblock_region *region;
 
        memory_end = memory_start = 0;
@@ -88,33 +83,17 @@ static void __init bootmem_init(void)
        if (!memory_end)
                panic("No memory!");
 
-       ram_start_pfn = PFN_UP(memory_start);
-       /* free_ram_start_pfn is first page after kernel */
-       free_ram_start_pfn = PFN_UP(__pa(_end));
-       ram_end_pfn = PFN_DOWN(memblock_end_of_DRAM());
+       /* setup bootmem globals (we use no_bootmem, but mm still depends on this) */
+       min_low_pfn = PFN_UP(memory_start);
+       max_low_pfn = PFN_DOWN(memblock_end_of_DRAM());
+       max_pfn = max_low_pfn;
 
-       max_pfn = ram_end_pfn;
+       memblock_reserve(__pa(_stext), _end - _stext);
 
-       /*
-        * give all the memory to the bootmap allocator,  tell it to put the
-        * boot mem_map at the start of memory
-        */
-       bootmap_size = init_bootmem_node(NODE_DATA(0),
-                                        free_ram_start_pfn,
-                                        0,
-                                        ram_end_pfn);
-       /*
-        * free the usable memory,  we have to make sure we do not free
-        * the bootmem bitmap so we then reserve it after freeing it :-)
-        */
-       free_bootmem(PFN_PHYS(free_ram_start_pfn),
-                    (ram_end_pfn - free_ram_start_pfn) << PAGE_SHIFT);
-       reserve_bootmem(PFN_PHYS(free_ram_start_pfn), bootmap_size,
-                       BOOTMEM_DEFAULT);
+       early_init_fdt_reserve_self();
+       early_init_fdt_scan_reserved_mem();
 
-       for_each_memblock(reserved, region) {
-               reserve_bootmem(region->base, region->size, BOOTMEM_DEFAULT);
-       }
+       memblock_dump_all();
 }
 
 void __init setup_arch(char **cmdline_p)
@@ -188,15 +167,6 @@ const struct seq_operations cpuinfo_op = {
        .show   = show_cpuinfo,
 };
 
-static int __init device_probe(void)
-{
-       of_platform_populate(NULL, NULL, NULL, NULL);
-
-       return 0;
-}
-
-device_initcall(device_probe);
-
 #if defined(CONFIG_CPU_H8300H)
 #define get_wait(base, addr) ({                \
        int baddr;                      \
index 46138f5..03aa35b 100644 (file)
 
 static void sim_write(struct console *con, const char *s, unsigned n)
 {
-       register const int fd __asm__("er0") = 1; /* stdout */
        register const char *_ptr __asm__("er1") = s;
        register const unsigned _len __asm__("er2") = n;
 
-       __asm__(".byte 0x5e,0x00,0x00,0xc7\n\t" /* jsr @0xc7 (sys_write) */
-               : : "g"(fd), "g"(_ptr), "g"(_len));
+       __asm__("sub.l er0,er0\n\t"             /* er0 = 1 (stdout) */
+               "inc.l #1,er0\n\t"
+               ".byte 0x5e,0x00,0x00,0xc7\n\t" /* jsr @0xc7 (sys_write) */
+               : : "g"(_ptr), "g"(_len):"er0");
 }
 
 static int __init sim_setup(struct earlycon_device *device, const char *opt)
index 2efaa18..4c5858b 100644 (file)
@@ -22,9 +22,7 @@ ldflags-y += $(call cc-option,-mv${CONFIG_HEXAGON_ARCH_VERSION})
 
 KBUILD_CFLAGS += $(cflags-y)
 KBUILD_AFLAGS += $(aflags-y)
-
-#  no KBUILD_LDFLAGS?
-LDFLAGS += $(ldflags-y)
+KBUILD_LDFLAGS += $(ldflags-y)
 
 # Thread-info register will be r19.  This value is not configureable;
 # it is hard-coded in several files.
index 2bf4ef7..8b4a0c1 100644 (file)
@@ -28,6 +28,7 @@ config IA64
        select HAVE_ARCH_TRACEHOOK
        select HAVE_MEMBLOCK
        select HAVE_MEMBLOCK_NODE_MAP
+       select NO_BOOTMEM
        select HAVE_VIRT_CPU_ACCOUNTING
        select ARCH_HAS_DMA_MARK_CLEAN
        select ARCH_HAS_SG_CHAIN
index ee5b652..671ce1e 100644 (file)
@@ -1805,7 +1805,7 @@ static struct ioc_iommu ioc_iommu_info[] __initdata = {
        { SX2000_IOC_ID, "sx2000", NULL },
 };
 
-static void ioc_init(unsigned long hpa, struct ioc *ioc)
+static void __init ioc_init(unsigned long hpa, struct ioc *ioc)
 {
        struct ioc_iommu *info;
 
@@ -2002,7 +2002,7 @@ sba_map_ioc_to_node(struct ioc *ioc, acpi_handle handle)
 #endif
 }
 
-static void acpi_sba_ioc_add(struct ioc *ioc)
+static void __init acpi_sba_ioc_add(struct ioc *ioc)
 {
        acpi_handle handle = ioc->handle;
        acpi_status status;
index 6f95217..1e6fef6 100644 (file)
@@ -454,6 +454,7 @@ extern void memset_io(volatile void __iomem *s, int c, long n);
 #define xlate_dev_kmem_ptr xlate_dev_kmem_ptr
 #define xlate_dev_mem_ptr xlate_dev_mem_ptr
 #include <asm-generic/io.h>
+#undef PCI_IOBASE
 
 # endif /* __KERNEL__ */
 
index f4db216..00e8e2a 100644 (file)
@@ -50,8 +50,7 @@ void foo(void)
 
        DEFINE(IA64_TASK_BLOCKED_OFFSET,offsetof (struct task_struct, blocked));
        DEFINE(IA64_TASK_CLEAR_CHILD_TID_OFFSET,offsetof (struct task_struct, clear_child_tid));
-       DEFINE(IA64_TASK_GROUP_LEADER_OFFSET, offsetof (struct task_struct, group_leader));
-       DEFINE(IA64_TASK_TGIDLINK_OFFSET, offsetof (struct task_struct, pids[PIDTYPE_PID].pid));
+       DEFINE(IA64_TASK_THREAD_PID_OFFSET,offsetof (struct task_struct, thread_pid));
        DEFINE(IA64_PID_LEVEL_OFFSET, offsetof (struct pid, level));
        DEFINE(IA64_PID_UPID_OFFSET, offsetof (struct pid, numbers[0]));
        DEFINE(IA64_TASK_PENDING_OFFSET,offsetof (struct task_struct, pending));
@@ -68,6 +67,7 @@ void foo(void)
        DEFINE(IA64_SIGNAL_GROUP_STOP_COUNT_OFFSET,offsetof (struct signal_struct,
                                                             group_stop_count));
        DEFINE(IA64_SIGNAL_SHARED_PENDING_OFFSET,offsetof (struct signal_struct, shared_pending));
+       DEFINE(IA64_SIGNAL_PIDS_TGID_OFFSET, offsetof (struct signal_struct, pids[PIDTYPE_TGID]));
 
        BLANK();
 
index fe742ff..d80c99a 100644 (file)
@@ -62,16 +62,16 @@ ENTRY(fsys_getpid)
        .prologue
        .altrp b6
        .body
-       add r17=IA64_TASK_GROUP_LEADER_OFFSET,r16
+       add r17=IA64_TASK_SIGNAL_OFFSET,r16
        ;;
-       ld8 r17=[r17]                           // r17 = current->group_leader
+       ld8 r17=[r17]                           // r17 = current->signal
        add r9=TI_FLAGS+IA64_TASK_SIZE,r16
        ;;
        ld4 r9=[r9]
-       add r17=IA64_TASK_TGIDLINK_OFFSET,r17
+       add r17=IA64_SIGNAL_PIDS_TGID_OFFSET,r17
        ;;
        and r9=TIF_ALLWORK_MASK,r9
-       ld8 r17=[r17]                           // r17 = current->group_leader->pids[PIDTYPE_PID].pid
+       ld8 r17=[r17]                           // r17 = current->signal->pids[PIDTYPE_TGID]
        ;;
        add r8=IA64_PID_LEVEL_OFFSET,r17
        ;;
@@ -96,11 +96,11 @@ ENTRY(fsys_set_tid_address)
        .altrp b6
        .body
        add r9=TI_FLAGS+IA64_TASK_SIZE,r16
-       add r17=IA64_TASK_TGIDLINK_OFFSET,r16
+       add r17=IA64_TASK_THREAD_PID_OFFSET,r16
        ;;
        ld4 r9=[r9]
        tnat.z p6,p7=r32                // check argument register for being NaT
-       ld8 r17=[r17]                           // r17 = current->pids[PIDTYPE_PID].pid
+       ld8 r17=[r17]                           // r17 = current->thread_pid
        ;;
        and r9=TIF_ALLWORK_MASK,r9
        add r8=IA64_PID_LEVEL_OFFSET,r17
index ad43cbf..0e6c2d9 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/delay.h>
 #include <linux/cpu.h>
 #include <linux/kernel.h>
+#include <linux/memblock.h>
 #include <linux/reboot.h>
 #include <linux/sched/mm.h>
 #include <linux/sched/clock.h>
@@ -383,8 +384,16 @@ reserve_memory (void)
 
        sort_regions(rsvd_region, num_rsvd_regions);
        num_rsvd_regions = merge_regions(rsvd_region, num_rsvd_regions);
-}
 
+       /* reserve all regions except the end of memory marker with memblock */
+       for (n = 0; n < num_rsvd_regions - 1; n++) {
+               struct rsvd_region *region = &rsvd_region[n];
+               phys_addr_t addr = __pa(region->start);
+               phys_addr_t size = region->end - region->start;
+
+               memblock_reserve(addr, size);
+       }
+}
 
 /**
  * find_initrd - get initrd parameters from the boot parameter structure
index 7d64b30..e2e40bb 100644 (file)
@@ -34,53 +34,6 @@ static unsigned long max_gap;
 /* physical address where the bootmem map is located */
 unsigned long bootmap_start;
 
-/**
- * find_bootmap_location - callback to find a memory area for the bootmap
- * @start: start of region
- * @end: end of region
- * @arg: unused callback data
- *
- * Find a place to put the bootmap and return its starting address in
- * bootmap_start.  This address must be page-aligned.
- */
-static int __init
-find_bootmap_location (u64 start, u64 end, void *arg)
-{
-       u64 needed = *(unsigned long *)arg;
-       u64 range_start, range_end, free_start;
-       int i;
-
-#if IGNORE_PFN0
-       if (start == PAGE_OFFSET) {
-               start += PAGE_SIZE;
-               if (start >= end)
-                       return 0;
-       }
-#endif
-
-       free_start = PAGE_OFFSET;
-
-       for (i = 0; i < num_rsvd_regions; i++) {
-               range_start = max(start, free_start);
-               range_end   = min(end, rsvd_region[i].start & PAGE_MASK);
-
-               free_start = PAGE_ALIGN(rsvd_region[i].end);
-
-               if (range_end <= range_start)
-                       continue; /* skip over empty range */
-
-               if (range_end - range_start >= needed) {
-                       bootmap_start = __pa(range_start);
-                       return -1;      /* done */
-               }
-
-               /* nothing more available in this segment */
-               if (range_end == end)
-                       return 0;
-       }
-       return 0;
-}
-
 #ifdef CONFIG_SMP
 static void *cpu_data;
 /**
@@ -196,8 +149,6 @@ setup_per_cpu_areas(void)
 void __init
 find_memory (void)
 {
-       unsigned long bootmap_size;
-
        reserve_memory();
 
        /* first find highest page frame number */
@@ -205,21 +156,12 @@ find_memory (void)
        max_low_pfn = 0;
        efi_memmap_walk(find_max_min_low_pfn, NULL);
        max_pfn = max_low_pfn;
-       /* how many bytes to cover all the pages */
-       bootmap_size = bootmem_bootmap_pages(max_pfn) << PAGE_SHIFT;
-
-       /* look for a location to hold the bootmap */
-       bootmap_start = ~0UL;
-       efi_memmap_walk(find_bootmap_location, &bootmap_size);
-       if (bootmap_start == ~0UL)
-               panic("Cannot find %ld bytes for bootmap\n", bootmap_size);
 
-       bootmap_size = init_bootmem_node(NODE_DATA(0),
-                       (bootmap_start >> PAGE_SHIFT), 0, max_pfn);
-
-       /* Free all available memory, then mark bootmem-map as being in use. */
-       efi_memmap_walk(filter_rsvd_memory, free_bootmem);
-       reserve_bootmem(bootmap_start, bootmap_size, BOOTMEM_DEFAULT);
+#ifdef CONFIG_VIRTUAL_MEM_MAP
+       efi_memmap_walk(filter_memory, register_active_ranges);
+#else
+       memblock_add_node(0, PFN_PHYS(max_low_pfn), 0);
+#endif
 
        find_initrd();
 
@@ -244,11 +186,9 @@ paging_init (void)
        max_zone_pfns[ZONE_NORMAL] = max_low_pfn;
 
 #ifdef CONFIG_VIRTUAL_MEM_MAP
-       efi_memmap_walk(filter_memory, register_active_ranges);
        efi_memmap_walk(find_largest_hole, (u64 *)&max_gap);
        if (max_gap < LARGE_GAP) {
                vmem_map = (struct page *) 0;
-               free_area_init_nodes(max_zone_pfns);
        } else {
                unsigned long map_size;
 
@@ -266,13 +206,10 @@ paging_init (void)
                 */
                NODE_DATA(0)->node_mem_map = vmem_map +
                        find_min_pfn_with_active_regions();
-               free_area_init_nodes(max_zone_pfns);
 
                printk("Virtual mem_map starts at 0x%p\n", mem_map);
        }
-#else /* !CONFIG_VIRTUAL_MEM_MAP */
-       memblock_add_node(0, PFN_PHYS(max_low_pfn), 0);
-       free_area_init_nodes(max_zone_pfns);
 #endif /* !CONFIG_VIRTUAL_MEM_MAP */
+       free_area_init_nodes(max_zone_pfns);
        zero_page_memmap_ptr = virt_to_page(ia64_imva(empty_zero_page));
 }
index 7d9bd20..1928d57 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/nmi.h>
 #include <linux/swap.h>
 #include <linux/bootmem.h>
+#include <linux/memblock.h>
 #include <linux/acpi.h>
 #include <linux/efi.h>
 #include <linux/nodemask.h>
@@ -38,9 +39,6 @@ struct early_node_data {
        struct ia64_node_data *node_data;
        unsigned long pernode_addr;
        unsigned long pernode_size;
-#ifdef CONFIG_ZONE_DMA32
-       unsigned long num_dma_physpages;
-#endif
        unsigned long min_pfn;
        unsigned long max_pfn;
 };
@@ -60,33 +58,31 @@ pg_data_t *pgdat_list[MAX_NUMNODES];
             (((node)*PERCPU_PAGE_SIZE) & (MAX_NODE_ALIGN_OFFSET - 1)))
 
 /**
- * build_node_maps - callback to setup bootmem structs for each node
+ * build_node_maps - callback to setup mem_data structs for each node
  * @start: physical start of range
  * @len: length of range
  * @node: node where this range resides
  *
- * We allocate a struct bootmem_data for each piece of memory that we wish to
+ * Detect extents of each piece of memory that we wish to
  * treat as a virtually contiguous block (i.e. each node). Each such block
  * must start on an %IA64_GRANULE_SIZE boundary, so we round the address down
  * if necessary.  Any non-existent pages will simply be part of the virtual
- * memmap.  We also update min_low_pfn and max_low_pfn here as we receive
- * memory ranges from the caller.
+ * memmap.
  */
 static int __init build_node_maps(unsigned long start, unsigned long len,
                                  int node)
 {
        unsigned long spfn, epfn, end = start + len;
-       struct bootmem_data *bdp = &bootmem_node_data[node];
 
        epfn = GRANULEROUNDUP(end) >> PAGE_SHIFT;
        spfn = GRANULEROUNDDOWN(start) >> PAGE_SHIFT;
 
-       if (!bdp->node_low_pfn) {
-               bdp->node_min_pfn = spfn;
-               bdp->node_low_pfn = epfn;
+       if (!mem_data[node].min_pfn) {
+               mem_data[node].min_pfn = spfn;
+               mem_data[node].max_pfn = epfn;
        } else {
-               bdp->node_min_pfn = min(spfn, bdp->node_min_pfn);
-               bdp->node_low_pfn = max(epfn, bdp->node_low_pfn);
+               mem_data[node].min_pfn = min(spfn, mem_data[node].min_pfn);
+               mem_data[node].max_pfn = max(epfn, mem_data[node].max_pfn);
        }
 
        return 0;
@@ -269,7 +265,6 @@ static void __init fill_pernode(int node, unsigned long pernode,
 {
        void *cpu_data;
        int cpus = early_nr_cpus_node(node);
-       struct bootmem_data *bdp = &bootmem_node_data[node];
 
        mem_data[node].pernode_addr = pernode;
        mem_data[node].pernode_size = pernodesize;
@@ -284,8 +279,6 @@ static void __init fill_pernode(int node, unsigned long pernode,
 
        mem_data[node].node_data = __va(pernode);
        pernode += L1_CACHE_ALIGN(sizeof(struct ia64_node_data));
-
-       pgdat_list[node]->bdata = bdp;
        pernode += L1_CACHE_ALIGN(sizeof(pg_data_t));
 
        cpu_data = per_cpu_node_setup(cpu_data, node);
@@ -325,20 +318,16 @@ static int __init find_pernode_space(unsigned long start, unsigned long len,
                                     int node)
 {
        unsigned long spfn, epfn;
-       unsigned long pernodesize = 0, pernode, pages, mapsize;
-       struct bootmem_data *bdp = &bootmem_node_data[node];
+       unsigned long pernodesize = 0, pernode;
 
        spfn = start >> PAGE_SHIFT;
        epfn = (start + len) >> PAGE_SHIFT;
 
-       pages = bdp->node_low_pfn - bdp->node_min_pfn;
-       mapsize = bootmem_bootmap_pages(pages) << PAGE_SHIFT;
-
        /*
         * Make sure this memory falls within this node's usable memory
         * since we may have thrown some away in build_maps().
         */
-       if (spfn < bdp->node_min_pfn || epfn > bdp->node_low_pfn)
+       if (spfn < mem_data[node].min_pfn || epfn > mem_data[node].max_pfn)
                return 0;
 
        /* Don't setup this node's local space twice... */
@@ -353,32 +342,13 @@ static int __init find_pernode_space(unsigned long start, unsigned long len,
        pernode = NODEDATA_ALIGN(start, node);
 
        /* Is this range big enough for what we want to store here? */
-       if (start + len > (pernode + pernodesize + mapsize))
+       if (start + len > (pernode + pernodesize))
                fill_pernode(node, pernode, pernodesize);
 
        return 0;
 }
 
 /**
- * free_node_bootmem - free bootmem allocator memory for use
- * @start: physical start of range
- * @len: length of range
- * @node: node where this range resides
- *
- * Simply calls the bootmem allocator to free the specified ranged from
- * the given pg_data_t's bdata struct.  After this function has been called
- * for all the entries in the EFI memory map, the bootmem allocator will
- * be ready to service allocation requests.
- */
-static int __init free_node_bootmem(unsigned long start, unsigned long len,
-                                   int node)
-{
-       free_bootmem_node(pgdat_list[node], start, len);
-
-       return 0;
-}
-
-/**
  * reserve_pernode_space - reserve memory for per-node space
  *
  * Reserve the space used by the bootmem maps & per-node space in the boot
@@ -387,28 +357,17 @@ static int __init free_node_bootmem(unsigned long start, unsigned long len,
  */
 static void __init reserve_pernode_space(void)
 {
-       unsigned long base, size, pages;
-       struct bootmem_data *bdp;
+       unsigned long base, size;
        int node;
 
        for_each_online_node(node) {
-               pg_data_t *pdp = pgdat_list[node];
-
                if (node_isset(node, memory_less_mask))
                        continue;
 
-               bdp = pdp->bdata;
-
-               /* First the bootmem_map itself */
-               pages = bdp->node_low_pfn - bdp->node_min_pfn;
-               size = bootmem_bootmap_pages(pages) << PAGE_SHIFT;
-               base = __pa(bdp->node_bootmem_map);
-               reserve_bootmem_node(pdp, base, size, BOOTMEM_DEFAULT);
-
                /* Now the per-node space */
                size = mem_data[node].pernode_size;
                base = __pa(mem_data[node].pernode_addr);
-               reserve_bootmem_node(pdp, base, size, BOOTMEM_DEFAULT);
+               memblock_reserve(base, size);
        }
 }
 
@@ -528,6 +487,7 @@ void __init find_memory(void)
        int node;
 
        reserve_memory();
+       efi_memmap_walk(filter_memory, register_active_ranges);
 
        if (num_online_nodes() == 0) {
                printk(KERN_ERR "node info missing!\n");
@@ -544,38 +504,8 @@ void __init find_memory(void)
        efi_memmap_walk(find_max_min_low_pfn, NULL);
 
        for_each_online_node(node)
-               if (bootmem_node_data[node].node_low_pfn) {
+               if (mem_data[node].min_pfn)
                        node_clear(node, memory_less_mask);
-                       mem_data[node].min_pfn = ~0UL;
-               }
-
-       efi_memmap_walk(filter_memory, register_active_ranges);
-
-       /*
-        * Initialize the boot memory maps in reverse order since that's
-        * what the bootmem allocator expects
-        */
-       for (node = MAX_NUMNODES - 1; node >= 0; node--) {
-               unsigned long pernode, pernodesize, map;
-               struct bootmem_data *bdp;
-
-               if (!node_online(node))
-                       continue;
-               else if (node_isset(node, memory_less_mask))
-                       continue;
-
-               bdp = &bootmem_node_data[node];
-               pernode = mem_data[node].pernode_addr;
-               pernodesize = mem_data[node].pernode_size;
-               map = pernode + pernodesize;
-
-               init_bootmem_node(pgdat_list[node],
-                                 map>>PAGE_SHIFT,
-                                 bdp->node_min_pfn,
-                                 bdp->node_low_pfn);
-       }
-
-       efi_memmap_walk(filter_rsvd_memory, free_node_bootmem);
 
        reserve_pernode_space();
        memory_less_nodes();
@@ -655,36 +585,6 @@ void call_pernode_memory(unsigned long start, unsigned long len, void *arg)
 }
 
 /**
- * count_node_pages - callback to build per-node memory info structures
- * @start: physical start of range
- * @len: length of range
- * @node: node where this range resides
- *
- * Each node has it's own number of physical pages, DMAable pages, start, and
- * end page frame number.  This routine will be called by call_pernode_memory()
- * for each piece of usable memory and will setup these values for each node.
- * Very similar to build_maps().
- */
-static __init int count_node_pages(unsigned long start, unsigned long len, int node)
-{
-       unsigned long end = start + len;
-
-#ifdef CONFIG_ZONE_DMA32
-       if (start <= __pa(MAX_DMA_ADDRESS))
-               mem_data[node].num_dma_physpages +=
-                       (min(end, __pa(MAX_DMA_ADDRESS)) - start) >>PAGE_SHIFT;
-#endif
-       start = GRANULEROUNDDOWN(start);
-       end = GRANULEROUNDUP(end);
-       mem_data[node].max_pfn = max(mem_data[node].max_pfn,
-                                    end >> PAGE_SHIFT);
-       mem_data[node].min_pfn = min(mem_data[node].min_pfn,
-                                    start >> PAGE_SHIFT);
-
-       return 0;
-}
-
-/**
  * paging_init - setup page tables
  *
  * paging_init() sets up the page tables for each node of the system and frees
@@ -700,8 +600,6 @@ void __init paging_init(void)
 
        max_dma = virt_to_phys((void *) MAX_DMA_ADDRESS) >> PAGE_SHIFT;
 
-       efi_memmap_walk(filter_rsvd_memory, count_node_pages);
-
        sparse_memory_present_with_active_regions(MAX_NUMNODES);
        sparse_init();
 
index f0dd9fc..997c9f2 100644 (file)
@@ -69,7 +69,7 @@ KBUILD_CFLAGS += -D__uClinux__
 KBUILD_AFLAGS += -D__uClinux__
 endif
 
-LDFLAGS := -m m68kelf
+KBUILD_LDFLAGS := -m m68kelf
 KBUILD_LDFLAGS_MODULE += -T $(srctree)/arch/m68k/kernel/module.lds
 
 ifdef CONFIG_SUN3
index 849cd20..7bc666e 100644 (file)
@@ -129,4 +129,33 @@ unsigned long clk_get_rate(struct clk *clk)
 }
 EXPORT_SYMBOL(clk_get_rate);
 
+/* dummy functions, should not be called */
+long clk_round_rate(struct clk *clk, unsigned long rate)
+{
+       WARN_ON(clk);
+       return 0;
+}
+EXPORT_SYMBOL(clk_round_rate);
+
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+       WARN_ON(clk);
+       return 0;
+}
+EXPORT_SYMBOL(clk_set_rate);
+
+int clk_set_parent(struct clk *clk, struct clk *parent)
+{
+       WARN_ON(clk);
+       return 0;
+}
+EXPORT_SYMBOL(clk_set_parent);
+
+struct clk *clk_get_parent(struct clk *clk)
+{
+       WARN_ON(clk);
+       return NULL;
+}
+EXPORT_SYMBOL(clk_get_parent);
+
 /***************************************************************************/
index b0978a2..ae20219 100644 (file)
@@ -390,7 +390,7 @@ static __inline__ void set_dma_mode(unsigned int dmanr, char mode)
 
 #ifdef DEBUG_DMA
   printk("%s(%d): dmanr=%d DMR[%x]=%x DIR[%x]=%x\n", __FILE__, __LINE__,
-         dmanr, (int) &dmalp[MCFDMA_DMR], dmabp[MCFDMA_DMR],
+        dmanr, (int) &dmalp[MCFDMA_DMR], dmalp[MCFDMA_DMR],
         (int) &dmawp[MCFDMA_DIR], dmawp[MCFDMA_DIR]);
 #endif
 }
@@ -421,7 +421,7 @@ static __inline__ void set_dma_addr(unsigned int dmanr, unsigned int a)
 
 #ifdef DEBUG_DMA
   printk("%s(%d): dmanr=%d DMR[%x]=%x SAR[%x]=%08x DAR[%x]=%08x\n",
-       __FILE__, __LINE__, dmanr, (int) &dmawp[MCFDMA_DMR], dmawp[MCFDMA_DMR],
+       __FILE__, __LINE__, dmanr, (int) &dmalp[MCFDMA_DMR], dmalp[MCFDMA_DMR],
        (int) &dmalp[MCFDMA_DSAR], dmalp[MCFDMA_DSAR],
        (int) &dmalp[MCFDMA_DDAR], dmalp[MCFDMA_DDAR]);
 #endif
index 6163a39..ace5c5b 100644 (file)
@@ -2,6 +2,8 @@ config MICROBLAZE
        def_bool y
        select ARCH_NO_SWAP
        select ARCH_HAS_GCOV_PROFILE_ALL
+       select ARCH_HAS_SYNC_DMA_FOR_CPU
+       select ARCH_HAS_SYNC_DMA_FOR_DEVICE
        select ARCH_MIGHT_HAVE_PC_PARPORT
        select ARCH_NO_COHERENT_DMA_MMAP if !MMU
        select ARCH_WANT_IPC_PARSE_VERSION
@@ -9,6 +11,8 @@ config MICROBLAZE
        select TIMER_OF
        select CLONE_BACKWARDS3
        select COMMON_CLK
+       select DMA_NONCOHERENT_OPS
+       select DMA_NONCOHERENT_MMAP
        select GENERIC_ATOMIC64
        select GENERIC_CLOCKEVENTS
        select GENERIC_CPU_DEVICES
index d269dd4..4f3ab57 100644 (file)
@@ -40,11 +40,11 @@ CPUFLAGS-$(CONFIG_XILINX_MICROBLAZE0_USE_PCMP_INSTR) += -mxl-pattern-compare
 ifdef CONFIG_CPU_BIG_ENDIAN
 KBUILD_CFLAGS += -mbig-endian
 KBUILD_AFLAGS += -mbig-endian
-LD += -EB
+KBUILD_LDFLAGS += -EB
 else
 KBUILD_CFLAGS += -mlittle-endian
 KBUILD_AFLAGS += -mlittle-endian
-LD += -EL
+KBUILD_LDFLAGS += -EL
 endif
 
 CPUFLAGS-1 += $(call cc-option,-mcpu=v$(CPU_VER))
index fe6a6c6..569ba9e 100644 (file)
@@ -5,6 +5,7 @@ generic-y += bugs.h
 generic-y += compat.h
 generic-y += device.h
 generic-y += div64.h
+generic-y += dma-mapping.h
 generic-y += emergency-restart.h
 generic-y += exec.h
 generic-y += extable.h
diff --git a/arch/microblaze/include/asm/dma-mapping.h b/arch/microblaze/include/asm/dma-mapping.h
deleted file mode 100644 (file)
index add50c1..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Implements the generic device dma API for microblaze and the pci
- *
- * Copyright (C) 2009-2010 Michal Simek <monstr@monstr.eu>
- * Copyright (C) 2009-2010 PetaLogix
- *
- * 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.
- *
- * This file is base on powerpc and x86 dma-mapping.h versions
- * Copyright (C) 2004 IBM
- */
-
-#ifndef _ASM_MICROBLAZE_DMA_MAPPING_H
-#define _ASM_MICROBLAZE_DMA_MAPPING_H
-
-/*
- * Available generic sets of operations
- */
-extern const struct dma_map_ops dma_nommu_ops;
-
-static inline const struct dma_map_ops *get_arch_dma_ops(struct bus_type *bus)
-{
-       return &dma_nommu_ops;
-}
-
-#endif /* _ASM_MICROBLAZE_DMA_MAPPING_H */
index db8b1fa..7b650ab 100644 (file)
@@ -553,11 +553,6 @@ void __init *early_get_page(void);
 
 extern unsigned long ioremap_bot, ioremap_base;
 
-void *consistent_alloc(gfp_t gfp, size_t size, dma_addr_t *dma_handle);
-void consistent_free(size_t size, void *vaddr);
-void consistent_sync(void *vaddr, size_t size, int direction);
-void consistent_sync_page(struct page *page, unsigned long offset,
-       size_t size, int direction);
 unsigned long consistent_virt_to_pfn(void *vaddr);
 
 void setup_memory(void);
index 3145e7d..71032cf 100644 (file)
@@ -8,29 +8,15 @@
  */
 
 #include <linux/device.h>
-#include <linux/dma-mapping.h>
+#include <linux/dma-noncoherent.h>
 #include <linux/gfp.h>
 #include <linux/dma-debug.h>
 #include <linux/export.h>
 #include <linux/bug.h>
 #include <asm/cacheflush.h>
 
-static void *dma_nommu_alloc_coherent(struct device *dev, size_t size,
-                                      dma_addr_t *dma_handle, gfp_t flag,
-                                      unsigned long attrs)
-{
-       return consistent_alloc(flag, size, dma_handle);
-}
-
-static void dma_nommu_free_coherent(struct device *dev, size_t size,
-                                    void *vaddr, dma_addr_t dma_handle,
-                                    unsigned long attrs)
-{
-       consistent_free(size, vaddr);
-}
-
-static inline void __dma_sync(unsigned long paddr,
-                             size_t size, enum dma_data_direction direction)
+static void __dma_sync(struct device *dev, phys_addr_t paddr, size_t size,
+               enum dma_data_direction direction)
 {
        switch (direction) {
        case DMA_TO_DEVICE:
@@ -45,113 +31,21 @@ static inline void __dma_sync(unsigned long paddr,
        }
 }
 
-static int dma_nommu_map_sg(struct device *dev, struct scatterlist *sgl,
-                            int nents, enum dma_data_direction direction,
-                            unsigned long attrs)
+void arch_sync_dma_for_device(struct device *dev, phys_addr_t paddr,
+               size_t size, enum dma_data_direction dir)
 {
-       struct scatterlist *sg;
-       int i;
-
-       /* FIXME this part of code is untested */
-       for_each_sg(sgl, sg, nents, i) {
-               sg->dma_address = sg_phys(sg);
-
-               if (attrs & DMA_ATTR_SKIP_CPU_SYNC)
-                       continue;
-
-               __dma_sync(sg_phys(sg), sg->length, direction);
-       }
-
-       return nents;
-}
-
-static inline dma_addr_t dma_nommu_map_page(struct device *dev,
-                                            struct page *page,
-                                            unsigned long offset,
-                                            size_t size,
-                                            enum dma_data_direction direction,
-                                            unsigned long attrs)
-{
-       if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC))
-               __dma_sync(page_to_phys(page) + offset, size, direction);
-       return page_to_phys(page) + offset;
+       __dma_sync(dev, paddr, size, dir);
 }
 
-static inline void dma_nommu_unmap_page(struct device *dev,
-                                        dma_addr_t dma_address,
-                                        size_t size,
-                                        enum dma_data_direction direction,
-                                        unsigned long attrs)
+void arch_sync_dma_for_cpu(struct device *dev, phys_addr_t paddr,
+               size_t size, enum dma_data_direction dir)
 {
-/* There is not necessary to do cache cleanup
- *
- * phys_to_virt is here because in __dma_sync_page is __virt_to_phys and
- * dma_address is physical address
- */
-       if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC))
-               __dma_sync(dma_address, size, direction);
+       __dma_sync(dev, paddr, size, dir);
 }
 
-static inline void
-dma_nommu_sync_single_for_cpu(struct device *dev,
-                              dma_addr_t dma_handle, size_t size,
-                              enum dma_data_direction direction)
-{
-       /*
-        * It's pointless to flush the cache as the memory segment
-        * is given to the CPU
-        */
-
-       if (direction == DMA_FROM_DEVICE)
-               __dma_sync(dma_handle, size, direction);
-}
-
-static inline void
-dma_nommu_sync_single_for_device(struct device *dev,
-                                 dma_addr_t dma_handle, size_t size,
-                                 enum dma_data_direction direction)
-{
-       /*
-        * It's pointless to invalidate the cache if the device isn't
-        * supposed to write to the relevant region
-        */
-
-       if (direction == DMA_TO_DEVICE)
-               __dma_sync(dma_handle, size, direction);
-}
-
-static inline void
-dma_nommu_sync_sg_for_cpu(struct device *dev,
-                          struct scatterlist *sgl, int nents,
-                          enum dma_data_direction direction)
-{
-       struct scatterlist *sg;
-       int i;
-
-       /* FIXME this part of code is untested */
-       if (direction == DMA_FROM_DEVICE)
-               for_each_sg(sgl, sg, nents, i)
-                       __dma_sync(sg->dma_address, sg->length, direction);
-}
-
-static inline void
-dma_nommu_sync_sg_for_device(struct device *dev,
-                             struct scatterlist *sgl, int nents,
-                             enum dma_data_direction direction)
-{
-       struct scatterlist *sg;
-       int i;
-
-       /* FIXME this part of code is untested */
-       if (direction == DMA_TO_DEVICE)
-               for_each_sg(sgl, sg, nents, i)
-                       __dma_sync(sg->dma_address, sg->length, direction);
-}
-
-static
-int dma_nommu_mmap_coherent(struct device *dev, struct vm_area_struct *vma,
-                            void *cpu_addr, dma_addr_t handle, size_t size,
-                            unsigned long attrs)
+int arch_dma_mmap(struct device *dev, struct vm_area_struct *vma,
+               void *cpu_addr, dma_addr_t handle, size_t size,
+               unsigned long attrs)
 {
 #ifdef CONFIG_MMU
        unsigned long user_count = vma_pages(vma);
@@ -170,17 +64,3 @@ int dma_nommu_mmap_coherent(struct device *dev, struct vm_area_struct *vma,
        return -ENXIO;
 #endif
 }
-
-const struct dma_map_ops dma_nommu_ops = {
-       .alloc                  = dma_nommu_alloc_coherent,
-       .free                   = dma_nommu_free_coherent,
-       .mmap                   = dma_nommu_mmap_coherent,
-       .map_sg                 = dma_nommu_map_sg,
-       .map_page               = dma_nommu_map_page,
-       .unmap_page             = dma_nommu_unmap_page,
-       .sync_single_for_cpu    = dma_nommu_sync_single_for_cpu,
-       .sync_single_for_device = dma_nommu_sync_single_for_device,
-       .sync_sg_for_cpu        = dma_nommu_sync_sg_for_cpu,
-       .sync_sg_for_device     = dma_nommu_sync_sg_for_device,
-};
-EXPORT_SYMBOL(dma_nommu_ops);
index 4655ff3..f264fdc 100644 (file)
@@ -341,11 +341,6 @@ start_here:
        /* Initialize r31 with current task address */
        addik   r31, r0, init_task
 
-       /*
-        * Call platform dependent initialize function.
-        * Please see $(ARCH)/mach-$(SUBARCH)/setup.c for
-        * the function.
-        */
        addik   r11, r0, machine_early_init
        brald   r15, r11
        nop
index b06c3a7..c9a278a 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/pci.h>
 #include <linux/interrupt.h>
 #include <linux/gfp.h>
+#include <linux/dma-noncoherent.h>
 
 #include <asm/pgalloc.h>
 #include <linux/io.h>
@@ -59,7 +60,8 @@
  * uncached region.  This will no doubt cause big problems if memory allocated
  * here is not also freed properly. -- JW
  */
-void *consistent_alloc(gfp_t gfp, size_t size, dma_addr_t *dma_handle)
+void *arch_dma_alloc(struct device *dev, size_t size, dma_addr_t *dma_handle,
+               gfp_t gfp, unsigned long attrs)
 {
        unsigned long order, vaddr;
        void *ret;
@@ -154,7 +156,6 @@ void *consistent_alloc(gfp_t gfp, size_t size, dma_addr_t *dma_handle)
 
        return ret;
 }
-EXPORT_SYMBOL(consistent_alloc);
 
 #ifdef CONFIG_MMU
 static pte_t *consistent_virt_to_pte(void *vaddr)
@@ -178,7 +179,8 @@ unsigned long consistent_virt_to_pfn(void *vaddr)
 /*
  * free page(s) as defined by the above mapping.
  */
-void consistent_free(size_t size, void *vaddr)
+void arch_dma_free(struct device *dev, size_t size, void *vaddr,
+               dma_addr_t dma_addr, unsigned long attrs)
 {
        struct page *page;
 
@@ -218,49 +220,3 @@ void consistent_free(size_t size, void *vaddr)
        flush_tlb_all();
 #endif
 }
-EXPORT_SYMBOL(consistent_free);
-
-/*
- * make an area consistent.
- */
-void consistent_sync(void *vaddr, size_t size, int direction)
-{
-       unsigned long start;
-       unsigned long end;
-
-       start = (unsigned long)vaddr;
-
-       /* Convert start address back down to unshadowed memory region */
-#ifdef CONFIG_XILINX_UNCACHED_SHADOW
-       start &= ~UNCACHED_SHADOW_MASK;
-#endif
-       end = start + size;
-
-       switch (direction) {
-       case PCI_DMA_NONE:
-               BUG();
-       case PCI_DMA_FROMDEVICE:        /* invalidate only */
-               invalidate_dcache_range(start, end);
-               break;
-       case PCI_DMA_TODEVICE:          /* writeback only */
-               flush_dcache_range(start, end);
-               break;
-       case PCI_DMA_BIDIRECTIONAL:     /* writeback and invalidate */
-               flush_dcache_range(start, end);
-               break;
-       }
-}
-EXPORT_SYMBOL(consistent_sync);
-
-/*
- * consistent_sync_page makes memory consistent. identical
- * to consistent_sync, but takes a struct page instead of a
- * virtual address
- */
-void consistent_sync_page(struct page *page, unsigned long offset,
-       size_t size, int direction)
-{
-       unsigned long start = (unsigned long)page_address(page) + offset;
-       consistent_sync((void *)start, size, direction);
-}
-EXPORT_SYMBOL(consistent_sync_page);
index f34346d..2ffd171 100644 (file)
@@ -597,19 +597,6 @@ static void pcibios_fixup_resources(struct pci_dev *dev)
 }
 DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pcibios_fixup_resources);
 
-/*
- * We need to avoid collisions with `mirrored' VGA ports
- * and other strange ISA hardware, so we always want the
- * addresses to be allocated in the 0x000-0x0ff region
- * modulo 0x400.
- *
- * Why? Because some silly external IO cards only decode
- * the low 10 bits of the IO address. The 0x00-0xff region
- * is reserved for motherboard devices that decode all 16
- * bits, so it's ok to allocate at, say, 0x2800-0x28ff,
- * but we want to try to avoid allocating at 0x2900-0x2bff
- * which might have be mirrored at 0x0100-0x03ff..
- */
 int pcibios_add_device(struct pci_dev *dev)
 {
        dev->irq = of_irq_parse_and_map_pci(dev, 0, 0);
index 14c7da5..b800909 100644 (file)
@@ -157,6 +157,7 @@ void __init xilinx_pci_init(void)
 
        /* Set the max bus number to 255, and bus/subbus no's to 0 */
        pci_reg = of_iomap(pci_node, 0);
+       WARN_ON(!pci_reg);
        out_be32(pci_reg + XPLB_PCI_BUS, 0x000000ff);
        iounmap(pci_reg);
 
index 2af13b1..3551199 100644 (file)
@@ -33,6 +33,7 @@ config MIPS
        select GENERIC_SMP_IDLE_THREAD
        select GENERIC_TIME_VSYSCALL
        select HANDLE_DOMAIN_IRQ
+       select HAVE_ARCH_COMPILER_H
        select HAVE_ARCH_JUMP_LABEL
        select HAVE_ARCH_KGDB
        select HAVE_ARCH_MMAP_RND_BITS if MMU
index 5425df0..d74b374 100644 (file)
@@ -309,7 +309,7 @@ endif
 # instead of .eh_frame so we don't discard them.
 KBUILD_CFLAGS += -fno-asynchronous-unwind-tables
 
-LDFLAGS                        += -m $(ld-emul)
+KBUILD_LDFLAGS         += -m $(ld-emul)
 
 ifdef CONFIG_MIPS
 CHECKFLAGS += $(shell $(CC) $(KBUILD_CFLAGS) -dM -E -x c /dev/null | \
index abe77ad..3c453a1 100644 (file)
@@ -92,7 +92,7 @@ UIMAGE_LOADADDR = $(VMLINUZ_LOAD_ADDRESS)
 vmlinuzobjs-y += $(obj)/piggy.o
 
 quiet_cmd_zld = LD      $@
-      cmd_zld = $(LD) $(LDFLAGS) -Ttext $(VMLINUZ_LOAD_ADDRESS) -T $< $(vmlinuzobjs-y) -o $@
+      cmd_zld = $(LD) $(KBUILD_LDFLAGS) -Ttext $(VMLINUZ_LOAD_ADDRESS) -T $< $(vmlinuzobjs-y) -o $@
 quiet_cmd_strip = STRIP          $@
       cmd_strip = $(STRIP) -s $@
 vmlinuz: $(src)/ld.script $(vmlinuzobjs-y) $(obj)/calc_vmlinuz_load_addr
index 576f1a6..f901ed0 100644 (file)
@@ -5,3 +5,4 @@
 #include <asm-generic/asm-prototypes.h>
 #include <linux/uaccess.h>
 #include <asm/ftrace.h>
+#include <asm/mmu_context.h>
index 0269b3d..d4ea7a5 100644 (file)
@@ -122,8 +122,8 @@ static __inline__ int atomic_fetch_##op##_relaxed(int i, atomic_t * v)            \
                "       " #asm_op " %0, %1, %3                          \n"   \
                "       sc      %0, %2                                  \n"   \
                "\t" __scbeqz " %0, 1b                                  \n"   \
-               "       move    %0, %1                                  \n"   \
                "       .set    mips0                                   \n"   \
+               "       move    %0, %1                                  \n"   \
                : "=&r" (result), "=&r" (temp),                               \
                  "+" GCC_OFF_SMALL_ASM() (v->counter)                        \
                : "Ir" (i));                                                  \
@@ -190,9 +190,11 @@ static __inline__ int atomic_sub_if_positive(int i, atomic_t * v)
                __asm__ __volatile__(
                "       .set    "MIPS_ISA_LEVEL"                        \n"
                "1:     ll      %1, %2          # atomic_sub_if_positive\n"
+               "       .set    mips0                                   \n"
                "       subu    %0, %1, %3                              \n"
                "       move    %1, %0                                  \n"
                "       bltz    %0, 1f                                  \n"
+               "       .set    "MIPS_ISA_LEVEL"                        \n"
                "       sc      %1, %2                                  \n"
                "\t" __scbeqz " %1, 1b                                  \n"
                "1:                                                     \n"
index e081a26..cc2eb1b 100644 (file)
@@ -8,6 +8,41 @@
 #ifndef _ASM_COMPILER_H
 #define _ASM_COMPILER_H
 
+/*
+ * With GCC 4.5 onwards we can use __builtin_unreachable to indicate to the
+ * compiler that a particular code path will never be hit. This allows it to be
+ * optimised out of the generated binary.
+ *
+ * Unfortunately at least GCC 4.6.3 through 7.3.0 inclusive suffer from a bug
+ * that can lead to instructions from beyond an unreachable statement being
+ * incorrectly reordered into earlier delay slots if the unreachable statement
+ * is the only content of a case in a switch statement. This can lead to
+ * seemingly random behaviour, such as invalid memory accesses from incorrectly
+ * reordered loads or stores. See this potential GCC fix for details:
+ *
+ *   https://gcc.gnu.org/ml/gcc-patches/2015-09/msg00360.html
+ *
+ * It is unclear whether GCC 8 onwards suffer from the same issue - nothing
+ * relevant is mentioned in GCC 8 release notes and nothing obviously relevant
+ * stands out in GCC commit logs, but these newer GCC versions generate very
+ * different code for the testcase which doesn't exhibit the bug.
+ *
+ * GCC also handles stack allocation suboptimally when calling noreturn
+ * functions or calling __builtin_unreachable():
+ *
+ *   https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82365
+ *
+ * We work around both of these issues by placing a volatile asm statement,
+ * which GCC is prevented from reordering past, prior to __builtin_unreachable
+ * calls.
+ *
+ * The .insn statement is required to ensure that any branches to the
+ * statement, which sadly must be kept due to the asm statement, are known to
+ * be branches to code and satisfy linker requirements for microMIPS kernels.
+ */
+#undef barrier_before_unreachable
+#define barrier_before_unreachable() asm volatile(".insn")
+
 #if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
 #define GCC_IMM_ASM() "n"
 #define GCC_REG_ACCUM "$0"
index b509371..9441456 100644 (file)
@@ -32,6 +32,7 @@ do {                                                                  \
 } while (0)
 
 extern void tlbmiss_handler_setup_pgd(unsigned long);
+extern char tlbmiss_handler_setup_pgd_end[];
 
 /* Note: This is also implemented with uasm in arch/mips/kvm/entry.c */
 #define TLBMISS_HANDLER_SETUP_PGD(pgd)                                 \
index 4ed7ebe..6d97e23 100644 (file)
@@ -24,4 +24,13 @@ void build_tlb_write_entry(u32 **p, struct uasm_label **l,
                           struct uasm_reloc **r,
                           enum tlb_write_entry wmode);
 
+extern void handle_tlbl(void);
+extern char handle_tlbl_end[];
+
+extern void handle_tlbs(void);
+extern char handle_tlbs_end[];
+
+extern void handle_tlbm(void);
+extern char handle_tlbm_end[];
+
 #endif /* __ASM_TLBEX_H */
index f8871d5..9dab0ed 100644 (file)
 #include <asm/mmu_context.h>
 #include <asm/types.h>
 #include <asm/stacktrace.h>
+#include <asm/tlbex.h>
 #include <asm/uasm.h>
 
 extern void check_wait(void);
 extern asmlinkage void rollback_handle_int(void);
 extern asmlinkage void handle_int(void);
-extern u32 handle_tlbl[];
-extern u32 handle_tlbs[];
-extern u32 handle_tlbm[];
 extern asmlinkage void handle_adel(void);
 extern asmlinkage void handle_ades(void);
 extern asmlinkage void handle_ibe(void);
index f7a0645..4aaff3b 100644 (file)
@@ -224,7 +224,7 @@ unsigned long arch_uretprobe_hijack_return_addr(
 int __weak set_swbp(struct arch_uprobe *auprobe, struct mm_struct *mm,
        unsigned long vaddr)
 {
-       return uprobe_write_opcode(mm, vaddr, UPROBE_SWBP_INSN);
+       return uprobe_write_opcode(auprobe, mm, vaddr, UPROBE_SWBP_INSN);
 }
 
 void arch_uprobe_copy_ixol(struct page *page, unsigned long vaddr,
index 9ab1326..78ce4cf 100644 (file)
@@ -38,7 +38,7 @@ $(obj)/rom.bin: $(obj)/rom
 
 # Rule to make the bootloader
 $(obj)/rom: $(addprefix $(obj)/,$(OBJECTS))
-       $(LD) $(LDFLAGS) $(LDSCRIPT) -o $@ $^
+       $(LD) $(KBUILD_LDFLAGS) $(LDSCRIPT) -o $@ $^
 
 $(obj)/%.o: $(obj)/%.gz
        $(LD) -r -o $@ -b binary $<
index 111ad47..4c2483f 100644 (file)
@@ -4,12 +4,12 @@
 #include "libgcc.h"
 
 /*
- * GCC 7 suboptimally generates __multi3 calls for mips64r6, so for that
- * specific case only we'll implement it here.
+ * GCC 7 & older can suboptimally generate __multi3 calls for mips64r6, so for
+ * that specific case only we implement that intrinsic here.
  *
  * See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82981
  */
-#if defined(CONFIG_64BIT) && defined(CONFIG_CPU_MIPSR6) && (__GNUC__ == 7)
+#if defined(CONFIG_64BIT) && defined(CONFIG_CPU_MIPSR6) && (__GNUC__ < 8)
 
 /* multiply 64-bit values, low 64-bits returned */
 static inline long long notrace dmulu(long long a, long long b)
index a5427c6..00fef57 100644 (file)
  * Copyright (C) 2012  Ralf Baechle <ralf@linux-mips.org>
  */
 #include <asm/asm.h>
+#include <asm/export.h>
 #include <asm/regdef.h>
 
 #define FASTPATH_SIZE  128
 
-EXPORT(tlbmiss_handler_setup_pgd_start)
 LEAF(tlbmiss_handler_setup_pgd)
 1:     j       1b              /* Dummy, will be replaced. */
        .space  64
 END(tlbmiss_handler_setup_pgd)
 EXPORT(tlbmiss_handler_setup_pgd_end)
+EXPORT_SYMBOL_GPL(tlbmiss_handler_setup_pgd)
 
 LEAF(handle_tlbm)
        .space          FASTPATH_SIZE * 4
index 49312a1..0677142 100644 (file)
@@ -31,6 +31,7 @@
 
 #include <asm/cacheflush.h>
 #include <asm/cpu-type.h>
+#include <asm/mmu_context.h>
 #include <asm/pgtable.h>
 #include <asm/war.h>
 #include <asm/uasm.h>
@@ -253,8 +254,10 @@ static void output_pgtable_bits_defines(void)
        pr_debug("\n");
 }
 
-static inline void dump_handler(const char *symbol, const u32 *handler, int count)
+static inline void dump_handler(const char *symbol, const void *start, const void *end)
 {
+       unsigned int count = (end - start) / sizeof(u32);
+       const u32 *handler = start;
        int i;
 
        pr_debug("LEAF(%s)\n", symbol);
@@ -402,12 +405,6 @@ static void build_restore_work_registers(u32 **p)
  * CONFIG_MIPS_PGD_C0_CONTEXT implies 64 bit and lack of pgd_current,
  * we cannot do r3000 under these circumstances.
  *
- * Declare pgd_current here instead of including mmu_context.h to avoid type
- * conflicts for tlbmiss_handler_setup_pgd
- */
-extern unsigned long pgd_current[];
-
-/*
  * The R3000 TLB handler is simple.
  */
 static void build_r3000_tlb_refill_handler(void)
@@ -444,8 +441,7 @@ static void build_r3000_tlb_refill_handler(void)
 
        memcpy((void *)ebase, tlb_handler, 0x80);
        local_flush_icache_range(ebase, ebase + 0x80);
-
-       dump_handler("r3000_tlb_refill", (u32 *)ebase, 32);
+       dump_handler("r3000_tlb_refill", (u32 *)ebase, (u32 *)(ebase + 0x80));
 }
 #endif /* CONFIG_MIPS_PGD_C0_CONTEXT */
 
@@ -1465,8 +1461,7 @@ static void build_r4000_tlb_refill_handler(void)
 
        memcpy((void *)ebase, final_handler, 0x100);
        local_flush_icache_range(ebase, ebase + 0x100);
-
-       dump_handler("r4000_tlb_refill", (u32 *)ebase, 64);
+       dump_handler("r4000_tlb_refill", (u32 *)ebase, (u32 *)(ebase + 0x100));
 }
 
 static void setup_pw(void)
@@ -1568,31 +1563,21 @@ static void build_loongson3_tlb_refill_handler(void)
        uasm_resolve_relocs(relocs, labels);
        memcpy((void *)(ebase + 0x80), tlb_handler, 0x80);
        local_flush_icache_range(ebase + 0x80, ebase + 0x100);
-       dump_handler("loongson3_tlb_refill", (u32 *)(ebase + 0x80), 32);
+       dump_handler("loongson3_tlb_refill",
+                    (u32 *)(ebase + 0x80), (u32 *)(ebase + 0x100));
 }
 
-extern u32 handle_tlbl[], handle_tlbl_end[];
-extern u32 handle_tlbs[], handle_tlbs_end[];
-extern u32 handle_tlbm[], handle_tlbm_end[];
-extern u32 tlbmiss_handler_setup_pgd_start[];
-extern u32 tlbmiss_handler_setup_pgd[];
-EXPORT_SYMBOL_GPL(tlbmiss_handler_setup_pgd);
-extern u32 tlbmiss_handler_setup_pgd_end[];
-
 static void build_setup_pgd(void)
 {
        const int a0 = 4;
        const int __maybe_unused a1 = 5;
        const int __maybe_unused a2 = 6;
-       u32 *p = tlbmiss_handler_setup_pgd_start;
-       const int tlbmiss_handler_setup_pgd_size =
-               tlbmiss_handler_setup_pgd_end - tlbmiss_handler_setup_pgd_start;
+       u32 *p = (u32 *)msk_isa16_mode((ulong)tlbmiss_handler_setup_pgd);
 #ifndef CONFIG_MIPS_PGD_C0_CONTEXT
        long pgdc = (long)pgd_current;
 #endif
 
-       memset(tlbmiss_handler_setup_pgd, 0, tlbmiss_handler_setup_pgd_size *
-                                       sizeof(tlbmiss_handler_setup_pgd[0]));
+       memset(p, 0, tlbmiss_handler_setup_pgd_end - (char *)p);
        memset(labels, 0, sizeof(labels));
        memset(relocs, 0, sizeof(relocs));
        pgd_reg = allocate_kscratch();
@@ -1645,15 +1630,15 @@ static void build_setup_pgd(void)
        else
                uasm_i_nop(&p);
 #endif
-       if (p >= tlbmiss_handler_setup_pgd_end)
+       if (p >= (u32 *)tlbmiss_handler_setup_pgd_end)
                panic("tlbmiss_handler_setup_pgd space exceeded");
 
        uasm_resolve_relocs(relocs, labels);
        pr_debug("Wrote tlbmiss_handler_setup_pgd (%u instructions).\n",
-                (unsigned int)(p - tlbmiss_handler_setup_pgd));
+                (unsigned int)(p - (u32 *)tlbmiss_handler_setup_pgd));
 
        dump_handler("tlbmiss_handler", tlbmiss_handler_setup_pgd,
-                                       tlbmiss_handler_setup_pgd_size);
+                                       tlbmiss_handler_setup_pgd_end);
 }
 
 static void
@@ -1922,12 +1907,11 @@ build_r3000_tlbchange_handler_head(u32 **p, unsigned int pte,
 
 static void build_r3000_tlb_load_handler(void)
 {
-       u32 *p = handle_tlbl;
-       const int handle_tlbl_size = handle_tlbl_end - handle_tlbl;
+       u32 *p = (u32 *)handle_tlbl;
        struct uasm_label *l = labels;
        struct uasm_reloc *r = relocs;
 
-       memset(handle_tlbl, 0, handle_tlbl_size * sizeof(handle_tlbl[0]));
+       memset(p, 0, handle_tlbl_end - (char *)p);
        memset(labels, 0, sizeof(labels));
        memset(relocs, 0, sizeof(relocs));
 
@@ -1941,24 +1925,23 @@ static void build_r3000_tlb_load_handler(void)
        uasm_i_j(&p, (unsigned long)tlb_do_page_fault_0 & 0x0fffffff);
        uasm_i_nop(&p);
 
-       if (p >= handle_tlbl_end)
+       if (p >= (u32 *)handle_tlbl_end)
                panic("TLB load handler fastpath space exceeded");
 
        uasm_resolve_relocs(relocs, labels);
        pr_debug("Wrote TLB load handler fastpath (%u instructions).\n",
-                (unsigned int)(p - handle_tlbl));
+                (unsigned int)(p - (u32 *)handle_tlbl));
 
-       dump_handler("r3000_tlb_load", handle_tlbl, handle_tlbl_size);
+       dump_handler("r3000_tlb_load", handle_tlbl, handle_tlbl_end);
 }
 
 static void build_r3000_tlb_store_handler(void)
 {
-       u32 *p = handle_tlbs;
-       const int handle_tlbs_size = handle_tlbs_end - handle_tlbs;
+       u32 *p = (u32 *)handle_tlbs;
        struct uasm_label *l = labels;
        struct uasm_reloc *r = relocs;
 
-       memset(handle_tlbs, 0, handle_tlbs_size * sizeof(handle_tlbs[0]));
+       memset(p, 0, handle_tlbs_end - (char *)p);
        memset(labels, 0, sizeof(labels));
        memset(relocs, 0, sizeof(relocs));
 
@@ -1972,24 +1955,23 @@ static void build_r3000_tlb_store_handler(void)
        uasm_i_j(&p, (unsigned long)tlb_do_page_fault_1 & 0x0fffffff);
        uasm_i_nop(&p);
 
-       if (p >= handle_tlbs_end)
+       if (p >= (u32 *)handle_tlbs_end)
                panic("TLB store handler fastpath space exceeded");
 
        uasm_resolve_relocs(relocs, labels);
        pr_debug("Wrote TLB store handler fastpath (%u instructions).\n",
-                (unsigned int)(p - handle_tlbs));
+                (unsigned int)(p - (u32 *)handle_tlbs));
 
-       dump_handler("r3000_tlb_store", handle_tlbs, handle_tlbs_size);
+       dump_handler("r3000_tlb_store", handle_tlbs, handle_tlbs_end);
 }
 
 static void build_r3000_tlb_modify_handler(void)
 {
-       u32 *p = handle_tlbm;
-       const int handle_tlbm_size = handle_tlbm_end - handle_tlbm;
+       u32 *p = (u32 *)handle_tlbm;
        struct uasm_label *l = labels;
        struct uasm_reloc *r = relocs;
 
-       memset(handle_tlbm, 0, handle_tlbm_size * sizeof(handle_tlbm[0]));
+       memset(p, 0, handle_tlbm_end - (char *)p);
        memset(labels, 0, sizeof(labels));
        memset(relocs, 0, sizeof(relocs));
 
@@ -2003,14 +1985,14 @@ static void build_r3000_tlb_modify_handler(void)
        uasm_i_j(&p, (unsigned long)tlb_do_page_fault_1 & 0x0fffffff);
        uasm_i_nop(&p);
 
-       if (p >= handle_tlbm_end)
+       if (p >= (u32 *)handle_tlbm_end)
                panic("TLB modify handler fastpath space exceeded");
 
        uasm_resolve_relocs(relocs, labels);
        pr_debug("Wrote TLB modify handler fastpath (%u instructions).\n",
-                (unsigned int)(p - handle_tlbm));
+                (unsigned int)(p - (u32 *)handle_tlbm));
 
-       dump_handler("r3000_tlb_modify", handle_tlbm, handle_tlbm_size);
+       dump_handler("r3000_tlb_modify", handle_tlbm, handle_tlbm_end);
 }
 #endif /* CONFIG_MIPS_PGD_C0_CONTEXT */
 
@@ -2102,12 +2084,11 @@ build_r4000_tlbchange_handler_tail(u32 **p, struct uasm_label **l,
 static void build_r4000_tlb_load_handler(void)
 {
        u32 *p = (u32 *)msk_isa16_mode((ulong)handle_tlbl);
-       const int handle_tlbl_size = handle_tlbl_end - handle_tlbl;
        struct uasm_label *l = labels;
        struct uasm_reloc *r = relocs;
        struct work_registers wr;
 
-       memset(handle_tlbl, 0, handle_tlbl_size * sizeof(handle_tlbl[0]));
+       memset(p, 0, handle_tlbl_end - (char *)p);
        memset(labels, 0, sizeof(labels));
        memset(relocs, 0, sizeof(relocs));
 
@@ -2288,25 +2269,24 @@ static void build_r4000_tlb_load_handler(void)
        uasm_i_j(&p, (unsigned long)tlb_do_page_fault_0 & 0x0fffffff);
        uasm_i_nop(&p);
 
-       if (p >= handle_tlbl_end)
+       if (p >= (u32 *)handle_tlbl_end)
                panic("TLB load handler fastpath space exceeded");
 
        uasm_resolve_relocs(relocs, labels);
        pr_debug("Wrote TLB load handler fastpath (%u instructions).\n",
-                (unsigned int)(p - handle_tlbl));
+                (unsigned int)(p - (u32 *)handle_tlbl));
 
-       dump_handler("r4000_tlb_load", handle_tlbl, handle_tlbl_size);
+       dump_handler("r4000_tlb_load", handle_tlbl, handle_tlbl_end);
 }
 
 static void build_r4000_tlb_store_handler(void)
 {
        u32 *p = (u32 *)msk_isa16_mode((ulong)handle_tlbs);
-       const int handle_tlbs_size = handle_tlbs_end - handle_tlbs;
        struct uasm_label *l = labels;
        struct uasm_reloc *r = relocs;
        struct work_registers wr;
 
-       memset(handle_tlbs, 0, handle_tlbs_size * sizeof(handle_tlbs[0]));
+       memset(p, 0, handle_tlbs_end - (char *)p);
        memset(labels, 0, sizeof(labels));
        memset(relocs, 0, sizeof(relocs));
 
@@ -2343,25 +2323,24 @@ static void build_r4000_tlb_store_handler(void)
        uasm_i_j(&p, (unsigned long)tlb_do_page_fault_1 & 0x0fffffff);
        uasm_i_nop(&p);
 
-       if (p >= handle_tlbs_end)
+       if (p >= (u32 *)handle_tlbs_end)
                panic("TLB store handler fastpath space exceeded");
 
        uasm_resolve_relocs(relocs, labels);
        pr_debug("Wrote TLB store handler fastpath (%u instructions).\n",
-                (unsigned int)(p - handle_tlbs));
+                (unsigned int)(p - (u32 *)handle_tlbs));
 
-       dump_handler("r4000_tlb_store", handle_tlbs, handle_tlbs_size);
+       dump_handler("r4000_tlb_store", handle_tlbs, handle_tlbs_end);
 }
 
 static void build_r4000_tlb_modify_handler(void)
 {
        u32 *p = (u32 *)msk_isa16_mode((ulong)handle_tlbm);
-       const int handle_tlbm_size = handle_tlbm_end - handle_tlbm;
        struct uasm_label *l = labels;
        struct uasm_reloc *r = relocs;
        struct work_registers wr;
 
-       memset(handle_tlbm, 0, handle_tlbm_size * sizeof(handle_tlbm[0]));
+       memset(p, 0, handle_tlbm_end - (char *)p);
        memset(labels, 0, sizeof(labels));
        memset(relocs, 0, sizeof(relocs));
 
@@ -2399,14 +2378,14 @@ static void build_r4000_tlb_modify_handler(void)
        uasm_i_j(&p, (unsigned long)tlb_do_page_fault_1 & 0x0fffffff);
        uasm_i_nop(&p);
 
-       if (p >= handle_tlbm_end)
+       if (p >= (u32 *)handle_tlbm_end)
                panic("TLB modify handler fastpath space exceeded");
 
        uasm_resolve_relocs(relocs, labels);
        pr_debug("Wrote TLB modify handler fastpath (%u instructions).\n",
-                (unsigned int)(p - handle_tlbm));
+                (unsigned int)(p - (u32 *)handle_tlbm));
 
-       dump_handler("r4000_tlb_modify", handle_tlbm, handle_tlbm_size);
+       dump_handler("r4000_tlb_modify", handle_tlbm, handle_tlbm_end);
 }
 
 static void flush_tlb_handlers(void)
index 031c676..63f4f17 100644 (file)
@@ -33,12 +33,12 @@ endif
 ifdef CONFIG_CPU_LITTLE_ENDIAN
 KBUILD_CFLAGS   += $(call cc-option, -EL)
 KBUILD_AFLAGS   += $(call cc-option, -EL)
-LDFLAGS         += $(call cc-option, -EL)
+KBUILD_LDFLAGS  += $(call cc-option, -EL)
 CHECKFLAGS      += -D__NDS32_EL__
 else
 KBUILD_CFLAGS   += $(call cc-option, -EB)
 KBUILD_AFLAGS   += $(call cc-option, -EB)
-LDFLAGS         += $(call cc-option, -EB)
+KBUILD_LDFLAGS  += $(call cc-option, -EB)
 CHECKFLAGS      += -D__NDS32_EB__
 endif
 
index ed5f32d..e0081e7 100644 (file)
@@ -6,6 +6,8 @@
 
 config OPENRISC
        def_bool y
+       select ARCH_HAS_SYNC_DMA_FOR_DEVICE
+       select DMA_NONCOHERENT_OPS
        select OF
        select OF_EARLY_FLATTREE
        select IRQ_DOMAIN
index 65964d3..eb87cd8 100644 (file)
@@ -7,6 +7,7 @@ generic-y += current.h
 generic-y += device.h
 generic-y += div64.h
 generic-y += dma.h
+generic-y += dma-mapping.h
 generic-y += emergency-restart.h
 generic-y += exec.h
 generic-y += extable.h
diff --git a/arch/openrisc/include/asm/dma-mapping.h b/arch/openrisc/include/asm/dma-mapping.h
deleted file mode 100644 (file)
index e212a1f..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * OpenRISC Linux
- *
- * Linux architectural port borrowing liberally from similar works of
- * others.  All original copyrights apply as per the original source
- * declaration.
- *
- * OpenRISC implementation:
- * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
- *
- * 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 __ASM_OPENRISC_DMA_MAPPING_H
-#define __ASM_OPENRISC_DMA_MAPPING_H
-
-/*
- * See Documentation/DMA-API-HOWTO.txt and
- * Documentation/DMA-API.txt for documentation.
- */
-
-#include <linux/dma-debug.h>
-#include <linux/dma-mapping.h>
-
-extern const struct dma_map_ops or1k_dma_map_ops;
-
-static inline const struct dma_map_ops *get_arch_dma_ops(struct bus_type *bus)
-{
-       return &or1k_dma_map_ops;
-}
-
-#endif /* __ASM_OPENRISC_DMA_MAPPING_H */
index ec7fd45..159336a 100644 (file)
@@ -19,9 +19,7 @@
  * the only thing implemented properly.  The rest need looking into...
  */
 
-#include <linux/dma-mapping.h>
-#include <linux/dma-debug.h>
-#include <linux/export.h>
+#include <linux/dma-noncoherent.h>
 
 #include <asm/cpuinfo.h>
 #include <asm/spr_defs.h>
@@ -80,10 +78,9 @@ page_clear_nocache(pte_t *pte, unsigned long addr,
  * is being ignored for now; uncached but write-combined memory is a
  * missing feature of the OR1K.
  */
-static void *
-or1k_dma_alloc(struct device *dev, size_t size,
-              dma_addr_t *dma_handle, gfp_t gfp,
-              unsigned long attrs)
+void *
+arch_dma_alloc(struct device *dev, size_t size, dma_addr_t *dma_handle,
+               gfp_t gfp, unsigned long attrs)
 {
        unsigned long va;
        void *page;
@@ -115,9 +112,9 @@ or1k_dma_alloc(struct device *dev, size_t size,
        return (void *)va;
 }
 
-static void
-or1k_dma_free(struct device *dev, size_t size, void *vaddr,
-             dma_addr_t dma_handle, unsigned long attrs)
+void
+arch_dma_free(struct device *dev, size_t size, void *vaddr,
+               dma_addr_t dma_handle, unsigned long attrs)
 {
        unsigned long va = (unsigned long)vaddr;
        struct mm_walk walk = {
@@ -133,19 +130,12 @@ or1k_dma_free(struct device *dev, size_t size, void *vaddr,
        free_pages_exact(vaddr, size);
 }
 
-static dma_addr_t
-or1k_map_page(struct device *dev, struct page *page,
-             unsigned long offset, size_t size,
-             enum dma_data_direction dir,
-             unsigned long attrs)
+void arch_sync_dma_for_device(struct device *dev, phys_addr_t addr, size_t size,
+               enum dma_data_direction dir)
 {
        unsigned long cl;
-       dma_addr_t addr = page_to_phys(page) + offset;
        struct cpuinfo_or1k *cpuinfo = &cpuinfo_or1k[smp_processor_id()];
 
-       if (attrs & DMA_ATTR_SKIP_CPU_SYNC)
-               return addr;
-
        switch (dir) {
        case DMA_TO_DEVICE:
                /* Flush the dcache for the requested range */
@@ -167,83 +157,4 @@ or1k_map_page(struct device *dev, struct page *page,
                 */
                break;
        }
-
-       return addr;
-}
-
-static void
-or1k_unmap_page(struct device *dev, dma_addr_t dma_handle,
-               size_t size, enum dma_data_direction dir,
-               unsigned long attrs)
-{
-       /* Nothing special to do here... */
-}
-
-static int
-or1k_map_sg(struct device *dev, struct scatterlist *sg,
-           int nents, enum dma_data_direction dir,
-           unsigned long attrs)
-{
-       struct scatterlist *s;
-       int i;
-
-       for_each_sg(sg, s, nents, i) {
-               s->dma_address = or1k_map_page(dev, sg_page(s), s->offset,
-                                              s->length, dir, 0);
-       }
-
-       return nents;
 }
-
-static void
-or1k_unmap_sg(struct device *dev, struct scatterlist *sg,
-             int nents, enum dma_data_direction dir,
-             unsigned long attrs)
-{
-       struct scatterlist *s;
-       int i;
-
-       for_each_sg(sg, s, nents, i) {
-               or1k_unmap_page(dev, sg_dma_address(s), sg_dma_len(s), dir, 0);
-       }
-}
-
-static void
-or1k_sync_single_for_cpu(struct device *dev,
-                        dma_addr_t dma_handle, size_t size,
-                        enum dma_data_direction dir)
-{
-       unsigned long cl;
-       dma_addr_t addr = dma_handle;
-       struct cpuinfo_or1k *cpuinfo = &cpuinfo_or1k[smp_processor_id()];
-
-       /* Invalidate the dcache for the requested range */
-       for (cl = addr; cl < addr + size; cl += cpuinfo->dcache_block_size)
-               mtspr(SPR_DCBIR, cl);
-}
-
-static void
-or1k_sync_single_for_device(struct device *dev,
-                           dma_addr_t dma_handle, size_t size,
-                           enum dma_data_direction dir)
-{
-       unsigned long cl;
-       dma_addr_t addr = dma_handle;
-       struct cpuinfo_or1k *cpuinfo = &cpuinfo_or1k[smp_processor_id()];
-
-       /* Flush the dcache for the requested range */
-       for (cl = addr; cl < addr + size; cl += cpuinfo->dcache_block_size)
-               mtspr(SPR_DCBFR, cl);
-}
-
-const struct dma_map_ops or1k_dma_map_ops = {
-       .alloc = or1k_dma_alloc,
-       .free = or1k_dma_free,
-       .map_page = or1k_map_page,
-       .unmap_page = or1k_unmap_page,
-       .map_sg = or1k_map_sg,
-       .unmap_sg = or1k_unmap_sg,
-       .sync_single_for_cpu = or1k_sync_single_for_cpu,
-       .sync_single_for_device = or1k_sync_single_for_device,
-};
-EXPORT_SYMBOL(or1k_dma_map_ops);
index f019d3e..d00973a 100644 (file)
@@ -235,6 +235,7 @@ typedef unsigned long elf_greg_t;
 #define SET_PERSONALITY(ex) \
 ({     \
        set_personality((current->personality & ~PER_MASK) | PER_LINUX); \
+       clear_thread_flag(TIF_32BIT); \
        current->thread.map_base = DEFAULT_MAP_BASE; \
        current->thread.task_size = DEFAULT_TASK_SIZE; \
  })
@@ -243,9 +244,11 @@ typedef unsigned long elf_greg_t;
 
 #define COMPAT_SET_PERSONALITY(ex) \
 ({     \
-       set_thread_flag(TIF_32BIT); \
-       current->thread.map_base = DEFAULT_MAP_BASE32; \
-       current->thread.task_size = DEFAULT_TASK_SIZE32; \
+       if ((ex).e_ident[EI_CLASS] == ELFCLASS32) { \
+               set_thread_flag(TIF_32BIT); \
+               current->thread.map_base = DEFAULT_MAP_BASE32; \
+               current->thread.task_size = DEFAULT_TASK_SIZE32; \
+       } else clear_thread_flag(TIF_32BIT); \
  })
 
 /*
index 49f6f3d..cd6fe4f 100644 (file)
 name:          ASM_NL\
        .export name
 
-#ifdef CONFIG_64BIT
-#define ENDPROC(name) \
-       END(name)
-#else
-#define ENDPROC(name) \
-       .type name, @function !\
-       END(name)
-#endif
-
 #define ENTRY_CFI(name, ...) \
        ENTRY(name)     ASM_NL\
        .proc           ASM_NL\
index 2dbe558..2bd5e69 100644 (file)
@@ -256,11 +256,7 @@ on downward growing arches, it looks like this:
  * it in here from the current->personality
  */
 
-#ifdef CONFIG_64BIT
-#define USER_WIDE_MODE (!test_thread_flag(TIF_32BIT))
-#else
-#define USER_WIDE_MODE 0
-#endif
+#define USER_WIDE_MODE (!is_32bit_task())
 
 #define start_thread(regs, new_pc, new_sp) do {                \
        elf_addr_t *sp = (elf_addr_t *)new_sp;          \
index e000132..8ecc1f0 100644 (file)
@@ -2,7 +2,9 @@
 #ifndef __ASM_TRAPS_H
 #define __ASM_TRAPS_H
 
-#ifdef __KERNEL__
+#define PARISC_ITLB_TRAP       6 /* defined by architecture. Do not change. */
+
+#if !defined(__ASSEMBLY__)
 struct pt_regs;
 
 /* traps.c */
index f133b7e..9547e52 100644 (file)
@@ -73,8 +73,10 @@ unwind_table_remove(struct unwind_table *table);
 
 void unwind_frame_init(struct unwind_frame_info *info, struct task_struct *t, 
                       struct pt_regs *regs);
-void unwind_frame_init_from_blocked_task(struct unwind_frame_info *info, struct task_struct *t);
-void unwind_frame_init_running(struct unwind_frame_info *info, struct pt_regs *regs);
+void unwind_frame_init_from_blocked_task(struct unwind_frame_info *info,
+                       struct task_struct *t);
+void unwind_frame_init_task(struct unwind_frame_info *info,
+                       struct task_struct *task, struct pt_regs *regs);
 int unwind_once(struct unwind_frame_info *info);
 int unwind_to_user(struct unwind_frame_info *info);
 
index c7508f5..242c5ab 100644 (file)
@@ -36,6 +36,7 @@
 #include <asm/signal.h>
 #include <asm/unistd.h>
 #include <asm/ldcw.h>
+#include <asm/traps.h>
 #include <asm/thread_info.h>
 
 #include <linux/linkage.h>
@@ -692,7 +693,7 @@ ENTRY(fault_vector_20)
        def              3
        extint           4
        def              5
-       itlb_20          6
+       itlb_20          PARISC_ITLB_TRAP
        def              7
        def              8
        def              9
@@ -735,7 +736,7 @@ ENTRY(fault_vector_11)
        def              3
        extint           4
        def              5
-       itlb_11          6
+       itlb_11          PARISC_ITLB_TRAP
        def              7
        def              8
        def              9
@@ -776,7 +777,7 @@ END(fault_vector_11)
         * copy_thread moved args into task save area.
         */
 
-ENTRY_CFI(ret_from_kernel_thread)
+ENTRY(ret_from_kernel_thread)
        /* Call schedule_tail first though */
        BL      schedule_tail, %r2
        nop
@@ -791,7 +792,7 @@ ENTRY_CFI(ret_from_kernel_thread)
        copy    %r31, %r2
        b       finish_child_return
        nop
-ENDPROC_CFI(ret_from_kernel_thread)
+END(ret_from_kernel_thread)
 
 
        /*
@@ -815,9 +816,8 @@ ENTRY_CFI(_switch_to)
        LDREG   TASK_THREAD_INFO(%r25), %r25
        bv      %r0(%r2)
        mtctl   %r25,%cr30
-ENDPROC_CFI(_switch_to)
 
-ENTRY_CFI(_switch_to_ret)
+ENTRY(_switch_to_ret)
        mtctl   %r0, %cr0               /* Needed for single stepping */
        callee_rest
        callee_rest_float
@@ -825,7 +825,7 @@ ENTRY_CFI(_switch_to_ret)
        LDREG   -RP_OFFSET(%r30), %r2
        bv      %r0(%r2)
        copy    %r26, %r28
-ENDPROC_CFI(_switch_to_ret)
+ENDPROC_CFI(_switch_to)
 
        /*
         * Common rfi return path for interruptions, kernel execve, and
@@ -886,14 +886,12 @@ ENTRY_CFI(syscall_exit_rfi)
        STREG   %r19,PT_SR5(%r16)
        STREG   %r19,PT_SR6(%r16)
        STREG   %r19,PT_SR7(%r16)
-ENDPROC_CFI(syscall_exit_rfi)
 
-ENTRY_CFI(intr_return)
+ENTRY(intr_return)
        /* check for reschedule */
        mfctl   %cr30,%r1
        LDREG   TI_FLAGS(%r1),%r19      /* sched.h: TIF_NEED_RESCHED */
        bb,<,n  %r19,31-TIF_NEED_RESCHED,intr_do_resched /* forward */
-ENDPROC_CFI(intr_return)
 
        .import do_notify_resume,code
 intr_check_sig:
@@ -1049,6 +1047,7 @@ intr_extint:
 
        b       do_cpu_irq_mask
        ldo     R%intr_return(%r2), %r2 /* return to intr_return, not here */
+ENDPROC_CFI(syscall_exit_rfi)
 
 
        /* Generic interruptions (illegal insn, unaligned, page fault, etc) */
@@ -1068,21 +1067,12 @@ ENTRY_CFI(intr_save)            /* for os_hpmc */
        save_specials   %r29
 
        /* If this trap is a itlb miss, skip saving/adjusting isr/ior */
-
-       /*
-        * FIXME: 1) Use a #define for the hardwired "6" below (and in
-        *           traps.c.
-        *        2) Once we start executing code above 4 Gb, we need
-        *           to adjust iasq/iaoq here in the same way we
-        *           adjust isr/ior below.
-        */
-
-       cmpib,COND(=),n        6,%r26,skip_save_ior
+       cmpib,COND(=),n        PARISC_ITLB_TRAP,%r26,skip_save_ior
 
 
-       mfctl           %cr20, %r16 /* isr */
+       mfctl           %isr, %r16
        nop             /* serialize mfctl on PA 2.0 to avoid 4 cycle penalty */
-       mfctl           %cr21, %r17 /* ior */
+       mfctl           %ior, %r17
 
 
 #ifdef CONFIG_64BIT
@@ -1094,22 +1084,34 @@ ENTRY_CFI(intr_save)            /* for os_hpmc */
        extrd,u,*<>     %r8,PSW_W_BIT,1,%r0
        depdi           0,1,2,%r17
 
-       /*
-        * FIXME: This code has hardwired assumptions about the split
-        *        between space bits and offset bits. This will change
-        *        when we allow alternate page sizes.
-        */
-
-       /* adjust isr/ior. */
-       extrd,u         %r16,63,SPACEID_SHIFT,%r1       /* get high bits from isr for ior */
-       depd            %r1,31,SPACEID_SHIFT,%r17       /* deposit them into ior */
-       depdi           0,63,SPACEID_SHIFT,%r16         /* clear them from isr */
+       /* adjust isr/ior: get high bits from isr and deposit in ior */
+       space_adjust    %r16,%r17,%r1
 #endif
        STREG           %r16, PT_ISR(%r29)
        STREG           %r17, PT_IOR(%r29)
 
+#if 0 && defined(CONFIG_64BIT)
+       /* Revisit when we have 64-bit code above 4Gb */
+       b,n             intr_save2
 
 skip_save_ior:
+       /* We have a itlb miss, and when executing code above 4 Gb on ILP64, we
+        * need to adjust iasq/iaoq here in the same way we adjusted isr/ior
+        * above.
+        */
+       extrd,u,*       %r8,PSW_W_BIT,1,%r1
+       cmpib,COND(=),n 1,%r1,intr_save2
+       LDREG           PT_IASQ0(%r29), %r16
+       LDREG           PT_IAOQ0(%r29), %r17
+       /* adjust iasq/iaoq */
+       space_adjust    %r16,%r17,%r1
+       STREG           %r16, PT_IASQ0(%r29)
+       STREG           %r17, PT_IAOQ0(%r29)
+#else
+skip_save_ior:
+#endif
+
+intr_save2:
        virt_map
        save_general    %r29
 
@@ -1747,7 +1749,7 @@ fork_like fork
 fork_like vfork
 
        /* Set the return value for the child */
-ENTRY_CFI(child_return)
+ENTRY(child_return)
        BL      schedule_tail, %r2
        nop
 finish_child_return:
@@ -1759,7 +1761,7 @@ finish_child_return:
        reg_restore %r1
        b       syscall_exit
        copy    %r0,%r28
-ENDPROC_CFI(child_return)
+END(child_return)
 
 ENTRY_CFI(sys_rt_sigreturn_wrapper)
        LDREG   TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r26
@@ -1791,7 +1793,7 @@ ENTRY_CFI(sys_rt_sigreturn_wrapper)
        LDREG   PT_GR28(%r1),%r28  /* reload original r28 for syscall_exit */
 ENDPROC_CFI(sys_rt_sigreturn_wrapper)
 
-ENTRY_CFI(syscall_exit)
+ENTRY(syscall_exit)
        /* NOTE: Not all syscalls exit this way.  rt_sigreturn will exit
         * via syscall_exit_rfi if the signal was received while the process
         * was running.
@@ -1990,15 +1992,13 @@ syscall_do_resched:
 #else
        nop
 #endif
-ENDPROC_CFI(syscall_exit)
+END(syscall_exit)
 
 
 #ifdef CONFIG_FUNCTION_TRACER
 
        .import ftrace_function_trampoline,code
        .align L1_CACHE_BYTES
-       .globl mcount
-       .type  mcount, @function
 ENTRY_CFI(mcount, caller)
 _mcount:
        .export _mcount,data
@@ -2027,8 +2027,6 @@ ENDPROC_CFI(mcount)
 
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
        .align 8
-       .globl return_to_handler
-       .type  return_to_handler, @function
 ENTRY_CFI(return_to_handler, caller,frame=FRAME_SIZE)
        .export parisc_return_to_handler,data
 parisc_return_to_handler:
@@ -2078,6 +2076,7 @@ ENDPROC_CFI(return_to_handler)
 /* void call_on_stack(unsigned long param1, void *func,
                      unsigned long new_stack) */
 ENTRY_CFI(call_on_stack, FRAME=2*FRAME_SIZE,CALLS,SAVE_RP,SAVE_SP)
+ENTRY(_call_on_stack)
        copy    %sp, %r1
 
        /* Regarding the HPPA calling conventions for function pointers,
index 45cc659..82bd0d0 100644 (file)
@@ -288,6 +288,8 @@ void __init collect_boot_cpu_data(void)
                printk(KERN_INFO "model %s\n",
                        boot_cpu_data.pdc.sys_model_name);
 
+       dump_stack_set_arch_desc("%s", boot_cpu_data.pdc.sys_model_name);
+
        boot_cpu_data.hversion =  boot_cpu_data.pdc.model.hversion;
        boot_cpu_data.sversion =  boot_cpu_data.pdc.model.sversion;
 
index 2fe914c..ec5835e 100644 (file)
@@ -16,20 +16,7 @@ static void dump_trace(struct task_struct *task, struct stack_trace *trace)
 {
        struct unwind_frame_info info;
 
-       /* initialize unwind info */
-       if (task == current) {
-               unsigned long sp;
-               struct pt_regs r;
-HERE:
-               asm volatile ("copy %%r30, %0" : "=r"(sp));
-               memset(&r, 0, sizeof(struct pt_regs));
-               r.iaoq[0] = (unsigned long)&&HERE;
-               r.gr[2] = (unsigned long)__builtin_return_address(0);
-               r.gr[30] = sp;
-               unwind_frame_init(&info, task, &r);
-       } else {
-               unwind_frame_init_from_blocked_task(&info, task);
-       }
+       unwind_frame_init_task(&info, task, NULL);
 
        /* unwind stack and save entries in stack_trace struct */
        trace->nr_entries = 0;
index 43b308c..376ea0d 100644 (file)
@@ -156,11 +156,6 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
        int do_color_align, last_mmap;
        struct vm_unmapped_area_info info;
 
-#ifdef CONFIG_64BIT
-       /* This should only ever run for 32-bit processes.  */
-       BUG_ON(!test_thread_flag(TIF_32BIT));
-#endif
-
        /* requested length too big for entire address space */
        if (len > TASK_SIZE)
                return -ENOMEM;
index 5f7e57f..f453997 100644 (file)
@@ -108,12 +108,8 @@ linux_gateway_entry:
        mtsp    %r0,%sr6                        /* get kernel space into sr6 */
 
 #ifdef CONFIG_64BIT
-       /* for now we can *always* set the W bit on entry to the syscall
-        * since we don't support wide userland processes.  We could
-        * also save the current SM other than in r0 and restore it on
-        * exit from the syscall, and also use that value to know
-        * whether to do narrow or wide syscalls. -PB
-        */
+       /* Store W bit on entry to the syscall in case it's a wide userland
+        * process. */
        ssm     PSW_SM_W, %r1
        extrd,u %r1,PSW_W_BIT,1,%r1
        /* sp must be aligned on 4, so deposit the W bit setting into
@@ -227,8 +223,7 @@ linux_gateway_entry:
        or,=    %r2,%r2,%r2
        ldo     R%sys_call_table64(%r1), %r19
 #else
-       ldil    L%sys_call_table, %r1
-       ldo     R%sys_call_table(%r1), %r19
+       load32  sys_call_table, %r19
 #endif 
        comiclr,>>      __NR_Linux_syscalls, %r20, %r0
        b,n     .Lsyscall_nosys
@@ -331,8 +326,6 @@ tracesys_next:
         *  task->thread.regs.gr[20] above.
         */
        copy    %ret0,%r20
-       ldil    L%sys_call_table,%r1
-       ldo     R%sys_call_table(%r1), %r19
 
        ldo     -THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1      /* get task ptr */
        LDREG   TI_TASK(%r1), %r1
@@ -354,6 +347,23 @@ tracesys_next:
        comiclr,>>      __NR_Linux_syscalls, %r20, %r0
        b,n     .Ltracesys_nosys
 
+       /* Note!  We cannot use the syscall table that is mapped
+       nearby since the gateway page is mapped execute-only. */
+
+#ifdef CONFIG_64BIT
+       LDREG   TASK_PT_GR30(%r1), %r19         /* get users sp back */
+       extrd,u %r19,63,1,%r2                   /* W hidden in bottom bit */
+
+       ldil    L%sys_call_table, %r1
+       or,=    %r2,%r2,%r2
+       addil   L%(sys_call_table64-sys_call_table), %r1
+       ldo     R%sys_call_table(%r1), %r19
+       or,=    %r2,%r2,%r2
+       ldo     R%sys_call_table64(%r1), %r19
+#else
+       load32  sys_call_table, %r19
+#endif
+
        LDREGX  %r20(%r19), %r19
 
        /* If this is a sys_rt_sigreturn call, and the signal was received
@@ -464,16 +474,13 @@ tracesys_sigexit:
 lws_start:
 
 #ifdef CONFIG_64BIT
-       /* FIXME: If we are a 64-bit kernel just
-        *        turn this on unconditionally.
-        */
        ssm     PSW_SM_W, %r1
        extrd,u %r1,PSW_W_BIT,1,%r1
        /* sp must be aligned on 4, so deposit the W bit setting into
         * the bottom of sp temporarily */
        or,ev   %r1,%r30,%r30
 
-       /* Clip LWS number to a 32-bit value always */
+       /* Clip LWS number to a 32-bit value for 32-bit processes */
        depdi   0, 31, 32, %r20
 #endif 
 
index 3188152..68f10f8 100644 (file)
@@ -45,7 +45,7 @@
 
 #include "../math-emu/math-emu.h"      /* for handle_fpe() */
 
-static void parisc_show_stack(struct task_struct *task, unsigned long *sp,
+static void parisc_show_stack(struct task_struct *task,
        struct pt_regs *regs);
 
 static int printbinary(char *buf, unsigned long x, int nbits)
@@ -152,7 +152,7 @@ void show_regs(struct pt_regs *regs)
                printk("%s IAOQ[1]: %pS\n", level, (void *) regs->iaoq[1]);
                printk("%s RP(r2): %pS\n", level, (void *) regs->gr[2]);
 
-               parisc_show_stack(current, NULL, regs);
+               parisc_show_stack(current, regs);
        }
 }
 
@@ -185,44 +185,19 @@ static void do_show_stack(struct unwind_frame_info *info)
        printk(KERN_CRIT "\n");
 }
 
-static void parisc_show_stack(struct task_struct *task, unsigned long *sp,
+static void parisc_show_stack(struct task_struct *task,
        struct pt_regs *regs)
 {
        struct unwind_frame_info info;
-       struct task_struct *t;
 
-       t = task ? task : current;
-       if (regs) {
-               unwind_frame_init(&info, t, regs);
-               goto show_stack;
-       }
-
-       if (t == current) {
-               unsigned long sp;
-
-HERE:
-               asm volatile ("copy %%r30, %0" : "=r"(sp));
-               {
-                       struct pt_regs r;
-
-                       memset(&r, 0, sizeof(struct pt_regs));
-                       r.iaoq[0] = (unsigned long)&&HERE;
-                       r.gr[2] = (unsigned long)__builtin_return_address(0);
-                       r.gr[30] = sp;
-
-                       unwind_frame_init(&info, current, &r);
-               }
-       } else {
-               unwind_frame_init_from_blocked_task(&info, t);
-       }
+       unwind_frame_init_task(&info, task, regs);
 
-show_stack:
        do_show_stack(&info);
 }
 
 void show_stack(struct task_struct *t, unsigned long *sp)
 {
-       return parisc_show_stack(t, sp, NULL);
+       parisc_show_stack(t, NULL);
 }
 
 int is_valid_bugaddr(unsigned long iaoq)
@@ -557,7 +532,7 @@ void notrace handle_interruption(int code, struct pt_regs *regs)
                cpu_lpmc(5, regs);
                return;
 
-       case  6:
+       case  PARISC_ITLB_TRAP:
                /* Instruction TLB miss fault/Instruction page fault */
                fault_address = regs->iaoq[0];
                fault_space   = regs->iasq[0];
index 5cdf130..f329b46 100644 (file)
@@ -209,6 +209,8 @@ static int unwind_special(struct unwind_frame_info *info, unsigned long pc, int
         * We have to use void * instead of a function pointer, because
         * function pointers aren't a pointer to the function on 64-bit.
         * Make them const so the compiler knows they live in .text
+        * Note: We could use dereference_kernel_function_descriptor()
+        * instead but we want to keep it simple here.
         */
        extern void * const handle_interruption;
        extern void * const ret_from_kernel_thread;
@@ -216,7 +218,7 @@ static int unwind_special(struct unwind_frame_info *info, unsigned long pc, int
        extern void * const intr_return;
        extern void * const _switch_to_ret;
 #ifdef CONFIG_IRQSTACKS
-       extern void * const call_on_stack;
+       extern void * const _call_on_stack;
 #endif /* CONFIG_IRQSTACKS */
 
        if (pc == (unsigned long) &handle_interruption) {
@@ -251,7 +253,7 @@ static int unwind_special(struct unwind_frame_info *info, unsigned long pc, int
        }
 
 #ifdef CONFIG_IRQSTACKS
-       if (pc == (unsigned long) &call_on_stack) {
+       if (pc == (unsigned long) &_call_on_stack) {
                info->prev_sp = *(unsigned long *)(info->sp - FRAME_SIZE - REG_SZ);
                info->prev_ip = *(unsigned long *)(info->sp - FRAME_SIZE - RP_OFFSET);
                return 1;
@@ -403,9 +405,31 @@ void unwind_frame_init_from_blocked_task(struct unwind_frame_info *info, struct
        kfree(r2);
 }
 
-void unwind_frame_init_running(struct unwind_frame_info *info, struct pt_regs *regs)
+#define get_parisc_stackpointer() ({ \
+       unsigned long sp; \
+       __asm__("copy %%r30, %0" : "=r"(sp)); \
+       (sp); \
+})
+
+void unwind_frame_init_task(struct unwind_frame_info *info,
+       struct task_struct *task, struct pt_regs *regs)
 {
-       unwind_frame_init(info, current, regs);
+       task = task ? task : current;
+
+       if (task == current) {
+               struct pt_regs r;
+
+               if (!regs) {
+                       memset(&r, 0, sizeof(r));
+                       r.iaoq[0] =  _THIS_IP_;
+                       r.gr[2] = _RET_IP_;
+                       r.gr[30] = get_parisc_stackpointer();
+                       regs = &r;
+               }
+               unwind_frame_init(info, task, &r);
+       } else {
+               unwind_frame_init_from_blocked_task(info, task);
+       }
 }
 
 int unwind_once(struct unwind_frame_info *next_frame)
@@ -442,19 +466,12 @@ int unwind_to_user(struct unwind_frame_info *info)
 unsigned long return_address(unsigned int level)
 {
        struct unwind_frame_info info;
-       struct pt_regs r;
-       unsigned long sp;
 
        /* initialize unwind info */
-       asm volatile ("copy %%r30, %0" : "=r"(sp));
-       memset(&r, 0, sizeof(struct pt_regs));
-       r.iaoq[0] = _THIS_IP_;
-       r.gr[2] = _RET_IP_;
-       r.gr[30] = sp;
-       unwind_frame_init(&info, current, &r);
+       unwind_frame_init_task(&info, current, NULL);
 
        /* unwind stack */
-       ++level;
+       level += 2;
        do {
                if (unwind_once(&info) < 0 || info.ip == 0)
                        return 0;
index a806692..db0b6ee 100644 (file)
@@ -177,6 +177,7 @@ config PPC
        select HAVE_ARCH_KGDB
        select HAVE_ARCH_MMAP_RND_BITS
        select HAVE_ARCH_MMAP_RND_COMPAT_BITS   if COMPAT
+       select HAVE_ARCH_PREL32_RELOCATIONS
        select HAVE_ARCH_SECCOMP_FILTER
        select HAVE_ARCH_TRACEHOOK
        select HAVE_CBPF_JIT                    if !PPC64
index 8397c7b..11a1acb 100644 (file)
@@ -76,14 +76,14 @@ endif
 
 ifdef CONFIG_CPU_LITTLE_ENDIAN
 KBUILD_CFLAGS  += -mlittle-endian
-LDFLAGS                += -EL
+KBUILD_LDFLAGS += -EL
 LDEMULATION    := lppc
 GNUTARGET      := powerpcle
 MULTIPLEWORD   := -mno-multiple
 KBUILD_CFLAGS_MODULE += $(call cc-option,-mno-save-toc-indirect)
 else
 KBUILD_CFLAGS += $(call cc-option,-mbig-endian)
-LDFLAGS                += -EB
+KBUILD_LDFLAGS += -EB
 LDEMULATION    := ppc
 GNUTARGET      := powerpc
 MULTIPLEWORD   := -mmultiple
@@ -108,7 +108,7 @@ aflags-$(CONFIG_CPU_LITTLE_ENDIAN)  += -mlittle-endian
 ifeq ($(HAS_BIARCH),y)
 KBUILD_CFLAGS  += -m$(BITS)
 KBUILD_AFLAGS  += -m$(BITS) -Wl,-a$(BITS)
-LDFLAGS                += -m elf$(BITS)$(LDEMULATION)
+KBUILD_LDFLAGS += -m elf$(BITS)$(LDEMULATION)
 KBUILD_ARFLAGS += --target=elf$(BITS)-$(GNUTARGET)
 endif
 
index 6761187..13a688f 100644 (file)
 
 #define _PAGE_PTE              0x4000000000000000UL    /* distinguishes PTEs from pointers */
 #define _PAGE_PRESENT          0x8000000000000000UL    /* pte contains a translation */
+/*
+ * We need to mark a pmd pte invalid while splitting. We can do that by clearing
+ * the _PAGE_PRESENT bit. But then that will be taken as a swap pte. In order to
+ * differentiate between two use a SW field when invalidating.
+ *
+ * We do that temporary invalidate for regular pte entry in ptep_set_access_flags
+ *
+ * This is used only when _PAGE_PRESENT is cleared.
+ */
+#define _PAGE_INVALID          _RPAGE_SW0
 
 /*
  * Top and bottom bits of RPN which can be used by hash
@@ -568,7 +578,13 @@ static inline pte_t pte_clear_savedwrite(pte_t pte)
 
 static inline int pte_present(pte_t pte)
 {
-       return !!(pte_raw(pte) & cpu_to_be64(_PAGE_PRESENT));
+       /*
+        * A pte is considerent present if _PAGE_PRESENT is set.
+        * We also need to consider the pte present which is marked
+        * invalid during ptep_set_access_flags. Hence we look for _PAGE_INVALID
+        * if we find _PAGE_PRESENT cleared.
+        */
+       return !!(pte_raw(pte) & cpu_to_be64(_PAGE_PRESENT | _PAGE_INVALID));
 }
 
 #ifdef CONFIG_PPC_MEM_KEYS
index 2160be2..b321c82 100644 (file)
@@ -51,17 +51,14 @@ static inline int pte_present(pte_t pte)
 #define pte_access_permitted pte_access_permitted
 static inline bool pte_access_permitted(pte_t pte, bool write)
 {
-       unsigned long pteval = pte_val(pte);
        /*
         * A read-only access is controlled by _PAGE_USER bit.
         * We have _PAGE_READ set for WRITE and EXECUTE
         */
-       unsigned long need_pte_bits = _PAGE_PRESENT | _PAGE_USER;
-
-       if (write)
-               need_pte_bits |= _PAGE_WRITE;
+       if (!pte_present(pte) || !pte_user(pte) || !pte_read(pte))
+               return false;
 
-       if ((pteval & need_pte_bits) != need_pte_bits)
+       if (write && !pte_write(pte))
                return false;
 
        return true;
index 834e7e2..ff38664 100644 (file)
@@ -308,6 +308,7 @@ extern void opal_configure_cores(void);
 extern int opal_get_chars(uint32_t vtermno, char *buf, int count);
 extern int opal_put_chars(uint32_t vtermno, const char *buf, int total_len);
 extern int opal_put_chars_atomic(uint32_t vtermno, const char *buf, int total_len);
+extern int opal_flush_chars(uint32_t vtermno, bool wait);
 extern int opal_flush_console(uint32_t vtermno);
 
 extern void hvc_opal_init_early(void);
index 16b0778..a4a718d 100644 (file)
@@ -92,6 +92,7 @@ extern int stop_topology_update(void);
 extern int prrn_is_enabled(void);
 extern int find_and_online_cpu_nid(int cpu);
 extern int timed_topology_update(int nsecs);
+extern void __init shared_proc_topology_init(void);
 #else
 static inline int start_topology_update(void)
 {
@@ -113,6 +114,10 @@ static inline int timed_topology_update(int nsecs)
 {
        return 0;
 }
+
+#ifdef CONFIG_SMP
+static inline void shared_proc_topology_init(void) {}
+#endif
 #endif /* CONFIG_NUMA && CONFIG_PPC_SPLPAR */
 
 #include <asm-generic/topology.h>
index 986ec47..a711d22 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/crash_dump.h>
 #include <linux/kobject.h>
 #include <linux/sysfs.h>
+#include <linux/slab.h>
 
 #include <asm/debugfs.h>
 #include <asm/page.h>
@@ -1019,13 +1020,6 @@ static int fadump_setup_crash_memory_ranges(void)
        pr_debug("Setup crash memory ranges.\n");
        crash_mem_ranges = 0;
 
-       /* allocate memory for crash memory ranges for the first time */
-       if (!max_crash_mem_ranges) {
-               ret = allocate_crash_memory_ranges();
-               if (ret)
-                       return ret;
-       }
-
        /*
         * add the first memory chunk (RMA_START through boot_memory_size) as
         * a separate memory chunk. The reason is, at the time crash firmware
index dd7471f..a09b3c7 100644 (file)
@@ -32,6 +32,8 @@ END_FTR_SECTION_IFCLR(CPU_FTR_CAN_NAP)
        cmpwi   0,r4,0
        beqlr
 
+       /* This sequence is similar to prep_irq_for_idle() */
+
        /* Hard disable interrupts */
        mfmsr   r7
        rldicl  r0,r7,48,1
@@ -41,10 +43,15 @@ END_FTR_SECTION_IFCLR(CPU_FTR_CAN_NAP)
        /* Check if something happened while soft-disabled */
        lbz     r0,PACAIRQHAPPENED(r13)
        cmpwi   cr0,r0,0
-       bnelr
+       bne-    2f
 
-       /* Soft-enable interrupts */
+       /*
+        * Soft-enable interrupts. This will make power4_fixup_nap return
+        * to our caller with interrupts enabled (soft and hard). The caller
+        * can cope with either interrupts disabled or enabled upon return.
+        */
 #ifdef CONFIG_TRACE_IRQFLAGS
+       /* Tell the tracer interrupts are on, because idle responds to them. */
        mflr    r0
        std     r0,16(r1)
        stdu    r1,-128(r1)
@@ -73,3 +80,8 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
        isync
        b       1b
 
+2:     /* Return if an interrupt had happened while soft disabled */
+       /* Set the HARD_DIS flag because interrupts are now hard disabled */
+       ori     r0,r0,PACA_IRQ_HARD_DIS
+       stb     r0,PACAIRQHAPPENED(r13)
+       blr
index b19d832..61c1fad 100644 (file)
@@ -1160,6 +1160,11 @@ void __init smp_cpus_done(unsigned int max_cpus)
        if (smp_ops && smp_ops->bringup_done)
                smp_ops->bringup_done();
 
+       /*
+        * On a shared LPAR, associativity needs to be requested.
+        * Hence, get numa topology before dumping cpu topology
+        */
+       shared_proc_topology_init();
        dump_numa_cpu_topology();
 
        /*
index 070e96f..c85adb8 100644 (file)
@@ -315,22 +315,21 @@ void user_single_step_siginfo(struct task_struct *tsk,
        info->si_addr = (void __user *)regs->nip;
 }
 
-static bool show_unhandled_signals_ratelimited(void)
+static void show_signal_msg(int signr, struct pt_regs *regs, int code,
+                           unsigned long addr)
 {
        static DEFINE_RATELIMIT_STATE(rs, DEFAULT_RATELIMIT_INTERVAL,
                                      DEFAULT_RATELIMIT_BURST);
-       return show_unhandled_signals && __ratelimit(&rs);
-}
 
-static void show_signal_msg(int signr, struct pt_regs *regs, int code,
-                           unsigned long addr)
-{
-       if (!show_unhandled_signals_ratelimited())
+       if (!show_unhandled_signals)
                return;
 
        if (!unhandled_signal(current, signr))
                return;
 
+       if (!__ratelimit(&rs))
+               return;
+
        pr_info("%s[%d]: %s (%d) at %lx nip %lx lr %lx code %x",
                current->comm, current->pid, signame(signr), signr,
                addr, regs->nip, regs->link, code);
index 574fc1d..3e3a715 100644 (file)
@@ -46,6 +46,7 @@
 #include <linux/compiler.h>
 #include <linux/of.h>
 
+#include <asm/ftrace.h>
 #include <asm/reg.h>
 #include <asm/ppc-opcode.h>
 #include <asm/asm-prototypes.h>
index 47ee43b..614ebb4 100644 (file)
@@ -514,7 +514,7 @@ static void kvmppc_set_msr_pr(struct kvm_vcpu *vcpu, u64 msr)
        /*
         * When switching from 32 to 64-bit, we may have a stale 32-bit
         * magic page around, we need to flush it. Typically 32-bit magic
-        * page will be instanciated when calling into RTAS. Note: We
+        * page will be instantiated when calling into RTAS. Note: We
         * assume that such transition only happens while in kernel mode,
         * ie, we never transition from user 32-bit to kernel 64-bit with
         * a 32-bit magic page around.
index 126f02b..30c2eb7 100644 (file)
@@ -38,7 +38,7 @@
  * Virtual mode variants of the hcalls for use on radix/radix
  * with AIL. They require the VCPU's VP to be "pushed"
  *
- * We still instanciate them here because we use some of the
+ * We still instantiate them here because we use some of the
  * generated utility functions as well in this file.
  */
 #define XIVE_RUNTIME_CHECKS
index 4a892d8..dbd8f76 100644 (file)
 #include <asm/mmu_context.h>
 #include <asm/pgalloc.h>
 
-static DEFINE_SPINLOCK(mmu_context_lock);
 static DEFINE_IDA(mmu_context_ida);
 
 static int alloc_context_id(int min_id, int max_id)
 {
-       int index, err;
-
-again:
-       if (!ida_pre_get(&mmu_context_ida, GFP_KERNEL))
-               return -ENOMEM;
-
-       spin_lock(&mmu_context_lock);
-       err = ida_get_new_above(&mmu_context_ida, min_id, &index);
-       spin_unlock(&mmu_context_lock);
-
-       if (err == -EAGAIN)
-               goto again;
-       else if (err)
-               return err;
-
-       if (index > max_id) {
-               spin_lock(&mmu_context_lock);
-               ida_remove(&mmu_context_ida, index);
-               spin_unlock(&mmu_context_lock);
-               return -ENOMEM;
-       }
-
-       return index;
+       return ida_alloc_range(&mmu_context_ida, min_id, max_id, GFP_KERNEL);
 }
 
 void hash__reserve_context_id(int id)
 {
-       int rc, result = 0;
-
-       do {
-               if (!ida_pre_get(&mmu_context_ida, GFP_KERNEL))
-                       break;
-
-               spin_lock(&mmu_context_lock);
-               rc = ida_get_new_above(&mmu_context_ida, id, &result);
-               spin_unlock(&mmu_context_lock);
-       } while (rc == -EAGAIN);
+       int result = ida_alloc_range(&mmu_context_ida, id, id, GFP_KERNEL);
 
        WARN(result != id, "mmu: Failed to reserve context id %d (rc %d)\n", id, result);
 }
@@ -172,9 +140,7 @@ int init_new_context(struct task_struct *tsk, struct mm_struct *mm)
 
 void __destroy_context(int context_id)
 {
-       spin_lock(&mmu_context_lock);
-       ida_remove(&mmu_context_ida, context_id);
-       spin_unlock(&mmu_context_lock);
+       ida_free(&mmu_context_ida, context_id);
 }
 EXPORT_SYMBOL_GPL(__destroy_context);
 
@@ -182,13 +148,11 @@ static void destroy_contexts(mm_context_t *ctx)
 {
        int index, context_id;
 
-       spin_lock(&mmu_context_lock);
        for (index = 0; index < ARRAY_SIZE(ctx->extended_id); index++) {
                context_id = ctx->extended_id[index];
                if (context_id)
-                       ida_remove(&mmu_context_ida, context_id);
+                       ida_free(&mmu_context_ida, context_id);
        }
-       spin_unlock(&mmu_context_lock);
 }
 
 static void pte_frag_destroy(void *pte_frag)
index a4ca576..c9ee9e2 100644 (file)
@@ -129,6 +129,7 @@ long mm_iommu_get(struct mm_struct *mm, unsigned long ua, unsigned long entries,
        long i, j, ret = 0, locked_entries = 0;
        unsigned int pageshift;
        unsigned long flags;
+       unsigned long cur_ua;
        struct page *page = NULL;
 
        mutex_lock(&mem_list_mutex);
@@ -177,7 +178,8 @@ long mm_iommu_get(struct mm_struct *mm, unsigned long ua, unsigned long entries,
        }
 
        for (i = 0; i < entries; ++i) {
-               if (1 != get_user_pages_fast(ua + (i << PAGE_SHIFT),
+               cur_ua = ua + (i << PAGE_SHIFT);
+               if (1 != get_user_pages_fast(cur_ua,
                                        1/* pages */, 1/* iswrite */, &page)) {
                        ret = -EFAULT;
                        for (j = 0; j < i; ++j)
@@ -196,7 +198,7 @@ long mm_iommu_get(struct mm_struct *mm, unsigned long ua, unsigned long entries,
                if (is_migrate_cma_page(page)) {
                        if (mm_iommu_move_page_from_cma(page))
                                goto populate;
-                       if (1 != get_user_pages_fast(ua + (i << PAGE_SHIFT),
+                       if (1 != get_user_pages_fast(cur_ua,
                                                1/* pages */, 1/* iswrite */,
                                                &page)) {
                                ret = -EFAULT;
@@ -210,20 +212,21 @@ long mm_iommu_get(struct mm_struct *mm, unsigned long ua, unsigned long entries,
                }
 populate:
                pageshift = PAGE_SHIFT;
-               if (PageCompound(page)) {
+               if (mem->pageshift > PAGE_SHIFT && PageCompound(page)) {
                        pte_t *pte;
                        struct page *head = compound_head(page);
                        unsigned int compshift = compound_order(head);
+                       unsigned int pteshift;
 
                        local_irq_save(flags); /* disables as well */
-                       pte = find_linux_pte(mm->pgd, ua, NULL, &pageshift);
-                       local_irq_restore(flags);
+                       pte = find_linux_pte(mm->pgd, cur_ua, NULL, &pteshift);
 
                        /* Double check it is still the same pinned page */
                        if (pte && pte_page(*pte) == head &&
-                                       pageshift == compshift)
-                               pageshift = max_t(unsigned int, pageshift,
+                           pteshift == compshift + PAGE_SHIFT)
+                               pageshift = max_t(unsigned int, pteshift,
                                                PAGE_SHIFT);
+                       local_irq_restore(flags);
                }
                mem->pageshift = min(mem->pageshift, pageshift);
                mem->hpas[i] = page_to_pfn(page) << PAGE_SHIFT;
index 0c7e05d..35ac542 100644 (file)
@@ -1078,7 +1078,6 @@ static int prrn_enabled;
 static void reset_topology_timer(void);
 static int topology_timer_secs = 1;
 static int topology_inited;
-static int topology_update_needed;
 
 /*
  * Change polling interval for associativity changes.
@@ -1306,11 +1305,8 @@ int numa_update_cpu_topology(bool cpus_locked)
        struct device *dev;
        int weight, new_nid, i = 0;
 
-       if (!prrn_enabled && !vphn_enabled) {
-               if (!topology_inited)
-                       topology_update_needed = 1;
+       if (!prrn_enabled && !vphn_enabled && topology_inited)
                return 0;
-       }
 
        weight = cpumask_weight(&cpu_associativity_changes_mask);
        if (!weight)
@@ -1423,7 +1419,6 @@ int numa_update_cpu_topology(bool cpus_locked)
 
 out:
        kfree(updates);
-       topology_update_needed = 0;
        return changed;
 }
 
@@ -1551,6 +1546,15 @@ int prrn_is_enabled(void)
        return prrn_enabled;
 }
 
+void __init shared_proc_topology_init(void)
+{
+       if (lppaca_shared_proc(get_lppaca())) {
+               bitmap_fill(cpumask_bits(&cpu_associativity_changes_mask),
+                           nr_cpumask_bits);
+               numa_update_cpu_topology(false);
+       }
+}
+
 static int topology_read(struct seq_file *file, void *v)
 {
        if (vphn_enabled || prrn_enabled)
@@ -1608,10 +1612,6 @@ static int topology_update_init(void)
                return -ENOMEM;
 
        topology_inited = 1;
-       if (topology_update_needed)
-               bitmap_fill(cpumask_bits(&cpu_associativity_changes_mask),
-                                       nr_cpumask_bits);
-
        return 0;
 }
 device_initcall(topology_update_init);
index 7be99fd..c879979 100644 (file)
@@ -1045,20 +1045,22 @@ void radix__ptep_set_access_flags(struct vm_area_struct *vma, pte_t *ptep,
        struct mm_struct *mm = vma->vm_mm;
        unsigned long set = pte_val(entry) & (_PAGE_DIRTY | _PAGE_ACCESSED |
                                              _PAGE_RW | _PAGE_EXEC);
+
+       unsigned long change = pte_val(entry) ^ pte_val(*ptep);
        /*
         * To avoid NMMU hang while relaxing access, we need mark
         * the pte invalid in between.
         */
-       if (atomic_read(&mm->context.copros) > 0) {
+       if ((change & _PAGE_RW) && atomic_read(&mm->context.copros) > 0) {
                unsigned long old_pte, new_pte;
 
-               old_pte = __radix_pte_update(ptep, ~0, 0);
+               old_pte = __radix_pte_update(ptep, _PAGE_PRESENT, _PAGE_INVALID);
                /*
                 * new value of pte
                 */
                new_pte = old_pte | set;
                radix__flush_tlb_page_psize(mm, address, psize);
-               __radix_pte_update(ptep, 0, new_pte);
+               __radix_pte_update(ptep, _PAGE_INVALID, new_pte);
        } else {
                __radix_pte_update(ptep, 0, set);
                /*
index 0b095fa..9f574e5 100644 (file)
@@ -70,7 +70,7 @@ static inline void slb_shadow_update(unsigned long ea, int ssize,
 
 static inline void slb_shadow_clear(enum slb_index index)
 {
-       WRITE_ONCE(get_slb_shadow()->save_area[index].esid, 0);
+       WRITE_ONCE(get_slb_shadow()->save_area[index].esid, cpu_to_be64(index));
 }
 
 static inline void create_shadowed_slbe(unsigned long ea, int ssize,
index fa89f30..d4d4118 100644 (file)
@@ -1192,7 +1192,7 @@ static void pmac_i2c_devscan(void (*callback)(struct device_node *dev,
                { NULL, NULL, 0 },
        };
 
-       /* Only some devices need to have platform functions instanciated
+       /* Only some devices need to have platform functions instantiated
         * here. For now, we have a table. Others, like 9554 i2c GPIOs used
         * on Xserve, if we ever do a driver for them, will use their own
         * platform function instance
index 404c379..38fe408 100644 (file)
@@ -370,12 +370,8 @@ static int __opal_put_chars(uint32_t vtermno, const char *data, int total_len, b
        olen = cpu_to_be64(total_len);
        rc = opal_console_write(vtermno, &olen, data);
        if (rc == OPAL_BUSY || rc == OPAL_BUSY_EVENT) {
-               if (rc == OPAL_BUSY_EVENT) {
-                       mdelay(OPAL_BUSY_DELAY_MS);
+               if (rc == OPAL_BUSY_EVENT)
                        opal_poll_events(NULL);
-               } else if (rc == OPAL_BUSY_EVENT) {
-                       mdelay(OPAL_BUSY_DELAY_MS);
-               }
                written = -EAGAIN;
                goto out;
        }
@@ -401,15 +397,6 @@ out:
        if (atomic)
                spin_unlock_irqrestore(&opal_write_lock, flags);
 
-       /* In the -EAGAIN case, callers loop, so we have to flush the console
-        * here in case they have interrupts off (and we don't want to wait
-        * for async flushing if we can make immediate progress here). If
-        * necessary the API could be made entirely non-flushing if the
-        * callers had a ->flush API to use.
-        */
-       if (written == -EAGAIN)
-               opal_flush_console(vtermno);
-
        return written;
 }
 
@@ -429,40 +416,74 @@ int opal_put_chars_atomic(uint32_t vtermno, const char *data, int total_len)
        return __opal_put_chars(vtermno, data, total_len, true);
 }
 
-int opal_flush_console(uint32_t vtermno)
+static s64 __opal_flush_console(uint32_t vtermno)
 {
        s64 rc;
 
        if (!opal_check_token(OPAL_CONSOLE_FLUSH)) {
                __be64 evt;
 
-               WARN_ONCE(1, "opal: OPAL_CONSOLE_FLUSH missing.\n");
                /*
                 * If OPAL_CONSOLE_FLUSH is not implemented in the firmware,
                 * the console can still be flushed by calling the polling
                 * function while it has OPAL_EVENT_CONSOLE_OUTPUT events.
                 */
-               do {
-                       opal_poll_events(&evt);
-               } while (be64_to_cpu(evt) & OPAL_EVENT_CONSOLE_OUTPUT);
+               WARN_ONCE(1, "opal: OPAL_CONSOLE_FLUSH missing.\n");
+
+               opal_poll_events(&evt);
+               if (!(be64_to_cpu(evt) & OPAL_EVENT_CONSOLE_OUTPUT))
+                       return OPAL_SUCCESS;
+               return OPAL_BUSY;
 
-               return OPAL_SUCCESS;
+       } else {
+               rc = opal_console_flush(vtermno);
+               if (rc == OPAL_BUSY_EVENT) {
+                       opal_poll_events(NULL);
+                       rc = OPAL_BUSY;
+               }
+               return rc;
        }
 
-       do  {
-               rc = OPAL_BUSY;
-               while (rc == OPAL_BUSY || rc == OPAL_BUSY_EVENT) {
-                       rc = opal_console_flush(vtermno);
-                       if (rc == OPAL_BUSY_EVENT) {
-                               mdelay(OPAL_BUSY_DELAY_MS);
-                               opal_poll_events(NULL);
-                       } else if (rc == OPAL_BUSY) {
-                               mdelay(OPAL_BUSY_DELAY_MS);
+}
+
+/*
+ * opal_flush_console spins until the console is flushed
+ */
+int opal_flush_console(uint32_t vtermno)
+{
+       for (;;) {
+               s64 rc = __opal_flush_console(vtermno);
+
+               if (rc == OPAL_BUSY || rc == OPAL_PARTIAL) {
+                       mdelay(1);
+                       continue;
+               }
+
+               return opal_error_code(rc);
+       }
+}
+
+/*
+ * opal_flush_chars is an hvc interface that sleeps until the console is
+ * flushed if wait, otherwise it will return -EBUSY if the console has data,
+ * -EAGAIN if it has data and some of it was flushed.
+ */
+int opal_flush_chars(uint32_t vtermno, bool wait)
+{
+       for (;;) {
+               s64 rc = __opal_flush_console(vtermno);
+
+               if (rc == OPAL_BUSY || rc == OPAL_PARTIAL) {
+                       if (wait) {
+                               msleep(OPAL_BUSY_DELAY_MS);
+                               continue;
                        }
+                       if (rc == OPAL_PARTIAL)
+                               return -EAGAIN;
                }
-       } while (rc == OPAL_PARTIAL); /* More to flush */
 
-       return opal_error_code(rc);
+               return opal_error_code(rc);
+       }
 }
 
 static int opal_recover_mce(struct pt_regs *regs,
index 4e6302b..cde7102 100644 (file)
@@ -3228,12 +3228,49 @@ static void pnv_pci_ioda_create_dbgfs(void)
 #endif /* CONFIG_DEBUG_FS */
 }
 
+static void pnv_pci_enable_bridge(struct pci_bus *bus)
+{
+       struct pci_dev *dev = bus->self;
+       struct pci_bus *child;
+
+       /* Empty bus ? bail */
+       if (list_empty(&bus->devices))
+               return;
+
+       /*
+        * If there's a bridge associated with that bus enable it. This works
+        * around races in the generic code if the enabling is done during
+        * parallel probing. This can be removed once those races have been
+        * fixed.
+        */
+       if (dev) {
+               int rc = pci_enable_device(dev);
+               if (rc)
+                       pci_err(dev, "Error enabling bridge (%d)\n", rc);
+               pci_set_master(dev);
+       }
+
+       /* Perform the same to child busses */
+       list_for_each_entry(child, &bus->children, node)
+               pnv_pci_enable_bridge(child);
+}
+
+static void pnv_pci_enable_bridges(void)
+{
+       struct pci_controller *hose;
+
+       list_for_each_entry(hose, &hose_list, list_node)
+               pnv_pci_enable_bridge(hose->bus);
+}
+
 static void pnv_pci_ioda_fixup(void)
 {
        pnv_pci_ioda_setup_PEs();
        pnv_pci_ioda_setup_iommu_api();
        pnv_pci_ioda_create_dbgfs();
 
+       pnv_pci_enable_bridges();
+
 #ifdef CONFIG_EEH
        pnv_eeh_post_init();
 #endif
index ff9f488..e59e0e6 100644 (file)
@@ -515,35 +515,17 @@ int init_winctx_regs(struct vas_window *window, struct vas_winctx *winctx)
        return 0;
 }
 
-static DEFINE_SPINLOCK(vas_ida_lock);
-
 static void vas_release_window_id(struct ida *ida, int winid)
 {
-       spin_lock(&vas_ida_lock);
-       ida_remove(ida, winid);
-       spin_unlock(&vas_ida_lock);
+       ida_free(ida, winid);
 }
 
 static int vas_assign_window_id(struct ida *ida)
 {
-       int rc, winid;
-
-       do {
-               rc = ida_pre_get(ida, GFP_KERNEL);
-               if (!rc)
-                       return -EAGAIN;
-
-               spin_lock(&vas_ida_lock);
-               rc = ida_get_new(ida, &winid);
-               spin_unlock(&vas_ida_lock);
-       } while (rc == -EAGAIN);
-
-       if (rc)
-               return rc;
+       int winid = ida_alloc_max(ida, VAS_WINDOWS_PER_CHIP - 1, GFP_KERNEL);
 
-       if (winid > VAS_WINDOWS_PER_CHIP) {
-               pr_err("Too many (%d) open windows\n", winid);
-               vas_release_window_id(ida, winid);
+       if (winid == -ENOSPC) {
+               pr_err("Too many (%d) open windows\n", VAS_WINDOWS_PER_CHIP);
                return -EAGAIN;
        }
 
index e8f5b05..959a2a6 100644 (file)
@@ -266,7 +266,7 @@ static unsigned int xive_get_irq(void)
         * of pending priorities. This will also have the effect of
         * updating the CPPR to the most favored pending interrupts.
         *
-        * In the future, if we have a way to differenciate a first
+        * In the future, if we have a way to differentiate a first
         * entry (on HW interrupt) from a replay triggered by EOI,
         * we could skip this on replays unless we soft-mask tells us
         * that a new HW interrupt occurred.
index 9ddd88b..61ec424 100644 (file)
@@ -29,7 +29,7 @@ ifeq ($(CONFIG_ARCH_RV64I),y)
        KBUILD_CFLAGS   += $(call cc-ifversion, -ge, 0500, -DCONFIG_ARCH_SUPPORTS_INT128)
 
        KBUILD_MARCH = rv64im
-       LDFLAGS += -melf64lriscv
+       KBUILD_LDFLAGS += -melf64lriscv
 else
        BITS := 32
        UTS_MACHINE := riscv32
@@ -37,7 +37,7 @@ else
        KBUILD_CFLAGS += -mabi=ilp32
        KBUILD_AFLAGS += -mabi=ilp32
        KBUILD_MARCH = rv32im
-       LDFLAGS += -melf32lriscv
+       KBUILD_LDFLAGS += -melf32lriscv
 endif
 
 KBUILD_CFLAGS += -Wall
index 576ffdc..efdbe31 100644 (file)
@@ -1,6 +1,7 @@
 generic-y += bugs.h
 generic-y += cacheflush.h
 generic-y += checksum.h
+generic-y += compat.h
 generic-y += cputime.h
 generic-y += device.h
 generic-y += div64.h
diff --git a/arch/riscv/include/asm/compat.h b/arch/riscv/include/asm/compat.h
deleted file mode 100644 (file)
index 044aecf..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2012 ARM Ltd.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-#ifndef __ASM_COMPAT_H
-#define __ASM_COMPAT_H
-#ifdef CONFIG_COMPAT
-
-#if defined(CONFIG_64BIT)
-#define COMPAT_UTS_MACHINE "riscv64\0\0"
-#elif defined(CONFIG_32BIT)
-#define COMPAT_UTS_MACHINE "riscv32\0\0"
-#else
-#error "Unknown RISC-V base ISA"
-#endif
-
-#endif /*CONFIG_COMPAT*/
-#endif /*__ASM_COMPAT_H*/
index 080fb28..0caea01 100644 (file)
  *   GNU General Public License for more details.
  */
 
+/*
+ * There is explicitly no include guard here because this file is expected to
+ * be included multiple times.  See uapi/asm/syscalls.h for more info.
+ */
+
 #define __ARCH_WANT_SYS_CLONE
 #include <uapi/asm/unistd.h>
 #include <uapi/asm/syscalls.h>
index 541544d..ec6180a 100644 (file)
@@ -38,8 +38,6 @@ struct vdso_data {
        (void __user *)((unsigned long)(base) + __vdso_##name);                 \
 })
 
-#ifdef CONFIG_SMP
 asmlinkage long sys_riscv_flush_icache(uintptr_t, uintptr_t, uintptr_t);
-#endif
 
 #endif /* _ASM_RISCV_VDSO_H */
index 818655b..206dc4b 100644 (file)
@@ -1,10 +1,13 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 /*
- * Copyright (C) 2017 SiFive
+ * Copyright (C) 2017-2018 SiFive
  */
 
-#ifndef _ASM__UAPI__SYSCALLS_H
-#define _ASM__UAPI__SYSCALLS_H
+/*
+ * There is explicitly no include guard here because this file is expected to
+ * be included multiple times in order to define the syscall macros via
+ * __SYSCALL.
+ */
 
 /*
  * Allows the instruction cache to be flushed from userspace.  Despite RISC-V
@@ -20,7 +23,7 @@
  * caller.  We don't currently do anything with the address range, that's just
  * in there for forwards compatibility.
  */
+#ifndef __NR_riscv_flush_icache
 #define __NR_riscv_flush_icache (__NR_arch_specific_syscall + 15)
-__SYSCALL(__NR_riscv_flush_icache, sys_riscv_flush_icache)
-
 #endif
+__SYSCALL(__NR_riscv_flush_icache, sys_riscv_flush_icache)
index f7181ed..568026c 100644 (file)
@@ -48,7 +48,6 @@ SYSCALL_DEFINE6(mmap2, unsigned long, addr, unsigned long, len,
 }
 #endif /* !CONFIG_64BIT */
 
-#ifdef CONFIG_SMP
 /*
  * Allows the instruction cache to be flushed from userspace.  Despite RISC-V
  * having a direct 'fence.i' instruction available to userspace (which we
@@ -66,15 +65,24 @@ SYSCALL_DEFINE6(mmap2, unsigned long, addr, unsigned long, len,
 SYSCALL_DEFINE3(riscv_flush_icache, uintptr_t, start, uintptr_t, end,
        uintptr_t, flags)
 {
+#ifdef CONFIG_SMP
        struct mm_struct *mm = current->mm;
        bool local = (flags & SYS_RISCV_FLUSH_ICACHE_LOCAL) != 0;
+#endif
 
        /* Check the reserved flags. */
        if (unlikely(flags & ~SYS_RISCV_FLUSH_ICACHE_ALL))
                return -EINVAL;
 
+       /*
+        * Without CONFIG_SMP flush_icache_mm is a just a flush_icache_all(),
+        * which generates unused variable warnings all over this function.
+        */
+#ifdef CONFIG_SMP
        flush_icache_mm(mm, local);
+#else
+       flush_icache_all();
+#endif
 
        return 0;
 }
-#endif
index a6afa60..9a9c7a6 100644 (file)
@@ -135,11 +135,12 @@ config S390
        select HAVE_DYNAMIC_FTRACE
        select HAVE_DYNAMIC_FTRACE_WITH_REGS
        select HAVE_EFFICIENT_UNALIGNED_ACCESS
+       select HAVE_FENTRY
        select HAVE_FTRACE_MCOUNT_RECORD
        select HAVE_FUNCTION_GRAPH_TRACER
        select HAVE_FUNCTION_TRACER
        select HAVE_FUTEX_CMPXCHG if FUTEX
-       select HAVE_GCC_PLUGINS if BROKEN
+       select HAVE_GCC_PLUGINS
        select HAVE_KERNEL_BZIP2
        select HAVE_KERNEL_GZIP
        select HAVE_KERNEL_LZ4
@@ -157,6 +158,7 @@ config S390
        select HAVE_MEMBLOCK_NODE_MAP
        select HAVE_MEMBLOCK_PHYS_MAP
        select HAVE_MOD_ARCH_SPECIFIC
+       select HAVE_NOP_MCOUNT
        select HAVE_OPROFILE
        select HAVE_PERF_EVENTS
        select HAVE_REGS_AND_STACK_ACCESS_API
index eee6703..ee65185 100644 (file)
@@ -11,7 +11,7 @@
 #
 
 LD_BFD         := elf64-s390
-LDFLAGS                := -m elf64_s390
+KBUILD_LDFLAGS := -m elf64_s390
 KBUILD_AFLAGS_MODULE += -fPIC
 KBUILD_CFLAGS_MODULE += -fPIC
 KBUILD_AFLAGS  += -m64
@@ -96,13 +96,15 @@ ifdef CONFIG_EXPOLINE
 endif
 
 ifdef CONFIG_FUNCTION_TRACER
-# make use of hotpatch feature if the compiler supports it
-cc_hotpatch    := -mhotpatch=0,3
-ifeq ($(call cc-option-yn,$(cc_hotpatch)),y)
-CC_FLAGS_FTRACE := $(cc_hotpatch)
-KBUILD_AFLAGS  += -DCC_USING_HOTPATCH
-KBUILD_CFLAGS  += -DCC_USING_HOTPATCH
-endif
+  ifeq ($(call cc-option-yn,-mfentry -mnop-mcount),n)
+    # make use of hotpatch feature if the compiler supports it
+    cc_hotpatch        := -mhotpatch=0,3
+    ifeq ($(call cc-option-yn,$(cc_hotpatch)),y)
+      CC_FLAGS_FTRACE := $(cc_hotpatch)
+      KBUILD_AFLAGS    += -DCC_USING_HOTPATCH
+      KBUILD_CFLAGS    += -DCC_USING_HOTPATCH
+    endif
+  endif
 endif
 
 # Test CFI features of binutils
index 046e044..8c00fd5 100644 (file)
@@ -49,23 +49,23 @@ struct ap_queue_status {
 /**
  * ap_intructions_available() - Test if AP instructions are available.
  *
- * Returns 0 if the AP instructions are installed.
+ * Returns true if the AP instructions are installed, otherwise false.
  */
-static inline int ap_instructions_available(void)
+static inline bool ap_instructions_available(void)
 {
        register unsigned long reg0 asm ("0") = AP_MKQID(0, 0);
-       register unsigned long reg1 asm ("1") = -ENODEV;
-       register unsigned long reg2 asm ("2");
+       register unsigned long reg1 asm ("1") = 0;
+       register unsigned long reg2 asm ("2") = 0;
 
        asm volatile(
                "   .long 0xb2af0000\n"         /* PQAP(TAPQ) */
-               "0: la    %0,0\n"
+               "0: la    %0,1\n"
                "1:\n"
                EX_TABLE(0b, 1b)
-               : "+d" (reg1), "=d" (reg2)
+               : "+d" (reg1), "+d" (reg2)
                : "d" (reg0)
                : "cc");
-       return reg1;
+       return reg1 != 0;
 }
 
 /**
index cfccc0e..8ea270f 100644 (file)
@@ -4,7 +4,7 @@
 
 #define ARCH_SUPPORTS_FTRACE_OPS 1
 
-#ifdef CC_USING_HOTPATCH
+#if defined(CC_USING_HOTPATCH) || defined(CC_USING_NOP_MCOUNT)
 #define MCOUNT_INSN_SIZE       6
 #else
 #define MCOUNT_INSN_SIZE       24
@@ -42,7 +42,7 @@ struct ftrace_insn {
 static inline void ftrace_generate_nop_insn(struct ftrace_insn *insn)
 {
 #ifdef CONFIG_FUNCTION_TRACER
-#ifdef CC_USING_HOTPATCH
+#if defined(CC_USING_HOTPATCH) || defined(CC_USING_NOP_MCOUNT)
        /* brcl 0,0 */
        insn->opc = 0xc004;
        insn->disp = 0;
@@ -57,7 +57,7 @@ static inline void ftrace_generate_nop_insn(struct ftrace_insn *insn)
 static inline int is_ftrace_nop(struct ftrace_insn *insn)
 {
 #ifdef CONFIG_FUNCTION_TRACER
-#ifdef CC_USING_HOTPATCH
+#if defined(CC_USING_HOTPATCH) || defined(CC_USING_NOP_MCOUNT)
        if (insn->disp == 0)
                return 1;
 #else
index b62e061..2bb1f3b 100644 (file)
  * - length(n_modulus) = inputdatalength
  */
 struct ica_rsa_modexpo {
-       char __user *   inputdata;
-       unsigned int    inputdatalength;
-       char __user *   outputdata;
-       unsigned int    outputdatalength;
-       char __user *   b_key;
-       char __user *   n_modulus;
+       char __user  *inputdata;
+       unsigned int  inputdatalength;
+       char __user  *outputdata;
+       unsigned int  outputdatalength;
+       char __user  *b_key;
+       char __user  *n_modulus;
 };
 
 /**
@@ -55,15 +55,15 @@ struct ica_rsa_modexpo {
  * - length(u_mult_inv) = inputdatalength/2 + 8
  */
 struct ica_rsa_modexpo_crt {
-       char __user *   inputdata;
-       unsigned int    inputdatalength;
-       char __user *   outputdata;
-       unsigned int    outputdatalength;
-       char __user *   bp_key;
-       char __user *   bq_key;
-       char __user *   np_prime;
-       char __user *   nq_prime;
-       char __user *   u_mult_inv;
+       char __user  *inputdata;
+       unsigned int  inputdatalength;
+       char __user  *outputdata;
+       unsigned int  outputdatalength;
+       char __user  *bp_key;
+       char __user  *bq_key;
+       char __user  *np_prime;
+       char __user  *nq_prime;
+       char __user  *u_mult_inv;
 };
 
 /**
@@ -93,18 +93,18 @@ struct CPRBX {
        unsigned int    req_extbl;      /* request extension block len   */
        unsigned char   pad_001[4];     /* reserved                      */
        unsigned int    rpld_extbl;     /* replied extension block len   */
-       unsigned char   padx000[16 - sizeof (char *)];
-       unsigned char req_parmb;      /* request parm block 'address'  */
-       unsigned char   padx001[16 - sizeof (char *)];
-       unsigned char req_datab;      /* request data block 'address'  */
-       unsigned char   padx002[16 - sizeof (char *)];
-       unsigned char rpl_parmb;      /* reply parm block 'address'    */
-       unsigned char   padx003[16 - sizeof (char *)];
-       unsigned char rpl_datab;      /* reply data block 'address'    */
-       unsigned char   padx004[16 - sizeof (char *)];
-       unsigned char req_extb;       /* request extension block 'addr'*/
-       unsigned char   padx005[16 - sizeof (char *)];
-       unsigned char rpl_extb;       /* reply extension block 'address'*/
+       unsigned char   padx000[16 - sizeof(char *)];
+       unsigned char  *req_parmb;      /* request parm block 'address'  */
+       unsigned char   padx001[16 - sizeof(char *)];
+       unsigned char  *req_datab;      /* request data block 'address'  */
+       unsigned char   padx002[16 - sizeof(char *)];
+       unsigned char  *rpl_parmb;      /* reply parm block 'address'    */
+       unsigned char   padx003[16 - sizeof(char *)];
+       unsigned char  *rpl_datab;      /* reply data block 'address'    */
+       unsigned char   padx004[16 - sizeof(char *)];
+       unsigned char  *req_extb;       /* request extension block 'addr'*/
+       unsigned char   padx005[16 - sizeof(char *)];
+       unsigned char  *rpl_extb;       /* reply extension block 'address'*/
        unsigned short  ccp_rtcode;     /* server return code            */
        unsigned short  ccp_rscode;     /* server reason code            */
        unsigned int    mac_data_len;   /* Mac Data Length               */
@@ -127,17 +127,17 @@ struct ica_xcRB {
        unsigned int    user_defined;
        unsigned short  request_ID;
        unsigned int    request_control_blk_length;
-       unsigned char   padding1[16 - sizeof (char *)];
-       char __user *   request_control_blk_addr;
+       unsigned char   padding1[16 - sizeof(char *)];
+       char __user    *request_control_blk_addr;
        unsigned int    request_data_length;
-       char            padding2[16 - sizeof (char *)];
-       char __user *   request_data_address;
+       char            padding2[16 - sizeof(char *)];
+       char __user    *request_data_address;
        unsigned int    reply_control_blk_length;
-       char            padding3[16 - sizeof (char *)];
-       char __user *   reply_control_blk_addr;
+       char            padding3[16 - sizeof(char *)];
+       char __user    *reply_control_blk_addr;
        unsigned int    reply_data_length;
-       char            padding4[16 - sizeof (char *)];
-       char __user *   reply_data_addr;
+       char            padding4[16 - sizeof(char *)];
+       char __user    *reply_data_addr;
        unsigned short  priority_window;
        unsigned int    status;
 } __attribute__((packed));
@@ -233,7 +233,7 @@ struct zcrypt_device_matrix_ext {
        struct zcrypt_device_status_ext device[MAX_ZDEV_ENTRIES_EXT];
 };
 
-#define AUTOSELECT ((unsigned int)0xFFFFFFFF)
+#define AUTOSELECT 0xFFFFFFFF
 
 #define ZCRYPT_IOCTL_MAGIC 'z'
 
index 11aea74..66e830f 100644 (file)
 #include <asm/gmap.h>
 #include <asm/nmi.h>
 
-/*
- * Make sure that the compiler is new enough. We want a compiler that
- * is known to work with the "Q" assembler constraint.
- */
-#if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 3)
-#error Your compiler is too old; please use version 4.3 or newer
-#endif
-
 int main(void)
 {
        /* task struct offsets */
index c3620ba..376f6b6 100644 (file)
@@ -293,19 +293,6 @@ int remap_oldmem_pfn_range(struct vm_area_struct *vma, unsigned long from,
                                                       prot);
 }
 
-/*
- * Alloc memory and panic in case of ENOMEM
- */
-static void *kzalloc_panic(int len)
-{
-       void *rc;
-
-       rc = kzalloc(len, GFP_KERNEL);
-       if (!rc)
-               panic("s390 kdump kzalloc (%d) failed", len);
-       return rc;
-}
-
 static const char *nt_name(Elf64_Word type)
 {
        const char *name = "LINUX";
@@ -451,11 +438,15 @@ static void *get_vmcoreinfo_old(unsigned long *size)
        if (copy_oldmem_kernel(nt_name, addr + sizeof(note),
                               sizeof(nt_name) - 1))
                return NULL;
-       if (strcmp(nt_name, "VMCOREINFO") != 0)
+       if (strcmp(nt_name, VMCOREINFO_NOTE_NAME) != 0)
+               return NULL;
+       vmcoreinfo = kzalloc(note.n_descsz, GFP_KERNEL);
+       if (!vmcoreinfo)
                return NULL;
-       vmcoreinfo = kzalloc_panic(note.n_descsz);
-       if (copy_oldmem_kernel(vmcoreinfo, addr + 24, note.n_descsz))
+       if (copy_oldmem_kernel(vmcoreinfo, addr + 24, note.n_descsz)) {
+               kfree(vmcoreinfo);
                return NULL;
+       }
        *size = note.n_descsz;
        return vmcoreinfo;
 }
@@ -465,39 +456,38 @@ static void *get_vmcoreinfo_old(unsigned long *size)
  */
 static void *nt_vmcoreinfo(void *ptr)
 {
+       const char *name = VMCOREINFO_NOTE_NAME;
        unsigned long size;
        void *vmcoreinfo;
 
        vmcoreinfo = os_info_old_entry(OS_INFO_VMCOREINFO, &size);
-       if (!vmcoreinfo)
-               vmcoreinfo = get_vmcoreinfo_old(&size);
+       if (vmcoreinfo)
+               return nt_init_name(ptr, 0, vmcoreinfo, size, name);
+
+       vmcoreinfo = get_vmcoreinfo_old(&size);
        if (!vmcoreinfo)
                return ptr;
-       return nt_init_name(ptr, 0, vmcoreinfo, size, "VMCOREINFO");
+       ptr = nt_init_name(ptr, 0, vmcoreinfo, size, name);
+       kfree(vmcoreinfo);
+       return ptr;
 }
 
 static size_t nt_vmcoreinfo_size(void)
 {
-       const char *name = "VMCOREINFO";
-       char nt_name[11];
-       Elf64_Nhdr note;
-       void *addr;
-
-       if (copy_oldmem_kernel(&addr, &S390_lowcore.vmcore_info, sizeof(addr)))
-               return 0;
-
-       if (copy_oldmem_kernel(&note, addr, sizeof(note)))
-               return 0;
+       const char *name = VMCOREINFO_NOTE_NAME;
+       unsigned long size;
+       void *vmcoreinfo;
 
-       memset(nt_name, 0, sizeof(nt_name));
-       if (copy_oldmem_kernel(nt_name, addr + sizeof(note),
-                              sizeof(nt_name) - 1))
-               return 0;
+       vmcoreinfo = os_info_old_entry(OS_INFO_VMCOREINFO, &size);
+       if (vmcoreinfo)
+               return nt_size_name(size, name);
 
-       if (strcmp(nt_name, name) != 0)
+       vmcoreinfo = get_vmcoreinfo_old(&size);
+       if (!vmcoreinfo)
                return 0;
 
-       return nt_size_name(note.n_descsz, name);
+       kfree(vmcoreinfo);
+       return nt_size_name(size, name);
 }
 
 /*
@@ -660,7 +650,15 @@ int elfcorehdr_alloc(unsigned long long *addr, unsigned long long *size)
 
        alloc_size = get_elfcorehdr_size(mem_chunk_cnt);
 
-       hdr = kzalloc_panic(alloc_size);
+       hdr = kzalloc(alloc_size, GFP_KERNEL);
+
+       /* Without elfcorehdr /proc/vmcore cannot be created. Thus creating
+        * a dump with this crash kernel will fail. Panic now to allow other
+        * dump mechanisms to take over.
+        */
+       if (!hdr)
+               panic("s390 kdump allocating elfcorehdr failed");
+
        /* Init elf header */
        ptr = ehdr_init(hdr, mem_chunk_cnt);
        /* Init program headers */
index c15caea..7f8246c 100644 (file)
@@ -111,15 +111,15 @@ __u8 _ebcasc[256] =
           0x07, 0x07, 0x16, 0x07, 0x07, 0x07, 0x07, 0x04,
  /* 0x38  -SBS   -IT  -RFF  -CU3   DC4   NAK  ----   SUB */
           0x07, 0x07, 0x07, 0x07, 0x14, 0x15, 0x07, 0x1A,
- /* 0x40    SP   RSP           \81ä              ----       */
+ /* 0x40    SP   RSP           ä              ----       */
           0x20, 0xFF, 0x83, 0x84, 0x85, 0xA0, 0x07, 0x86,
  /* 0x48                       .     <     (     +     | */
           0x87, 0xA4, 0x9B, 0x2E, 0x3C, 0x28, 0x2B, 0x7C,
  /* 0x50     &                                      ---- */
           0x26, 0x82, 0x88, 0x89, 0x8A, 0xA1, 0x8C, 0x07,
- /* 0x58           \81ß     !     $     *     )     ;       */
+ /* 0x58           ß     !     $     *     )     ;       */
           0x8D, 0xE1, 0x21, 0x24, 0x2A, 0x29, 0x3B, 0xAA,
- /* 0x60     -     /  ----     \81Ä  ----  ----  ----       */
+ /* 0x60     -     /  ----     Ä  ----  ----  ----       */
           0x2D, 0x2F, 0x07, 0x8E, 0x07, 0x07, 0x07, 0x8F,
  /* 0x68              ----     ,     %     _     >     ? */ 
           0x80, 0xA5, 0x07, 0x2C, 0x25, 0x5F, 0x3E, 0x3F,
@@ -131,7 +131,7 @@ __u8 _ebcasc[256] =
           0x07, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
  /* 0x88     h     i              ----  ----  ----       */
           0x68, 0x69, 0xAE, 0xAF, 0x07, 0x07, 0x07, 0xF1,
- /* 0x90     \81°     j     k     l     m     n     o     p */
+ /* 0x90     Â°     j     k     l     m     n     o     p */
           0xF8, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70,
  /* 0x98     q     r                    ----        ---- */
           0x71, 0x72, 0xA6, 0xA7, 0x91, 0x07, 0x92, 0x07,
@@ -139,25 +139,25 @@ __u8 _ebcasc[256] =
           0xE6, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
  /* 0xA8     y     z              ----  ----  ----  ---- */
           0x79, 0x7A, 0xAD, 0xAB, 0x07, 0x07, 0x07, 0x07,
- /* 0xB0     ^                    ----     \81§  ----       */
+ /* 0xB0     ^                    ----     Â§  ----       */
           0x5E, 0x9C, 0x9D, 0xFA, 0x07, 0x07, 0x07, 0xAC,
  /* 0xB8        ----     [     ]  ----  ----  ----  ---- */
           0xAB, 0x07, 0x5B, 0x5D, 0x07, 0x07, 0x07, 0x07,
  /* 0xC0     {     A     B     C     D     E     F     G */
           0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
- /* 0xC8     H     I  ----           \81ö              ---- */
+ /* 0xC8     H     I  ----           ö              ---- */
           0x48, 0x49, 0x07, 0x93, 0x94, 0x95, 0xA2, 0x07,
  /* 0xD0     }     J     K     L     M     N     O     P */
           0x7D, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50,
- /* 0xD8     Q     R  ----           \81ü                   */
+ /* 0xD8     Q     R  ----           ü                   */
           0x51, 0x52, 0x07, 0x96, 0x81, 0x97, 0xA3, 0x98,
  /* 0xE0     \           S     T     U     V     W     X */
           0x5C, 0xF6, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
- /* 0xE8     Y     Z        ----     \81Ö  ----  ----  ---- */
+ /* 0xE8     Y     Z        ----     Ö  ----  ----  ---- */
           0x59, 0x5A, 0xFD, 0x07, 0x99, 0x07, 0x07, 0x07,
  /* 0xF0     0     1     2     3     4     5     6     7 */
           0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
- /* 0xF8     8     9  ----  ----     \81Ü  ----  ----  ---- */
+ /* 0xF8     8     9  ----  ----     Ü  ----  ----  ---- */
           0x38, 0x39, 0x07, 0x07, 0x9A, 0x07, 0x07, 0x07
 };
 
@@ -260,15 +260,15 @@ __u8 _ebcasc_500[256] =
           0x07, 0x07, 0x16, 0x07, 0x07, 0x07, 0x07, 0x04,
  /* 0x38  -SBS   -IT  -RFF  -CU3   DC4   NAK  ----   SUB */
           0x07, 0x07, 0x07, 0x07, 0x14, 0x15, 0x07, 0x1A,
- /* 0x40    SP   RSP           \81ä              ----       */
+ /* 0x40    SP   RSP           ä              ----       */
           0x20, 0xFF, 0x83, 0x84, 0x85, 0xA0, 0x07, 0x86,
  /* 0x48                 [     .     <     (     +     ! */
           0x87, 0xA4, 0x5B, 0x2E, 0x3C, 0x28, 0x2B, 0x21,
  /* 0x50     &                                      ---- */
           0x26, 0x82, 0x88, 0x89, 0x8A, 0xA1, 0x8C, 0x07,
- /* 0x58           \81ß     ]     $     *     )     ;     ^ */
+ /* 0x58           ß     ]     $     *     )     ;     ^ */
           0x8D, 0xE1, 0x5D, 0x24, 0x2A, 0x29, 0x3B, 0x5E,
- /* 0x60     -     /  ----     \81Ä  ----  ----  ----       */
+ /* 0x60     -     /  ----     Ä  ----  ----  ----       */
           0x2D, 0x2F, 0x07, 0x8E, 0x07, 0x07, 0x07, 0x8F,
  /* 0x68              ----     ,     %     _     >     ? */ 
           0x80, 0xA5, 0x07, 0x2C, 0x25, 0x5F, 0x3E, 0x3F,
@@ -280,7 +280,7 @@ __u8 _ebcasc_500[256] =
           0x07, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
  /* 0x88     h     i              ----  ----  ----       */
           0x68, 0x69, 0xAE, 0xAF, 0x07, 0x07, 0x07, 0xF1,
- /* 0x90     \81°     j     k     l     m     n     o     p */
+ /* 0x90     Â°     j     k     l     m     n     o     p */
           0xF8, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70,
  /* 0x98     q     r                    ----        ---- */
           0x71, 0x72, 0xA6, 0xA7, 0x91, 0x07, 0x92, 0x07,
@@ -288,25 +288,25 @@ __u8 _ebcasc_500[256] =
           0xE6, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
  /* 0xA8     y     z              ----  ----  ----  ---- */
           0x79, 0x7A, 0xAD, 0xAB, 0x07, 0x07, 0x07, 0x07,
- /* 0xB0                          ----     \81§  ----       */
+ /* 0xB0                          ----     Â§  ----       */
           0x9B, 0x9C, 0x9D, 0xFA, 0x07, 0x07, 0x07, 0xAC,
  /* 0xB8        ----           |  ----  ----  ----  ---- */
           0xAB, 0x07, 0xAA, 0x7C, 0x07, 0x07, 0x07, 0x07,
  /* 0xC0     {     A     B     C     D     E     F     G */
           0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
- /* 0xC8     H     I  ----           \81ö              ---- */
+ /* 0xC8     H     I  ----           ö              ---- */
           0x48, 0x49, 0x07, 0x93, 0x94, 0x95, 0xA2, 0x07,
  /* 0xD0     }     J     K     L     M     N     O     P */
           0x7D, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50,
- /* 0xD8     Q     R  ----           \81ü                   */
+ /* 0xD8     Q     R  ----           ü                   */
           0x51, 0x52, 0x07, 0x96, 0x81, 0x97, 0xA3, 0x98,
  /* 0xE0     \           S     T     U     V     W     X */
           0x5C, 0xF6, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
- /* 0xE8     Y     Z        ----     \81Ö  ----  ----  ---- */
+ /* 0xE8     Y     Z        ----     Ö  ----  ----  ---- */
           0x59, 0x5A, 0xFD, 0x07, 0x99, 0x07, 0x07, 0x07,
  /* 0xF0     0     1     2     3     4     5     6     7 */
           0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
- /* 0xF8     8     9  ----  ----     \81Ü  ----  ----  ---- */
+ /* 0xF8     8     9  ----  ----     Ü  ----  ----  ---- */
           0x38, 0x39, 0x07, 0x07, 0x9A, 0x07, 0x07, 0x07
 };
 
index dc76d81..84be7f0 100644 (file)
@@ -61,7 +61,7 @@ unsigned long ftrace_plt;
 
 static inline void ftrace_generate_orig_insn(struct ftrace_insn *insn)
 {
-#ifdef CC_USING_HOTPATCH
+#if defined(CC_USING_HOTPATCH) || defined(CC_USING_NOP_MCOUNT)
        /* brcl 0,0 */
        insn->opc = 0xc004;
        insn->disp = 0;
index 27110f3..e93fbf0 100644 (file)
@@ -35,7 +35,7 @@ ENTRY(ftrace_caller)
        .globl  ftrace_regs_caller
        .set    ftrace_regs_caller,ftrace_caller
        lgr     %r1,%r15
-#ifndef CC_USING_HOTPATCH
+#if !(defined(CC_USING_HOTPATCH) || defined(CC_USING_NOP_MCOUNT))
        aghi    %r0,MCOUNT_RETURN_FIXUP
 #endif
        aghi    %r15,-STACK_FRAME_SIZE
index cb198d4..5c53e97 100644 (file)
@@ -665,7 +665,7 @@ static void cpumsf_output_event_pid(struct perf_event *event,
                goto out;
 
        /* Update the process ID (see also kernel/events/core.c) */
-       data->tid_entry.pid = cpumsf_pid_type(event, pid, __PIDTYPE_TGID);
+       data->tid_entry.pid = cpumsf_pid_type(event, pid, PIDTYPE_TGID);
        data->tid_entry.tid = cpumsf_pid_type(event, pid, PIDTYPE_PID);
 
        perf_output_sample(&handle, &header, data, event);
index 4902fed..9f6f392 100644 (file)
@@ -420,7 +420,8 @@ int arch_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
        /* Request MSI interrupts */
        hwirq = 0;
        for_each_pci_msi_entry(msi, pdev) {
-               rc = -EIO;
+               if (hwirq >= msi_vecs)
+                       break;
                irq = irq_alloc_desc(0);        /* Alloc irq on node 0 */
                if (irq < 0)
                        return -ENOMEM;
index 57f7cda..04388a2 100644 (file)
@@ -93,7 +93,6 @@ static int pci_perf_show(struct seq_file *m, void *v)
        }
 
        /* header */
-       seq_printf(m, "FMB @ %p\n", zdev->fmb);
        seq_printf(m, "Update interval: %u ms\n", zdev->fmb_update);
        seq_printf(m, "Samples: %u\n", zdev->fmb->samples);
        seq_printf(m, "Last update TOD: %Lx\n", zdev->fmb->last_update);
index 6530019..c521ade 100644 (file)
@@ -122,11 +122,11 @@ endif
 ifdef CONFIG_CPU_LITTLE_ENDIAN
 ld-bfd                 := elf32-$(UTS_MACHINE)-linux
 LDFLAGS_vmlinux                += --defsym jiffies=jiffies_64 --oformat $(ld-bfd)
-LDFLAGS                        += -EL
+KBUILD_LDFLAGS         += -EL
 else
 ld-bfd                 := elf32-$(UTS_MACHINE)big-linux
 LDFLAGS_vmlinux                += --defsym jiffies=jiffies_64+4 --oformat $(ld-bfd)
-LDFLAGS                        += -EB
+KBUILD_LDFLAGS         += -EB
 endif
 
 export ld-bfd BITS
index 2d58c26..e6f2a38 100644 (file)
@@ -45,9 +45,13 @@ config SPARC
        select LOCKDEP_SMALL if LOCKDEP
        select NEED_DMA_MAP_STATE
        select NEED_SG_DMA_LENGTH
+       select HAVE_MEMBLOCK
+       select NO_BOOTMEM
 
 config SPARC32
        def_bool !64BIT
+       select ARCH_HAS_SYNC_DMA_FOR_CPU
+       select DMA_NONCOHERENT_OPS
        select GENERIC_ATOMIC64
        select CLZ_TAB
        select HAVE_UID16
@@ -60,7 +64,6 @@ config SPARC64
        select HAVE_KRETPROBES
        select HAVE_KPROBES
        select HAVE_RCU_TABLE_FREE if SMP
-       select HAVE_MEMBLOCK
        select HAVE_MEMBLOCK_NODE_MAP
        select HAVE_ARCH_TRANSPARENT_HUGEPAGE
        select HAVE_DYNAMIC_FTRACE
@@ -79,7 +82,6 @@ config SPARC64
        select IRQ_PREFLOW_FASTEOI
        select ARCH_HAVE_NMI_SAFE_CMPXCHG
        select HAVE_C_RECORDMCOUNT
-       select NO_BOOTMEM
        select HAVE_ARCH_AUDITSYSCALL
        select ARCH_SUPPORTS_ATOMIC_RMW
        select HAVE_NMI
index 966a13d..048a033 100644 (file)
@@ -9,10 +9,10 @@
 # Copyright (C) 1998 Jakub Jelinek (jj@ultra.linux.cz)
 
 # We are not yet configured - so test on arch
-ifeq ($(ARCH),sparc)
-        KBUILD_DEFCONFIG := sparc32_defconfig
-else
+ifeq ($(ARCH),sparc64)
         KBUILD_DEFCONFIG := sparc64_defconfig
+else
+        KBUILD_DEFCONFIG := sparc32_defconfig
 endif
 
 ifeq ($(CONFIG_SPARC32),y)
@@ -21,7 +21,7 @@ ifeq ($(CONFIG_SPARC32),y)
 #
 
 CHECKFLAGS     += -D__sparc__
-LDFLAGS        := -m elf32_sparc
+KBUILD_LDFLAGS := -m elf32_sparc
 export BITS    := 32
 UTS_MACHINE    := sparc
 
@@ -40,7 +40,7 @@ else
 #
 
 CHECKFLAGS    += -D__sparc__ -D__sparc_v9__ -D__arch64__
-LDFLAGS       := -m elf64_sparc
+KBUILD_LDFLAGS := -m elf64_sparc
 export BITS   := 64
 UTS_MACHINE   := sparc64
 
index 12ae33d..e175663 100644 (file)
@@ -7,7 +7,6 @@
 #include <linux/dma-debug.h>
 
 extern const struct dma_map_ops *dma_ops;
-extern const struct dma_map_ops pci32_dma_ops;
 
 extern struct bus_type pci_bus_type;
 
@@ -15,11 +14,11 @@ static inline const struct dma_map_ops *get_arch_dma_ops(struct bus_type *bus)
 {
 #ifdef CONFIG_SPARC_LEON
        if (sparc_cpu_model == sparc_leon)
-               return &pci32_dma_ops;
+               return &dma_noncoherent_ops;
 #endif
 #if defined(CONFIG_SPARC32) && defined(CONFIG_PCI)
        if (bus == &pci_bus_type)
-               return &pci32_dma_ops;
+               return &dma_noncoherent_ops;
 #endif
        return dma_ops;
 }
index cca9134..6799c93 100644 (file)
@@ -38,6 +38,7 @@
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
 #include <linux/scatterlist.h>
+#include <linux/dma-noncoherent.h>
 #include <linux/of_device.h>
 
 #include <asm/io.h>
@@ -434,42 +435,41 @@ arch_initcall(sparc_register_ioport);
 /* Allocate and map kernel buffer using consistent mode DMA for a device.
  * hwdev should be valid struct pci_dev pointer for PCI devices.
  */
-static void *pci32_alloc_coherent(struct device *dev, size_t len,
-                                 dma_addr_t *pba, gfp_t gfp,
-                                 unsigned long attrs)
+void *arch_dma_alloc(struct device *dev, size_t size, dma_addr_t *dma_handle,
+               gfp_t gfp, unsigned long attrs)
 {
-       unsigned long len_total = PAGE_ALIGN(len);
+       unsigned long len_total = PAGE_ALIGN(size);
        void *va;
        struct resource *res;
        int order;
 
-       if (len == 0) {
+       if (size == 0) {
                return NULL;
        }
-       if (len > 256*1024) {                   /* __get_free_pages() limit */
+       if (size > 256*1024) {                  /* __get_free_pages() limit */
                return NULL;
        }
 
        order = get_order(len_total);
        va = (void *) __get_free_pages(gfp, order);
        if (va == NULL) {
-               printk("pci_alloc_consistent: no %ld pages\n", len_total>>PAGE_SHIFT);
+               printk("%s: no %ld pages\n", __func__, len_total>>PAGE_SHIFT);
                goto err_nopages;
        }
 
        if ((res = kzalloc(sizeof(struct resource), GFP_KERNEL)) == NULL) {
-               printk("pci_alloc_consistent: no core\n");
+               printk("%s: no core\n", __func__);
                goto err_nomem;
        }
 
        if (allocate_resource(&_sparc_dvma, res, len_total,
            _sparc_dvma.start, _sparc_dvma.end, PAGE_SIZE, NULL, NULL) != 0) {
-               printk("pci_alloc_consistent: cannot occupy 0x%lx", len_total);
+               printk("%s: cannot occupy 0x%lx", __func__, len_total);
                goto err_nova;
        }
        srmmu_mapiorange(0, virt_to_phys(va), res->start, len_total);
 
-       *pba = virt_to_phys(va); /* equals virt_to_bus (R.I.P.) for us. */
+       *dma_handle = virt_to_phys(va);
        return (void *) res->start;
 
 err_nova:
@@ -481,184 +481,53 @@ err_nopages:
 }
 
 /* Free and unmap a consistent DMA buffer.
- * cpu_addr is what was returned from pci_alloc_consistent,
- * size must be the same as what as passed into pci_alloc_consistent,
- * and likewise dma_addr must be the same as what *dma_addrp was set to.
+ * cpu_addr is what was returned arch_dma_alloc, size must be the same as what
+ * was passed into arch_dma_alloc, and likewise dma_addr must be the same as
+ * what *dma_ndler was set to.
  *
  * References to the memory and mappings associated with cpu_addr/dma_addr
  * past this call are illegal.
  */
-static void pci32_free_coherent(struct device *dev, size_t n, void *p,
-                               dma_addr_t ba, unsigned long attrs)
+void arch_dma_free(struct device *dev, size_t size, void *cpu_addr,
+               dma_addr_t dma_addr, unsigned long attrs)
 {
        struct resource *res;
 
        if ((res = lookup_resource(&_sparc_dvma,
-           (unsigned long)p)) == NULL) {
-               printk("pci_free_consistent: cannot free %p\n", p);
+           (unsigned long)cpu_addr)) == NULL) {
+               printk("%s: cannot free %p\n", __func__, cpu_addr);
                return;
        }
 
-       if (((unsigned long)p & (PAGE_SIZE-1)) != 0) {
-               printk("pci_free_consistent: unaligned va %p\n", p);
+       if (((unsigned long)cpu_addr & (PAGE_SIZE-1)) != 0) {
+               printk("%s: unaligned va %p\n", __func__, cpu_addr);
                return;
        }
 
-       n = PAGE_ALIGN(n);
-       if (resource_size(res) != n) {
-               printk("pci_free_consistent: region 0x%lx asked 0x%lx\n",
-                   (long)resource_size(res), (long)n);
+       size = PAGE_ALIGN(size);
+       if (resource_size(res) != size) {
+               printk("%s: region 0x%lx asked 0x%zx\n", __func__,
+                   (long)resource_size(res), size);
                return;
        }
 
-       dma_make_coherent(ba, n);
-       srmmu_unmapiorange((unsigned long)p, n);
+       dma_make_coherent(dma_addr, size);
+       srmmu_unmapiorange((unsigned long)cpu_addr, size);
 
        release_resource(res);
        kfree(res);
-       free_pages((unsigned long)phys_to_virt(ba), get_order(n));
-}
-
-/*
- * Same as pci_map_single, but with pages.
- */
-static dma_addr_t pci32_map_page(struct device *dev, struct page *page,
-                                unsigned long offset, size_t size,
-                                enum dma_data_direction dir,
-                                unsigned long attrs)
-{
-       /* IIep is write-through, not flushing. */
-       return page_to_phys(page) + offset;
-}
-
-static void pci32_unmap_page(struct device *dev, dma_addr_t ba, size_t size,
-                            enum dma_data_direction dir, unsigned long attrs)
-{
-       if (dir != PCI_DMA_TODEVICE && !(attrs & DMA_ATTR_SKIP_CPU_SYNC))
-               dma_make_coherent(ba, PAGE_ALIGN(size));
-}
-
-/* Map a set of buffers described by scatterlist in streaming
- * mode for DMA.  This is the scatter-gather version of the
- * above pci_map_single interface.  Here the scatter gather list
- * elements are each tagged with the appropriate dma address
- * and length.  They are obtained via sg_dma_{address,length}(SG).
- *
- * NOTE: An implementation may be able to use a smaller number of
- *       DMA address/length pairs than there are SG table elements.
- *       (for example via virtual mapping capabilities)
- *       The routine returns the number of addr/length pairs actually
- *       used, at most nents.
- *
- * Device ownership issues as mentioned above for pci_map_single are
- * the same here.
- */
-static int pci32_map_sg(struct device *device, struct scatterlist *sgl,
-                       int nents, enum dma_data_direction dir,
-                       unsigned long attrs)
-{
-       struct scatterlist *sg;
-       int n;
-
-       /* IIep is write-through, not flushing. */
-       for_each_sg(sgl, sg, nents, n) {
-               sg->dma_address = sg_phys(sg);
-               sg->dma_length = sg->length;
-       }
-       return nents;
-}
-
-/* Unmap a set of streaming mode DMA translations.
- * Again, cpu read rules concerning calls here are the same as for
- * pci_unmap_single() above.
- */
-static void pci32_unmap_sg(struct device *dev, struct scatterlist *sgl,
-                          int nents, enum dma_data_direction dir,
-                          unsigned long attrs)
-{
-       struct scatterlist *sg;
-       int n;
-
-       if (dir != PCI_DMA_TODEVICE && !(attrs & DMA_ATTR_SKIP_CPU_SYNC)) {
-               for_each_sg(sgl, sg, nents, n) {
-                       dma_make_coherent(sg_phys(sg), PAGE_ALIGN(sg->length));
-               }
-       }
-}
-
-/* Make physical memory consistent for a single
- * streaming mode DMA translation before or after a transfer.
- *
- * If you perform a pci_map_single() but wish to interrogate the
- * buffer using the cpu, yet do not wish to teardown the PCI dma
- * mapping, you must call this function before doing so.  At the
- * next point you give the PCI dma address back to the card, you
- * must first perform a pci_dma_sync_for_device, and then the
- * device again owns the buffer.
- */
-static void pci32_sync_single_for_cpu(struct device *dev, dma_addr_t ba,
-                                     size_t size, enum dma_data_direction dir)
-{
-       if (dir != PCI_DMA_TODEVICE) {
-               dma_make_coherent(ba, PAGE_ALIGN(size));
-       }
-}
-
-static void pci32_sync_single_for_device(struct device *dev, dma_addr_t ba,
-                                        size_t size, enum dma_data_direction dir)
-{
-       if (dir != PCI_DMA_TODEVICE) {
-               dma_make_coherent(ba, PAGE_ALIGN(size));
-       }
+       free_pages((unsigned long)phys_to_virt(dma_addr), get_order(size));
 }
 
-/* Make physical memory consistent for a set of streaming
- * mode DMA translations after a transfer.
- *
- * The same as pci_dma_sync_single_* but for a scatter-gather list,
- * same rules and usage.
- */
-static void pci32_sync_sg_for_cpu(struct device *dev, struct scatterlist *sgl,
-                                 int nents, enum dma_data_direction dir)
-{
-       struct scatterlist *sg;
-       int n;
-
-       if (dir != PCI_DMA_TODEVICE) {
-               for_each_sg(sgl, sg, nents, n) {
-                       dma_make_coherent(sg_phys(sg), PAGE_ALIGN(sg->length));
-               }
-       }
-}
+/* IIep is write-through, not flushing on cpu to device transfer. */
 
-static void pci32_sync_sg_for_device(struct device *device, struct scatterlist *sgl,
-                                    int nents, enum dma_data_direction dir)
+void arch_sync_dma_for_cpu(struct device *dev, phys_addr_t paddr,
+               size_t size, enum dma_data_direction dir)
 {
-       struct scatterlist *sg;
-       int n;
-
-       if (dir != PCI_DMA_TODEVICE) {
-               for_each_sg(sgl, sg, nents, n) {
-                       dma_make_coherent(sg_phys(sg), PAGE_ALIGN(sg->length));
-               }
-       }
+       if (dir != PCI_DMA_TODEVICE)
+               dma_make_coherent(paddr, PAGE_ALIGN(size));
 }
 
-/* note: leon re-uses pci32_dma_ops */
-const struct dma_map_ops pci32_dma_ops = {
-       .alloc                  = pci32_alloc_coherent,
-       .free                   = pci32_free_coherent,
-       .map_page               = pci32_map_page,
-       .unmap_page             = pci32_unmap_page,
-       .map_sg                 = pci32_map_sg,
-       .unmap_sg               = pci32_unmap_sg,
-       .sync_single_for_cpu    = pci32_sync_single_for_cpu,
-       .sync_single_for_device = pci32_sync_single_for_device,
-       .sync_sg_for_cpu        = pci32_sync_sg_for_cpu,
-       .sync_sg_for_device     = pci32_sync_sg_for_device,
-};
-EXPORT_SYMBOL(pci32_dma_ops);
-
 const struct dma_map_ops *dma_ops = &sbus_dma_ops;
 EXPORT_SYMBOL(dma_ops);
 
index 7f3d9c5..452e4d0 100644 (file)
@@ -197,23 +197,27 @@ SYSCALL_DEFINE5(rt_sigaction, int, sig,
 
 SYSCALL_DEFINE2(getdomainname, char __user *, name, int, len)
 {
-       int nlen, err;
-       
+       int nlen, err;
+       char tmp[__NEW_UTS_LEN + 1];
+
        if (len < 0)
                return -EINVAL;
 
-       down_read(&uts_sem);
-       
+       down_read(&uts_sem);
+
        nlen = strlen(utsname()->domainname) + 1;
        err = -EINVAL;
        if (nlen > len)
-               goto out;
+               goto out_unlock;
+       memcpy(tmp, utsname()->domainname, nlen);
 
-       err = -EFAULT;
-       if (!copy_to_user(name, utsname()->domainname, nlen))
-               err = 0;
+       up_read(&uts_sem);
 
-out:
+       if (copy_to_user(name, tmp, nlen))
+               return -EFAULT;
+       return 0;
+
+out_unlock:
        up_read(&uts_sem);
        return err;
 }
index 63baa8a..274ed0b 100644 (file)
@@ -519,23 +519,27 @@ asmlinkage void sparc_breakpoint(struct pt_regs *regs)
 
 SYSCALL_DEFINE2(getdomainname, char __user *, name, int, len)
 {
-        int nlen, err;
+       int nlen, err;
+       char tmp[__NEW_UTS_LEN + 1];
 
        if (len < 0)
                return -EINVAL;
 
-       down_read(&uts_sem);
-       
+       down_read(&uts_sem);
+
        nlen = strlen(utsname()->domainname) + 1;
        err = -EINVAL;
        if (nlen > len)
-               goto out;
+               goto out_unlock;
+       memcpy(tmp, utsname()->domainname, nlen);
+
+       up_read(&uts_sem);
 
-       err = -EFAULT;
-       if (!copy_to_user(name, utsname()->domainname, nlen))
-               err = 0;
+       if (copy_to_user(name, tmp, nlen))
+               return -EFAULT;
+       return 0;
 
-out:
+out_unlock:
        up_read(&uts_sem);
        return err;
 }
index 95fe4f0..92634d4 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/init.h>
 #include <linux/highmem.h>
 #include <linux/bootmem.h>
+#include <linux/memblock.h>
 #include <linux/pagemap.h>
 #include <linux/poison.h>
 #include <linux/gfp.h>
@@ -101,13 +102,46 @@ static unsigned long calc_max_low_pfn(void)
        return tmp;
 }
 
+static void __init find_ramdisk(unsigned long end_of_phys_memory)
+{
+#ifdef CONFIG_BLK_DEV_INITRD
+       unsigned long size;
+
+       /* Now have to check initial ramdisk, so that it won't pass
+        * the end of memory
+        */
+       if (sparc_ramdisk_image) {
+               if (sparc_ramdisk_image >= (unsigned long)&_end - 2 * PAGE_SIZE)
+                       sparc_ramdisk_image -= KERNBASE;
+               initrd_start = sparc_ramdisk_image + phys_base;
+               initrd_end = initrd_start + sparc_ramdisk_size;
+               if (initrd_end > end_of_phys_memory) {
+                       printk(KERN_CRIT "initrd extends beyond end of memory "
+                              "(0x%016lx > 0x%016lx)\ndisabling initrd\n",
+                              initrd_end, end_of_phys_memory);
+                       initrd_start = 0;
+               } else {
+                       /* Reserve the initrd image area. */
+                       size = initrd_end - initrd_start;
+                       memblock_reserve(initrd_start, size);
+
+                       initrd_start = (initrd_start - phys_base) + PAGE_OFFSET;
+                       initrd_end = (initrd_end - phys_base) + PAGE_OFFSET;
+               }
+       }
+#endif
+}
+
 unsigned long __init bootmem_init(unsigned long *pages_avail)
 {
-       unsigned long bootmap_size, start_pfn;
-       unsigned long end_of_phys_memory = 0UL;
-       unsigned long bootmap_pfn, bytes_avail, size;
+       unsigned long start_pfn, bytes_avail, size;
+       unsigned long end_of_phys_memory = 0;
+       unsigned long high_pages = 0;
        int i;
 
+       memblock_set_bottom_up(true);
+       memblock_allow_resize();
+
        bytes_avail = 0UL;
        for (i = 0; sp_banks[i].num_bytes != 0; i++) {
                end_of_phys_memory = sp_banks[i].base_addr +
@@ -124,24 +158,25 @@ unsigned long __init bootmem_init(unsigned long *pages_avail)
                                if (sp_banks[i].num_bytes == 0) {
                                        sp_banks[i].base_addr = 0xdeadbeef;
                                } else {
+                                       memblock_add(sp_banks[i].base_addr,
+                                                    sp_banks[i].num_bytes);
                                        sp_banks[i+1].num_bytes = 0;
                                        sp_banks[i+1].base_addr = 0xdeadbeef;
                                }
                                break;
                        }
                }
+               memblock_add(sp_banks[i].base_addr, sp_banks[i].num_bytes);
        }
 
        /* Start with page aligned address of last symbol in kernel
-        * image.  
+        * image.
         */
        start_pfn  = (unsigned long)__pa(PAGE_ALIGN((unsigned long) &_end));
 
        /* Now shift down to get the real physical page frame number. */
        start_pfn >>= PAGE_SHIFT;
 
-       bootmap_pfn = start_pfn;
-
        max_pfn = end_of_phys_memory >> PAGE_SHIFT;
 
        max_low_pfn = max_pfn;
@@ -150,85 +185,19 @@ unsigned long __init bootmem_init(unsigned long *pages_avail)
        if (max_low_pfn > pfn_base + (SRMMU_MAXMEM >> PAGE_SHIFT)) {
                highstart_pfn = pfn_base + (SRMMU_MAXMEM >> PAGE_SHIFT);
                max_low_pfn = calc_max_low_pfn();
+               high_pages = calc_highpages();
                printk(KERN_NOTICE "%ldMB HIGHMEM available.\n",
-                   calc_highpages() >> (20 - PAGE_SHIFT));
+                   high_pages >> (20 - PAGE_SHIFT));
        }
 
-#ifdef CONFIG_BLK_DEV_INITRD
-       /* Now have to check initial ramdisk, so that bootmap does not overwrite it */
-       if (sparc_ramdisk_image) {
-               if (sparc_ramdisk_image >= (unsigned long)&_end - 2 * PAGE_SIZE)
-                       sparc_ramdisk_image -= KERNBASE;
-               initrd_start = sparc_ramdisk_image + phys_base;
-               initrd_end = initrd_start + sparc_ramdisk_size;
-               if (initrd_end > end_of_phys_memory) {
-                       printk(KERN_CRIT "initrd extends beyond end of memory "
-                                        "(0x%016lx > 0x%016lx)\ndisabling initrd\n",
-                              initrd_end, end_of_phys_memory);
-                       initrd_start = 0;
-               }
-               if (initrd_start) {
-                       if (initrd_start >= (start_pfn << PAGE_SHIFT) &&
-                           initrd_start < (start_pfn << PAGE_SHIFT) + 2 * PAGE_SIZE)
-                               bootmap_pfn = PAGE_ALIGN (initrd_end) >> PAGE_SHIFT;
-               }
-       }
-#endif 
-       /* Initialize the boot-time allocator. */
-       bootmap_size = init_bootmem_node(NODE_DATA(0), bootmap_pfn, pfn_base,
-                                        max_low_pfn);
-
-       /* Now register the available physical memory with the
-        * allocator.
-        */
-       *pages_avail = 0;
-       for (i = 0; sp_banks[i].num_bytes != 0; i++) {
-               unsigned long curr_pfn, last_pfn;
+       find_ramdisk(end_of_phys_memory);
 
-               curr_pfn = sp_banks[i].base_addr >> PAGE_SHIFT;
-               if (curr_pfn >= max_low_pfn)
-                       break;
-
-               last_pfn = (sp_banks[i].base_addr + sp_banks[i].num_bytes) >> PAGE_SHIFT;
-               if (last_pfn > max_low_pfn)
-                       last_pfn = max_low_pfn;
-
-               /*
-                * .. finally, did all the rounding and playing
-                * around just make the area go away?
-                */
-               if (last_pfn <= curr_pfn)
-                       continue;
-
-               size = (last_pfn - curr_pfn) << PAGE_SHIFT;
-               *pages_avail += last_pfn - curr_pfn;
-
-               free_bootmem(sp_banks[i].base_addr, size);
-       }
-
-#ifdef CONFIG_BLK_DEV_INITRD
-       if (initrd_start) {
-               /* Reserve the initrd image area. */
-               size = initrd_end - initrd_start;
-               reserve_bootmem(initrd_start, size, BOOTMEM_DEFAULT);
-               *pages_avail -= PAGE_ALIGN(size) >> PAGE_SHIFT;
-
-               initrd_start = (initrd_start - phys_base) + PAGE_OFFSET;
-               initrd_end = (initrd_end - phys_base) + PAGE_OFFSET;            
-       }
-#endif
        /* Reserve the kernel text/data/bss. */
        size = (start_pfn << PAGE_SHIFT) - phys_base;
-       reserve_bootmem(phys_base, size, BOOTMEM_DEFAULT);
-       *pages_avail -= PAGE_ALIGN(size) >> PAGE_SHIFT;
+       memblock_reserve(phys_base, size);
 
-       /* Reserve the bootmem map.   We do not account for it
-        * in pages_avail because we will release that memory
-        * in free_all_bootmem.
-        */
-       size = bootmap_size;
-       reserve_bootmem((bootmap_pfn << PAGE_SHIFT), size, BOOTMEM_DEFAULT);
-       *pages_avail -= PAGE_ALIGN(size) >> PAGE_SHIFT;
+       size = memblock_phys_mem_size() - memblock_reserved_size();
+       *pages_avail = (size >> PAGE_SHIFT) - high_pages;
 
        return max_pfn;
 }
@@ -322,7 +291,7 @@ void __init mem_init(void)
 
                map_high_region(start_pfn, end_pfn);
        }
-       
+
        mem_init_print_info(NULL);
 }
 
index 44ddc3e..ab1066c 100644 (file)
@@ -133,7 +133,7 @@ export LDS_ELF_FORMAT := $(ELF_FORMAT)
 # The wrappers will select whether using "malloc" or the kernel allocator.
 LINK_WRAPS = -Wl,--wrap,malloc -Wl,--wrap,free -Wl,--wrap,calloc
 
-LD_FLAGS_CMDLINE = $(foreach opt,$(LDFLAGS),-Wl,$(opt))
+LD_FLAGS_CMDLINE = $(foreach opt,$(KBUILD_LDFLAGS),-Wl,$(opt))
 
 # Used by link-vmlinux.sh which has special support for um link
 export CFLAGS_vmlinux := $(LINK-y) $(LINK_WRAPS) $(LD_FLAGS_CMDLINE)
index b0312f8..c5ff296 100644 (file)
@@ -124,6 +124,7 @@ config X86
        select HAVE_ARCH_MMAP_RND_BITS          if MMU
        select HAVE_ARCH_MMAP_RND_COMPAT_BITS   if MMU && COMPAT
        select HAVE_ARCH_COMPAT_MMAP_BASES      if MMU && COMPAT
+       select HAVE_ARCH_PREL32_RELOCATIONS
        select HAVE_ARCH_SECCOMP_FILTER
        select HAVE_ARCH_THREAD_STRUCT_WHITELIST
        select HAVE_ARCH_TRACEHOOK
@@ -179,7 +180,8 @@ config X86
        select HAVE_HARDLOCKUP_DETECTOR_PERF    if PERF_EVENTS && HAVE_PERF_EVENTS_NMI
        select HAVE_PERF_REGS
        select HAVE_PERF_USER_STACK_DUMP
-       select HAVE_RCU_TABLE_FREE
+       select HAVE_RCU_TABLE_FREE              if PARAVIRT
+       select HAVE_RCU_TABLE_INVALIDATE        if HAVE_RCU_TABLE_FREE
        select HAVE_REGS_AND_STACK_ACCESS_API
        select HAVE_RELIABLE_STACKTRACE         if X86_64 && (UNWINDER_FRAME_POINTER || UNWINDER_ORC) && STACK_VALIDATION
        select HAVE_STACKPROTECTOR              if CC_HAS_SANE_STACKPROTECTOR
index 7e3c07d..9485924 100644 (file)
@@ -219,7 +219,7 @@ sha256_ni_instr :=$(call as-instr,sha256msg1 %xmm0$(comma)%xmm1,-DCONFIG_AS_SHA2
 KBUILD_AFLAGS += $(cfi) $(cfi-sigframe) $(cfi-sections) $(asinstr) $(avx_instr) $(avx2_instr) $(avx512_instr) $(sha1_ni_instr) $(sha256_ni_instr)
 KBUILD_CFLAGS += $(cfi) $(cfi-sigframe) $(cfi-sections) $(asinstr) $(avx_instr) $(avx2_instr) $(avx512_instr) $(sha1_ni_instr) $(sha256_ni_instr)
 
-LDFLAGS := -m elf_$(UTS_MACHINE)
+KBUILD_LDFLAGS := -m elf_$(UTS_MACHINE)
 
 #
 # The 64-bit kernel must be aligned to 2MB.  Pass -z max-page-size=0x200000 to
@@ -227,7 +227,7 @@ LDFLAGS := -m elf_$(UTS_MACHINE)
 # by the linker.
 #
 ifdef CONFIG_X86_64
-LDFLAGS += $(call ld-option, -z max-page-size=0x200000)
+KBUILD_LDFLAGS += $(call ld-option, -z max-page-size=0x200000)
 endif
 
 # Speed up the build
index 5296f8c..91085a0 100644 (file)
@@ -4,7 +4,7 @@ core-y += arch/x86/crypto/
 ifeq ($(CONFIG_X86_32),y)
 START := 0x8048000
 
-LDFLAGS                        += -m elf_i386
+KBUILD_LDFLAGS         += -m elf_i386
 ELF_ARCH               := i386
 ELF_FORMAT             := elf32-i386
 CHECKFLAGS     += -D__i386__
@@ -43,7 +43,7 @@ KBUILD_CFLAGS += -fno-builtin -m64
 
 CHECKFLAGS  += -m64 -D__x86_64__
 KBUILD_AFLAGS += -m64
-LDFLAGS += -m elf_x86_64
+KBUILD_LDFLAGS += -m elf_x86_64
 KBUILD_CPPFLAGS += -m64
 
 ELF_ARCH := i386:x86-64
index 169c2fe..28764da 100644 (file)
@@ -42,16 +42,16 @@ KBUILD_AFLAGS  := $(KBUILD_CFLAGS) -D__ASSEMBLY__
 GCOV_PROFILE := n
 UBSAN_SANITIZE :=n
 
-LDFLAGS := -m elf_$(UTS_MACHINE)
+KBUILD_LDFLAGS := -m elf_$(UTS_MACHINE)
 # Compressed kernel should be built as PIE since it may be loaded at any
 # address by the bootloader.
 ifeq ($(CONFIG_X86_32),y)
-LDFLAGS += $(call ld-option, -pie) $(call ld-option, --no-dynamic-linker)
+KBUILD_LDFLAGS += $(call ld-option, -pie) $(call ld-option, --no-dynamic-linker)
 else
 # To build 64-bit compressed kernel as PIE, we disable relocation
 # overflow check to avoid relocation overflow error with a new linker
 # command-line option, -z noreloc-overflow.
-LDFLAGS += $(shell $(LD) --help 2>&1 | grep -q "\-z noreloc-overflow" \
+KBUILD_LDFLAGS += $(shell $(LD) --help 2>&1 | grep -q "\-z noreloc-overflow" \
        && echo "-z noreloc-overflow -pie --no-dynamic-linker")
 endif
 LDFLAGS_vmlinux := -T
index 3025179..d1e19f3 100644 (file)
  * _ctype[] in lib/ctype.c is needed by isspace() of linux/ctype.h.
  * While both lib/ctype.c and lib/cmdline.c will bring EXPORT_SYMBOL
  * which is meaningless and will cause compiling error in some cases.
- * So do not include linux/export.h and define EXPORT_SYMBOL(sym)
- * as empty.
  */
-#define _LINUX_EXPORT_H
-#define EXPORT_SYMBOL(sym)
+#define __DISABLE_EXPORTS
 
 #include "misc.h"
 #include "error.h"
index 9f695f5..fa3f439 100644 (file)
@@ -68,9 +68,9 @@ $(obj)/vdso-image-%.c: $(obj)/vdso%.so.dbg $(obj)/vdso%.so $(obj)/vdso2c FORCE
 CFL := $(PROFILING) -mcmodel=small -fPIC -O2 -fasynchronous-unwind-tables -m64 \
        $(filter -g%,$(KBUILD_CFLAGS)) $(call cc-option, -fno-stack-protector) \
        -fno-omit-frame-pointer -foptimize-sibling-calls \
-       -DDISABLE_BRANCH_PROFILING -DBUILD_VDSO
+       -DDISABLE_BRANCH_PROFILING -DBUILD_VDSO $(RETPOLINE_VDSO_CFLAGS)
 
-$(vobjs): KBUILD_CFLAGS := $(filter-out $(GCC_PLUGINS_CFLAGS),$(KBUILD_CFLAGS)) $(CFL)
+$(vobjs): KBUILD_CFLAGS := $(filter-out $(GCC_PLUGINS_CFLAGS) $(RETPOLINE_CFLAGS),$(KBUILD_CFLAGS)) $(CFL)
 
 #
 # vDSO code runs in userspace and -pg doesn't help with profiling anyway.
@@ -132,11 +132,13 @@ KBUILD_CFLAGS_32 := $(filter-out -mcmodel=kernel,$(KBUILD_CFLAGS_32))
 KBUILD_CFLAGS_32 := $(filter-out -fno-pic,$(KBUILD_CFLAGS_32))
 KBUILD_CFLAGS_32 := $(filter-out -mfentry,$(KBUILD_CFLAGS_32))
 KBUILD_CFLAGS_32 := $(filter-out $(GCC_PLUGINS_CFLAGS),$(KBUILD_CFLAGS_32))
+KBUILD_CFLAGS_32 := $(filter-out $(RETPOLINE_CFLAGS),$(KBUILD_CFLAGS_32))
 KBUILD_CFLAGS_32 += -m32 -msoft-float -mregparm=0 -fpic
 KBUILD_CFLAGS_32 += $(call cc-option, -fno-stack-protector)
 KBUILD_CFLAGS_32 += $(call cc-option, -foptimize-sibling-calls)
 KBUILD_CFLAGS_32 += -fno-omit-frame-pointer
 KBUILD_CFLAGS_32 += -DDISABLE_BRANCH_PROFILING
+KBUILD_CFLAGS_32 += $(RETPOLINE_VDSO_CFLAGS)
 $(obj)/vdso32.so.dbg: KBUILD_CFLAGS = $(KBUILD_CFLAGS_32)
 
 $(obj)/vdso32.so.dbg: FORCE \
index 1147e1f..ef5f29f 100644 (file)
@@ -9,6 +9,7 @@
 #include <asm/mshyperv.h>
 #include <asm/msr.h>
 #include <asm/tlbflush.h>
+#include <asm/tlb.h>
 
 #define CREATE_TRACE_POINTS
 #include <asm/trace/hyperv.h>
@@ -231,4 +232,5 @@ void hyperv_setup_mmu_ops(void)
 
        pr_info("Using hypercall for remote TLB flush\n");
        pv_mmu_ops.flush_tlb_others = hyperv_flush_tlb_others;
+       pv_mmu_ops.tlb_remove_table = tlb_remove_table;
 }
index de690c2..a0ab9ab 100644 (file)
@@ -8,5 +8,6 @@ generated-y += xen-hypercalls.h
 
 generic-y += dma-contiguous.h
 generic-y += early_ioremap.h
+generic-y += export.h
 generic-y += mcs_spinlock.h
 generic-y += mm-arch-hooks.h
diff --git a/arch/x86/include/asm/export.h b/arch/x86/include/asm/export.h
deleted file mode 100644 (file)
index 2a51d66..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifdef CONFIG_64BIT
-#define KSYM_ALIGN 16
-#endif
-#include <asm-generic/export.h>
index 023b4a9..5f26962 100644 (file)
@@ -33,6 +33,11 @@ enum irq_remap_cap {
        IRQ_POSTING_CAP = 0,
 };
 
+enum {
+       IRQ_REMAP_XAPIC_MODE,
+       IRQ_REMAP_X2APIC_MODE,
+};
+
 struct vcpu_data {
        u64 pi_desc_addr;       /* Physical address of PI Descriptor */
        u32 vector;             /* Guest vector of the interrupt */
index 8c7b3e5..3a17107 100644 (file)
@@ -148,6 +148,7 @@ enum mce_notifier_prios {
        MCE_PRIO_LOWEST         = 0,
 };
 
+struct notifier_block;
 extern void mce_register_decode_chain(struct notifier_block *nb);
 extern void mce_unregister_decode_chain(struct notifier_block *nb);
 
index d49bbf4..e375d42 100644 (file)
@@ -309,6 +309,11 @@ static inline void flush_tlb_others(const struct cpumask *cpumask,
        PVOP_VCALL2(pv_mmu_ops.flush_tlb_others, cpumask, info);
 }
 
+static inline void paravirt_tlb_remove_table(struct mmu_gather *tlb, void *table)
+{
+       PVOP_VCALL2(pv_mmu_ops.tlb_remove_table, tlb, table);
+}
+
 static inline int paravirt_pgd_alloc(struct mm_struct *mm)
 {
        return PVOP_CALL1(int, pv_mmu_ops.pgd_alloc, mm);
index 180bc0b..4b75acc 100644 (file)
@@ -54,6 +54,7 @@ struct desc_struct;
 struct task_struct;
 struct cpumask;
 struct flush_tlb_info;
+struct mmu_gather;
 
 /*
  * Wrapper type for pointers to code which uses the non-standard
@@ -222,6 +223,8 @@ struct pv_mmu_ops {
        void (*flush_tlb_others)(const struct cpumask *cpus,
                                 const struct flush_tlb_info *info);
 
+       void (*tlb_remove_table)(struct mmu_gather *tlb, void *table);
+
        /* Hooks for allocating and freeing a pagetable top-level */
        int  (*pgd_alloc)(struct mm_struct *mm);
        void (*pgd_free)(struct mm_struct *mm, pgd_t *pgd);
index 682286a..c242972 100644 (file)
@@ -181,9 +181,9 @@ extern const struct seq_operations cpuinfo_op;
 
 extern void cpu_detect(struct cpuinfo_x86 *c);
 
-static inline unsigned long l1tf_pfn_limit(void)
+static inline unsigned long long l1tf_pfn_limit(void)
 {
-       return BIT(boot_cpu_data.x86_phys_bits - 1 - PAGE_SHIFT) - 1;
+       return BIT_ULL(boot_cpu_data.x86_phys_bits - 1 - PAGE_SHIFT);
 }
 
 extern void early_cpu_init(void);
index 34cffce..07a2575 100644 (file)
@@ -89,4 +89,46 @@ extern int kernel_set_to_readonly;
 void set_kernel_text_rw(void);
 void set_kernel_text_ro(void);
 
+#ifdef CONFIG_X86_64
+static inline int set_mce_nospec(unsigned long pfn)
+{
+       unsigned long decoy_addr;
+       int rc;
+
+       /*
+        * Mark the linear address as UC to make sure we don't log more
+        * errors because of speculative access to the page.
+        * We would like to just call:
+        *      set_memory_uc((unsigned long)pfn_to_kaddr(pfn), 1);
+        * but doing that would radically increase the odds of a
+        * speculative access to the poison page because we'd have
+        * the virtual address of the kernel 1:1 mapping sitting
+        * around in registers.
+        * Instead we get tricky.  We create a non-canonical address
+        * that looks just like the one we want, but has bit 63 flipped.
+        * This relies on set_memory_uc() properly sanitizing any __pa()
+        * results with __PHYSICAL_MASK or PTE_PFN_MASK.
+        */
+       decoy_addr = (pfn << PAGE_SHIFT) + (PAGE_OFFSET ^ BIT(63));
+
+       rc = set_memory_uc(decoy_addr, 1);
+       if (rc)
+               pr_warn("Could not invalidate pfn=0x%lx from 1:1 map\n", pfn);
+       return rc;
+}
+#define set_mce_nospec set_mce_nospec
+
+/* Restore full speculative operation to the pfn. */
+static inline int clear_mce_nospec(unsigned long pfn)
+{
+       return set_memory_wb((unsigned long) pfn_to_kaddr(pfn), 1);
+}
+#define clear_mce_nospec clear_mce_nospec
+#else
+/*
+ * Few people would run a 32-bit kernel on a machine that supports
+ * recoverable errors because they have too much memory to boot 32-bit.
+ */
+#endif
+
 #endif /* _ASM_X86_SET_MEMORY_H */
index 511bf5f..29c9da6 100644 (file)
@@ -148,6 +148,22 @@ static inline unsigned long build_cr3_noflush(pgd_t *pgd, u16 asid)
 #define __flush_tlb_one_user(addr) __native_flush_tlb_one_user(addr)
 #endif
 
+static inline bool tlb_defer_switch_to_init_mm(void)
+{
+       /*
+        * If we have PCID, then switching to init_mm is reasonably
+        * fast.  If we don't have PCID, then switching to init_mm is
+        * quite slow, so we try to defer it in the hopes that we can
+        * avoid it entirely.  The latter approach runs the risk of
+        * receiving otherwise unnecessary IPIs.
+        *
+        * This choice is just a heuristic.  The tlb code can handle this
+        * function returning true or false regardless of whether we have
+        * PCID.
+        */
+       return !static_cpu_has(X86_FEATURE_PCID);
+}
+
 struct tlb_context {
        u64 ctx_id;
        u64 tlb_gen;
@@ -536,11 +552,9 @@ extern void arch_tlbbatch_flush(struct arch_tlbflush_unmap_batch *batch);
 #ifndef CONFIG_PARAVIRT
 #define flush_tlb_others(mask, info)   \
        native_flush_tlb_others(mask, info)
-#endif
 
-extern void tlb_flush_remove_tables(struct mm_struct *mm);
-extern void tlb_flush_remove_tables_local(void *arg);
-
-#define HAVE_TLB_FLUSH_REMOVE_TABLES
+#define paravirt_tlb_remove_table(tlb, page) \
+       tlb_remove_page(tlb, (void *)(page))
+#endif
 
 #endif /* _ASM_X86_TLBFLUSH_H */
index 95f9107..9527ba5 100644 (file)
@@ -74,6 +74,7 @@
 #define SECONDARY_EXEC_ENABLE_INVPCID          0x00001000
 #define SECONDARY_EXEC_ENABLE_VMFUNC            0x00002000
 #define SECONDARY_EXEC_SHADOW_VMCS              0x00004000
+#define SECONDARY_EXEC_ENCLS_EXITING           0x00008000
 #define SECONDARY_EXEC_RDSEED_EXITING          0x00010000
 #define SECONDARY_EXEC_ENABLE_PML               0x00020000
 #define SECONDARY_EXEC_XSAVES                  0x00100000
@@ -213,6 +214,8 @@ enum vmcs_field {
        VMWRITE_BITMAP_HIGH             = 0x00002029,
        XSS_EXIT_BITMAP                 = 0x0000202C,
        XSS_EXIT_BITMAP_HIGH            = 0x0000202D,
+       ENCLS_EXITING_BITMAP            = 0x0000202E,
+       ENCLS_EXITING_BITMAP_HIGH       = 0x0000202F,
        TSC_MULTIPLIER                  = 0x00002032,
        TSC_MULTIPLIER_HIGH             = 0x00002033,
        GUEST_PHYSICAL_ADDRESS          = 0x00002400,
index 6b2f90a..ef05bea 100644 (file)
@@ -197,17 +197,6 @@ extern struct { char _entry[32]; } hypercall_page[];
        (type)__res;                                                    \
 })
 
-#define _hypercall5(type, name, a1, a2, a3, a4, a5)                    \
-({                                                                     \
-       __HYPERCALL_DECLS;                                              \
-       __HYPERCALL_5ARG(a1, a2, a3, a4, a5);                           \
-       asm volatile (__HYPERCALL                                       \
-                     : __HYPERCALL_5PARAM                              \
-                     : __HYPERCALL_ENTRY(name)                         \
-                     : __HYPERCALL_CLOBBER5);                          \
-       (type)__res;                                                    \
-})
-
 static inline long
 xen_single_call(unsigned int call,
                unsigned long a1, unsigned long a2,
@@ -267,47 +256,12 @@ HYPERVISOR_set_gdt(unsigned long *frame_list, int entries)
 }
 
 static inline int
-HYPERVISOR_stack_switch(unsigned long ss, unsigned long esp)
-{
-       return _hypercall2(int, stack_switch, ss, esp);
-}
-
-#ifdef CONFIG_X86_32
-static inline int
-HYPERVISOR_set_callbacks(unsigned long event_selector,
-                        unsigned long event_address,
-                        unsigned long failsafe_selector,
-                        unsigned long failsafe_address)
-{
-       return _hypercall4(int, set_callbacks,
-                          event_selector, event_address,
-                          failsafe_selector, failsafe_address);
-}
-#else  /* CONFIG_X86_64 */
-static inline int
-HYPERVISOR_set_callbacks(unsigned long event_address,
-                       unsigned long failsafe_address,
-                       unsigned long syscall_address)
-{
-       return _hypercall3(int, set_callbacks,
-                          event_address, failsafe_address,
-                          syscall_address);
-}
-#endif  /* CONFIG_X86_{32,64} */
-
-static inline int
 HYPERVISOR_callback_op(int cmd, void *arg)
 {
        return _hypercall2(int, callback_op, cmd, arg);
 }
 
 static inline int
-HYPERVISOR_fpu_taskswitch(int set)
-{
-       return _hypercall1(int, fpu_taskswitch, set);
-}
-
-static inline int
 HYPERVISOR_sched_op(int cmd, void *arg)
 {
        return _hypercall2(int, sched_op, cmd, arg);
@@ -419,19 +373,6 @@ HYPERVISOR_grant_table_op(unsigned int cmd, void *uop, unsigned int count)
 }
 
 static inline int
-HYPERVISOR_update_va_mapping_otherdomain(unsigned long va, pte_t new_val,
-                                        unsigned long flags, domid_t domid)
-{
-       if (sizeof(new_val) == sizeof(long))
-               return _hypercall4(int, update_va_mapping_otherdomain, va,
-                                  new_val.pte, flags, domid);
-       else
-               return _hypercall5(int, update_va_mapping_otherdomain, va,
-                                  new_val.pte, new_val.pte >> 32,
-                                  flags, domid);
-}
-
-static inline int
 HYPERVISOR_vm_assist(unsigned int cmd, unsigned int type)
 {
        return _hypercall2(int, vm_assist, cmd, type);
@@ -465,12 +406,6 @@ HYPERVISOR_suspend(unsigned long start_info_mfn)
        return _hypercall3(int, sched_op, SCHEDOP_shutdown, &r, start_info_mfn);
 }
 
-static inline int
-HYPERVISOR_nmi_op(unsigned long op, unsigned long arg)
-{
-       return _hypercall2(int, nmi_op, op, arg);
-}
-
 static inline unsigned long __must_check
 HYPERVISOR_hvm_op(int op, void *arg)
 {
@@ -529,39 +464,6 @@ MULTI_update_va_mapping(struct multicall_entry *mcl, unsigned long va,
 }
 
 static inline void
-MULTI_grant_table_op(struct multicall_entry *mcl, unsigned int cmd,
-                    void *uop, unsigned int count)
-{
-       mcl->op = __HYPERVISOR_grant_table_op;
-       mcl->args[0] = cmd;
-       mcl->args[1] = (unsigned long)uop;
-       mcl->args[2] = count;
-
-       trace_xen_mc_entry(mcl, 3);
-}
-
-static inline void
-MULTI_update_va_mapping_otherdomain(struct multicall_entry *mcl, unsigned long va,
-                                   pte_t new_val, unsigned long flags,
-                                   domid_t domid)
-{
-       mcl->op = __HYPERVISOR_update_va_mapping_otherdomain;
-       mcl->args[0] = va;
-       if (sizeof(new_val) == sizeof(long)) {
-               mcl->args[1] = new_val.pte;
-               mcl->args[2] = flags;
-               mcl->args[3] = domid;
-       } else {
-               mcl->args[1] = new_val.pte;
-               mcl->args[2] = new_val.pte >> 32;
-               mcl->args[3] = flags;
-               mcl->args[4] = domid;
-       }
-
-       trace_xen_mc_entry(mcl, sizeof(new_val) == sizeof(long) ? 4 : 5);
-}
-
-static inline void
 MULTI_update_descriptor(struct multicall_entry *mcl, u64 maddr,
                        struct desc_struct desc)
 {
@@ -582,16 +484,6 @@ MULTI_update_descriptor(struct multicall_entry *mcl, u64 maddr,
 }
 
 static inline void
-MULTI_memory_op(struct multicall_entry *mcl, unsigned int cmd, void *arg)
-{
-       mcl->op = __HYPERVISOR_memory_op;
-       mcl->args[0] = cmd;
-       mcl->args[1] = (unsigned long)arg;
-
-       trace_xen_mc_entry(mcl, 2);
-}
-
-static inline void
 MULTI_mmu_update(struct multicall_entry *mcl, struct mmu_update *req,
                 int count, int *success_count, domid_t domid)
 {
@@ -618,16 +510,6 @@ MULTI_mmuext_op(struct multicall_entry *mcl, struct mmuext_op *op, int count,
 }
 
 static inline void
-MULTI_set_gdt(struct multicall_entry *mcl, unsigned long *frames, int entries)
-{
-       mcl->op = __HYPERVISOR_set_gdt;
-       mcl->args[0] = (unsigned long)frames;
-       mcl->args[1] = entries;
-
-       trace_xen_mc_entry(mcl, 2);
-}
-
-static inline void
 MULTI_stack_switch(struct multicall_entry *mcl,
                   unsigned long ss, unsigned long esp)
 {
index dde437f..158ad14 100644 (file)
@@ -108,7 +108,7 @@ static long acpi_processor_ffh_cstate_probe_cpu(void *_cx)
                        cx->type);
        }
        snprintf(cx->desc,
-                       ACPI_CX_DESC_LEN, "ACPI FFH INTEL MWAIT 0x%x",
+                       ACPI_CX_DESC_LEN, "ACPI FFH MWAIT 0x%x",
                        cx->address);
 out:
        return retval;
index cb4a162..4c2313d 100644 (file)
@@ -702,6 +702,10 @@ static void __init l1tf_select_mitigation(void)
        half_pa = (u64)l1tf_pfn_limit() << PAGE_SHIFT;
        if (e820__mapped_any(half_pa, ULLONG_MAX - half_pa, E820_TYPE_RAM)) {
                pr_warn("System has more than MAX_PA/2 memory. L1TF mitigation not effective.\n");
+               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");
                return;
        }
 
index 374d1aa..ceb67cd 100644 (file)
@@ -113,21 +113,6 @@ static inline void mce_register_injector_chain(struct notifier_block *nb)  { }
 static inline void mce_unregister_injector_chain(struct notifier_block *nb)    { }
 #endif
 
-#ifndef CONFIG_X86_64
-/*
- * On 32-bit systems it would be difficult to safely unmap a poison page
- * from the kernel 1:1 map because there are no non-canonical addresses that
- * we can use to refer to the address without risking a speculative access.
- * However, this isn't much of an issue because:
- * 1) Few unmappable pages are in the 1:1 map. Most are in HIGHMEM which
- *    are only mapped into the kernel as needed
- * 2) Few people would run a 32-bit kernel on a machine that supports
- *    recoverable errors because they have too much memory to boot 32-bit.
- */
-static inline void mce_unmap_kpfn(unsigned long pfn) {}
-#define mce_unmap_kpfn mce_unmap_kpfn
-#endif
-
 struct mca_config {
        bool dont_log_ce;
        bool cmci_disabled;
index 4b76728..953b3ce 100644 (file)
@@ -42,6 +42,7 @@
 #include <linux/irq_work.h>
 #include <linux/export.h>
 #include <linux/jump_label.h>
+#include <linux/set_memory.h>
 
 #include <asm/intel-family.h>
 #include <asm/processor.h>
@@ -50,7 +51,6 @@
 #include <asm/mce.h>
 #include <asm/msr.h>
 #include <asm/reboot.h>
-#include <asm/set_memory.h>
 
 #include "mce-internal.h"
 
@@ -108,10 +108,6 @@ static struct irq_work mce_irq_work;
 
 static void (*quirk_no_way_out)(int bank, struct mce *m, struct pt_regs *regs);
 
-#ifndef mce_unmap_kpfn
-static void mce_unmap_kpfn(unsigned long pfn);
-#endif
-
 /*
  * CPU/chipset specific EDAC code can register a notifier call here to print
  * MCE errors in a human-readable form.
@@ -602,7 +598,7 @@ static int srao_decode_notifier(struct notifier_block *nb, unsigned long val,
        if (mce_usable_address(mce) && (mce->severity == MCE_AO_SEVERITY)) {
                pfn = mce->addr >> PAGE_SHIFT;
                if (!memory_failure(pfn, 0))
-                       mce_unmap_kpfn(pfn);
+                       set_mce_nospec(pfn);
        }
 
        return NOTIFY_OK;
@@ -1072,38 +1068,10 @@ static int do_memory_failure(struct mce *m)
        if (ret)
                pr_err("Memory error not recovered");
        else
-               mce_unmap_kpfn(m->addr >> PAGE_SHIFT);
+               set_mce_nospec(m->addr >> PAGE_SHIFT);
        return ret;
 }
 
-#ifndef mce_unmap_kpfn
-static void mce_unmap_kpfn(unsigned long pfn)
-{
-       unsigned long decoy_addr;
-
-       /*
-        * Unmap this page from the kernel 1:1 mappings to make sure
-        * we don't log more errors because of speculative access to
-        * the page.
-        * We would like to just call:
-        *      set_memory_np((unsigned long)pfn_to_kaddr(pfn), 1);
-        * but doing that would radically increase the odds of a
-        * speculative access to the poison page because we'd have
-        * the virtual address of the kernel 1:1 mapping sitting
-        * around in registers.
-        * Instead we get tricky.  We create a non-canonical address
-        * that looks just like the one we want, but has bit 63 flipped.
-        * This relies on set_memory_np() not checking whether we passed
-        * a legal address.
-        */
-
-       decoy_addr = (pfn << PAGE_SHIFT) + (PAGE_OFFSET ^ BIT(63));
-
-       if (set_memory_np(decoy_addr, 1))
-               pr_warn("Could not invalidate pfn=0x%lx from 1:1 map\n", pfn);
-}
-#endif
-
 
 /*
  * Cases where we avoid rendezvous handler timeout:
index 0f471bd..d9b7192 100644 (file)
@@ -45,6 +45,7 @@
 #include <asm/apic.h>
 #include <asm/apicdef.h>
 #include <asm/hypervisor.h>
+#include <asm/tlb.h>
 
 static int kvmapf = 1;
 
@@ -636,8 +637,10 @@ static void __init kvm_guest_init(void)
 
        if (kvm_para_has_feature(KVM_FEATURE_PV_TLB_FLUSH) &&
            !kvm_para_has_hint(KVM_HINTS_REALTIME) &&
-           kvm_para_has_feature(KVM_FEATURE_STEAL_TIME))
+           kvm_para_has_feature(KVM_FEATURE_STEAL_TIME)) {
                pv_mmu_ops.flush_tlb_others = kvm_flush_tlb_others;
+               pv_mmu_ops.tlb_remove_table = tlb_remove_table;
+       }
 
        if (kvm_para_has_feature(KVM_FEATURE_PV_EOI))
                apic_set_eoi_write(kvm_guest_apic_eoi_write);
index 930c883..afdb303 100644 (file)
@@ -41,6 +41,7 @@
 #include <asm/tlbflush.h>
 #include <asm/timer.h>
 #include <asm/special_insns.h>
+#include <asm/tlb.h>
 
 /*
  * nop stub, which must not clobber anything *including the stack* to
@@ -409,6 +410,7 @@ struct pv_mmu_ops pv_mmu_ops __ro_after_init = {
        .flush_tlb_kernel = native_flush_tlb_global,
        .flush_tlb_one_user = native_flush_tlb_one_user,
        .flush_tlb_others = native_flush_tlb_others,
+       .tlb_remove_table = (void (*)(struct mmu_gather *, void *))tlb_remove_page,
 
        .pgd_alloc = __paravirt_pgd_alloc,
        .pgd_free = paravirt_nop,
index acfd041..7ba73fe 100644 (file)
@@ -40,8 +40,14 @@ int iommu_detected __read_mostly = 0;
  * devices and allow every device to access to whole physical memory. This is
  * useful if a user wants to use an IOMMU only for KVM device assignment to
  * guests and not for driver dma translation.
+ * It is also possible to disable by default in kernel config, and enable with
+ * iommu=nopt at boot time.
  */
+#ifdef CONFIG_IOMMU_DEFAULT_PASSTHROUGH
+int iommu_pass_through __read_mostly = 1;
+#else
 int iommu_pass_through __read_mostly;
+#endif
 
 extern struct iommu_table_entry __iommu_table[], __iommu_table_end[];
 
@@ -135,6 +141,8 @@ static __init int iommu_setup(char *p)
 #endif
                if (!strncmp(p, "pt", 2))
                        iommu_pass_through = 1;
+               if (!strncmp(p, "nopt", 4))
+                       iommu_pass_through = 0;
 
                gart_parse_options(p);
 
index 476e3dd..a451bc3 100644 (file)
@@ -384,6 +384,7 @@ start_thread(struct pt_regs *regs, unsigned long new_ip, unsigned long new_sp)
        start_thread_common(regs, new_ip, new_sp,
                            __USER_CS, __USER_DS, 0);
 }
+EXPORT_SYMBOL_GPL(start_thread);
 
 #ifdef CONFIG_COMPAT
 void compat_start_thread(struct pt_regs *regs, u32 new_ip, u32 new_sp)
index 73e27a9..6276140 100644 (file)
@@ -5586,8 +5586,6 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu)
 
        clgi();
 
-       local_irq_enable();
-
        /*
         * If this vCPU has touched SPEC_CTRL, restore the guest's value if
         * it's non-zero. Since vmentry is serialising on affected CPUs, there
@@ -5596,6 +5594,8 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu)
         */
        x86_spec_ctrl_set_guest(svm->spec_ctrl, svm->virt_spec_ctrl);
 
+       local_irq_enable();
+
        asm volatile (
                "push %%" _ASM_BP "; \n\t"
                "mov %c[rbx](%[svm]), %%" _ASM_BX " \n\t"
@@ -5718,12 +5718,12 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu)
        if (unlikely(!msr_write_intercepted(vcpu, MSR_IA32_SPEC_CTRL)))
                svm->spec_ctrl = native_read_msr(MSR_IA32_SPEC_CTRL);
 
-       x86_spec_ctrl_restore_host(svm->spec_ctrl, svm->virt_spec_ctrl);
-
        reload_tss(vcpu);
 
        local_irq_disable();
 
+       x86_spec_ctrl_restore_host(svm->spec_ctrl, svm->virt_spec_ctrl);
+
        vcpu->arch.cr2 = svm->vmcb->save.cr2;
        vcpu->arch.regs[VCPU_REGS_RAX] = svm->vmcb->save.rax;
        vcpu->arch.regs[VCPU_REGS_RSP] = svm->vmcb->save.rsp;
index 1519f03..1d26f3c 100644 (file)
@@ -198,12 +198,14 @@ static enum vmx_l1d_flush_state __read_mostly vmentry_l1d_flush_param = VMENTER_
 
 static const struct {
        const char *option;
-       enum vmx_l1d_flush_state cmd;
+       bool for_parse;
 } vmentry_l1d_param[] = {
-       {"auto",        VMENTER_L1D_FLUSH_AUTO},
-       {"never",       VMENTER_L1D_FLUSH_NEVER},
-       {"cond",        VMENTER_L1D_FLUSH_COND},
-       {"always",      VMENTER_L1D_FLUSH_ALWAYS},
+       [VMENTER_L1D_FLUSH_AUTO]         = {"auto", true},
+       [VMENTER_L1D_FLUSH_NEVER]        = {"never", true},
+       [VMENTER_L1D_FLUSH_COND]         = {"cond", true},
+       [VMENTER_L1D_FLUSH_ALWAYS]       = {"always", true},
+       [VMENTER_L1D_FLUSH_EPT_DISABLED] = {"EPT disabled", false},
+       [VMENTER_L1D_FLUSH_NOT_REQUIRED] = {"not required", false},
 };
 
 #define L1D_CACHE_ORDER 4
@@ -219,15 +221,15 @@ static int vmx_setup_l1d_flush(enum vmx_l1d_flush_state l1tf)
                return 0;
        }
 
-       if (boot_cpu_has(X86_FEATURE_ARCH_CAPABILITIES)) {
-              u64 msr;
+       if (boot_cpu_has(X86_FEATURE_ARCH_CAPABILITIES)) {
+               u64 msr;
 
-              rdmsrl(MSR_IA32_ARCH_CAPABILITIES, msr);
-              if (msr & ARCH_CAP_SKIP_VMENTRY_L1DFLUSH) {
-                      l1tf_vmx_mitigation = VMENTER_L1D_FLUSH_NOT_REQUIRED;
-                      return 0;
-              }
-       }
+               rdmsrl(MSR_IA32_ARCH_CAPABILITIES, msr);
+               if (msr & ARCH_CAP_SKIP_VMENTRY_L1DFLUSH) {
+                       l1tf_vmx_mitigation = VMENTER_L1D_FLUSH_NOT_REQUIRED;
+                       return 0;
+               }
+       }
 
        /* If set to auto use the default l1tf mitigation method */
        if (l1tf == VMENTER_L1D_FLUSH_AUTO) {
@@ -287,8 +289,9 @@ static int vmentry_l1d_flush_parse(const char *s)
 
        if (s) {
                for (i = 0; i < ARRAY_SIZE(vmentry_l1d_param); i++) {
-                       if (sysfs_streq(s, vmentry_l1d_param[i].option))
-                               return vmentry_l1d_param[i].cmd;
+                       if (vmentry_l1d_param[i].for_parse &&
+                           sysfs_streq(s, vmentry_l1d_param[i].option))
+                               return i;
                }
        }
        return -EINVAL;
@@ -298,13 +301,13 @@ static int vmentry_l1d_flush_set(const char *s, const struct kernel_param *kp)
 {
        int l1tf, ret;
 
-       if (!boot_cpu_has(X86_BUG_L1TF))
-               return 0;
-
        l1tf = vmentry_l1d_flush_parse(s);
        if (l1tf < 0)
                return l1tf;
 
+       if (!boot_cpu_has(X86_BUG_L1TF))
+               return 0;
+
        /*
         * Has vmx_init() run already? If not then this is the pre init
         * parameter parsing. In that case just store the value and let
@@ -324,6 +327,9 @@ static int vmentry_l1d_flush_set(const char *s, const struct kernel_param *kp)
 
 static int vmentry_l1d_flush_get(char *s, const struct kernel_param *kp)
 {
+       if (WARN_ON_ONCE(l1tf_vmx_mitigation >= ARRAY_SIZE(vmentry_l1d_param)))
+               return sprintf(s, "???\n");
+
        return sprintf(s, "%s\n", vmentry_l1d_param[l1tf_vmx_mitigation].option);
 }
 
@@ -1684,6 +1690,12 @@ static inline bool cpu_has_vmx_virtual_intr_delivery(void)
                SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY;
 }
 
+static inline bool cpu_has_vmx_encls_vmexit(void)
+{
+       return vmcs_config.cpu_based_2nd_exec_ctrl &
+               SECONDARY_EXEC_ENCLS_EXITING;
+}
+
 /*
  * Comment's format: document - errata name - stepping - processor name.
  * Refer from
@@ -4551,7 +4563,8 @@ static __init int setup_vmcs_config(struct vmcs_config *vmcs_conf)
                        SECONDARY_EXEC_RDRAND_EXITING |
                        SECONDARY_EXEC_ENABLE_PML |
                        SECONDARY_EXEC_TSC_SCALING |
-                       SECONDARY_EXEC_ENABLE_VMFUNC;
+                       SECONDARY_EXEC_ENABLE_VMFUNC |
+                       SECONDARY_EXEC_ENCLS_EXITING;
                if (adjust_vmx_controls(min2, opt2,
                                        MSR_IA32_VMX_PROCBASED_CTLS2,
                                        &_cpu_based_2nd_exec_control) < 0)
@@ -6648,6 +6661,9 @@ static void vmx_vcpu_setup(struct vcpu_vmx *vmx)
                vmcs_write64(PML_ADDRESS, page_to_phys(vmx->pml_pg));
                vmcs_write16(GUEST_PML_INDEX, PML_ENTITY_NUM - 1);
        }
+
+       if (cpu_has_vmx_encls_vmexit())
+               vmcs_write64(ENCLS_EXITING_BITMAP, -1ull);
 }
 
 static void vmx_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event)
@@ -9314,6 +9330,17 @@ fail:
        return 1;
 }
 
+static int handle_encls(struct kvm_vcpu *vcpu)
+{
+       /*
+        * SGX virtualization is not yet supported.  There is no software
+        * enable bit for SGX, so we have to trap ENCLS and inject a #UD
+        * to prevent the guest from executing ENCLS.
+        */
+       kvm_queue_exception(vcpu, UD_VECTOR);
+       return 1;
+}
+
 /*
  * The exit handlers return 1 if the exit was handled fully and guest execution
  * may resume.  Otherwise they set the kvm_run parameter to indicate what needs
@@ -9371,6 +9398,7 @@ static int (*const kvm_vmx_exit_handlers[])(struct kvm_vcpu *vcpu) = {
        [EXIT_REASON_INVPCID]                 = handle_invpcid,
        [EXIT_REASON_VMFUNC]                  = handle_vmfunc,
        [EXIT_REASON_PREEMPTION_TIMER]        = handle_preemption_timer,
+       [EXIT_REASON_ENCLS]                   = handle_encls,
 };
 
 static const int kvm_vmx_max_exit_handlers =
@@ -9741,6 +9769,9 @@ static bool nested_vmx_exit_reflected(struct kvm_vcpu *vcpu, u32 exit_reason)
        case EXIT_REASON_VMFUNC:
                /* VM functions are emulated through L2->L0 vmexits. */
                return false;
+       case EXIT_REASON_ENCLS:
+               /* SGX is never exposed to L1 */
+               return false;
        default:
                return true;
        }
@@ -10100,9 +10131,6 @@ static int vmx_handle_exit(struct kvm_vcpu *vcpu)
  * information but as all relevant affected CPUs have 32KiB L1D cache size
  * there is no point in doing so.
  */
-#define L1D_CACHE_ORDER 4
-static void *vmx_l1d_flush_pages;
-
 static void vmx_l1d_flush(struct kvm_vcpu *vcpu)
 {
        int size = PAGE_SIZE << L1D_CACHE_ORDER;
@@ -12101,6 +12129,9 @@ static int prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12,
                if (exec_control & SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES)
                        vmcs_write64(APIC_ACCESS_ADDR, -1ull);
 
+               if (exec_control & SECONDARY_EXEC_ENCLS_EXITING)
+                       vmcs_write64(ENCLS_EXITING_BITMAP, -1ull);
+
                vmcs_write32(SECONDARY_VM_EXEC_CONTROL, exec_control);
        }
 
index f7dff04..506bd2b 100644 (file)
@@ -6576,14 +6576,12 @@ static void kvm_set_mmio_spte_mask(void)
        /* Set the present bit. */
        mask |= 1ull;
 
-#ifdef CONFIG_X86_64
        /*
         * If reserved bit is not supported, clear the present bit to disable
         * mmio page fault.
         */
-       if (maxphyaddr == 52)
+       if (IS_ENABLED(CONFIG_X86_64) && maxphyaddr == 52)
                mask &= ~1ull;
-#endif
 
        kvm_mmu_set_mmio_spte_mask(mask, mask);
 }
@@ -7305,8 +7303,9 @@ static void vcpu_load_eoi_exitmap(struct kvm_vcpu *vcpu)
        kvm_x86_ops->load_eoi_exitmap(vcpu, eoi_exit_bitmap);
 }
 
-void kvm_arch_mmu_notifier_invalidate_range(struct kvm *kvm,
-               unsigned long start, unsigned long end)
+int kvm_arch_mmu_notifier_invalidate_range(struct kvm *kvm,
+               unsigned long start, unsigned long end,
+               bool blockable)
 {
        unsigned long apic_address;
 
@@ -7317,6 +7316,8 @@ void kvm_arch_mmu_notifier_invalidate_range(struct kvm *kvm,
        apic_address = gfn_to_hva(kvm, APIC_DEFAULT_PHYS_BASE >> PAGE_SHIFT);
        if (start <= apic_address && apic_address < end)
                kvm_make_all_cpus_request(kvm, KVM_REQ_APIC_PAGE_RELOAD);
+
+       return 0;
 }
 
 void kvm_vcpu_reload_apic_access_page(struct kvm_vcpu *vcpu)
index b45f5aa..076ebdc 100644 (file)
@@ -2,6 +2,8 @@
 
 #include <linux/spinlock.h>
 #include <linux/percpu.h>
+#include <linux/kallsyms.h>
+#include <linux/kcore.h>
 
 #include <asm/cpu_entry_area.h>
 #include <asm/pgtable.h>
@@ -13,6 +15,7 @@ static DEFINE_PER_CPU_PAGE_ALIGNED(struct entry_stack_page, entry_stack_storage)
 #ifdef CONFIG_X86_64
 static DEFINE_PER_CPU_PAGE_ALIGNED(char, exception_stacks
        [(N_EXCEPTION_STACKS - 1) * EXCEPTION_STKSZ + DEBUG_STKSZ]);
+static DEFINE_PER_CPU(struct kcore_list, kcore_entry_trampoline);
 #endif
 
 struct cpu_entry_area *get_cpu_entry_area(int cpu)
@@ -146,10 +149,40 @@ static void __init setup_cpu_entry_area(int cpu)
 
        cea_set_pte(&get_cpu_entry_area(cpu)->entry_trampoline,
                     __pa_symbol(_entry_trampoline), PAGE_KERNEL_RX);
+       /*
+        * The cpu_entry_area alias addresses are not in the kernel binary
+        * so they do not show up in /proc/kcore normally.  This adds entries
+        * for them manually.
+        */
+       kclist_add_remap(&per_cpu(kcore_entry_trampoline, cpu),
+                        _entry_trampoline,
+                        &get_cpu_entry_area(cpu)->entry_trampoline, PAGE_SIZE);
 #endif
        percpu_setup_debug_store(cpu);
 }
 
+#ifdef CONFIG_X86_64
+int arch_get_kallsym(unsigned int symnum, unsigned long *value, char *type,
+                    char *name)
+{
+       unsigned int cpu, ncpu = 0;
+
+       if (symnum >= num_possible_cpus())
+               return -EINVAL;
+
+       for_each_possible_cpu(cpu) {
+               if (ncpu++ >= symnum)
+                       break;
+       }
+
+       *value = (unsigned long)&get_cpu_entry_area(cpu)->entry_trampoline;
+       *type = 't';
+       strlcpy(name, "__entry_SYSCALL_64_trampoline", KSYM_NAME_LEN);
+
+       return 0;
+}
+#endif
+
 static __init void setup_cpu_entry_area_ptes(void)
 {
 #ifdef CONFIG_X86_32
index acfab32..7a8fc26 100644 (file)
@@ -99,15 +99,22 @@ __ref void *alloc_low_pages(unsigned int num)
        }
 
        if ((pgt_buf_end + num) > pgt_buf_top || !can_use_brk_pgt) {
-               unsigned long ret;
-               if (min_pfn_mapped >= max_pfn_mapped)
-                       panic("alloc_low_pages: ran out of memory");
-               ret = memblock_find_in_range(min_pfn_mapped << PAGE_SHIFT,
+               unsigned long ret = 0;
+
+               if (min_pfn_mapped < max_pfn_mapped) {
+                       ret = memblock_find_in_range(
+                                       min_pfn_mapped << PAGE_SHIFT,
                                        max_pfn_mapped << PAGE_SHIFT,
                                        PAGE_SIZE * num , PAGE_SIZE);
+               }
+               if (ret)
+                       memblock_reserve(ret, PAGE_SIZE * num);
+               else if (can_use_brk_pgt)
+                       ret = __pa(extend_brk(PAGE_SIZE * num, PAGE_SIZE));
+
                if (!ret)
                        panic("alloc_low_pages: can not alloc memory");
-               memblock_reserve(ret, PAGE_SIZE * num);
+
                pfn = ret >> PAGE_SHIFT;
        } else {
                pfn = pgt_buf_end;
@@ -923,7 +930,7 @@ unsigned long max_swapfile_size(void)
 
        if (boot_cpu_has_bug(X86_BUG_L1TF)) {
                /* Limit the swap file size to MAX_PA/2 for L1TF workaround */
-               unsigned long l1tf_limit = l1tf_pfn_limit() + 1;
+               unsigned long long l1tf_limit = l1tf_pfn_limit();
                /*
                 * We encode swap offsets also with 3 bits below those for pfn
                 * which makes the usable limit higher.
@@ -931,7 +938,7 @@ unsigned long max_swapfile_size(void)
 #if CONFIG_PGTABLE_LEVELS > 2
                l1tf_limit <<= PAGE_SHIFT - SWP_OFFSET_FIRST_BIT;
 #endif
-               pages = min_t(unsigned long, l1tf_limit, pages);
+               pages = min_t(unsigned long long, l1tf_limit, pages);
        }
        return pages;
 }
index f40ab81..1e95d57 100644 (file)
@@ -257,7 +257,7 @@ bool pfn_modify_allowed(unsigned long pfn, pgprot_t prot)
        /* If it's real memory always allow */
        if (pfn_valid(pfn))
                return true;
-       if (pfn > l1tf_pfn_limit() && !capable(CAP_SYS_ADMIN))
+       if (pfn >= l1tf_pfn_limit() && !capable(CAP_SYS_ADMIN))
                return false;
        return true;
 }
index 1555bd7..3d0c83e 100644 (file)
@@ -512,6 +512,17 @@ static int free_ram_pages_type(u64 start, u64 end)
        return 0;
 }
 
+static u64 sanitize_phys(u64 address)
+{
+       /*
+        * When changing the memtype for pages containing poison allow
+        * for a "decoy" virtual address (bit 63 clear) passed to
+        * set_memory_X(). __pa() on a "decoy" address results in a
+        * physical address with bit 63 set.
+        */
+       return address & __PHYSICAL_MASK;
+}
+
 /*
  * req_type typically has one of the:
  * - _PAGE_CACHE_MODE_WB
@@ -533,6 +544,8 @@ int reserve_memtype(u64 start, u64 end, enum page_cache_mode req_type,
        int is_range_ram;
        int err = 0;
 
+       start = sanitize_phys(start);
+       end = sanitize_phys(end);
        BUG_ON(start >= end); /* end is exclusive */
 
        if (!pat_enabled()) {
@@ -609,6 +622,9 @@ int free_memtype(u64 start, u64 end)
        if (!pat_enabled())
                return 0;
 
+       start = sanitize_phys(start);
+       end = sanitize_phys(end);
+
        /* Low ISA region is always mapped WB. No need to track */
        if (x86_platform.is_untracked_pat_range(start, end))
                return 0;
index 3ef095c..e848a48 100644 (file)
@@ -63,7 +63,7 @@ void ___pte_free_tlb(struct mmu_gather *tlb, struct page *pte)
 {
        pgtable_page_dtor(pte);
        paravirt_release_pte(page_to_pfn(pte));
-       tlb_remove_table(tlb, pte);
+       paravirt_tlb_remove_table(tlb, pte);
 }
 
 #if CONFIG_PGTABLE_LEVELS > 2
@@ -79,21 +79,21 @@ void ___pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd)
        tlb->need_flush_all = 1;
 #endif
        pgtable_pmd_page_dtor(page);
-       tlb_remove_table(tlb, page);
+       paravirt_tlb_remove_table(tlb, page);
 }
 
 #if CONFIG_PGTABLE_LEVELS > 3
 void ___pud_free_tlb(struct mmu_gather *tlb, pud_t *pud)
 {
        paravirt_release_pud(__pa(pud) >> PAGE_SHIFT);
-       tlb_remove_table(tlb, virt_to_page(pud));
+       paravirt_tlb_remove_table(tlb, virt_to_page(pud));
 }
 
 #if CONFIG_PGTABLE_LEVELS > 4
 void ___p4d_free_tlb(struct mmu_gather *tlb, p4d_t *p4d)
 {
        paravirt_release_p4d(__pa(p4d) >> PAGE_SHIFT);
-       tlb_remove_table(tlb, virt_to_page(p4d));
+       paravirt_tlb_remove_table(tlb, virt_to_page(p4d));
 }
 #endif /* CONFIG_PGTABLE_LEVELS > 4 */
 #endif /* CONFIG_PGTABLE_LEVELS > 3 */
index 752dbf4..9517d1b 100644 (file)
@@ -7,7 +7,6 @@
 #include <linux/export.h>
 #include <linux/cpu.h>
 #include <linux/debugfs.h>
-#include <linux/gfp.h>
 
 #include <asm/tlbflush.h>
 #include <asm/mmu_context.h>
@@ -186,11 +185,8 @@ void switch_mm_irqs_off(struct mm_struct *prev, struct mm_struct *next,
 {
        struct mm_struct *real_prev = this_cpu_read(cpu_tlbstate.loaded_mm);
        u16 prev_asid = this_cpu_read(cpu_tlbstate.loaded_mm_asid);
-       bool was_lazy = this_cpu_read(cpu_tlbstate.is_lazy);
        unsigned cpu = smp_processor_id();
        u64 next_tlb_gen;
-       bool need_flush;
-       u16 new_asid;
 
        /*
         * NB: The scheduler will call us with prev == next when switching
@@ -244,41 +240,20 @@ void switch_mm_irqs_off(struct mm_struct *prev, struct mm_struct *next,
                           next->context.ctx_id);
 
                /*
-                * Even in lazy TLB mode, the CPU should stay set in the
-                * mm_cpumask. The TLB shootdown code can figure out from
-                * from cpu_tlbstate.is_lazy whether or not to send an IPI.
+                * We don't currently support having a real mm loaded without
+                * our cpu set in mm_cpumask().  We have all the bookkeeping
+                * in place to figure out whether we would need to flush
+                * if our cpu were cleared in mm_cpumask(), but we don't
+                * currently use it.
                 */
                if (WARN_ON_ONCE(real_prev != &init_mm &&
                                 !cpumask_test_cpu(cpu, mm_cpumask(next))))
                        cpumask_set_cpu(cpu, mm_cpumask(next));
 
-               /*
-                * If the CPU is not in lazy TLB mode, we are just switching
-                * from one thread in a process to another thread in the same
-                * process. No TLB flush required.
-                */
-               if (!was_lazy)
-                       return;
-
-               /*
-                * Read the tlb_gen to check whether a flush is needed.
-                * If the TLB is up to date, just use it.
-                * The barrier synchronizes with the tlb_gen increment in
-                * the TLB shootdown code.
-                */
-               smp_mb();
-               next_tlb_gen = atomic64_read(&next->context.tlb_gen);
-               if (this_cpu_read(cpu_tlbstate.ctxs[prev_asid].tlb_gen) ==
-                               next_tlb_gen)
-                       return;
-
-               /*
-                * TLB contents went out of date while we were in lazy
-                * mode. Fall through to the TLB switching code below.
-                */
-               new_asid = prev_asid;
-               need_flush = true;
+               return;
        } else {
+               u16 new_asid;
+               bool need_flush;
                u64 last_ctx_id = this_cpu_read(cpu_tlbstate.last_ctx_id);
 
                /*
@@ -329,41 +304,41 @@ void switch_mm_irqs_off(struct mm_struct *prev, struct mm_struct *next,
                next_tlb_gen = atomic64_read(&next->context.tlb_gen);
 
                choose_new_asid(next, next_tlb_gen, &new_asid, &need_flush);
-       }
 
-       if (need_flush) {
-               this_cpu_write(cpu_tlbstate.ctxs[new_asid].ctx_id, next->context.ctx_id);
-               this_cpu_write(cpu_tlbstate.ctxs[new_asid].tlb_gen, next_tlb_gen);
-               load_new_mm_cr3(next->pgd, new_asid, true);
+               if (need_flush) {
+                       this_cpu_write(cpu_tlbstate.ctxs[new_asid].ctx_id, next->context.ctx_id);
+                       this_cpu_write(cpu_tlbstate.ctxs[new_asid].tlb_gen, next_tlb_gen);
+                       load_new_mm_cr3(next->pgd, new_asid, true);
+
+                       /*
+                        * NB: This gets called via leave_mm() in the idle path
+                        * where RCU functions differently.  Tracing normally
+                        * uses RCU, so we need to use the _rcuidle variant.
+                        *
+                        * (There is no good reason for this.  The idle code should
+                        *  be rearranged to call this before rcu_idle_enter().)
+                        */
+                       trace_tlb_flush_rcuidle(TLB_FLUSH_ON_TASK_SWITCH, TLB_FLUSH_ALL);
+               } else {
+                       /* The new ASID is already up to date. */
+                       load_new_mm_cr3(next->pgd, new_asid, false);
+
+                       /* See above wrt _rcuidle. */
+                       trace_tlb_flush_rcuidle(TLB_FLUSH_ON_TASK_SWITCH, 0);
+               }
 
                /*
-                * NB: This gets called via leave_mm() in the idle path
-                * where RCU functions differently.  Tracing normally
-                * uses RCU, so we need to use the _rcuidle variant.
-                *
-                * (There is no good reason for this.  The idle code should
-                *  be rearranged to call this before rcu_idle_enter().)
+                * Record last user mm's context id, so we can avoid
+                * flushing branch buffer with IBPB if we switch back
+                * to the same user.
                 */
-               trace_tlb_flush_rcuidle(TLB_FLUSH_ON_TASK_SWITCH, TLB_FLUSH_ALL);
-       } else {
-               /* The new ASID is already up to date. */
-               load_new_mm_cr3(next->pgd, new_asid, false);
+               if (next != &init_mm)
+                       this_cpu_write(cpu_tlbstate.last_ctx_id, next->context.ctx_id);
 
-               /* See above wrt _rcuidle. */
-               trace_tlb_flush_rcuidle(TLB_FLUSH_ON_TASK_SWITCH, 0);
+               this_cpu_write(cpu_tlbstate.loaded_mm, next);
+               this_cpu_write(cpu_tlbstate.loaded_mm_asid, new_asid);
        }
 
-       /*
-        * Record last user mm's context id, so we can avoid
-        * flushing branch buffer with IBPB if we switch back
-        * to the same user.
-        */
-       if (next != &init_mm)
-               this_cpu_write(cpu_tlbstate.last_ctx_id, next->context.ctx_id);
-
-       this_cpu_write(cpu_tlbstate.loaded_mm, next);
-       this_cpu_write(cpu_tlbstate.loaded_mm_asid, new_asid);
-
        load_mm_cr4(next);
        switch_ldt(real_prev, next);
 }
@@ -386,7 +361,20 @@ void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
        if (this_cpu_read(cpu_tlbstate.loaded_mm) == &init_mm)
                return;
 
-       this_cpu_write(cpu_tlbstate.is_lazy, true);
+       if (tlb_defer_switch_to_init_mm()) {
+               /*
+                * There's a significant optimization that may be possible
+                * here.  We have accurate enough TLB flush tracking that we
+                * don't need to maintain coherence of TLB per se when we're
+                * lazy.  We do, however, need to maintain coherence of
+                * paging-structure caches.  We could, in principle, leave our
+                * old mm loaded and only switch to init_mm when
+                * tlb_remove_page() happens.
+                */
+               this_cpu_write(cpu_tlbstate.is_lazy, true);
+       } else {
+               switch_mm(NULL, &init_mm, NULL);
+       }
 }
 
 /*
@@ -473,9 +461,6 @@ static void flush_tlb_func_common(const struct flush_tlb_info *f,
                 * paging-structure cache to avoid speculatively reading
                 * garbage into our TLB.  Since switching to init_mm is barely
                 * slower than a minimal flush, just switch to init_mm.
-                *
-                * This should be rare, with native_flush_tlb_others skipping
-                * IPIs to lazy TLB mode CPUs.
                 */
                switch_mm_irqs_off(NULL, &init_mm, NULL);
                return;
@@ -582,9 +567,6 @@ static void flush_tlb_func_remote(void *info)
 void native_flush_tlb_others(const struct cpumask *cpumask,
                             const struct flush_tlb_info *info)
 {
-       cpumask_var_t lazymask;
-       unsigned int cpu;
-
        count_vm_tlb_event(NR_TLB_REMOTE_FLUSH);
        if (info->end == TLB_FLUSH_ALL)
                trace_tlb_flush(TLB_REMOTE_SEND_IPI, TLB_FLUSH_ALL);
@@ -608,6 +590,8 @@ void native_flush_tlb_others(const struct cpumask *cpumask,
                 * that UV should be updated so that smp_call_function_many(),
                 * etc, are optimal on UV.
                 */
+               unsigned int cpu;
+
                cpu = smp_processor_id();
                cpumask = uv_flush_tlb_others(cpumask, info);
                if (cpumask)
@@ -615,29 +599,8 @@ void native_flush_tlb_others(const struct cpumask *cpumask,
                                               (void *)info, 1);
                return;
        }
-
-       /*
-        * A temporary cpumask is used in order to skip sending IPIs
-        * to CPUs in lazy TLB state, while keeping them in mm_cpumask(mm).
-        * If the allocation fails, simply IPI every CPU in mm_cpumask.
-        */
-       if (!alloc_cpumask_var(&lazymask, GFP_ATOMIC)) {
-               smp_call_function_many(cpumask, flush_tlb_func_remote,
-                              (void *)info, 1);
-               return;
-       }
-
-       cpumask_copy(lazymask, cpumask);
-
-       for_each_cpu(cpu, lazymask) {
-               if (per_cpu(cpu_tlbstate.is_lazy, cpu))
-                       cpumask_clear_cpu(cpu, lazymask);
-       }
-
-       smp_call_function_many(lazymask, flush_tlb_func_remote,
+       smp_call_function_many(cpumask, flush_tlb_func_remote,
                               (void *)info, 1);
-
-       free_cpumask_var(lazymask);
 }
 
 /*
@@ -690,68 +653,6 @@ void flush_tlb_mm_range(struct mm_struct *mm, unsigned long start,
        put_cpu();
 }
 
-void tlb_flush_remove_tables_local(void *arg)
-{
-       struct mm_struct *mm = arg;
-
-       if (this_cpu_read(cpu_tlbstate.loaded_mm) == mm &&
-                       this_cpu_read(cpu_tlbstate.is_lazy)) {
-               /*
-                * We're in lazy mode.  We need to at least flush our
-                * paging-structure cache to avoid speculatively reading
-                * garbage into our TLB.  Since switching to init_mm is barely
-                * slower than a minimal flush, just switch to init_mm.
-                */
-               switch_mm_irqs_off(NULL, &init_mm, NULL);
-       }
-}
-
-static void mm_fill_lazy_tlb_cpu_mask(struct mm_struct *mm,
-                                     struct cpumask *lazy_cpus)
-{
-       int cpu;
-
-       for_each_cpu(cpu, mm_cpumask(mm)) {
-               if (!per_cpu(cpu_tlbstate.is_lazy, cpu))
-                       cpumask_set_cpu(cpu, lazy_cpus);
-       }
-}
-
-void tlb_flush_remove_tables(struct mm_struct *mm)
-{
-       int cpu = get_cpu();
-       cpumask_var_t lazy_cpus;
-
-       if (cpumask_any_but(mm_cpumask(mm), cpu) >= nr_cpu_ids) {
-               put_cpu();
-               return;
-       }
-
-       if (!zalloc_cpumask_var(&lazy_cpus, GFP_ATOMIC)) {
-               /*
-                * If the cpumask allocation fails, do a brute force flush
-                * on all the CPUs that have this mm loaded.
-                */
-               smp_call_function_many(mm_cpumask(mm),
-                               tlb_flush_remove_tables_local, (void *)mm, 1);
-               put_cpu();
-               return;
-       }
-
-       /*
-        * CPUs with !is_lazy either received a TLB flush IPI while the user
-        * pages in this address range were unmapped, or have context switched
-        * and reloaded %CR3 since then.
-        *
-        * Shootdown IPIs at page table freeing time only need to be sent to
-        * CPUs that may have out of date TLB contents.
-        */
-       mm_fill_lazy_tlb_cpu_mask(mm, lazy_cpus);
-       smp_call_function_many(lazy_cpus,
-                               tlb_flush_remove_tables_local, (void *)mm, 1);
-       free_cpumask_var(lazy_cpus);
-       put_cpu();
-}
 
 static void do_flush_tlb_all(void *info)
 {
index ee3b00c..52a7c3f 100644 (file)
@@ -122,6 +122,8 @@ static void __init xen_banner(void)
 
 static void __init xen_pv_init_platform(void)
 {
+       populate_extra_pte(fix_to_virt(FIX_PARAVIRT_BOOTMAP));
+
        set_fixmap(FIX_PARAVIRT_BOOTMAP, xen_start_info->shared_info);
        HYPERVISOR_shared_info = (void *)fix_to_virt(FIX_PARAVIRT_BOOTMAP);
 
@@ -1170,13 +1172,13 @@ static void __init xen_boot_params_init_edd(void)
  * we do this, we have to be careful not to call any stack-protected
  * function, which is most of the kernel.
  */
-static void xen_setup_gdt(int cpu)
+static void __init xen_setup_gdt(int cpu)
 {
        pv_cpu_ops.write_gdt_entry = xen_write_gdt_entry_boot;
        pv_cpu_ops.load_gdt = xen_load_gdt_boot;
 
-       setup_stack_canary_segment(0);
-       switch_to_new_gdt(0);
+       setup_stack_canary_segment(cpu);
+       switch_to_new_gdt(cpu);
 
        pv_cpu_ops.write_gdt_entry = xen_write_gdt_entry;
        pv_cpu_ops.load_gdt = xen_load_gdt;
@@ -1385,8 +1387,11 @@ asmlinkage __visible void __init xen_start_kernel(void)
                xen_boot_params_init_edd();
        }
 
-       add_preferred_console("tty", 0, NULL);
+       if (!boot_params.screen_info.orig_video_isVGA)
+               add_preferred_console("tty", 0, NULL);
        add_preferred_console("hvc", 0, NULL);
+       if (boot_params.screen_info.orig_video_isVGA)
+               add_preferred_console("tty", 0, NULL);
 
 #ifdef CONFIG_PCI
        /* PCI BIOS service won't work from a PV guest. */
index 52206ad..45b700a 100644 (file)
@@ -67,6 +67,7 @@
 #include <asm/init.h>
 #include <asm/pat.h>
 #include <asm/smp.h>
+#include <asm/tlb.h>
 
 #include <asm/xen/hypercall.h>
 #include <asm/xen/hypervisor.h>
@@ -2171,6 +2172,8 @@ void __init xen_relocate_p2m(void)
 #else  /* !CONFIG_X86_64 */
 static RESERVE_BRK_ARRAY(pmd_t, initial_kernel_pmd, PTRS_PER_PMD);
 static RESERVE_BRK_ARRAY(pmd_t, swapper_kernel_pmd, PTRS_PER_PMD);
+RESERVE_BRK(fixup_kernel_pmd, PAGE_SIZE);
+RESERVE_BRK(fixup_kernel_pte, PAGE_SIZE);
 
 static void __init xen_write_cr3_init(unsigned long cr3)
 {
@@ -2397,6 +2400,7 @@ static const struct pv_mmu_ops xen_mmu_ops __initconst = {
        .flush_tlb_kernel = xen_flush_tlb,
        .flush_tlb_one_user = xen_flush_tlb_one_user,
        .flush_tlb_others = xen_flush_tlb_others,
+       .tlb_remove_table = tlb_remove_table,
 
        .pgd_alloc = xen_pgd_alloc,
        .pgd_free = xen_pgd_free,
index 6e0d208..1163e33 100644 (file)
@@ -906,37 +906,6 @@ char * __init xen_memory_setup(void)
 }
 
 /*
- * Machine specific memory setup for auto-translated guests.
- */
-char * __init xen_auto_xlated_memory_setup(void)
-{
-       struct xen_memory_map memmap;
-       int i;
-       int rc;
-
-       memmap.nr_entries = ARRAY_SIZE(xen_e820_table.entries);
-       set_xen_guest_handle(memmap.buffer, xen_e820_table.entries);
-
-       rc = HYPERVISOR_memory_op(XENMEM_memory_map, &memmap);
-       if (rc < 0)
-               panic("No memory map (%d)\n", rc);
-
-       xen_e820_table.nr_entries = memmap.nr_entries;
-
-       e820__update_table(&xen_e820_table);
-
-       for (i = 0; i < xen_e820_table.nr_entries; i++)
-               e820__range_add(xen_e820_table.entries[i].addr, xen_e820_table.entries[i].size, xen_e820_table.entries[i].type);
-
-       /* Remove p2m info, it is not needed. */
-       xen_start_info->mfn_list = 0;
-       xen_start_info->first_p2m_pfn = 0;
-       xen_start_info->nr_p2m_frames = 0;
-
-       return "Xen";
-}
-
-/*
  * Set the bit indicating "nosegneg" library variants should be used.
  * We only need to bother in pure 32-bit mode; compat 32-bit processes
  * can have un-truncated segments, so wrapping around is allowed.
index e786845..0e60bd9 100644 (file)
@@ -50,7 +50,6 @@ void __init xen_inv_extra_mem(void);
 void __init xen_remap_memory(void);
 phys_addr_t __init xen_find_free_area(phys_addr_t size);
 char * __init xen_memory_setup(void);
-char * xen_auto_xlated_memory_setup(void);
 void __init xen_arch_setup(void);
 void xen_enable_sysenter(void);
 void xen_enable_syscall(void);
index 801491e..04d038f 100644 (file)
@@ -4,12 +4,15 @@ config ZONE_DMA
 
 config XTENSA
        def_bool y
+       select ARCH_HAS_SYNC_DMA_FOR_CPU
+       select ARCH_HAS_SYNC_DMA_FOR_DEVICE
        select ARCH_NO_COHERENT_DMA_MMAP if !MMU
        select ARCH_WANT_FRAME_POINTERS
        select ARCH_WANT_IPC_PARSE_VERSION
        select BUILDTIME_EXTABLE_SORT
        select CLONE_BACKWARDS
        select COMMON_CLK
+       select DMA_NONCOHERENT_OPS
        select GENERIC_ATOMIC64
        select GENERIC_CLOCKEVENTS
        select GENERIC_IRQ_SHOW
@@ -72,9 +75,6 @@ config TRACE_IRQFLAGS_SUPPORT
 config MMU
        def_bool n
 
-config VARIANT_IRQ_SWITCH
-       def_bool n
-
 config HAVE_XTENSA_GPIO32
        def_bool n
 
@@ -244,6 +244,23 @@ config INITIALIZE_XTENSA_MMU_INSIDE_VMLINUX
 
          If in doubt, say Y.
 
+config MEMMAP_CACHEATTR
+       hex "Cache attributes for the memory address space"
+       depends on !MMU
+       default 0x22222222
+       help
+         These cache attributes are set up for noMMU systems. Each hex digit
+         specifies cache attributes for the corresponding 512MB memory
+         region: bits 0..3 -- for addresses 0x00000000..0x1fffffff,
+         bits 4..7 -- for addresses 0x20000000..0x3fffffff, and so on.
+
+         Cache attribute values are specific for the MMU type, so e.g.
+         for region protection MMUs: 2 is cache bypass, 4 is WB cached,
+         1 is WT cached, f is illegal. For ful MMU: bit 0 makes it executable,
+         bit 1 makes it writable, bits 2..3 meaning is 0: cache bypass,
+         1: WB cache, 2: WT cache, 3: special (c and e are illegal, f is
+         reserved).
+
 config KSEG_PADDR
        hex "Physical address of the KSEG mapping"
        depends on INITIALIZE_XTENSA_MMU_INSIDE_VMLINUX && MMU
@@ -413,6 +430,10 @@ config XTENSA_PLATFORM_XTFPGA
 
 endchoice
 
+config PLATFORM_NR_IRQS
+       int
+       default 3 if XTENSA_PLATFORM_XT2000
+       default 0
 
 config XTENSA_CPU_CLOCK
        int "CPU clock rate [MHz]"
@@ -450,6 +471,15 @@ config BUILTIN_DTB
        string "DTB to build into the kernel image"
        depends on OF
 
+config PARSE_BOOTPARAM
+       bool "Parse bootparam block"
+       default y
+       help
+         Parse parameters passed to the kernel from the bootloader. It may
+         be disabled if the kernel is known to run without the bootloader.
+
+         If unsure, say Y.
+
 config BLK_DEV_SIMDISK
        tristate "Host file-based simulated block device support"
        default n
@@ -506,25 +536,13 @@ config PLATFORM_WANT_DEFAULT_MEM
        def_bool n
 
 config DEFAULT_MEM_START
-       hex "Physical address of the default memory area start"
-       depends on PLATFORM_WANT_DEFAULT_MEM
-       default 0x00000000 if MMU
-       default 0x60000000 if !MMU
-       help
-         This is the base address of the default memory area.
-         Default memory area has platform-specific meaning, it may be used
-         for e.g. early cache initialization.
-
-         If unsure, leave the default value here.
-
-config DEFAULT_MEM_SIZE
-       hex "Maximal size of the default memory area"
-       depends on PLATFORM_WANT_DEFAULT_MEM
-       default 0x04000000
+       hex
+       prompt "PAGE_OFFSET/PHYS_OFFSET" if !MMU && PLATFORM_WANT_DEFAULT_MEM
+       default 0x60000000 if PLATFORM_WANT_DEFAULT_MEM
+       default 0x00000000
        help
-         This is the size of the default memory area.
-         Default memory area has platform-specific meaning, it may be used
-         for e.g. early cache initialization.
+         This is the base address used for both PAGE_OFFSET and PHYS_OFFSET
+         in noMMU configurations.
 
          If unsure, leave the default value here.
 
index 3a934b7..295c120 100644 (file)
@@ -49,7 +49,7 @@ KBUILD_CFLAGS += $(call cc-option,-mno-serialize-volatile,)
 KBUILD_AFLAGS += -mlongcalls -mtext-section-literals
 
 ifneq ($(CONFIG_LD_NO_RELAX),)
-LDFLAGS := --no-relax
+KBUILD_LDFLAGS := --no-relax
 endif
 
 ifeq ($(shell echo __XTENSA_EB__ | $(CC) -E - | grep -v "\#"),1)
index 5214719..12ae1e9 100644 (file)
@@ -25,7 +25,7 @@ $(obj)/Image.o: vmlinux.bin $(OBJS)
                $(OBJS) $@
 
 $(obj)/../Image.elf: $(obj)/Image.o $(obj)/boot.lds
-       $(Q)$(LD) $(LDFLAGS) $(LDFLAGS_vmlinux) \
+       $(Q)$(LD) $(KBUILD_LDFLAGS) $(LDFLAGS_vmlinux) \
                -T $(obj)/boot.lds \
                --build-id=none \
                -o $@ $(obj)/Image.o
index b6aa853..29c6842 100644 (file)
  */
 
 #include <asm/bootparam.h>
-#include <asm/processor.h>
-#include <asm/pgtable.h>
-#include <asm/page.h>
-#include <asm/cacheasm.h>
 #include <asm/initialize_mmu.h>
 #include <asm/vectors.h>
 #include <linux/linkage.h>
@@ -33,16 +29,18 @@ _ResetVector:
        .begin  no-absolute-literals
        .literal_position
 
-       .align 4
-RomInitAddr:
 #if defined(CONFIG_INITIALIZE_XTENSA_MMU_INSIDE_VMLINUX) && \
        XCHAL_HAVE_PTP_MMU && XCHAL_HAVE_SPANNING_WAY
-       .word   CONFIG_KERNEL_LOAD_ADDRESS
+       .literal RomInitAddr, CONFIG_KERNEL_LOAD_ADDRESS
 #else
-       .word   KERNELOFFSET
+       .literal RomInitAddr, KERNELOFFSET
 #endif
-RomBootParam:
-       .word _bootparam
+#ifndef CONFIG_PARSE_BOOTPARAM
+       .literal RomBootParam, 0
+#else
+       .literal RomBootParam, _bootparam
+
+       .align 4
 _bootparam:
        .short  BP_TAG_FIRST
        .short  4
@@ -50,6 +48,7 @@ _bootparam:
        .short  BP_TAG_LAST
        .short  0
        .long   0
+#endif
 
        .align  4
 _SetupMMU:
index 624f9b3..f3fc4f9 100644 (file)
@@ -33,13 +33,13 @@ CONFIG_XTENSA_VARIANT_CUSTOM_NAME="de212"
 # CONFIG_XTENSA_VARIANT_MMU is not set
 CONFIG_XTENSA_UNALIGNED_USER=y
 CONFIG_PREEMPT=y
+CONFIG_MEMMAP_CACHEATTR=0xfff2442f
 # CONFIG_PCI is not set
 CONFIG_XTENSA_PLATFORM_XTFPGA=y
 CONFIG_CMDLINE_BOOL=y
 CONFIG_CMDLINE="earlycon=uart8250,mmio32native,0x9d050020,115200n8 console=ttyS0,115200n8 ip=dhcp root=/dev/nfs rw debug memmap=256M@0x60000000"
 CONFIG_USE_OF=y
 CONFIG_BUILTIN_DTB="kc705_nommu"
-CONFIG_DEFAULT_MEM_SIZE=0x10000000
 CONFIG_BINFMT_FLAT=y
 CONFIG_NET=y
 CONFIG_PACKET=y
index e5e1e61..82c7564 100644 (file)
@@ -3,6 +3,7 @@ generic-y += compat.h
 generic-y += device.h
 generic-y += div64.h
 generic-y += dma-contiguous.h
+generic-y += dma-mapping.h
 generic-y += emergency-restart.h
 generic-y += exec.h
 generic-y += extable.h
index 2041abb..34545ec 100644 (file)
  *
  */
 
-       .macro  __loop_cache_all ar at insn size line_width
 
-       movi    \ar, 0
+       .macro  __loop_cache_unroll ar at insn size line_width max_immed
+
+       .if     (1 << (\line_width)) > (\max_immed)
+       .set    _reps, 1
+       .elseif (2 << (\line_width)) > (\max_immed)
+       .set    _reps, 2
+       .else
+       .set    _reps, 4
+       .endif
+
+       __loopi \ar, \at, \size, (_reps << (\line_width))
+       .set    _index, 0
+       .rep    _reps
+       \insn   \ar, _index << (\line_width)
+       .set    _index, _index + 1
+       .endr
+       __endla \ar, \at, _reps << (\line_width)
+
+       .endm
+
 
-       __loopi \ar, \at, \size, (4 << (\line_width))
-       \insn   \ar, 0 << (\line_width)
-       \insn   \ar, 1 << (\line_width)
-       \insn   \ar, 2 << (\line_width)
-       \insn   \ar, 3 << (\line_width)
-       __endla \ar, \at, 4 << (\line_width)
+       .macro  __loop_cache_all ar at insn size line_width max_immed
+
+       movi    \ar, 0
+       __loop_cache_unroll \ar, \at, \insn, \size, \line_width, \max_immed
 
        .endm
 
        .endm
 
 
-       .macro  __loop_cache_page ar at insn line_width
+       .macro  __loop_cache_page ar at insn line_width max_immed
 
-       __loopi \ar, \at, PAGE_SIZE, 4 << (\line_width)
-       \insn   \ar, 0 << (\line_width)
-       \insn   \ar, 1 << (\line_width)
-       \insn   \ar, 2 << (\line_width)
-       \insn   \ar, 3 << (\line_width)
-       __endla \ar, \at, 4 << (\line_width)
+       __loop_cache_unroll \ar, \at, \insn, PAGE_SIZE, \line_width, \max_immed
 
        .endm
 
@@ -72,7 +83,8 @@
        .macro  ___unlock_dcache_all ar at
 
 #if XCHAL_DCACHE_LINE_LOCKABLE && XCHAL_DCACHE_SIZE
-       __loop_cache_all \ar \at diu XCHAL_DCACHE_SIZE XCHAL_DCACHE_LINEWIDTH
+       __loop_cache_all \ar \at diu XCHAL_DCACHE_SIZE \
+               XCHAL_DCACHE_LINEWIDTH 240
 #endif
 
        .endm
@@ -81,7 +93,8 @@
        .macro  ___unlock_icache_all ar at
 
 #if XCHAL_ICACHE_LINE_LOCKABLE && XCHAL_ICACHE_SIZE
-       __loop_cache_all \ar \at iiu XCHAL_ICACHE_SIZE XCHAL_ICACHE_LINEWIDTH
+       __loop_cache_all \ar \at iiu XCHAL_ICACHE_SIZE \
+               XCHAL_ICACHE_LINEWIDTH 240
 #endif
 
        .endm
        .macro  ___flush_invalidate_dcache_all ar at
 
 #if XCHAL_DCACHE_SIZE
-       __loop_cache_all \ar \at diwbi XCHAL_DCACHE_SIZE XCHAL_DCACHE_LINEWIDTH
+       __loop_cache_all \ar \at diwbi XCHAL_DCACHE_SIZE \
+               XCHAL_DCACHE_LINEWIDTH 240
 #endif
 
        .endm
        .macro  ___flush_dcache_all ar at
 
 #if XCHAL_DCACHE_SIZE
-       __loop_cache_all \ar \at diwb XCHAL_DCACHE_SIZE XCHAL_DCACHE_LINEWIDTH
+       __loop_cache_all \ar \at diwb XCHAL_DCACHE_SIZE \
+               XCHAL_DCACHE_LINEWIDTH 240
 #endif
 
        .endm
        .macro  ___invalidate_dcache_all ar at
 
 #if XCHAL_DCACHE_SIZE
-       __loop_cache_all \ar \at dii __stringify(DCACHE_WAY_SIZE) \
-                        XCHAL_DCACHE_LINEWIDTH
+       __loop_cache_all \ar \at dii XCHAL_DCACHE_SIZE \
+                        XCHAL_DCACHE_LINEWIDTH 1020
 #endif
 
        .endm
        .macro  ___invalidate_icache_all ar at
 
 #if XCHAL_ICACHE_SIZE
-       __loop_cache_all \ar \at iii __stringify(ICACHE_WAY_SIZE) \
-                        XCHAL_ICACHE_LINEWIDTH
+       __loop_cache_all \ar \at iii XCHAL_ICACHE_SIZE \
+                        XCHAL_ICACHE_LINEWIDTH 1020
 #endif
 
        .endm
        .macro  ___flush_invalidate_dcache_page ar as
 
 #if XCHAL_DCACHE_SIZE
-       __loop_cache_page \ar \as dhwbi XCHAL_DCACHE_LINEWIDTH
+       __loop_cache_page \ar \as dhwbi XCHAL_DCACHE_LINEWIDTH 1020
 #endif
 
        .endm
        .macro ___flush_dcache_page ar as
 
 #if XCHAL_DCACHE_SIZE
-       __loop_cache_page \ar \as dhwb XCHAL_DCACHE_LINEWIDTH
+       __loop_cache_page \ar \as dhwb XCHAL_DCACHE_LINEWIDTH 1020
 #endif
 
        .endm
        .macro  ___invalidate_dcache_page ar as
 
 #if XCHAL_DCACHE_SIZE
-       __loop_cache_page \ar \as dhi XCHAL_DCACHE_LINEWIDTH
+       __loop_cache_page \ar \as dhi XCHAL_DCACHE_LINEWIDTH 1020
 #endif
 
        .endm
        .macro  ___invalidate_icache_page ar as
 
 #if XCHAL_ICACHE_SIZE
-       __loop_cache_page \ar \as ihi XCHAL_ICACHE_LINEWIDTH
+       __loop_cache_page \ar \as ihi XCHAL_ICACHE_LINEWIDTH 1020
 #endif
 
        .endm
diff --git a/arch/xtensa/include/asm/dma-mapping.h b/arch/xtensa/include/asm/dma-mapping.h
deleted file mode 100644 (file)
index 4409880..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * 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) 2003 - 2005 Tensilica Inc.
- * Copyright (C) 2015 Cadence Design Systems Inc.
- */
-
-#ifndef _XTENSA_DMA_MAPPING_H
-#define _XTENSA_DMA_MAPPING_H
-
-#include <asm/cache.h>
-#include <asm/io.h>
-
-#include <linux/mm.h>
-#include <linux/scatterlist.h>
-
-extern const struct dma_map_ops xtensa_dma_map_ops;
-
-static inline const struct dma_map_ops *get_arch_dma_ops(struct bus_type *bus)
-{
-       return &xtensa_dma_map_ops;
-}
-
-#endif /* _XTENSA_DMA_MAPPING_H */
index 42410f2..10e9852 100644 (file)
 #endif /* defined(CONFIG_MMU) && XCHAL_HAVE_PTP_MMU &&
          XCHAL_HAVE_SPANNING_WAY */
 
-#if !defined(CONFIG_MMU) && XCHAL_HAVE_TLBS && \
-               (XCHAL_DCACHE_SIZE || XCHAL_ICACHE_SIZE)
-       /* Enable data and instruction cache in the DEFAULT_MEMORY region
-        * if the processor has DTLB and ITLB.
-        */
+       .endm
+
+       .macro  initialize_cacheattr
 
-       movi    a5, PLATFORM_DEFAULT_MEM_START | XCHAL_SPANNING_WAY
+#if !defined(CONFIG_MMU) && XCHAL_HAVE_TLBS
+#if CONFIG_MEMMAP_CACHEATTR == 0x22222222 && XCHAL_HAVE_PTP_MMU
+#error Default MEMMAP_CACHEATTR of 0x22222222 does not work with full MMU.
+#endif
+
+       movi    a5, XCHAL_SPANNING_WAY
        movi    a6, ~_PAGE_ATTRIB_MASK
-       movi    a7, CA_WRITEBACK
+       movi    a4, CONFIG_MEMMAP_CACHEATTR
        movi    a8, 0x20000000
-       movi    a9, PLATFORM_DEFAULT_MEM_SIZE
-       j       2f
 1:
-       sub     a9, a9, a8
-2:
-#if XCHAL_DCACHE_SIZE
        rdtlb1  a3, a5
+       xor     a3, a3, a4
        and     a3, a3, a6
-       or      a3, a3, a7
+       xor     a3, a3, a4
        wdtlb   a3, a5
-#endif
-#if XCHAL_ICACHE_SIZE
-       ritlb1  a4, a5
-       and     a4, a4, a6
-       or      a4, a4, a7
-       witlb   a4, a5
-#endif
+       ritlb1  a3, a5
+       xor     a3, a3, a4
+       and     a3, a3, a6
+       xor     a3, a3, a4
+       witlb   a3, a5
+
        add     a5, a5, a8
-       bltu    a8, a9, 1b
+       srli    a4, a4, 4
+       bgeu    a5, a8, 1b
 
+       isync
 #endif
 
        .endm
index 19707db..6c6ed23 100644 (file)
 #define _XTENSA_IRQ_H
 
 #include <linux/init.h>
-#include <platform/hardware.h>
 #include <variant/core.h>
 
-#ifdef CONFIG_VARIANT_IRQ_SWITCH
-#include <variant/irq.h>
+#ifdef CONFIG_PLATFORM_NR_IRQS
+# define PLATFORM_NR_IRQS CONFIG_PLATFORM_NR_IRQS
 #else
-static inline void variant_irq_enable(unsigned int irq) { }
-static inline void variant_irq_disable(unsigned int irq) { }
-#endif
-
-#ifndef VARIANT_NR_IRQS
-# define VARIANT_NR_IRQS 0
-#endif
-#ifndef PLATFORM_NR_IRQS
 # define PLATFORM_NR_IRQS 0
 #endif
 #define XTENSA_NR_IRQS XCHAL_NUM_INTERRUPTS
-#define NR_IRQS (XTENSA_NR_IRQS + VARIANT_NR_IRQS + PLATFORM_NR_IRQS + 1)
+#define NR_IRQS (XTENSA_NR_IRQS + PLATFORM_NR_IRQS + 1)
 #define XTENSA_PIC_LINUX_IRQ(hwirq) ((hwirq) + 1)
 
-#if VARIANT_NR_IRQS == 0
-static inline void variant_init_irq(void) { }
-#else
-void variant_init_irq(void) __init;
-#endif
-
 static __inline__ int irq_canonicalize(int irq)
 {
        return (irq);
index 2317c83..9c12bab 100644 (file)
 #error XCHAL_KSEG_PADDR is not properly aligned to XCHAL_KSEG_ALIGNMENT
 #endif
 
-#else
-
-#define XCHAL_KSEG_CACHED_VADDR        __XTENSA_UL_CONST(0xd0000000)
-#define XCHAL_KSEG_BYPASS_VADDR        __XTENSA_UL_CONST(0xd8000000)
-#define XCHAL_KSEG_SIZE                __XTENSA_UL_CONST(0x08000000)
-
 #endif
 
 #ifndef CONFIG_KASAN
index 5d69c11..09c56cb 100644 (file)
@@ -14,7 +14,6 @@
 #include <asm/processor.h>
 #include <asm/types.h>
 #include <asm/cache.h>
-#include <platform/hardware.h>
 #include <asm/kmem_layout.h>
 
 /*
@@ -31,8 +30,8 @@
 #define MAX_LOW_PFN    (PHYS_PFN(XCHAL_KSEG_PADDR) + \
                         PHYS_PFN(XCHAL_KSEG_SIZE))
 #else
-#define PAGE_OFFSET    PLATFORM_DEFAULT_MEM_START
-#define PHYS_OFFSET    PLATFORM_DEFAULT_MEM_START
+#define PAGE_OFFSET    _AC(CONFIG_DEFAULT_MEM_START, UL)
+#define PHYS_OFFSET    _AC(CONFIG_DEFAULT_MEM_START, UL)
 #define MAX_LOW_PFN    PHYS_PFN(0xfffffffful)
 #endif
 
index 3880225..29cfe42 100644 (file)
@@ -66,6 +66,7 @@
 #define FIRST_USER_ADDRESS     0UL
 #define FIRST_USER_PGD_NR      (FIRST_USER_ADDRESS >> PGDIR_SHIFT)
 
+#ifdef CONFIG_MMU
 /*
  * Virtual memory area. We keep a distance to other memory regions to be
  * on the safe side. We also use this area for cache aliasing.
 #define TLBTEMP_SIZE           ICACHE_WAY_SIZE
 #endif
 
+#else
+
+#define VMALLOC_START          __XTENSA_UL_CONST(0)
+#define VMALLOC_END            __XTENSA_UL_CONST(0xffffffff)
+
+#endif
+
 /*
  * For the Xtensa architecture, the PTE layout is as follows:
  *
index f8fbef6..5604833 100644 (file)
@@ -75,4 +75,31 @@ extern void platform_calibrate_ccount (void);
  */
 void cpu_reset(void) __attribute__((noreturn));
 
+/*
+ * Memory caching is platform-dependent in noMMU xtensa configurations.
+ * The following set of functions should be implemented in platform code
+ * in order to enable coherent DMA memory operations when CONFIG_MMU is not
+ * enabled. Default implementations do nothing and issue a warning.
+ */
+
+/*
+ * Check whether p points to a cached memory.
+ */
+bool platform_vaddr_cached(const void *p);
+
+/*
+ * Check whether p points to an uncached memory.
+ */
+bool platform_vaddr_uncached(const void *p);
+
+/*
+ * Return pointer to an uncached view of the cached sddress p.
+ */
+void *platform_vaddr_to_uncached(void *p);
+
+/*
+ * Return pointer to a cached view of the uncached sddress p.
+ */
+void *platform_vaddr_to_cached(void *p);
+
 #endif /* _XTENSA_PLATFORM_H */
index 5b0027d..e4ccb88 100644 (file)
@@ -11,7 +11,6 @@
 #define _XTENSA_PROCESSOR_H
 
 #include <variant/core.h>
-#include <platform/hardware.h>
 
 #include <linux/compiler.h>
 #include <asm/ptrace.h>
index 65d3da9..7111280 100644 (file)
@@ -19,7 +19,6 @@
 #define _XTENSA_VECTORS_H
 
 #include <variant/core.h>
-#include <platform/hardware.h>
 #include <asm/kmem_layout.h>
 
 #if XCHAL_HAVE_PTP_MMU
index 9c4e943..2f76118 100644 (file)
@@ -181,6 +181,8 @@ ENTRY(_startup)
 
        isync
 
+       initialize_cacheattr
+
 #ifdef CONFIG_HAVE_SMP
        movi    a2, CCON        # MX External Register to Configure Cache
        movi    a3, 1
index 18e4ef3..a48bf2d 100644 (file)
@@ -158,7 +158,6 @@ void __init init_IRQ(void)
 #ifdef CONFIG_SMP
        ipi_init();
 #endif
-       variant_init_irq();
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
index a02dc56..1fc138b 100644 (file)
  */
 
 #include <linux/dma-contiguous.h>
+#include <linux/dma-noncoherent.h>
 #include <linux/dma-direct.h>
 #include <linux/gfp.h>
 #include <linux/highmem.h>
 #include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/string.h>
 #include <linux/types.h>
 #include <asm/cacheflush.h>
 #include <asm/io.h>
+#include <asm/platform.h>
 
-static void do_cache_op(dma_addr_t dma_handle, size_t size,
+static void do_cache_op(phys_addr_t paddr, size_t size,
                        void (*fn)(unsigned long, unsigned long))
 {
-       unsigned long off = dma_handle & (PAGE_SIZE - 1);
-       unsigned long pfn = PFN_DOWN(dma_handle);
+       unsigned long off = paddr & (PAGE_SIZE - 1);
+       unsigned long pfn = PFN_DOWN(paddr);
        struct page *page = pfn_to_page(pfn);
 
        if (!PageHighMem(page))
-               fn((unsigned long)bus_to_virt(dma_handle), size);
+               fn((unsigned long)phys_to_virt(paddr), size);
        else
                while (size > 0) {
                        size_t sz = min_t(size_t, size, PAGE_SIZE - off);
@@ -49,14 +48,13 @@ static void do_cache_op(dma_addr_t dma_handle, size_t size,
                }
 }
 
-static void xtensa_sync_single_for_cpu(struct device *dev,
-                                      dma_addr_t dma_handle, size_t size,
-                                      enum dma_data_direction dir)
+void arch_sync_dma_for_cpu(struct device *dev, phys_addr_t paddr,
+               size_t size, enum dma_data_direction dir)
 {
        switch (dir) {
        case DMA_BIDIRECTIONAL:
        case DMA_FROM_DEVICE:
-               do_cache_op(dma_handle, size, __invalidate_dcache_range);
+               do_cache_op(paddr, size, __invalidate_dcache_range);
                break;
 
        case DMA_NONE:
@@ -68,15 +66,14 @@ static void xtensa_sync_single_for_cpu(struct device *dev,
        }
 }
 
-static void xtensa_sync_single_for_device(struct device *dev,
-                                         dma_addr_t dma_handle, size_t size,
-                                         enum dma_data_direction dir)
+void arch_sync_dma_for_device(struct device *dev, phys_addr_t paddr,
+               size_t size, enum dma_data_direction dir)
 {
        switch (dir) {
        case DMA_BIDIRECTIONAL:
        case DMA_TO_DEVICE:
                if (XCHAL_DCACHE_IS_WRITEBACK)
-                       do_cache_op(dma_handle, size, __flush_dcache_range);
+                       do_cache_op(paddr, size, __flush_dcache_range);
                break;
 
        case DMA_NONE:
@@ -88,43 +85,66 @@ static void xtensa_sync_single_for_device(struct device *dev,
        }
 }
 
-static void xtensa_sync_sg_for_cpu(struct device *dev,
-                                  struct scatterlist *sg, int nents,
-                                  enum dma_data_direction dir)
+#ifdef CONFIG_MMU
+bool platform_vaddr_cached(const void *p)
 {
-       struct scatterlist *s;
-       int i;
+       unsigned long addr = (unsigned long)p;
 
-       for_each_sg(sg, s, nents, i) {
-               xtensa_sync_single_for_cpu(dev, sg_dma_address(s),
-                                          sg_dma_len(s), dir);
-       }
+       return addr >= XCHAL_KSEG_CACHED_VADDR &&
+              addr - XCHAL_KSEG_CACHED_VADDR < XCHAL_KSEG_SIZE;
 }
 
-static void xtensa_sync_sg_for_device(struct device *dev,
-                                     struct scatterlist *sg, int nents,
-                                     enum dma_data_direction dir)
+bool platform_vaddr_uncached(const void *p)
 {
-       struct scatterlist *s;
-       int i;
+       unsigned long addr = (unsigned long)p;
 
-       for_each_sg(sg, s, nents, i) {
-               xtensa_sync_single_for_device(dev, sg_dma_address(s),
-                                             sg_dma_len(s), dir);
-       }
+       return addr >= XCHAL_KSEG_BYPASS_VADDR &&
+              addr - XCHAL_KSEG_BYPASS_VADDR < XCHAL_KSEG_SIZE;
+}
+
+void *platform_vaddr_to_uncached(void *p)
+{
+       return p + XCHAL_KSEG_BYPASS_VADDR - XCHAL_KSEG_CACHED_VADDR;
+}
+
+void *platform_vaddr_to_cached(void *p)
+{
+       return p + XCHAL_KSEG_CACHED_VADDR - XCHAL_KSEG_BYPASS_VADDR;
+}
+#else
+bool __attribute__((weak)) platform_vaddr_cached(const void *p)
+{
+       WARN_ONCE(1, "Default %s implementation is used\n", __func__);
+       return true;
+}
+
+bool __attribute__((weak)) platform_vaddr_uncached(const void *p)
+{
+       WARN_ONCE(1, "Default %s implementation is used\n", __func__);
+       return false;
+}
+
+void __attribute__((weak)) *platform_vaddr_to_uncached(void *p)
+{
+       WARN_ONCE(1, "Default %s implementation is used\n", __func__);
+       return p;
+}
+
+void __attribute__((weak)) *platform_vaddr_to_cached(void *p)
+{
+       WARN_ONCE(1, "Default %s implementation is used\n", __func__);
+       return p;
 }
+#endif
 
 /*
  * Note: We assume that the full memory space is always mapped to 'kseg'
  *      Otherwise we have to use page attributes (not implemented).
  */
 
-static void *xtensa_dma_alloc(struct device *dev, size_t size,
-                             dma_addr_t *handle, gfp_t flag,
-                             unsigned long attrs)
+void *arch_dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
+               gfp_t flag, unsigned long attrs)
 {
-       unsigned long ret;
-       unsigned long uncached;
        unsigned long count = PAGE_ALIGN(size) >> PAGE_SHIFT;
        struct page *page = NULL;
 
@@ -147,6 +167,10 @@ static void *xtensa_dma_alloc(struct device *dev, size_t size,
 
        *handle = phys_to_dma(dev, page_to_phys(page));
 
+       if (attrs & DMA_ATTR_NO_KERNEL_MAPPING) {
+               return page;
+       }
+
 #ifdef CONFIG_MMU
        if (PageHighMem(page)) {
                void *p;
@@ -161,27 +185,21 @@ static void *xtensa_dma_alloc(struct device *dev, size_t size,
                return p;
        }
 #endif
-       ret = (unsigned long)page_address(page);
-       BUG_ON(ret < XCHAL_KSEG_CACHED_VADDR ||
-              ret > XCHAL_KSEG_CACHED_VADDR + XCHAL_KSEG_SIZE - 1);
-
-       uncached = ret + XCHAL_KSEG_BYPASS_VADDR - XCHAL_KSEG_CACHED_VADDR;
-       __invalidate_dcache_range(ret, size);
-
-       return (void *)uncached;
+       BUG_ON(!platform_vaddr_cached(page_address(page)));
+       __invalidate_dcache_range((unsigned long)page_address(page), size);
+       return platform_vaddr_to_uncached(page_address(page));
 }
 
-static void xtensa_dma_free(struct device *dev, size_t size, void *vaddr,
-                           dma_addr_t dma_handle, unsigned long attrs)
+void arch_dma_free(struct device *dev, size_t size, void *vaddr,
+               dma_addr_t dma_handle, unsigned long attrs)
 {
        unsigned long count = PAGE_ALIGN(size) >> PAGE_SHIFT;
-       unsigned long addr = (unsigned long)vaddr;
        struct page *page;
 
-       if (addr >= XCHAL_KSEG_BYPASS_VADDR &&
-           addr - XCHAL_KSEG_BYPASS_VADDR < XCHAL_KSEG_SIZE) {
-               addr += XCHAL_KSEG_CACHED_VADDR - XCHAL_KSEG_BYPASS_VADDR;
-               page = virt_to_page(addr);
+       if (attrs & DMA_ATTR_NO_KERNEL_MAPPING) {
+               page = vaddr;
+       } else if (platform_vaddr_uncached(vaddr)) {
+               page = virt_to_page(platform_vaddr_to_cached(vaddr));
        } else {
 #ifdef CONFIG_MMU
                dma_common_free_remap(vaddr, size, VM_MAP);
@@ -192,72 +210,3 @@ static void xtensa_dma_free(struct device *dev, size_t size, void *vaddr,
        if (!dma_release_from_contiguous(dev, page, count))
                __free_pages(page, get_order(size));
 }
-
-static dma_addr_t xtensa_map_page(struct device *dev, struct page *page,
-                                 unsigned long offset, size_t size,
-                                 enum dma_data_direction dir,
-                                 unsigned long attrs)
-{
-       dma_addr_t dma_handle = page_to_phys(page) + offset;
-
-       if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC))
-               xtensa_sync_single_for_device(dev, dma_handle, size, dir);
-
-       return dma_handle;
-}
-
-static void xtensa_unmap_page(struct device *dev, dma_addr_t dma_handle,
-                             size_t size, enum dma_data_direction dir,
-                             unsigned long attrs)
-{
-       if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC))
-               xtensa_sync_single_for_cpu(dev, dma_handle, size, dir);
-}
-
-static int xtensa_map_sg(struct device *dev, struct scatterlist *sg,
-                        int nents, enum dma_data_direction dir,
-                        unsigned long attrs)
-{
-       struct scatterlist *s;
-       int i;
-
-       for_each_sg(sg, s, nents, i) {
-               s->dma_address = xtensa_map_page(dev, sg_page(s), s->offset,
-                                                s->length, dir, attrs);
-       }
-       return nents;
-}
-
-static void xtensa_unmap_sg(struct device *dev,
-                           struct scatterlist *sg, int nents,
-                           enum dma_data_direction dir,
-                           unsigned long attrs)
-{
-       struct scatterlist *s;
-       int i;
-
-       for_each_sg(sg, s, nents, i) {
-               xtensa_unmap_page(dev, sg_dma_address(s),
-                                 sg_dma_len(s), dir, attrs);
-       }
-}
-
-int xtensa_dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
-{
-       return 0;
-}
-
-const struct dma_map_ops xtensa_dma_map_ops = {
-       .alloc = xtensa_dma_alloc,
-       .free = xtensa_dma_free,
-       .map_page = xtensa_map_page,
-       .unmap_page = xtensa_unmap_page,
-       .map_sg = xtensa_map_sg,
-       .unmap_sg = xtensa_unmap_sg,
-       .sync_single_for_cpu = xtensa_sync_single_for_cpu,
-       .sync_single_for_device = xtensa_sync_single_for_device,
-       .sync_sg_for_cpu = xtensa_sync_sg_for_cpu,
-       .sync_sg_for_device = xtensa_sync_sg_for_device,
-       .mapping_error = xtensa_dma_mapping_error,
-};
-EXPORT_SYMBOL(xtensa_dma_map_ops);
index 686a274..351283b 100644 (file)
@@ -47,8 +47,6 @@
 #include <asm/smp.h>
 #include <asm/sysmem.h>
 
-#include <platform/hardware.h>
-
 #if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE)
 struct screen_info screen_info = {
        .orig_x = 0,
@@ -81,6 +79,7 @@ static char __initdata command_line[COMMAND_LINE_SIZE];
 static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE;
 #endif
 
+#ifdef CONFIG_PARSE_BOOTPARAM
 /*
  * Boot parameter parsing.
  *
@@ -178,6 +177,13 @@ static int __init parse_bootparam(const bp_tag_t* tag)
 
        return 0;
 }
+#else
+static int __init parse_bootparam(const bp_tag_t *tag)
+{
+       pr_info("Ignoring boot parameters at %p\n", tag);
+       return 0;
+}
+#endif
 
 #ifdef CONFIG_OF
 
index 70b731e..a1c3edb 100644 (file)
@@ -20,7 +20,7 @@
 
 #include <asm/vectors.h>
 #include <variant/core.h>
-#include <platform/hardware.h>
+
 OUTPUT_ARCH(xtensa)
 ENTRY(_start)
 
diff --git a/arch/xtensa/platforms/iss/include/platform/hardware.h b/arch/xtensa/platforms/iss/include/platform/hardware.h
deleted file mode 100644 (file)
index 6930c12..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * include/asm-xtensa/platform-iss/hardware.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 Tensilica Inc.
- */
-
-/*
- * This file contains the default configuration of ISS.
- */
-
-#ifndef _XTENSA_PLATFORM_ISS_HARDWARE_H
-#define _XTENSA_PLATFORM_ISS_HARDWARE_H
-
-/*
- * Memory configuration.
- */
-
-#define PLATFORM_DEFAULT_MEM_START     0x00000000
-#define PLATFORM_DEFAULT_MEM_SIZE      0x08000000
-
-/*
- * Interrupt configuration.
- */
-
-#endif /* _XTENSA_PLATFORM_ISS_HARDWARE_H */
index 886ef15..8e5e0d6 100644 (file)
 
 #include <variant/core.h>
 
-/* 
- * Memory configuration.
- */
-
-#define PLATFORM_DEFAULT_MEM_START 0x00000000
-#define PLATFORM_DEFAULT_MEM_SIZE 0x08000000
-
-/*
- * Number of platform IRQs
- */
-#define PLATFORM_NR_IRQS 3
 /*
  * On-board components.
  */
index 1fda7e2..30d9cb6 100644 (file)
 #ifndef __XTENSA_XTAVNET_HARDWARE_H
 #define __XTENSA_XTAVNET_HARDWARE_H
 
-/* Memory configuration. */
-
-#define PLATFORM_DEFAULT_MEM_START __XTENSA_UL(CONFIG_DEFAULT_MEM_START)
-#define PLATFORM_DEFAULT_MEM_SIZE  __XTENSA_UL(CONFIG_DEFAULT_MEM_SIZE)
-
-/* Interrupt configuration. */
-
-#define PLATFORM_NR_IRQS       0
-
 /* Default assignment of LX60 devices to external interrupts. */
 
 #ifdef CONFIG_XTENSA_MX
diff --git a/arch/xtensa/variants/test_kc705_be/include/variant/core.h b/arch/xtensa/variants/test_kc705_be/include/variant/core.h
new file mode 100644 (file)
index 0000000..a4ebdf7
--- /dev/null
@@ -0,0 +1,575 @@
+/* 
+ * xtensa/config/core-isa.h -- HAL definitions that are dependent on Xtensa
+ *                             processor CORE configuration
+ *
+ *  See <xtensa/config/core.h>, which includes this file, for more details.
+ */
+
+/* Xtensa processor core configuration information.
+
+   Copyright (c) 1999-2015 Tensilica Inc.
+
+   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.  */
+
+#ifndef _XTENSA_CORE_CONFIGURATION_H
+#define _XTENSA_CORE_CONFIGURATION_H
+
+
+/****************************************************************************
+           Parameters Useful for Any Code, USER or PRIVILEGED
+ ****************************************************************************/
+
+/*
+ *  Note:  Macros of the form XCHAL_HAVE_*** have a value of 1 if the option is
+ *  configured, and a value of 0 otherwise.  These macros are always defined.
+ */
+
+
+/*----------------------------------------------------------------------
+                               ISA
+  ----------------------------------------------------------------------*/
+
+#define XCHAL_HAVE_BE                  1       /* big-endian byte ordering */
+#define XCHAL_HAVE_WINDOWED            1       /* windowed registers option */
+#define XCHAL_NUM_AREGS                        32      /* num of physical addr regs */
+#define XCHAL_NUM_AREGS_LOG2           5       /* log2(XCHAL_NUM_AREGS) */
+#define XCHAL_MAX_INSTRUCTION_SIZE     8       /* max instr bytes (3..8) */
+#define XCHAL_HAVE_DEBUG               1       /* debug option */
+#define XCHAL_HAVE_DENSITY             1       /* 16-bit instructions */
+#define XCHAL_HAVE_LOOPS               1       /* zero-overhead loops */
+#define XCHAL_LOOP_BUFFER_SIZE         0       /* zero-ov. loop instr buffer size */
+#define XCHAL_HAVE_NSA                 1       /* NSA/NSAU instructions */
+#define XCHAL_HAVE_MINMAX              1       /* MIN/MAX instructions */
+#define XCHAL_HAVE_SEXT                        1       /* SEXT instruction */
+#define XCHAL_HAVE_DEPBITS             0       /* DEPBITS instruction */
+#define XCHAL_HAVE_CLAMPS              1       /* CLAMPS instruction */
+#define XCHAL_HAVE_MUL16               1       /* MUL16S/MUL16U instructions */
+#define XCHAL_HAVE_MUL32               1       /* MULL instruction */
+#define XCHAL_HAVE_MUL32_HIGH          1       /* MULUH/MULSH instructions */
+#define XCHAL_HAVE_DIV32               1       /* QUOS/QUOU/REMS/REMU instructions */
+#define XCHAL_HAVE_L32R                        1       /* L32R instruction */
+#define XCHAL_HAVE_ABSOLUTE_LITERALS   0       /* non-PC-rel (extended) L32R */
+#define XCHAL_HAVE_CONST16             0       /* CONST16 instruction */
+#define XCHAL_HAVE_ADDX                        1       /* ADDX#/SUBX# instructions */
+#define XCHAL_HAVE_WIDE_BRANCHES       0       /* B*.W18 or B*.W15 instr's */
+#define XCHAL_HAVE_PREDICTED_BRANCHES  0       /* B[EQ/EQZ/NE/NEZ]T instr's */
+#define XCHAL_HAVE_CALL4AND12          1       /* (obsolete option) */
+#define XCHAL_HAVE_ABS                 1       /* ABS instruction */
+/*#define XCHAL_HAVE_POPC              0*/     /* POPC instruction */
+/*#define XCHAL_HAVE_CRC               0*/     /* CRC instruction */
+#define XCHAL_HAVE_RELEASE_SYNC                1       /* L32AI/S32RI instructions */
+#define XCHAL_HAVE_S32C1I              1       /* S32C1I instruction */
+#define XCHAL_HAVE_SPECULATION         0       /* speculation */
+#define XCHAL_HAVE_FULL_RESET          1       /* all regs/state reset */
+#define XCHAL_NUM_CONTEXTS             1       /* */
+#define XCHAL_NUM_MISC_REGS            2       /* num of scratch regs (0..4) */
+#define XCHAL_HAVE_TAP_MASTER          0       /* JTAG TAP control instr's */
+#define XCHAL_HAVE_PRID                        1       /* processor ID register */
+#define XCHAL_HAVE_EXTERN_REGS         1       /* WER/RER instructions */
+#define XCHAL_HAVE_MX                  0       /* MX core (Tensilica internal) */
+#define XCHAL_HAVE_MP_INTERRUPTS       0       /* interrupt distributor port */
+#define XCHAL_HAVE_MP_RUNSTALL         0       /* core RunStall control port */
+#define XCHAL_HAVE_PSO                 0       /* Power Shut-Off */
+#define XCHAL_HAVE_PSO_CDM             0       /* core/debug/mem pwr domains */
+#define XCHAL_HAVE_PSO_FULL_RETENTION  0       /* all regs preserved on PSO */
+#define XCHAL_HAVE_THREADPTR           1       /* THREADPTR register */
+#define XCHAL_HAVE_BOOLEANS            1       /* boolean registers */
+#define XCHAL_HAVE_CP                  1       /* CPENABLE reg (coprocessor) */
+#define XCHAL_CP_MAXCFG                        8       /* max allowed cp id plus one */
+#define XCHAL_HAVE_MAC16               1       /* MAC16 package */
+
+#define XCHAL_HAVE_FUSION               0      /* Fusion*/
+#define XCHAL_HAVE_FUSION_FP    0              /* Fusion FP option */
+#define XCHAL_HAVE_FUSION_LOW_POWER 0  /* Fusion Low Power option */
+#define XCHAL_HAVE_FUSION_AES   0              /* Fusion BLE/Wifi AES-128 CCM option */
+#define XCHAL_HAVE_FUSION_CONVENC       0       /* Fusion Conv Encode option */
+#define XCHAL_HAVE_FUSION_LFSR_CRC      0      /* Fusion LFSR-CRC option */
+#define XCHAL_HAVE_FUSION_BITOPS        0      /* Fusion Bit Operations Support option */
+#define XCHAL_HAVE_FUSION_AVS   0      /* Fusion AVS option */
+#define XCHAL_HAVE_FUSION_16BIT_BASEBAND        0      /* Fusion 16-bit Baseband option */
+#define XCHAL_HAVE_HIFIPRO             0       /* HiFiPro Audio Engine pkg */
+#define XCHAL_HAVE_HIFI4               0       /* HiFi4 Audio Engine pkg */
+#define XCHAL_HAVE_HIFI4_VFPU          0       /* HiFi4 Audio Engine VFPU option */
+#define XCHAL_HAVE_HIFI3               0       /* HiFi3 Audio Engine pkg */
+#define XCHAL_HAVE_HIFI3_VFPU          0       /* HiFi3 Audio Engine VFPU option */
+#define XCHAL_HAVE_HIFI2               1       /* HiFi2 Audio Engine pkg */
+#define XCHAL_HAVE_HIFI2_MUL32X24      1       /* HiFi2 and 32x24 MACs */
+#define XCHAL_HAVE_HIFI2EP             1       /* HiFi2EP */
+#define XCHAL_HAVE_HIFI_MINI           0       
+
+
+#define XCHAL_HAVE_VECTORFPU2005       0       /* vector or user floating-point pkg */
+#define XCHAL_HAVE_USER_DPFPU         0       /* user DP floating-point pkg */
+#define XCHAL_HAVE_USER_SPFPU         0       /* user DP floating-point pkg */
+#define XCHAL_HAVE_FP                 0      /* single prec floating point */
+#define XCHAL_HAVE_FP_DIV             0  /* FP with DIV instructions */
+#define XCHAL_HAVE_FP_RECIP           0        /* FP with RECIP instructions */
+#define XCHAL_HAVE_FP_SQRT            0 /* FP with SQRT instructions */
+#define XCHAL_HAVE_FP_RSQRT           0        /* FP with RSQRT instructions */
+#define XCHAL_HAVE_DFP                        0     /* double precision FP pkg */
+#define XCHAL_HAVE_DFP_DIV            0 /* DFP with DIV instructions */
+#define XCHAL_HAVE_DFP_RECIP          0       /* DFP with RECIP instructions*/
+#define XCHAL_HAVE_DFP_SQRT           0        /* DFP with SQRT instructions */
+#define XCHAL_HAVE_DFP_RSQRT          0       /* DFP with RSQRT instructions*/
+#define XCHAL_HAVE_DFP_ACCEL           0       /* double precision FP acceleration pkg */
+#define XCHAL_HAVE_DFP_accel           XCHAL_HAVE_DFP_ACCEL                            /* for backward compatibility */
+
+#define XCHAL_HAVE_DFPU_SINGLE_ONLY    0                       /* DFPU Coprocessor, single precision only */
+#define XCHAL_HAVE_DFPU_SINGLE_DOUBLE  0                       /* DFPU Coprocessor, single and double precision */
+#define XCHAL_HAVE_VECTRA1             0       /* Vectra I  pkg */
+#define XCHAL_HAVE_VECTRALX            0       /* Vectra LX pkg */
+#define XCHAL_HAVE_PDX4                        0       /* PDX4 */
+#define XCHAL_HAVE_CONNXD2             0       /* ConnX D2 pkg */
+#define XCHAL_HAVE_CONNXD2_DUALLSFLIX   0      /* ConnX D2 & Dual LoadStore Flix */
+#define XCHAL_HAVE_BBE16               0       /* ConnX BBE16 pkg */
+#define XCHAL_HAVE_BBE16_RSQRT         0       /* BBE16 & vector recip sqrt */
+#define XCHAL_HAVE_BBE16_VECDIV                0       /* BBE16 & vector divide */
+#define XCHAL_HAVE_BBE16_DESPREAD      0       /* BBE16 & despread */
+#define XCHAL_HAVE_BBENEP              0       /* ConnX BBENEP pkgs */
+#define XCHAL_HAVE_BSP3                        0       /* ConnX BSP3 pkg */
+#define XCHAL_HAVE_BSP3_TRANSPOSE      0       /* BSP3 & transpose32x32 */
+#define XCHAL_HAVE_SSP16               0       /* ConnX SSP16 pkg */
+#define XCHAL_HAVE_SSP16_VITERBI       0       /* SSP16 & viterbi */
+#define XCHAL_HAVE_TURBO16             0       /* ConnX Turbo16 pkg */
+#define XCHAL_HAVE_BBP16               0       /* ConnX BBP16 pkg */
+#define XCHAL_HAVE_FLIX3               0       /* basic 3-way FLIX option */
+#define XCHAL_HAVE_GRIVPEP              0   /*  GRIVPEP is General Release of IVPEP */
+#define XCHAL_HAVE_GRIVPEP_HISTOGRAM    0   /* Histogram option on GRIVPEP */
+
+
+/*----------------------------------------------------------------------
+                               MISC
+  ----------------------------------------------------------------------*/
+
+#define XCHAL_NUM_LOADSTORE_UNITS      1       /* load/store units */
+#define XCHAL_NUM_WRITEBUFFER_ENTRIES  8       /* size of write buffer */
+#define XCHAL_INST_FETCH_WIDTH         8       /* instr-fetch width in bytes */
+#define XCHAL_DATA_WIDTH               8       /* data width in bytes */
+#define XCHAL_DATA_PIPE_DELAY          1       /* d-side pipeline delay
+                                                  (1 = 5-stage, 2 = 7-stage) */
+#define XCHAL_CLOCK_GATING_GLOBAL      0       /* global clock gating */
+#define XCHAL_CLOCK_GATING_FUNCUNIT    0       /* funct. unit clock gating */
+/*  In T1050, applies to selected core load and store instructions (see ISA): */
+#define XCHAL_UNALIGNED_LOAD_EXCEPTION 1       /* unaligned loads cause exc. */
+#define XCHAL_UNALIGNED_STORE_EXCEPTION        1       /* unaligned stores cause exc.*/
+#define XCHAL_UNALIGNED_LOAD_HW                0       /* unaligned loads work in hw */
+#define XCHAL_UNALIGNED_STORE_HW       0       /* unaligned stores work in hw*/
+
+#define XCHAL_SW_VERSION               1100002 /* sw version of this header */
+
+#define XCHAL_CORE_ID                  "test_kc705_be" /* alphanum core name
+                                                  (CoreID) set in the Xtensa
+                                                  Processor Generator */
+
+#define XCHAL_BUILD_UNIQUE_ID          0x00058D8C      /* 22-bit sw build ID */
+
+/*
+ *  These definitions describe the hardware targeted by this software.
+ */
+#define XCHAL_HW_CONFIGID0             0xC1B3FFFF      /* ConfigID hi 32 bits*/
+#define XCHAL_HW_CONFIGID1             0x1C858D8C      /* ConfigID lo 32 bits*/
+#define XCHAL_HW_VERSION_NAME          "LX6.0.2"       /* full version name */
+#define XCHAL_HW_VERSION_MAJOR         2600    /* major ver# of targeted hw */
+#define XCHAL_HW_VERSION_MINOR         2       /* minor ver# of targeted hw */
+#define XCHAL_HW_VERSION               260002  /* major*100+minor */
+#define XCHAL_HW_REL_LX6               1
+#define XCHAL_HW_REL_LX6_0             1
+#define XCHAL_HW_REL_LX6_0_2           1
+#define XCHAL_HW_CONFIGID_RELIABLE     1
+/*  If software targets a *range* of hardware versions, these are the bounds: */
+#define XCHAL_HW_MIN_VERSION_MAJOR     2600    /* major v of earliest tgt hw */
+#define XCHAL_HW_MIN_VERSION_MINOR     2       /* minor v of earliest tgt hw */
+#define XCHAL_HW_MIN_VERSION           260002  /* earliest targeted hw */
+#define XCHAL_HW_MAX_VERSION_MAJOR     2600    /* major v of latest tgt hw */
+#define XCHAL_HW_MAX_VERSION_MINOR     2       /* minor v of latest tgt hw */
+#define XCHAL_HW_MAX_VERSION           260002  /* latest targeted hw */
+
+
+/*----------------------------------------------------------------------
+                               CACHE
+  ----------------------------------------------------------------------*/
+
+#define XCHAL_ICACHE_LINESIZE          32      /* I-cache line size in bytes */
+#define XCHAL_DCACHE_LINESIZE          32      /* D-cache line size in bytes */
+#define XCHAL_ICACHE_LINEWIDTH         5       /* log2(I line size in bytes) */
+#define XCHAL_DCACHE_LINEWIDTH         5       /* log2(D line size in bytes) */
+
+#define XCHAL_ICACHE_SIZE              16384   /* I-cache size in bytes or 0 */
+#define XCHAL_DCACHE_SIZE              16384   /* D-cache size in bytes or 0 */
+
+#define XCHAL_DCACHE_IS_WRITEBACK      1       /* writeback feature */
+#define XCHAL_DCACHE_IS_COHERENT       0       /* MP coherence feature */
+
+#define XCHAL_HAVE_PREFETCH            1       /* PREFCTL register */
+#define XCHAL_HAVE_PREFETCH_L1         0       /* prefetch to L1 dcache */
+#define XCHAL_PREFETCH_CASTOUT_LINES   1       /* dcache pref. castout bufsz */
+#define XCHAL_PREFETCH_ENTRIES         8       /* cache prefetch entries */
+#define XCHAL_PREFETCH_BLOCK_ENTRIES   0       /* prefetch block streams */
+#define XCHAL_HAVE_CACHE_BLOCKOPS      0       /* block prefetch for caches */
+#define XCHAL_HAVE_ICACHE_TEST         1       /* Icache test instructions */
+#define XCHAL_HAVE_DCACHE_TEST         1       /* Dcache test instructions */
+#define XCHAL_HAVE_ICACHE_DYN_WAYS     0       /* Icache dynamic way support */
+#define XCHAL_HAVE_DCACHE_DYN_WAYS     0       /* Dcache dynamic way support */
+
+
+
+
+/****************************************************************************
+    Parameters Useful for PRIVILEGED (Supervisory or Non-Virtualized) Code
+ ****************************************************************************/
+
+
+#ifndef XTENSA_HAL_NON_PRIVILEGED_ONLY
+
+/*----------------------------------------------------------------------
+                               CACHE
+  ----------------------------------------------------------------------*/
+
+#define XCHAL_HAVE_PIF                 1       /* any outbound PIF present */
+
+/*  If present, cache size in bytes == (ways * 2^(linewidth + setwidth)).  */
+
+/*  Number of cache sets in log2(lines per way):  */
+#define XCHAL_ICACHE_SETWIDTH          7
+#define XCHAL_DCACHE_SETWIDTH          7
+
+/*  Cache set associativity (number of ways):  */
+#define XCHAL_ICACHE_WAYS              4
+#define XCHAL_DCACHE_WAYS              4
+
+/*  Cache features:  */
+#define XCHAL_ICACHE_LINE_LOCKABLE     1
+#define XCHAL_DCACHE_LINE_LOCKABLE     1
+#define XCHAL_ICACHE_ECC_PARITY                0
+#define XCHAL_DCACHE_ECC_PARITY                0
+
+/*  Cache access size in bytes (affects operation of SICW instruction):  */
+#define XCHAL_ICACHE_ACCESS_SIZE       8
+#define XCHAL_DCACHE_ACCESS_SIZE       8
+
+#define XCHAL_DCACHE_BANKS             1       /* number of banks */
+
+/*  Number of encoded cache attr bits (see <xtensa/hal.h> for decoded bits):  */
+#define XCHAL_CA_BITS                  4
+
+/*  Whether MEMCTL register has anything useful  */
+#define XCHAL_USE_MEMCTL               (((XCHAL_LOOP_BUFFER_SIZE > 0)  ||      \
+                                          XCHAL_DCACHE_IS_COHERENT     ||      \
+                                          XCHAL_HAVE_ICACHE_DYN_WAYS   ||      \
+                                          XCHAL_HAVE_DCACHE_DYN_WAYS)  &&      \
+                                          (XCHAL_HW_MIN_VERSION >= XTENSA_HWVERSION_RE_2012_0))
+
+
+/*----------------------------------------------------------------------
+                       INTERNAL I/D RAM/ROMs and XLMI
+  ----------------------------------------------------------------------*/
+
+#define XCHAL_NUM_INSTROM              0       /* number of core instr. ROMs */
+#define XCHAL_NUM_INSTRAM              0       /* number of core instr. RAMs */
+#define XCHAL_NUM_DATAROM              0       /* number of core data ROMs */
+#define XCHAL_NUM_DATARAM              0       /* number of core data RAMs */
+#define XCHAL_NUM_URAM                 0       /* number of core unified RAMs*/
+#define XCHAL_NUM_XLMI                 0       /* number of core XLMI ports */
+
+#define XCHAL_HAVE_IMEM_LOADSTORE      1       /* can load/store to IROM/IRAM*/
+
+
+/*----------------------------------------------------------------------
+                       INTERRUPTS and TIMERS
+  ----------------------------------------------------------------------*/
+
+#define XCHAL_HAVE_INTERRUPTS          1       /* interrupt option */
+#define XCHAL_HAVE_HIGHPRI_INTERRUPTS  1       /* med/high-pri. interrupts */
+#define XCHAL_HAVE_NMI                 1       /* non-maskable interrupt */
+#define XCHAL_HAVE_CCOUNT              1       /* CCOUNT reg. (timer option) */
+#define XCHAL_NUM_TIMERS               3       /* number of CCOMPAREn regs */
+#define XCHAL_NUM_INTERRUPTS           22      /* number of interrupts */
+#define XCHAL_NUM_INTERRUPTS_LOG2      5       /* ceil(log2(NUM_INTERRUPTS)) */
+#define XCHAL_NUM_EXTINTERRUPTS                16      /* num of external interrupts */
+#define XCHAL_NUM_INTLEVELS            6       /* number of interrupt levels
+                                                  (not including level zero) */
+#define XCHAL_EXCM_LEVEL               4       /* level masked by PS.EXCM */
+       /* (always 1 in XEA1; levels 2 .. EXCM_LEVEL are "medium priority") */
+
+/*  Masks of interrupts at each interrupt level:  */
+#define XCHAL_INTLEVEL1_MASK           0x001F00BF
+#define XCHAL_INTLEVEL2_MASK           0x00000140
+#define XCHAL_INTLEVEL3_MASK           0x00200E00
+#define XCHAL_INTLEVEL4_MASK           0x00008000
+#define XCHAL_INTLEVEL5_MASK           0x00003000
+#define XCHAL_INTLEVEL6_MASK           0x00000000
+#define XCHAL_INTLEVEL7_MASK           0x00004000
+
+/*  Masks of interrupts at each range 1..n of interrupt levels:  */
+#define XCHAL_INTLEVEL1_ANDBELOW_MASK  0x001F00BF
+#define XCHAL_INTLEVEL2_ANDBELOW_MASK  0x001F01FF
+#define XCHAL_INTLEVEL3_ANDBELOW_MASK  0x003F0FFF
+#define XCHAL_INTLEVEL4_ANDBELOW_MASK  0x003F8FFF
+#define XCHAL_INTLEVEL5_ANDBELOW_MASK  0x003FBFFF
+#define XCHAL_INTLEVEL6_ANDBELOW_MASK  0x003FBFFF
+#define XCHAL_INTLEVEL7_ANDBELOW_MASK  0x003FFFFF
+
+/*  Level of each interrupt:  */
+#define XCHAL_INT0_LEVEL               1
+#define XCHAL_INT1_LEVEL               1
+#define XCHAL_INT2_LEVEL               1
+#define XCHAL_INT3_LEVEL               1
+#define XCHAL_INT4_LEVEL               1
+#define XCHAL_INT5_LEVEL               1
+#define XCHAL_INT6_LEVEL               2
+#define XCHAL_INT7_LEVEL               1
+#define XCHAL_INT8_LEVEL               2
+#define XCHAL_INT9_LEVEL               3
+#define XCHAL_INT10_LEVEL              3
+#define XCHAL_INT11_LEVEL              3
+#define XCHAL_INT12_LEVEL              5
+#define XCHAL_INT13_LEVEL              5
+#define XCHAL_INT14_LEVEL              7
+#define XCHAL_INT15_LEVEL              4
+#define XCHAL_INT16_LEVEL              1
+#define XCHAL_INT17_LEVEL              1
+#define XCHAL_INT18_LEVEL              1
+#define XCHAL_INT19_LEVEL              1
+#define XCHAL_INT20_LEVEL              1
+#define XCHAL_INT21_LEVEL              3
+#define XCHAL_DEBUGLEVEL               6       /* debug interrupt level */
+#define XCHAL_HAVE_DEBUG_EXTERN_INT    1       /* OCD external db interrupt */
+#define XCHAL_NMILEVEL                 7       /* NMI "level" (for use with
+                                                  EXCSAVE/EPS/EPC_n, RFI n) */
+
+/*  Type of each interrupt:  */
+#define XCHAL_INT0_TYPE        XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT1_TYPE        XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT2_TYPE        XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT3_TYPE        XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT4_TYPE        XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT5_TYPE        XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT6_TYPE        XTHAL_INTTYPE_TIMER
+#define XCHAL_INT7_TYPE        XTHAL_INTTYPE_SOFTWARE
+#define XCHAL_INT8_TYPE        XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT9_TYPE        XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT10_TYPE       XTHAL_INTTYPE_TIMER
+#define XCHAL_INT11_TYPE       XTHAL_INTTYPE_SOFTWARE
+#define XCHAL_INT12_TYPE       XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT13_TYPE       XTHAL_INTTYPE_TIMER
+#define XCHAL_INT14_TYPE       XTHAL_INTTYPE_NMI
+#define XCHAL_INT15_TYPE       XTHAL_INTTYPE_PROFILING
+#define XCHAL_INT16_TYPE       XTHAL_INTTYPE_EXTERN_EDGE
+#define XCHAL_INT17_TYPE       XTHAL_INTTYPE_EXTERN_EDGE
+#define XCHAL_INT18_TYPE       XTHAL_INTTYPE_EXTERN_EDGE
+#define XCHAL_INT19_TYPE       XTHAL_INTTYPE_EXTERN_EDGE
+#define XCHAL_INT20_TYPE       XTHAL_INTTYPE_EXTERN_EDGE
+#define XCHAL_INT21_TYPE       XTHAL_INTTYPE_EXTERN_EDGE
+
+/*  Masks of interrupts for each type of interrupt:  */
+#define XCHAL_INTTYPE_MASK_UNCONFIGURED        0xFFC00000
+#define XCHAL_INTTYPE_MASK_SOFTWARE    0x00000880
+#define XCHAL_INTTYPE_MASK_EXTERN_EDGE 0x003F0000
+#define XCHAL_INTTYPE_MASK_EXTERN_LEVEL        0x0000133F
+#define XCHAL_INTTYPE_MASK_TIMER       0x00002440
+#define XCHAL_INTTYPE_MASK_NMI         0x00004000
+#define XCHAL_INTTYPE_MASK_WRITE_ERROR 0x00000000
+#define XCHAL_INTTYPE_MASK_PROFILING   0x00008000
+
+/*  Interrupt numbers assigned to specific interrupt sources:  */
+#define XCHAL_TIMER0_INTERRUPT         6       /* CCOMPARE0 */
+#define XCHAL_TIMER1_INTERRUPT         10      /* CCOMPARE1 */
+#define XCHAL_TIMER2_INTERRUPT         13      /* CCOMPARE2 */
+#define XCHAL_TIMER3_INTERRUPT         XTHAL_TIMER_UNCONFIGURED
+#define XCHAL_NMI_INTERRUPT            14      /* non-maskable interrupt */
+#define XCHAL_PROFILING_INTERRUPT      15      /* profiling interrupt */
+
+/*  Interrupt numbers for levels at which only one interrupt is configured:  */
+#define XCHAL_INTLEVEL4_NUM            15
+#define XCHAL_INTLEVEL7_NUM            14
+/*  (There are many interrupts each at level(s) 1, 2, 3, 5.)  */
+
+
+/*
+ *  External interrupt mapping.
+ *  These macros describe how Xtensa processor interrupt numbers
+ *  (as numbered internally, eg. in INTERRUPT and INTENABLE registers)
+ *  map to external BInterrupt<n> pins, for those interrupts
+ *  configured as external (level-triggered, edge-triggered, or NMI).
+ *  See the Xtensa processor databook for more details.
+ */
+
+/*  Core interrupt numbers mapped to each EXTERNAL BInterrupt pin number:  */
+#define XCHAL_EXTINT0_NUM              0       /* (intlevel 1) */
+#define XCHAL_EXTINT1_NUM              1       /* (intlevel 1) */
+#define XCHAL_EXTINT2_NUM              2       /* (intlevel 1) */
+#define XCHAL_EXTINT3_NUM              3       /* (intlevel 1) */
+#define XCHAL_EXTINT4_NUM              4       /* (intlevel 1) */
+#define XCHAL_EXTINT5_NUM              5       /* (intlevel 1) */
+#define XCHAL_EXTINT6_NUM              8       /* (intlevel 2) */
+#define XCHAL_EXTINT7_NUM              9       /* (intlevel 3) */
+#define XCHAL_EXTINT8_NUM              12      /* (intlevel 5) */
+#define XCHAL_EXTINT9_NUM              14      /* (intlevel 7) */
+#define XCHAL_EXTINT10_NUM             16      /* (intlevel 1) */
+#define XCHAL_EXTINT11_NUM             17      /* (intlevel 1) */
+#define XCHAL_EXTINT12_NUM             18      /* (intlevel 1) */
+#define XCHAL_EXTINT13_NUM             19      /* (intlevel 1) */
+#define XCHAL_EXTINT14_NUM             20      /* (intlevel 1) */
+#define XCHAL_EXTINT15_NUM             21      /* (intlevel 3) */
+/*  EXTERNAL BInterrupt pin numbers mapped to each core interrupt number:  */
+#define XCHAL_INT0_EXTNUM              0       /* (intlevel 1) */
+#define XCHAL_INT1_EXTNUM              1       /* (intlevel 1) */
+#define XCHAL_INT2_EXTNUM              2       /* (intlevel 1) */
+#define XCHAL_INT3_EXTNUM              3       /* (intlevel 1) */
+#define XCHAL_INT4_EXTNUM              4       /* (intlevel 1) */
+#define XCHAL_INT5_EXTNUM              5       /* (intlevel 1) */
+#define XCHAL_INT8_EXTNUM              6       /* (intlevel 2) */
+#define XCHAL_INT9_EXTNUM              7       /* (intlevel 3) */
+#define XCHAL_INT12_EXTNUM             8       /* (intlevel 5) */
+#define XCHAL_INT14_EXTNUM             9       /* (intlevel 7) */
+#define XCHAL_INT16_EXTNUM             10      /* (intlevel 1) */
+#define XCHAL_INT17_EXTNUM             11      /* (intlevel 1) */
+#define XCHAL_INT18_EXTNUM             12      /* (intlevel 1) */
+#define XCHAL_INT19_EXTNUM             13      /* (intlevel 1) */
+#define XCHAL_INT20_EXTNUM             14      /* (intlevel 1) */
+#define XCHAL_INT21_EXTNUM             15      /* (intlevel 3) */
+
+
+/*----------------------------------------------------------------------
+                       EXCEPTIONS and VECTORS
+  ----------------------------------------------------------------------*/
+
+#define XCHAL_XEA_VERSION              2       /* Xtensa Exception Architecture
+                                                  number: 1 == XEA1 (old)
+                                                          2 == XEA2 (new)
+                                                          0 == XEAX (extern) or TX */
+#define XCHAL_HAVE_XEA1                        0       /* Exception Architecture 1 */
+#define XCHAL_HAVE_XEA2                        1       /* Exception Architecture 2 */
+#define XCHAL_HAVE_XEAX                        0       /* External Exception Arch. */
+#define XCHAL_HAVE_EXCEPTIONS          1       /* exception option */
+#define XCHAL_HAVE_HALT                        0       /* halt architecture option */
+#define XCHAL_HAVE_BOOTLOADER          0       /* boot loader (for TX) */
+#define XCHAL_HAVE_MEM_ECC_PARITY      0       /* local memory ECC/parity */
+#define XCHAL_HAVE_VECTOR_SELECT       1       /* relocatable vectors */
+#define XCHAL_HAVE_VECBASE             1       /* relocatable vectors */
+#define XCHAL_VECBASE_RESET_VADDR      0x00002000  /* VECBASE reset value */
+#define XCHAL_VECBASE_RESET_PADDR      0x00002000
+#define XCHAL_RESET_VECBASE_OVERLAP    0
+
+#define XCHAL_RESET_VECTOR0_VADDR      0xFE000000
+#define XCHAL_RESET_VECTOR0_PADDR      0xFE000000
+#define XCHAL_RESET_VECTOR1_VADDR      0x00001000
+#define XCHAL_RESET_VECTOR1_PADDR      0x00001000
+#define XCHAL_RESET_VECTOR_VADDR       0xFE000000
+#define XCHAL_RESET_VECTOR_PADDR       0xFE000000
+#define XCHAL_USER_VECOFS              0x00000340
+#define XCHAL_USER_VECTOR_VADDR                0x00002340
+#define XCHAL_USER_VECTOR_PADDR                0x00002340
+#define XCHAL_KERNEL_VECOFS            0x00000300
+#define XCHAL_KERNEL_VECTOR_VADDR      0x00002300
+#define XCHAL_KERNEL_VECTOR_PADDR      0x00002300
+#define XCHAL_DOUBLEEXC_VECOFS         0x000003C0
+#define XCHAL_DOUBLEEXC_VECTOR_VADDR   0x000023C0
+#define XCHAL_DOUBLEEXC_VECTOR_PADDR   0x000023C0
+#define XCHAL_WINDOW_OF4_VECOFS                0x00000000
+#define XCHAL_WINDOW_UF4_VECOFS                0x00000040
+#define XCHAL_WINDOW_OF8_VECOFS                0x00000080
+#define XCHAL_WINDOW_UF8_VECOFS                0x000000C0
+#define XCHAL_WINDOW_OF12_VECOFS       0x00000100
+#define XCHAL_WINDOW_UF12_VECOFS       0x00000140
+#define XCHAL_WINDOW_VECTORS_VADDR     0x00002000
+#define XCHAL_WINDOW_VECTORS_PADDR     0x00002000
+#define XCHAL_INTLEVEL2_VECOFS         0x00000180
+#define XCHAL_INTLEVEL2_VECTOR_VADDR   0x00002180
+#define XCHAL_INTLEVEL2_VECTOR_PADDR   0x00002180
+#define XCHAL_INTLEVEL3_VECOFS         0x000001C0
+#define XCHAL_INTLEVEL3_VECTOR_VADDR   0x000021C0
+#define XCHAL_INTLEVEL3_VECTOR_PADDR   0x000021C0
+#define XCHAL_INTLEVEL4_VECOFS         0x00000200
+#define XCHAL_INTLEVEL4_VECTOR_VADDR   0x00002200
+#define XCHAL_INTLEVEL4_VECTOR_PADDR   0x00002200
+#define XCHAL_INTLEVEL5_VECOFS         0x00000240
+#define XCHAL_INTLEVEL5_VECTOR_VADDR   0x00002240
+#define XCHAL_INTLEVEL5_VECTOR_PADDR   0x00002240
+#define XCHAL_INTLEVEL6_VECOFS         0x00000280
+#define XCHAL_INTLEVEL6_VECTOR_VADDR   0x00002280
+#define XCHAL_INTLEVEL6_VECTOR_PADDR   0x00002280
+#define XCHAL_DEBUG_VECOFS             XCHAL_INTLEVEL6_VECOFS
+#define XCHAL_DEBUG_VECTOR_VADDR       XCHAL_INTLEVEL6_VECTOR_VADDR
+#define XCHAL_DEBUG_VECTOR_PADDR       XCHAL_INTLEVEL6_VECTOR_PADDR
+#define XCHAL_NMI_VECOFS               0x000002C0
+#define XCHAL_NMI_VECTOR_VADDR         0x000022C0
+#define XCHAL_NMI_VECTOR_PADDR         0x000022C0
+#define XCHAL_INTLEVEL7_VECOFS         XCHAL_NMI_VECOFS
+#define XCHAL_INTLEVEL7_VECTOR_VADDR   XCHAL_NMI_VECTOR_VADDR
+#define XCHAL_INTLEVEL7_VECTOR_PADDR   XCHAL_NMI_VECTOR_PADDR
+
+
+/*----------------------------------------------------------------------
+                               DEBUG MODULE
+  ----------------------------------------------------------------------*/
+
+/*  Misc  */
+#define XCHAL_HAVE_DEBUG_ERI           1       /* ERI to debug module */
+#define XCHAL_HAVE_DEBUG_APB           0       /* APB to debug module */
+#define XCHAL_HAVE_DEBUG_JTAG          1       /* JTAG to debug module */
+
+/*  On-Chip Debug (OCD)  */
+#define XCHAL_HAVE_OCD                 1       /* OnChipDebug option */
+#define XCHAL_NUM_IBREAK               2       /* number of IBREAKn regs */
+#define XCHAL_NUM_DBREAK               2       /* number of DBREAKn regs */
+#define XCHAL_HAVE_OCD_DIR_ARRAY       0       /* faster OCD option (to LX4) */
+#define XCHAL_HAVE_OCD_LS32DDR         1       /* L32DDR/S32DDR (faster OCD) */
+
+/*  TRAX (in core)  */
+#define XCHAL_HAVE_TRAX                        1       /* TRAX in debug module */
+#define XCHAL_TRAX_MEM_SIZE            262144  /* TRAX memory size in bytes */
+#define XCHAL_TRAX_MEM_SHAREABLE       1       /* start/end regs; ready sig. */
+#define XCHAL_TRAX_ATB_WIDTH           0       /* ATB width (bits), 0=no ATB */
+#define XCHAL_TRAX_TIME_WIDTH          0       /* timestamp bitwidth, 0=none */
+
+/*  Perf counters  */
+#define XCHAL_NUM_PERF_COUNTERS                8       /* performance counters */
+
+
+/*----------------------------------------------------------------------
+                               MMU
+  ----------------------------------------------------------------------*/
+
+/*  See core-matmap.h header file for more details.  */
+
+#define XCHAL_HAVE_TLBS                        1       /* inverse of HAVE_CACHEATTR */
+#define XCHAL_HAVE_SPANNING_WAY                1       /* one way maps I+D 4GB vaddr */
+#define XCHAL_SPANNING_WAY             6       /* TLB spanning way number */
+#define XCHAL_HAVE_IDENTITY_MAP                0       /* vaddr == paddr always */
+#define XCHAL_HAVE_CACHEATTR           0       /* CACHEATTR register present */
+#define XCHAL_HAVE_MIMIC_CACHEATTR     0       /* region protection */
+#define XCHAL_HAVE_XLT_CACHEATTR       0       /* region prot. w/translation */
+#define XCHAL_HAVE_PTP_MMU             1       /* full MMU (with page table
+                                                  [autorefill] and protection)
+                                                  usable for an MMU-based OS */
+/*  If none of the above last 4 are set, it's a custom TLB configuration.  */
+#define XCHAL_ITLB_ARF_ENTRIES_LOG2    2       /* log2(autorefill way size) */
+#define XCHAL_DTLB_ARF_ENTRIES_LOG2    2       /* log2(autorefill way size) */
+
+#define XCHAL_MMU_ASID_BITS            8       /* number of bits in ASIDs */
+#define XCHAL_MMU_RINGS                        4       /* number of rings (1..4) */
+#define XCHAL_MMU_RING_BITS            2       /* num of bits in RING field */
+
+#endif /* !XTENSA_HAL_NON_PRIVILEGED_ONLY */
+
+
+#endif /* _XTENSA_CORE_CONFIGURATION_H */
+
diff --git a/arch/xtensa/variants/test_kc705_be/include/variant/tie-asm.h b/arch/xtensa/variants/test_kc705_be/include/variant/tie-asm.h
new file mode 100644 (file)
index 0000000..b87fe1a
--- /dev/null
@@ -0,0 +1,308 @@
+/* 
+ * tie-asm.h -- compile-time HAL assembler definitions dependent on CORE & TIE
+ *
+ *  NOTE:  This header file is not meant to be included directly.
+ */
+
+/* This header file contains assembly-language definitions (assembly
+   macros, etc.) for this specific Xtensa processor's TIE extensions
+   and options.  It is customized to this Xtensa processor configuration.
+
+   Copyright (c) 1999-2015 Cadence Design Systems Inc.
+
+   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.  */
+
+#ifndef _XTENSA_CORE_TIE_ASM_H
+#define _XTENSA_CORE_TIE_ASM_H
+
+/*  Selection parameter values for save-area save/restore macros:  */
+/*  Option vs. TIE:  */
+#define XTHAL_SAS_TIE  0x0001  /* custom extension or coprocessor */
+#define XTHAL_SAS_OPT  0x0002  /* optional (and not a coprocessor) */
+#define XTHAL_SAS_ANYOT        0x0003  /* both of the above */
+/*  Whether used automatically by compiler:  */
+#define XTHAL_SAS_NOCC 0x0004  /* not used by compiler w/o special opts/code */
+#define XTHAL_SAS_CC   0x0008  /* used by compiler without special opts/code */
+#define XTHAL_SAS_ANYCC        0x000C  /* both of the above */
+/*  ABI handling across function calls:  */
+#define XTHAL_SAS_CALR 0x0010  /* caller-saved */
+#define XTHAL_SAS_CALE 0x0020  /* callee-saved */
+#define XTHAL_SAS_GLOB 0x0040  /* global across function calls (in thread) */
+#define XTHAL_SAS_ANYABI       0x0070  /* all of the above three */
+/*  Misc  */
+#define XTHAL_SAS_ALL  0xFFFF  /* include all default NCP contents */
+#define XTHAL_SAS3(optie,ccuse,abi)    ( ((optie) & XTHAL_SAS_ANYOT)  \
+                                       | ((ccuse) & XTHAL_SAS_ANYCC)  \
+                                       | ((abi)   & XTHAL_SAS_ANYABI) )
+
+
+    /*
+      *  Macro to store all non-coprocessor (extra) custom TIE and optional state
+      *  (not including zero-overhead loop registers).
+      *  Required parameters:
+      *      ptr         Save area pointer address register (clobbered)
+      *                  (register must contain a 4 byte aligned address).
+      *      at1..at4    Four temporary address registers (first XCHAL_NCP_NUM_ATMPS
+      *                  registers are clobbered, the remaining are unused).
+      *  Optional parameters:
+      *      continue    If macro invoked as part of a larger store sequence, set to 1
+      *                  if this is not the first in the sequence.  Defaults to 0.
+      *      ofs         Offset from start of larger sequence (from value of first ptr
+      *                  in sequence) at which to store.  Defaults to next available space
+      *                  (or 0 if <continue> is 0).
+      *      select      Select what category(ies) of registers to store, as a bitmask
+      *                  (see XTHAL_SAS_xxx constants).  Defaults to all registers.
+      *      alloc       Select what category(ies) of registers to allocate; if any
+      *                  category is selected here that is not in <select>, space for
+      *                  the corresponding registers is skipped without doing any store.
+      */
+    .macro xchal_ncp_store  ptr at1 at2 at3 at4  continue=0 ofs=-1 select=XTHAL_SAS_ALL alloc=0
+       xchal_sa_start  \continue, \ofs
+       // Optional global registers used by default by the compiler:
+       .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_GLOB) & ~(\select)
+       xchal_sa_align  \ptr, 0, 1020, 4, 4
+       rur.THREADPTR   \at1            // threadptr option
+       s32i    \at1, \ptr, .Lxchal_ofs_+0
+       .set    .Lxchal_ofs_, .Lxchal_ofs_ + 4
+       .elseif ((XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_GLOB) & ~(\alloc)) == 0
+       xchal_sa_align  \ptr, 0, 1020, 4, 4
+       .set    .Lxchal_ofs_, .Lxchal_ofs_ + 4
+       .endif
+       // Optional caller-saved registers used by default by the compiler:
+       .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_CALR) & ~(\select)
+       xchal_sa_align  \ptr, 0, 1016, 4, 4
+       rsr.ACCLO       \at1            // MAC16 option
+       s32i    \at1, \ptr, .Lxchal_ofs_+0
+       rsr.ACCHI       \at1            // MAC16 option
+       s32i    \at1, \ptr, .Lxchal_ofs_+4
+       .set    .Lxchal_ofs_, .Lxchal_ofs_ + 8
+       .elseif ((XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_CALR) & ~(\alloc)) == 0
+       xchal_sa_align  \ptr, 0, 1016, 4, 4
+       .set    .Lxchal_ofs_, .Lxchal_ofs_ + 8
+       .endif
+       // Optional caller-saved registers not used by default by the compiler:
+       .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select)
+       xchal_sa_align  \ptr, 0, 1000, 4, 4
+       rsr.BR  \at1            // boolean option
+       s32i    \at1, \ptr, .Lxchal_ofs_+0
+       rsr.SCOMPARE1   \at1            // conditional store option
+       s32i    \at1, \ptr, .Lxchal_ofs_+4
+       rsr.M0  \at1            // MAC16 option
+       s32i    \at1, \ptr, .Lxchal_ofs_+8
+       rsr.M1  \at1            // MAC16 option
+       s32i    \at1, \ptr, .Lxchal_ofs_+12
+       rsr.M2  \at1            // MAC16 option
+       s32i    \at1, \ptr, .Lxchal_ofs_+16
+       rsr.M3  \at1            // MAC16 option
+       s32i    \at1, \ptr, .Lxchal_ofs_+20
+       .set    .Lxchal_ofs_, .Lxchal_ofs_ + 24
+       .elseif ((XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0
+       xchal_sa_align  \ptr, 0, 1000, 4, 4
+       .set    .Lxchal_ofs_, .Lxchal_ofs_ + 24
+       .endif
+    .endm      // xchal_ncp_store
+
+    /*
+      *  Macro to load all non-coprocessor (extra) custom TIE and optional state
+      *  (not including zero-overhead loop registers).
+      *  Required parameters:
+      *      ptr         Save area pointer address register (clobbered)
+      *                  (register must contain a 4 byte aligned address).
+      *      at1..at4    Four temporary address registers (first XCHAL_NCP_NUM_ATMPS
+      *                  registers are clobbered, the remaining are unused).
+      *  Optional parameters:
+      *      continue    If macro invoked as part of a larger load sequence, set to 1
+      *                  if this is not the first in the sequence.  Defaults to 0.
+      *      ofs         Offset from start of larger sequence (from value of first ptr
+      *                  in sequence) at which to load.  Defaults to next available space
+      *                  (or 0 if <continue> is 0).
+      *      select      Select what category(ies) of registers to load, as a bitmask
+      *                  (see XTHAL_SAS_xxx constants).  Defaults to all registers.
+      *      alloc       Select what category(ies) of registers to allocate; if any
+      *                  category is selected here that is not in <select>, space for
+      *                  the corresponding registers is skipped without doing any load.
+      */
+    .macro xchal_ncp_load  ptr at1 at2 at3 at4  continue=0 ofs=-1 select=XTHAL_SAS_ALL alloc=0
+       xchal_sa_start  \continue, \ofs
+       // Optional global registers used by default by the compiler:
+       .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_GLOB) & ~(\select)
+       xchal_sa_align  \ptr, 0, 1020, 4, 4
+       l32i    \at1, \ptr, .Lxchal_ofs_+0
+       wur.THREADPTR   \at1            // threadptr option
+       .set    .Lxchal_ofs_, .Lxchal_ofs_ + 4
+       .elseif ((XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_GLOB) & ~(\alloc)) == 0
+       xchal_sa_align  \ptr, 0, 1020, 4, 4
+       .set    .Lxchal_ofs_, .Lxchal_ofs_ + 4
+       .endif
+       // Optional caller-saved registers used by default by the compiler:
+       .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_CALR) & ~(\select)
+       xchal_sa_align  \ptr, 0, 1016, 4, 4
+       l32i    \at1, \ptr, .Lxchal_ofs_+0
+       wsr.ACCLO       \at1            // MAC16 option
+       l32i    \at1, \ptr, .Lxchal_ofs_+4
+       wsr.ACCHI       \at1            // MAC16 option
+       .set    .Lxchal_ofs_, .Lxchal_ofs_ + 8
+       .elseif ((XTHAL_SAS_OPT | XTHAL_SAS_CC | XTHAL_SAS_CALR) & ~(\alloc)) == 0
+       xchal_sa_align  \ptr, 0, 1016, 4, 4
+       .set    .Lxchal_ofs_, .Lxchal_ofs_ + 8
+       .endif
+       // Optional caller-saved registers not used by default by the compiler:
+       .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select)
+       xchal_sa_align  \ptr, 0, 1000, 4, 4
+       l32i    \at1, \ptr, .Lxchal_ofs_+0
+       wsr.BR  \at1            // boolean option
+       l32i    \at1, \ptr, .Lxchal_ofs_+4
+       wsr.SCOMPARE1   \at1            // conditional store option
+       l32i    \at1, \ptr, .Lxchal_ofs_+8
+       wsr.M0  \at1            // MAC16 option
+       l32i    \at1, \ptr, .Lxchal_ofs_+12
+       wsr.M1  \at1            // MAC16 option
+       l32i    \at1, \ptr, .Lxchal_ofs_+16
+       wsr.M2  \at1            // MAC16 option
+       l32i    \at1, \ptr, .Lxchal_ofs_+20
+       wsr.M3  \at1            // MAC16 option
+       .set    .Lxchal_ofs_, .Lxchal_ofs_ + 24
+       .elseif ((XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0
+       xchal_sa_align  \ptr, 0, 1000, 4, 4
+       .set    .Lxchal_ofs_, .Lxchal_ofs_ + 24
+       .endif
+    .endm      // xchal_ncp_load
+
+
+#define XCHAL_NCP_NUM_ATMPS    1
+
+    /* 
+     *  Macro to store the state of TIE coprocessor AudioEngineLX.
+     *  Required parameters:
+     *      ptr         Save area pointer address register (clobbered)
+     *                  (register must contain a 8 byte aligned address).
+     *      at1..at4    Four temporary address registers (first XCHAL_CP1_NUM_ATMPS
+     *                  registers are clobbered, the remaining are unused).
+     *  Optional parameters are the same as for xchal_ncp_store.
+     */
+#define xchal_cp_AudioEngineLX_store   xchal_cp1_store
+    .macro     xchal_cp1_store  ptr at1 at2 at3 at4  continue=0 ofs=-1 select=XTHAL_SAS_ALL alloc=0
+       xchal_sa_start \continue, \ofs
+       // Custom caller-saved registers not used by default by the compiler:
+       .ifeq (XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select)
+       xchal_sa_align  \ptr, 0, 0, 8, 8
+       rur.AE_OVF_SAR  \at1            // ureg 240
+       s32i    \at1, \ptr, .Lxchal_ofs_+0
+       rur.AE_BITHEAD  \at1            // ureg 241
+       s32i    \at1, \ptr, .Lxchal_ofs_+4
+       rur.AE_TS_FTS_BU_BP     \at1            // ureg 242
+       s32i    \at1, \ptr, .Lxchal_ofs_+8
+       rur.AE_SD_NO    \at1            // ureg 243
+       s32i    \at1, \ptr, .Lxchal_ofs_+12
+       rur.AE_CBEGIN0  \at1            // ureg 246
+       s32i    \at1, \ptr, .Lxchal_ofs_+16
+       rur.AE_CEND0    \at1            // ureg 247
+       s32i    \at1, \ptr, .Lxchal_ofs_+20
+       ae_sp24x2s.i    aep0, \ptr, .Lxchal_ofs_+24
+       ae_sp24x2s.i    aep1, \ptr, .Lxchal_ofs_+32
+       ae_sp24x2s.i    aep2, \ptr, .Lxchal_ofs_+40
+       ae_sp24x2s.i    aep3, \ptr, .Lxchal_ofs_+48
+       ae_sp24x2s.i    aep4, \ptr, .Lxchal_ofs_+56
+       addi    \ptr, \ptr, 64
+       ae_sp24x2s.i    aep5, \ptr, .Lxchal_ofs_+0
+       ae_sp24x2s.i    aep6, \ptr, .Lxchal_ofs_+8
+       ae_sp24x2s.i    aep7, \ptr, .Lxchal_ofs_+16
+       ae_sq56s.i      aeq0, \ptr, .Lxchal_ofs_+24
+       ae_sq56s.i      aeq1, \ptr, .Lxchal_ofs_+32
+       ae_sq56s.i      aeq2, \ptr, .Lxchal_ofs_+40
+       ae_sq56s.i      aeq3, \ptr, .Lxchal_ofs_+48
+       .set    .Lxchal_pofs_, .Lxchal_pofs_ + 64
+       .set    .Lxchal_ofs_, .Lxchal_ofs_ + 56
+       .elseif ((XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0
+       xchal_sa_align  \ptr, 0, 0, 8, 8
+       .set    .Lxchal_ofs_, .Lxchal_ofs_ + 120
+       .endif
+    .endm      // xchal_cp1_store
+
+    /* 
+     *  Macro to load the state of TIE coprocessor AudioEngineLX.
+     *  Required parameters:
+     *      ptr         Save area pointer address register (clobbered)
+     *                  (register must contain a 8 byte aligned address).
+     *      at1..at4    Four temporary address registers (first XCHAL_CP1_NUM_ATMPS
+     *                  registers are clobbered, the remaining are unused).
+     *  Optional parameters are the same as for xchal_ncp_load.
+     */
+#define xchal_cp_AudioEngineLX_load    xchal_cp1_load
+    .macro     xchal_cp1_load  ptr at1 at2 at3 at4  continue=0 ofs=-1 select=XTHAL_SAS_ALL alloc=0
+       xchal_sa_start \continue, \ofs
+       // Custom caller-saved registers not used by default by the compiler:
+       .ifeq (XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\select)
+       xchal_sa_align  \ptr, 0, 0, 8, 8
+       l32i    \at1, \ptr, .Lxchal_ofs_+0
+       wur.AE_OVF_SAR  \at1            // ureg 240
+       l32i    \at1, \ptr, .Lxchal_ofs_+4
+       wur.AE_BITHEAD  \at1            // ureg 241
+       l32i    \at1, \ptr, .Lxchal_ofs_+8
+       wur.AE_TS_FTS_BU_BP     \at1            // ureg 242
+       l32i    \at1, \ptr, .Lxchal_ofs_+12
+       wur.AE_SD_NO    \at1            // ureg 243
+       l32i    \at1, \ptr, .Lxchal_ofs_+16
+       wur.AE_CBEGIN0  \at1            // ureg 246
+       l32i    \at1, \ptr, .Lxchal_ofs_+20
+       wur.AE_CEND0    \at1            // ureg 247
+       ae_lp24x2.i     aep0, \ptr, .Lxchal_ofs_+24
+       ae_lp24x2.i     aep1, \ptr, .Lxchal_ofs_+32
+       ae_lp24x2.i     aep2, \ptr, .Lxchal_ofs_+40
+       ae_lp24x2.i     aep3, \ptr, .Lxchal_ofs_+48
+       ae_lp24x2.i     aep4, \ptr, .Lxchal_ofs_+56
+       addi    \ptr, \ptr, 64
+       ae_lp24x2.i     aep5, \ptr, .Lxchal_ofs_+0
+       ae_lp24x2.i     aep6, \ptr, .Lxchal_ofs_+8
+       ae_lp24x2.i     aep7, \ptr, .Lxchal_ofs_+16
+       addi    \ptr, \ptr, 24
+       ae_lq56.i       aeq0, \ptr, .Lxchal_ofs_+0
+       ae_lq56.i       aeq1, \ptr, .Lxchal_ofs_+8
+       ae_lq56.i       aeq2, \ptr, .Lxchal_ofs_+16
+       ae_lq56.i       aeq3, \ptr, .Lxchal_ofs_+24
+       .set    .Lxchal_pofs_, .Lxchal_pofs_ + 88
+       .set    .Lxchal_ofs_, .Lxchal_ofs_ + 32
+       .elseif ((XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~(\alloc)) == 0
+       xchal_sa_align  \ptr, 0, 0, 8, 8
+       .set    .Lxchal_ofs_, .Lxchal_ofs_ + 120
+       .endif
+    .endm      // xchal_cp1_load
+
+#define XCHAL_CP1_NUM_ATMPS    1
+#define XCHAL_SA_NUM_ATMPS     1
+
+       /*  Empty macros for unconfigured coprocessors:  */
+       .macro xchal_cp0_store  p a b c d continue=0 ofs=-1 select=-1 ; .endm
+       .macro xchal_cp0_load   p a b c d continue=0 ofs=-1 select=-1 ; .endm
+       .macro xchal_cp2_store  p a b c d continue=0 ofs=-1 select=-1 ; .endm
+       .macro xchal_cp2_load   p a b c d continue=0 ofs=-1 select=-1 ; .endm
+       .macro xchal_cp3_store  p a b c d continue=0 ofs=-1 select=-1 ; .endm
+       .macro xchal_cp3_load   p a b c d continue=0 ofs=-1 select=-1 ; .endm
+       .macro xchal_cp4_store  p a b c d continue=0 ofs=-1 select=-1 ; .endm
+       .macro xchal_cp4_load   p a b c d continue=0 ofs=-1 select=-1 ; .endm
+       .macro xchal_cp5_store  p a b c d continue=0 ofs=-1 select=-1 ; .endm
+       .macro xchal_cp5_load   p a b c d continue=0 ofs=-1 select=-1 ; .endm
+       .macro xchal_cp6_store  p a b c d continue=0 ofs=-1 select=-1 ; .endm
+       .macro xchal_cp6_load   p a b c d continue=0 ofs=-1 select=-1 ; .endm
+       .macro xchal_cp7_store  p a b c d continue=0 ofs=-1 select=-1 ; .endm
+       .macro xchal_cp7_load   p a b c d continue=0 ofs=-1 select=-1 ; .endm
+
+#endif /*_XTENSA_CORE_TIE_ASM_H*/
+
diff --git a/arch/xtensa/variants/test_kc705_be/include/variant/tie.h b/arch/xtensa/variants/test_kc705_be/include/variant/tie.h
new file mode 100644 (file)
index 0000000..4e1b4ba
--- /dev/null
@@ -0,0 +1,182 @@
+/* 
+ * tie.h -- compile-time HAL definitions dependent on CORE & TIE configuration
+ *
+ *  NOTE:  This header file is not meant to be included directly.
+ */
+
+/* This header file describes this specific Xtensa processor's TIE extensions
+   that extend basic Xtensa core functionality.  It is customized to this
+   Xtensa processor configuration.
+
+   Copyright (c) 1999-2015 Cadence Design Systems Inc.
+
+   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.  */
+
+#ifndef _XTENSA_CORE_TIE_H
+#define _XTENSA_CORE_TIE_H
+
+#define XCHAL_CP_NUM                   2       /* number of coprocessors */
+#define XCHAL_CP_MAX                   8       /* max CP ID + 1 (0 if none) */
+#define XCHAL_CP_MASK                  0x82    /* bitmask of all CPs by ID */
+#define XCHAL_CP_PORT_MASK             0x80    /* bitmask of only port CPs */
+
+/*  Basic parameters of each coprocessor:  */
+#define XCHAL_CP1_NAME                 "AudioEngineLX"
+#define XCHAL_CP1_IDENT                        AudioEngineLX
+#define XCHAL_CP1_SA_SIZE              120     /* size of state save area */
+#define XCHAL_CP1_SA_ALIGN             8       /* min alignment of save area */
+#define XCHAL_CP_ID_AUDIOENGINELX      1       /* coprocessor ID (0..7) */
+#define XCHAL_CP7_NAME                 "XTIOP"
+#define XCHAL_CP7_IDENT                        XTIOP
+#define XCHAL_CP7_SA_SIZE              0       /* size of state save area */
+#define XCHAL_CP7_SA_ALIGN             1       /* min alignment of save area */
+#define XCHAL_CP_ID_XTIOP              7       /* coprocessor ID (0..7) */
+
+/*  Filler info for unassigned coprocessors, to simplify arrays etc:  */
+#define XCHAL_CP0_SA_SIZE              0
+#define XCHAL_CP0_SA_ALIGN             1
+#define XCHAL_CP2_SA_SIZE              0
+#define XCHAL_CP2_SA_ALIGN             1
+#define XCHAL_CP3_SA_SIZE              0
+#define XCHAL_CP3_SA_ALIGN             1
+#define XCHAL_CP4_SA_SIZE              0
+#define XCHAL_CP4_SA_ALIGN             1
+#define XCHAL_CP5_SA_SIZE              0
+#define XCHAL_CP5_SA_ALIGN             1
+#define XCHAL_CP6_SA_SIZE              0
+#define XCHAL_CP6_SA_ALIGN             1
+
+/*  Save area for non-coprocessor optional and custom (TIE) state:  */
+#define XCHAL_NCP_SA_SIZE              36
+#define XCHAL_NCP_SA_ALIGN             4
+
+/*  Total save area for optional and custom state (NCP + CPn):  */
+#define XCHAL_TOTAL_SA_SIZE            160     /* with 16-byte align padding */
+#define XCHAL_TOTAL_SA_ALIGN           8       /* actual minimum alignment */
+
+/*
+ * Detailed contents of save areas.
+ * NOTE:  caller must define the XCHAL_SA_REG macro (not defined here)
+ * before expanding the XCHAL_xxx_SA_LIST() macros.
+ *
+ * XCHAL_SA_REG(s,ccused,abikind,kind,opt,name,galign,align,asize,
+ *             dbnum,base,regnum,bitsz,gapsz,reset,x...)
+ *
+ *     s = passed from XCHAL_*_LIST(s), eg. to select how to expand
+ *     ccused = set if used by compiler without special options or code
+ *     abikind = 0 (caller-saved), 1 (callee-saved), or 2 (thread-global)
+ *     kind = 0 (special reg), 1 (TIE user reg), or 2 (TIE regfile reg)
+ *     opt = 0 (custom TIE extension or coprocessor), or 1 (optional reg)
+ *     name = lowercase reg name (no quotes)
+ *     galign = group byte alignment (power of 2) (galign >= align)
+ *     align = register byte alignment (power of 2)
+ *     asize = allocated size in bytes (asize*8 == bitsz + gapsz + padsz)
+ *       (not including any pad bytes required to galign this or next reg)
+ *     dbnum = unique target number f/debug (see <xtensa-libdb-macros.h>)
+ *     base = reg shortname w/o index (or sr=special, ur=TIE user reg)
+ *     regnum = reg index in regfile, or special/TIE-user reg number
+ *     bitsz = number of significant bits (regfile width, or ur/sr mask bits)
+ *     gapsz = intervening bits, if bitsz bits not stored contiguously
+ *     (padsz = pad bits at end [TIE regfile] or at msbits [ur,sr] of asize)
+ *     reset = register reset value (or 0 if undefined at reset)
+ *     x = reserved for future use (0 until then)
+ *
+ *  To filter out certain registers, e.g. to expand only the non-global
+ *  registers used by the compiler, you can do something like this:
+ *
+ *  #define XCHAL_SA_REG(s,ccused,p...)        SELCC##ccused(p)
+ *  #define SELCC0(p...)
+ *  #define SELCC1(abikind,p...)       SELAK##abikind(p)
+ *  #define SELAK0(p...)               REG(p)
+ *  #define SELAK1(p...)               REG(p)
+ *  #define SELAK2(p...)
+ *  #define REG(kind,tie,name,galn,aln,asz,csz,dbnum,base,rnum,bsz,rst,x...) \
+ *             ...what you want to expand...
+ */
+
+#define XCHAL_NCP_SA_NUM       9
+#define XCHAL_NCP_SA_LIST(s)   \
+ XCHAL_SA_REG(s,1,2,1,1,      threadptr, 4, 4, 4,0x03E7,  ur,231, 32,0,0,0) \
+ XCHAL_SA_REG(s,1,0,0,1,          acclo, 4, 4, 4,0x0210,  sr,16 , 32,0,0,0) \
+ XCHAL_SA_REG(s,1,0,0,1,          acchi, 4, 4, 4,0x0211,  sr,17 ,  8,0,0,0) \
+ XCHAL_SA_REG(s,0,0,0,1,             br, 4, 4, 4,0x0204,  sr,4  , 16,0,0,0) \
+ XCHAL_SA_REG(s,0,0,0,1,      scompare1, 4, 4, 4,0x020C,  sr,12 , 32,0,0,0) \
+ XCHAL_SA_REG(s,0,0,0,1,             m0, 4, 4, 4,0x0220,  sr,32 , 32,0,0,0) \
+ XCHAL_SA_REG(s,0,0,0,1,             m1, 4, 4, 4,0x0221,  sr,33 , 32,0,0,0) \
+ XCHAL_SA_REG(s,0,0,0,1,             m2, 4, 4, 4,0x0222,  sr,34 , 32,0,0,0) \
+ XCHAL_SA_REG(s,0,0,0,1,             m3, 4, 4, 4,0x0223,  sr,35 , 32,0,0,0)
+
+#define XCHAL_CP0_SA_NUM       0
+#define XCHAL_CP0_SA_LIST(s)   /* empty */
+
+#define XCHAL_CP1_SA_NUM       18
+#define XCHAL_CP1_SA_LIST(s)   \
+ XCHAL_SA_REG(s,0,0,1,0,     ae_ovf_sar, 8, 4, 4,0x03F0,  ur,240,  7,0,0,0) \
+ XCHAL_SA_REG(s,0,0,1,0,     ae_bithead, 4, 4, 4,0x03F1,  ur,241, 32,0,0,0) \
+ XCHAL_SA_REG(s,0,0,1,0,ae_ts_fts_bu_bp, 4, 4, 4,0x03F2,  ur,242, 16,0,0,0) \
+ XCHAL_SA_REG(s,0,0,1,0,       ae_sd_no, 4, 4, 4,0x03F3,  ur,243, 28,0,0,0) \
+ XCHAL_SA_REG(s,0,0,1,0,     ae_cbegin0, 4, 4, 4,0x03F6,  ur,246, 32,0,0,0) \
+ XCHAL_SA_REG(s,0,0,1,0,       ae_cend0, 4, 4, 4,0x03F7,  ur,247, 32,0,0,0) \
+ XCHAL_SA_REG(s,0,0,2,0,           aep0, 8, 8, 8,0x0060, aep,0  , 48,0,0,0) \
+ XCHAL_SA_REG(s,0,0,2,0,           aep1, 8, 8, 8,0x0061, aep,1  , 48,0,0,0) \
+ XCHAL_SA_REG(s,0,0,2,0,           aep2, 8, 8, 8,0x0062, aep,2  , 48,0,0,0) \
+ XCHAL_SA_REG(s,0,0,2,0,           aep3, 8, 8, 8,0x0063, aep,3  , 48,0,0,0) \
+ XCHAL_SA_REG(s,0,0,2,0,           aep4, 8, 8, 8,0x0064, aep,4  , 48,0,0,0) \
+ XCHAL_SA_REG(s,0,0,2,0,           aep5, 8, 8, 8,0x0065, aep,5  , 48,0,0,0) \
+ XCHAL_SA_REG(s,0,0,2,0,           aep6, 8, 8, 8,0x0066, aep,6  , 48,0,0,0) \
+ XCHAL_SA_REG(s,0,0,2,0,           aep7, 8, 8, 8,0x0067, aep,7  , 48,0,0,0) \
+ XCHAL_SA_REG(s,0,0,2,0,           aeq0, 8, 8, 8,0x0068, aeq,0  , 56,0,0,0) \
+ XCHAL_SA_REG(s,0,0,2,0,           aeq1, 8, 8, 8,0x0069, aeq,1  , 56,0,0,0) \
+ XCHAL_SA_REG(s,0,0,2,0,           aeq2, 8, 8, 8,0x006A, aeq,2  , 56,0,0,0) \
+ XCHAL_SA_REG(s,0,0,2,0,           aeq3, 8, 8, 8,0x006B, aeq,3  , 56,0,0,0)
+
+#define XCHAL_CP2_SA_NUM       0
+#define XCHAL_CP2_SA_LIST(s)   /* empty */
+
+#define XCHAL_CP3_SA_NUM       0
+#define XCHAL_CP3_SA_LIST(s)   /* empty */
+
+#define XCHAL_CP4_SA_NUM       0
+#define XCHAL_CP4_SA_LIST(s)   /* empty */
+
+#define XCHAL_CP5_SA_NUM       0
+#define XCHAL_CP5_SA_LIST(s)   /* empty */
+
+#define XCHAL_CP6_SA_NUM       0
+#define XCHAL_CP6_SA_LIST(s)   /* empty */
+
+#define XCHAL_CP7_SA_NUM       0
+#define XCHAL_CP7_SA_LIST(s)   /* empty */
+
+/* Byte length of instruction from its first nibble (op0 field), per FLIX.  */
+#define XCHAL_OP0_FORMAT_LENGTHS       3,3,3,3,3,3,3,3,2,2,2,2,2,2,3,8
+/* Byte length of instruction from its first byte, per FLIX.  */
+#define XCHAL_BYTE0_FORMAT_LENGTHS     \
+       3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,\
+       3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,\
+       3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,\
+       3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,\
+       2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,\
+       2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,\
+       2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,\
+       3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8
+
+#endif /*_XTENSA_CORE_TIE_H*/
+
index a9e8633..58c6efa 100644 (file)
@@ -913,7 +913,8 @@ static ssize_t bfq_io_set_weight(struct kernfs_open_file *of,
        if (ret)
                return ret;
 
-       return bfq_io_set_weight_legacy(of_css(of), NULL, weight);
+       ret = bfq_io_set_weight_legacy(of_css(of), NULL, weight);
+       return ret ?: nbytes;
 }
 
 #ifdef CONFIG_DEBUG_BLK_CGROUP
index 41d9036..653100f 100644 (file)
@@ -187,11 +187,25 @@ static const int bfq_stats_min_budgets = 194;
 static const int bfq_default_max_budget = 16 * 1024;
 
 /*
- * Async to sync throughput distribution is controlled as follows:
- * when an async request is served, the entity is charged the number
- * of sectors of the request, multiplied by the factor below
+ * When a sync request is dispatched, the queue that contains that
+ * request, and all the ancestor entities of that queue, are charged
+ * with the number of sectors of the request. In constrast, if the
+ * request is async, then the queue and its ancestor entities are
+ * charged with the number of sectors of the request, multiplied by
+ * the factor below. This throttles the bandwidth for async I/O,
+ * w.r.t. to sync I/O, and it is done to counter the tendency of async
+ * writes to steal I/O throughput to reads.
+ *
+ * The current value of this parameter is the result of a tuning with
+ * several hardware and software configurations. We tried to find the
+ * lowest value for which writes do not cause noticeable problems to
+ * reads. In fact, the lower this parameter, the stabler I/O control,
+ * in the following respect.  The lower this parameter is, the less
+ * the bandwidth enjoyed by a group decreases
+ * - when the group does writes, w.r.t. to when it does reads;
+ * - when other groups do reads, w.r.t. to when they do writes.
  */
-static const int bfq_async_charge_factor = 10;
+static const int bfq_async_charge_factor = 3;
 
 /* Default timeout values, in jiffies, approximating CFQ defaults. */
 const int bfq_timeout = HZ / 8;
@@ -853,16 +867,7 @@ static unsigned long bfq_serv_to_charge(struct request *rq,
        if (bfq_bfqq_sync(bfqq) || bfqq->wr_coeff > 1)
                return blk_rq_sectors(rq);
 
-       /*
-        * If there are no weight-raised queues, then amplify service
-        * by just the async charge factor; otherwise amplify service
-        * by twice the async charge factor, to further reduce latency
-        * for weight-raised queues.
-        */
-       if (bfqq->bfqd->wr_busy_queues == 0)
-               return blk_rq_sectors(rq) * bfq_async_charge_factor;
-
-       return blk_rq_sectors(rq) * 2 * bfq_async_charge_factor;
+       return blk_rq_sectors(rq) * bfq_async_charge_factor;
 }
 
 /**
@@ -3298,6 +3303,27 @@ void bfq_bfqq_expire(struct bfq_data *bfqd,
                 */
        } else
                entity->service = 0;
+
+       /*
+        * Reset the received-service counter for every parent entity.
+        * Differently from what happens with bfqq->entity.service,
+        * the resetting of this counter never needs to be postponed
+        * for parent entities. In fact, in case bfqq may have a
+        * chance to go on being served using the last, partially
+        * consumed budget, bfqq->entity.service needs to be kept,
+        * because if bfqq then actually goes on being served using
+        * the same budget, the last value of bfqq->entity.service is
+        * needed to properly decrement bfqq->entity.budget by the
+        * portion already consumed. In contrast, it is not necessary
+        * to keep entity->service for parent entities too, because
+        * the bubble up of the new value of bfqq->entity.budget will
+        * make sure that the budgets of parent entities are correct,
+        * even in case bfqq and thus parent entities go on receiving
+        * service with the same budget.
+        */
+       entity = entity->parent;
+       for_each_entity(entity)
+               entity->service = 0;
 }
 
 /*
index dbc07b4..ae52bff 100644 (file)
@@ -130,10 +130,14 @@ static bool bfq_update_next_in_service(struct bfq_sched_data *sd,
        if (!change_without_lookup) /* lookup needed */
                next_in_service = bfq_lookup_next_entity(sd, expiration);
 
-       if (next_in_service)
-               parent_sched_may_change = !sd->next_in_service ||
+       if (next_in_service) {
+               bool new_budget_triggers_change =
                        bfq_update_parent_budget(next_in_service);
 
+               parent_sched_may_change = !sd->next_in_service ||
+                       new_budget_triggers_change;
+       }
+
        sd->next_in_service = next_in_service;
 
        if (!next_in_service)
@@ -877,15 +881,11 @@ void bfq_bfqq_charge_time(struct bfq_data *bfqd, struct bfq_queue *bfqq,
                          unsigned long time_ms)
 {
        struct bfq_entity *entity = &bfqq->entity;
-       int tot_serv_to_charge = entity->service;
-       unsigned int timeout_ms = jiffies_to_msecs(bfq_timeout);
-
-       if (time_ms > 0 && time_ms < timeout_ms)
-               tot_serv_to_charge =
-                       (bfqd->bfq_max_budget * time_ms) / timeout_ms;
-
-       if (tot_serv_to_charge < entity->service)
-               tot_serv_to_charge = entity->service;
+       unsigned long timeout_ms = jiffies_to_msecs(bfq_timeout);
+       unsigned long bounded_time_ms = min(time_ms, timeout_ms);
+       int serv_to_charge_for_time =
+               (bfqd->bfq_max_budget * bounded_time_ms) / timeout_ms;
+       int tot_serv_to_charge = max(serv_to_charge_for_time, entity->service);
 
        /* Increase budget to avoid inconsistencies */
        if (tot_serv_to_charge > entity->budget)
index 1255034..dee56c2 100644 (file)
@@ -1036,7 +1036,6 @@ struct request_queue *blk_alloc_queue_node(gfp_t gfp_mask, int node_id,
                    laptop_mode_timer_fn, 0);
        timer_setup(&q->timeout, blk_rq_timed_out_timer, 0);
        INIT_WORK(&q->timeout_work, NULL);
-       INIT_LIST_HEAD(&q->queue_head);
        INIT_LIST_HEAD(&q->timeout_list);
        INIT_LIST_HEAD(&q->icq_list);
 #ifdef CONFIG_BLK_CGROUP
@@ -2162,7 +2161,9 @@ static inline bool should_fail_request(struct hd_struct *part,
 
 static inline bool bio_check_ro(struct bio *bio, struct hd_struct *part)
 {
-       if (part->policy && op_is_write(bio_op(bio))) {
+       const int op = bio_op(bio);
+
+       if (part->policy && (op_is_write(op) && !op_is_flush(op))) {
                char b[BDEVNAME_SIZE];
 
                WARN_ONCE(1,
index cf9c66c..29bfe80 100644 (file)
@@ -462,50 +462,6 @@ static void blk_mq_sched_tags_teardown(struct request_queue *q)
                blk_mq_sched_free_tags(set, hctx, i);
 }
 
-int blk_mq_sched_init_hctx(struct request_queue *q, struct blk_mq_hw_ctx *hctx,
-                          unsigned int hctx_idx)
-{
-       struct elevator_queue *e = q->elevator;
-       int ret;
-
-       if (!e)
-               return 0;
-
-       ret = blk_mq_sched_alloc_tags(q, hctx, hctx_idx);
-       if (ret)
-               return ret;
-
-       if (e->type->ops.mq.init_hctx) {
-               ret = e->type->ops.mq.init_hctx(hctx, hctx_idx);
-               if (ret) {
-                       blk_mq_sched_free_tags(q->tag_set, hctx, hctx_idx);
-                       return ret;
-               }
-       }
-
-       blk_mq_debugfs_register_sched_hctx(q, hctx);
-
-       return 0;
-}
-
-void blk_mq_sched_exit_hctx(struct request_queue *q, struct blk_mq_hw_ctx *hctx,
-                           unsigned int hctx_idx)
-{
-       struct elevator_queue *e = q->elevator;
-
-       if (!e)
-               return;
-
-       blk_mq_debugfs_unregister_sched_hctx(hctx);
-
-       if (e->type->ops.mq.exit_hctx && hctx->sched_data) {
-               e->type->ops.mq.exit_hctx(hctx, hctx_idx);
-               hctx->sched_data = NULL;
-       }
-
-       blk_mq_sched_free_tags(q->tag_set, hctx, hctx_idx);
-}
-
 int blk_mq_init_sched(struct request_queue *q, struct elevator_type *e)
 {
        struct blk_mq_hw_ctx *hctx;
index 0cb8f93..4e028ee 100644 (file)
@@ -28,11 +28,6 @@ void blk_mq_sched_dispatch_requests(struct blk_mq_hw_ctx *hctx);
 int blk_mq_init_sched(struct request_queue *q, struct elevator_type *e);
 void blk_mq_exit_sched(struct request_queue *q, struct elevator_queue *e);
 
-int blk_mq_sched_init_hctx(struct request_queue *q, struct blk_mq_hw_ctx *hctx,
-                          unsigned int hctx_idx);
-void blk_mq_sched_exit_hctx(struct request_queue *q, struct blk_mq_hw_ctx *hctx,
-                           unsigned int hctx_idx);
-
 static inline bool
 blk_mq_sched_bio_merge(struct request_queue *q, struct bio *bio)
 {
index 816923b..94e1ed6 100644 (file)
@@ -320,6 +320,18 @@ void blk_mq_queue_tag_busy_iter(struct request_queue *q, busy_iter_fn *fn,
        struct blk_mq_hw_ctx *hctx;
        int i;
 
+       /*
+        * __blk_mq_update_nr_hw_queues will update the nr_hw_queues and
+        * queue_hw_ctx after freeze the queue. So we could use q_usage_counter
+        * to avoid race with it. __blk_mq_update_nr_hw_queues will users
+        * synchronize_rcu to ensure all of the users go out of the critical
+        * section below and see zeroed q_usage_counter.
+        */
+       rcu_read_lock();
+       if (percpu_ref_is_zero(&q->q_usage_counter)) {
+               rcu_read_unlock();
+               return;
+       }
 
        queue_for_each_hw_ctx(q, hctx, i) {
                struct blk_mq_tags *tags = hctx->tags;
@@ -335,7 +347,7 @@ void blk_mq_queue_tag_busy_iter(struct request_queue *q, busy_iter_fn *fn,
                        bt_for_each(hctx, &tags->breserved_tags, fn, priv, true);
                bt_for_each(hctx, &tags->bitmap_tags, fn, priv, false);
        }
-
+       rcu_read_unlock();
 }
 
 static int bt_alloc(struct sbitmap_queue *bt, unsigned int depth,
index 72a0033..85a1c1a 100644 (file)
@@ -2145,8 +2145,6 @@ static void blk_mq_exit_hctx(struct request_queue *q,
        if (set->ops->exit_request)
                set->ops->exit_request(set, hctx->fq->flush_rq, hctx_idx);
 
-       blk_mq_sched_exit_hctx(q, hctx, hctx_idx);
-
        if (set->ops->exit_hctx)
                set->ops->exit_hctx(hctx, hctx_idx);
 
@@ -2214,12 +2212,9 @@ static int blk_mq_init_hctx(struct request_queue *q,
            set->ops->init_hctx(hctx, set->driver_data, hctx_idx))
                goto free_bitmap;
 
-       if (blk_mq_sched_init_hctx(q, hctx, hctx_idx))
-               goto exit_hctx;
-
        hctx->fq = blk_alloc_flush_queue(q, hctx->numa_node, set->cmd_size);
        if (!hctx->fq)
-               goto sched_exit_hctx;
+               goto exit_hctx;
 
        if (blk_mq_init_request(set, hctx->fq->flush_rq, hctx_idx, node))
                goto free_fq;
@@ -2233,8 +2228,6 @@ static int blk_mq_init_hctx(struct request_queue *q,
 
  free_fq:
        kfree(hctx->fq);
- sched_exit_hctx:
-       blk_mq_sched_exit_hctx(q, hctx, hctx_idx);
  exit_hctx:
        if (set->ops->exit_hctx)
                set->ops->exit_hctx(hctx, hctx_idx);
@@ -2896,10 +2889,81 @@ int blk_mq_update_nr_requests(struct request_queue *q, unsigned int nr)
        return ret;
 }
 
+/*
+ * request_queue and elevator_type pair.
+ * It is just used by __blk_mq_update_nr_hw_queues to cache
+ * the elevator_type associated with a request_queue.
+ */
+struct blk_mq_qe_pair {
+       struct list_head node;
+       struct request_queue *q;
+       struct elevator_type *type;
+};
+
+/*
+ * Cache the elevator_type in qe pair list and switch the
+ * io scheduler to 'none'
+ */
+static bool blk_mq_elv_switch_none(struct list_head *head,
+               struct request_queue *q)
+{
+       struct blk_mq_qe_pair *qe;
+
+       if (!q->elevator)
+               return true;
+
+       qe = kmalloc(sizeof(*qe), GFP_NOIO | __GFP_NOWARN | __GFP_NORETRY);
+       if (!qe)
+               return false;
+
+       INIT_LIST_HEAD(&qe->node);
+       qe->q = q;
+       qe->type = q->elevator->type;
+       list_add(&qe->node, head);
+
+       mutex_lock(&q->sysfs_lock);
+       /*
+        * After elevator_switch_mq, the previous elevator_queue will be
+        * released by elevator_release. The reference of the io scheduler
+        * module get by elevator_get will also be put. So we need to get
+        * a reference of the io scheduler module here to prevent it to be
+        * removed.
+        */
+       __module_get(qe->type->elevator_owner);
+       elevator_switch_mq(q, NULL);
+       mutex_unlock(&q->sysfs_lock);
+
+       return true;
+}
+
+static void blk_mq_elv_switch_back(struct list_head *head,
+               struct request_queue *q)
+{
+       struct blk_mq_qe_pair *qe;
+       struct elevator_type *t = NULL;
+
+       list_for_each_entry(qe, head, node)
+               if (qe->q == q) {
+                       t = qe->type;
+                       break;
+               }
+
+       if (!t)
+               return;
+
+       list_del(&qe->node);
+       kfree(qe);
+
+       mutex_lock(&q->sysfs_lock);
+       elevator_switch_mq(q, t);
+       mutex_unlock(&q->sysfs_lock);
+}
+
 static void __blk_mq_update_nr_hw_queues(struct blk_mq_tag_set *set,
                                                        int nr_hw_queues)
 {
        struct request_queue *q;
+       LIST_HEAD(head);
 
        lockdep_assert_held(&set->tag_list_lock);
 
@@ -2910,6 +2974,18 @@ static void __blk_mq_update_nr_hw_queues(struct blk_mq_tag_set *set,
 
        list_for_each_entry(q, &set->tag_list, tag_set_list)
                blk_mq_freeze_queue(q);
+       /*
+        * Sync with blk_mq_queue_tag_busy_iter.
+        */
+       synchronize_rcu();
+       /*
+        * Switch IO scheduler to 'none', cleaning up the data associated
+        * with the previous scheduler. We will switch back once we are done
+        * updating the new sw to hw queue mappings.
+        */
+       list_for_each_entry(q, &set->tag_list, tag_set_list)
+               if (!blk_mq_elv_switch_none(&head, q))
+                       goto switch_back;
 
        set->nr_hw_queues = nr_hw_queues;
        blk_mq_update_queue_map(set);
@@ -2918,6 +2994,10 @@ static void __blk_mq_update_nr_hw_queues(struct blk_mq_tag_set *set,
                blk_mq_queue_reinit(q);
        }
 
+switch_back:
+       list_for_each_entry(q, &set->tag_list, tag_set_list)
+               blk_mq_elv_switch_back(&head, q);
+
        list_for_each_entry(q, &set->tag_list, tag_set_list)
                blk_mq_unfreeze_queue(q);
 }
index bb109bb..3772671 100644 (file)
@@ -453,9 +453,26 @@ static ssize_t queue_wb_lat_store(struct request_queue *q, const char *page,
        else if (val >= 0)
                val *= 1000ULL;
 
-       wbt_set_min_lat(q, val);
+       /*
+        * Ensure that the queue is idled, in case the latency update
+        * ends up either enabling or disabling wbt completely. We can't
+        * have IO inflight if that happens.
+        */
+       if (q->mq_ops) {
+               blk_mq_freeze_queue(q);
+               blk_mq_quiesce_queue(q);
+       } else
+               blk_queue_bypass_start(q);
 
+       wbt_set_min_lat(q, val);
        wbt_update_limits(q);
+
+       if (q->mq_ops) {
+               blk_mq_unquiesce_queue(q);
+               blk_mq_unfreeze_queue(q);
+       } else
+               blk_queue_bypass_end(q);
+
        return count;
 }
 
index 1d94a20..84507d3 100644 (file)
@@ -118,7 +118,7 @@ static void rwb_wake_all(struct rq_wb *rwb)
        for (i = 0; i < WBT_NUM_RWQ; i++) {
                struct rq_wait *rqw = &rwb->rq_wait[i];
 
-               if (waitqueue_active(&rqw->wait))
+               if (wq_has_sleeper(&rqw->wait))
                        wake_up_all(&rqw->wait);
        }
 }
@@ -162,7 +162,7 @@ static void __wbt_done(struct rq_qos *rqos, enum wbt_flags wb_acct)
        if (inflight && inflight >= limit)
                return;
 
-       if (waitqueue_active(&rqw->wait)) {
+       if (wq_has_sleeper(&rqw->wait)) {
                int diff = limit - inflight;
 
                if (!inflight || diff >= rwb->wb_background / 2)
@@ -449,6 +449,13 @@ static inline unsigned int get_limit(struct rq_wb *rwb, unsigned long rw)
 {
        unsigned int limit;
 
+       /*
+        * If we got disabled, just return UINT_MAX. This ensures that
+        * we'll properly inc a new IO, and dec+wakeup at the end.
+        */
+       if (!rwb_enabled(rwb))
+               return UINT_MAX;
+
        if ((rw & REQ_OP_MASK) == REQ_OP_DISCARD)
                return rwb->wb_background;
 
@@ -485,31 +492,17 @@ static void __wbt_wait(struct rq_wb *rwb, enum wbt_flags wb_acct,
 {
        struct rq_wait *rqw = get_rq_wait(rwb, wb_acct);
        DECLARE_WAITQUEUE(wait, current);
+       bool has_sleeper;
 
-       /*
-       * inc it here even if disabled, since we'll dec it at completion.
-       * this only happens if the task was sleeping in __wbt_wait(),
-       * and someone turned it off at the same time.
-       */
-       if (!rwb_enabled(rwb)) {
-               atomic_inc(&rqw->inflight);
-               return;
-       }
-
-       if (!waitqueue_active(&rqw->wait)
-               && rq_wait_inc_below(rqw, get_limit(rwb, rw)))
+       has_sleeper = wq_has_sleeper(&rqw->wait);
+       if (!has_sleeper && rq_wait_inc_below(rqw, get_limit(rwb, rw)))
                return;
 
        add_wait_queue_exclusive(&rqw->wait, &wait);
        do {
                set_current_state(TASK_UNINTERRUPTIBLE);
 
-               if (!rwb_enabled(rwb)) {
-                       atomic_inc(&rqw->inflight);
-                       break;
-               }
-
-               if (rq_wait_inc_below(rqw, get_limit(rwb, rw)))
+               if (!has_sleeper && rq_wait_inc_below(rqw, get_limit(rwb, rw)))
                        break;
 
                if (lock) {
@@ -518,6 +511,7 @@ static void __wbt_wait(struct rq_wb *rwb, enum wbt_flags wb_acct,
                        spin_lock_irq(lock);
                } else
                        io_schedule();
+               has_sleeper = false;
        } while (1);
 
        __set_current_state(TASK_RUNNING);
@@ -546,6 +540,9 @@ static enum wbt_flags bio_to_wbt_flags(struct rq_wb *rwb, struct bio *bio)
 {
        enum wbt_flags flags = 0;
 
+       if (!rwb_enabled(rwb))
+               return 0;
+
        if (bio_op(bio) == REQ_OP_READ) {
                flags = WBT_READ;
        } else if (wbt_should_throttle(rwb, bio)) {
@@ -576,12 +573,8 @@ static void wbt_wait(struct rq_qos *rqos, struct bio *bio, spinlock_t *lock)
        struct rq_wb *rwb = RQWB(rqos);
        enum wbt_flags flags;
 
-       if (!rwb_enabled(rwb))
-               return;
-
        flags = bio_to_wbt_flags(rwb, bio);
-
-       if (!wbt_should_throttle(rwb, bio)) {
+       if (!(flags & WBT_TRACKED)) {
                if (flags & WBT_READ)
                        wb_timestamp(rwb, &rwb->last_issue);
                return;
index d4d67e9..9db4e38 100644 (file)
@@ -234,6 +234,8 @@ static inline void elv_deactivate_rq(struct request_queue *q, struct request *rq
 
 int elevator_init(struct request_queue *);
 int elevator_init_mq(struct request_queue *q);
+int elevator_switch_mq(struct request_queue *q,
+                             struct elevator_type *new_e);
 void elevator_exit(struct request_queue *, struct elevator_queue *);
 int elv_register_queue(struct request_queue *q);
 void elv_unregister_queue(struct request_queue *q);
@@ -297,7 +299,7 @@ extern int blk_update_nr_requests(struct request_queue *, unsigned int);
  *     b) the queue had IO stats enabled when this request was started, and
  *     c) it's a file system request
  */
-static inline int blk_do_io_stat(struct request *rq)
+static inline bool blk_do_io_stat(struct request *rq)
 {
        return rq->rq_disk &&
               (rq->rq_flags & RQF_IO_STAT) &&
index fa828b5..5ea6e7d 100644 (file)
@@ -933,16 +933,13 @@ void elv_unregister(struct elevator_type *e)
 }
 EXPORT_SYMBOL_GPL(elv_unregister);
 
-static int elevator_switch_mq(struct request_queue *q,
+int elevator_switch_mq(struct request_queue *q,
                              struct elevator_type *new_e)
 {
        int ret;
 
        lockdep_assert_held(&q->sysfs_lock);
 
-       blk_mq_freeze_queue(q);
-       blk_mq_quiesce_queue(q);
-
        if (q->elevator) {
                if (q->elevator->registered)
                        elv_unregister_queue(q);
@@ -968,8 +965,6 @@ static int elevator_switch_mq(struct request_queue *q,
                blk_add_trace_msg(q, "elv switch: none");
 
 out:
-       blk_mq_unquiesce_queue(q);
-       blk_mq_unfreeze_queue(q);
        return ret;
 }
 
@@ -1021,8 +1016,17 @@ static int elevator_switch(struct request_queue *q, struct elevator_type *new_e)
 
        lockdep_assert_held(&q->sysfs_lock);
 
-       if (q->mq_ops)
-               return elevator_switch_mq(q, new_e);
+       if (q->mq_ops) {
+               blk_mq_freeze_queue(q);
+               blk_mq_quiesce_queue(q);
+
+               err = elevator_switch_mq(q, new_e);
+
+               blk_mq_unquiesce_queue(q);
+               blk_mq_unfreeze_queue(q);
+
+               return err;
+       }
 
        /*
         * Turn on BYPASS and drain all requests w/ elevator private data.
index 3918ff7..8f29058 100644 (file)
@@ -5,8 +5,8 @@
        __INITRODATA
 
        .align 8
-       .globl VMLINUX_SYMBOL(system_certificate_list)
-VMLINUX_SYMBOL(system_certificate_list):
+       .globl system_certificate_list
+system_certificate_list:
 __cert_list_start:
 #ifdef CONFIG_MODULE_SIG
        .incbin "certs/signing_key.x509"
@@ -15,21 +15,21 @@ __cert_list_start:
 __cert_list_end:
 
 #ifdef CONFIG_SYSTEM_EXTRA_CERTIFICATE
-       .globl VMLINUX_SYMBOL(system_extra_cert)
+       .globl system_extra_cert
        .size system_extra_cert, CONFIG_SYSTEM_EXTRA_CERTIFICATE_SIZE
-VMLINUX_SYMBOL(system_extra_cert):
+system_extra_cert:
        .fill CONFIG_SYSTEM_EXTRA_CERTIFICATE_SIZE, 1, 0
 
        .align 4
-       .globl VMLINUX_SYMBOL(system_extra_cert_used)
-VMLINUX_SYMBOL(system_extra_cert_used):
+       .globl system_extra_cert_used
+system_extra_cert_used:
        .int 0
 
 #endif /* CONFIG_SYSTEM_EXTRA_CERTIFICATE */
 
        .align 8
-       .globl VMLINUX_SYMBOL(system_certificate_list_size)
-VMLINUX_SYMBOL(system_certificate_list_size):
+       .globl system_certificate_list_size
+system_certificate_list_size:
 #ifdef CONFIG_64BIT
        .quad __cert_list_end - __cert_list_start
 #else
index 4a46344..dd1eea9 100644 (file)
@@ -3,6 +3,9 @@
 # ACPI Configuration
 #
 
+config ARCH_SUPPORTS_ACPI
+       bool
+
 menuconfig ACPI
        bool "ACPI (Advanced Configuration and Power Interface) Support"
        depends on ARCH_SUPPORTS_ACPI
@@ -40,9 +43,6 @@ menuconfig ACPI
          <http://www.acpi.info>
          <http://www.uefi.org/acpi/specs>
 
-config ARCH_SUPPORTS_ACPI
-       bool
-
 if ACPI
 
 config ACPI_LEGACY_TABLES_LOOKUP
index c5367bf..0f28a38 100644 (file)
@@ -164,6 +164,7 @@ struct acpi_namespace_node {
 #define ANOBJ_SUBTREE_HAS_INI           0x10   /* Used to optimize device initialization */
 #define ANOBJ_EVALUATED                 0x20   /* Set on first evaluation of node */
 #define ANOBJ_ALLOCATED_BUFFER          0x40   /* Method AML buffer is dynamic (install_method) */
+#define ANOBJ_NODE_EARLY_INIT           0x80   /* acpi_exec only: Node was create via init file (-fi) */
 
 #define ANOBJ_IS_EXTERNAL               0x08   /* iASL only: This object created via External() */
 #define ANOBJ_METHOD_NO_RETVAL          0x10   /* iASL only: Method has no return value */
index 3825df9..bbb3b4d 100644 (file)
 /* Flags for acpi_ns_lookup, acpi_ns_search_and_enter */
 
 #define ACPI_NS_NO_UPSEARCH         0
-#define ACPI_NS_SEARCH_PARENT       0x01
-#define ACPI_NS_DONT_OPEN_SCOPE     0x02
-#define ACPI_NS_NO_PEER_SEARCH      0x04
-#define ACPI_NS_ERROR_IF_FOUND      0x08
-#define ACPI_NS_PREFIX_IS_SCOPE     0x10
-#define ACPI_NS_EXTERNAL            0x20
-#define ACPI_NS_TEMPORARY           0x40
-#define ACPI_NS_OVERRIDE_IF_FOUND   0x80
+#define ACPI_NS_SEARCH_PARENT       0x0001
+#define ACPI_NS_DONT_OPEN_SCOPE     0x0002
+#define ACPI_NS_NO_PEER_SEARCH      0x0004
+#define ACPI_NS_ERROR_IF_FOUND      0x0008
+#define ACPI_NS_PREFIX_IS_SCOPE     0x0010
+#define ACPI_NS_EXTERNAL            0x0020
+#define ACPI_NS_TEMPORARY           0x0040
+#define ACPI_NS_OVERRIDE_IF_FOUND   0x0080
+#define ACPI_NS_EARLY_INIT          0x0100
 
 /* Flags for acpi_ns_walk_namespace */
 
index 2733cd4..3374d41 100644 (file)
@@ -180,6 +180,8 @@ char acpi_ut_remove_leading_zeros(char **string);
 
 u8 acpi_ut_detect_hex_prefix(char **string);
 
+void acpi_ut_remove_hex_prefix(char **string);
+
 u8 acpi_ut_detect_octal_prefix(char **string);
 
 /*
index 556ff59..3e5f953 100644 (file)
@@ -763,7 +763,12 @@ acpi_db_command_dispatch(char *input_buffer,
        case CMD_DISASSEMBLE:
        case CMD_DISASM:
 
+#ifdef ACPI_DISASSEMBLER
                (void)acpi_db_disassemble_method(acpi_gbl_db_args[1]);
+#else
+               acpi_os_printf
+                   ("The AML Disassembler is not configured/present\n");
+#endif
                break;
 
        case CMD_DUMP:
@@ -872,7 +877,12 @@ acpi_db_command_dispatch(char *input_buffer,
 
        case CMD_LIST:
 
+#ifdef ACPI_DISASSEMBLER
                acpi_db_disassemble_aml(acpi_gbl_db_args[1], op);
+#else
+               acpi_os_printf
+                   ("The AML Disassembler is not configured/present\n");
+#endif
                break;
 
        case CMD_LOCKS:
index 9fcecf1..d8b7a0f 100644 (file)
@@ -216,6 +216,7 @@ cleanup:
        acpi_ut_remove_reference(obj_desc);
 }
 
+#ifdef ACPI_DISASSEMBLER
 /*******************************************************************************
  *
  * FUNCTION:    acpi_db_disassemble_aml
@@ -242,9 +243,8 @@ void acpi_db_disassemble_aml(char *statements, union acpi_parse_object *op)
        if (statements) {
                num_statements = strtoul(statements, NULL, 0);
        }
-#ifdef ACPI_DISASSEMBLER
+
        acpi_dm_disassemble(NULL, op, num_statements);
-#endif
 }
 
 /*******************************************************************************
@@ -317,8 +317,6 @@ acpi_status acpi_db_disassemble_method(char *name)
        walk_state->parse_flags |= ACPI_PARSE_DISASSEMBLE;
 
        status = acpi_ps_parse_aml(walk_state);
-
-#ifdef ACPI_DISASSEMBLER
        (void)acpi_dm_parse_deferred_ops(op);
 
        /* Now we can disassemble the method */
@@ -326,7 +324,6 @@ acpi_status acpi_db_disassemble_method(char *name)
        acpi_gbl_dm_opt_verbose = FALSE;
        acpi_dm_disassemble(NULL, op, 0);
        acpi_gbl_dm_opt_verbose = TRUE;
-#endif
 
        acpi_ps_delete_parse_tree(op);
 
@@ -337,6 +334,7 @@ acpi_status acpi_db_disassemble_method(char *name)
        acpi_ut_release_owner_id(&obj_desc->method.owner_id);
        return (AE_OK);
 }
+#endif
 
 /*******************************************************************************
  *
index 4647aa8..f252672 100644 (file)
@@ -10,6 +10,7 @@
 #include "amlcode.h"
 #include "acdebug.h"
 #include "acinterp.h"
+#include "acparser.h"
 
 #define _COMPONENT          ACPI_CA_DEBUGGER
 ACPI_MODULE_NAME("dbxface")
@@ -262,10 +263,17 @@ acpi_db_single_step(struct acpi_walk_state *walk_state,
                        }
                }
 
-               /* Now we can display it */
+               /* Now we can disassemble and display it */
 
 #ifdef ACPI_DISASSEMBLER
                acpi_dm_disassemble(walk_state, display_op, ACPI_UINT32_MAX);
+#else
+               /*
+                * The AML Disassembler is not configured - at least we can
+                * display the opcode value and name
+                */
+               acpi_os_printf("AML Opcode: %4.4X %s\n", op->common.aml_opcode,
+                              acpi_ps_get_opcode_name(op->common.aml_opcode));
 #endif
 
                if ((op->common.aml_opcode == AML_IF_OP) ||
index 7c93759..30fe895 100644 (file)
 #include "acnamesp.h"
 #include "acparser.h"
 
+#ifdef ACPI_EXEC_APP
+#include "aecommon.h"
+#endif
+
 #define _COMPONENT          ACPI_DISPATCHER
 ACPI_MODULE_NAME("dsfield")
 
@@ -259,6 +263,13 @@ acpi_ds_get_field_names(struct acpi_create_field_info *info,
        u64 position;
        union acpi_parse_object *child;
 
+#ifdef ACPI_EXEC_APP
+       u64 value = 0;
+       union acpi_operand_object *result_desc;
+       union acpi_operand_object *obj_desc;
+       char *name_path;
+#endif
+
        ACPI_FUNCTION_TRACE_PTR(ds_get_field_names, info);
 
        /* First field starts at bit zero */
@@ -391,6 +402,25 @@ acpi_ds_get_field_names(struct acpi_create_field_info *info,
                                        if (ACPI_FAILURE(status)) {
                                                return_ACPI_STATUS(status);
                                        }
+#ifdef ACPI_EXEC_APP
+                                       name_path =
+                                           acpi_ns_get_external_pathname(info->
+                                                                         field_node);
+                                       obj_desc =
+                                           acpi_ut_create_integer_object
+                                           (value);
+                                       if (ACPI_SUCCESS
+                                           (ae_lookup_init_file_entry
+                                            (name_path, &value))) {
+                                               acpi_ex_write_data_to_field
+                                                   (obj_desc,
+                                                    acpi_ns_get_attached_object
+                                                    (info->field_node),
+                                                    &result_desc);
+                                       }
+                                       acpi_ut_remove_reference(obj_desc);
+                                       ACPI_FREE(name_path);
+#endif
                                }
                        }
 
@@ -573,7 +603,9 @@ acpi_ds_init_field_objects(union acpi_parse_object *op,
            !(walk_state->parse_flags & ACPI_PARSE_MODULE_LEVEL)) {
                flags |= ACPI_NS_TEMPORARY;
        }
-
+#ifdef ACPI_EXEC_APP
+       flags |= ACPI_NS_OVERRIDE_IF_FOUND;
+#endif
        /*
         * Walk the list of entries in the field_list
         * Note: field_list can be of zero length. In this case, Arg will be NULL.
index 3de794b..69603ba 100644 (file)
@@ -528,13 +528,18 @@ acpi_status acpi_hw_register_read(u32 register_id, u32 *return_value)
 
                status =
                    acpi_hw_read(&value64, &acpi_gbl_FADT.xpm2_control_block);
-               value = (u32)value64;
+               if (ACPI_SUCCESS(status)) {
+                       value = (u32)value64;
+               }
                break;
 
        case ACPI_REGISTER_PM_TIMER:    /* 32-bit access */
 
                status = acpi_hw_read(&value64, &acpi_gbl_FADT.xpm_timer_block);
-               value = (u32)value64;
+               if (ACPI_SUCCESS(status)) {
+                       value = (u32)value64;
+               }
+
                break;
 
        case ACPI_REGISTER_SMI_COMMAND_BLOCK:   /* 8-bit access */
index fe9d46d..d8b8fc2 100644 (file)
@@ -56,14 +56,9 @@ acpi_status acpi_hw_legacy_sleep(u8 sleep_state)
        if (ACPI_FAILURE(status)) {
                return_ACPI_STATUS(status);
        }
-       /*
-        * If the target sleep state is S5, clear all GPEs and fixed events too
-        */
-       if (sleep_state == ACPI_STATE_S5) {
-               status = acpi_hw_clear_acpi_status();
-               if (ACPI_FAILURE(status)) {
-                       return_ACPI_STATUS(status);
-               }
+       status = acpi_hw_clear_acpi_status();
+       if (ACPI_FAILURE(status)) {
+               return_ACPI_STATUS(status);
        }
        acpi_gbl_system_awake_and_running = FALSE;
 
index 83a593e..e3f10af 100644 (file)
@@ -558,6 +558,14 @@ acpi_ns_lookup(union acpi_generic_state *scope_info,
                                                  (char *)&current_node->name,
                                                  current_node));
                        }
+#ifdef ACPI_EXEC_APP
+                       if ((status == AE_ALREADY_EXISTS) &&
+                           (this_node->flags & ANOBJ_NODE_EARLY_INIT)) {
+                               this_node->flags &= ~ANOBJ_NODE_EARLY_INIT;
+                               status = AE_OK;
+                       }
+#endif
+
 #ifdef ACPI_ASL_COMPILER
                        /*
                         * If this ACPI name already exists within the namespace as an
@@ -676,6 +684,11 @@ acpi_ns_lookup(union acpi_generic_state *scope_info,
                        }
                }
        }
+#ifdef ACPI_EXEC_APP
+       if (flags & ACPI_NS_EARLY_INIT) {
+               this_node->flags |= ANOBJ_NODE_EARLY_INIT;
+       }
+#endif
 
        *return_node = this_node;
        return_ACPI_STATUS(AE_OK);
index 44f35ab..34fc2f7 100644 (file)
@@ -22,6 +22,7 @@
 #include "acdispat.h"
 #include "amlcode.h"
 #include "acconvert.h"
+#include "acnamesp.h"
 
 #define _COMPONENT          ACPI_PARSER
 ACPI_MODULE_NAME("psloop")
@@ -527,12 +528,18 @@ acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state)
                                if (ACPI_FAILURE(status)) {
                                        return_ACPI_STATUS(status);
                                }
-                               if (walk_state->opcode == AML_SCOPE_OP) {
+                               if (acpi_ns_opens_scope
+                                   (acpi_ps_get_opcode_info
+                                    (walk_state->opcode)->object_type)) {
                                        /*
-                                        * If the scope op fails to parse, skip the body of the
-                                        * scope op because the parse failure indicates that the
-                                        * device may not exist.
+                                        * If the scope/device op fails to parse, skip the body of
+                                        * the scope op because the parse failure indicates that
+                                        * the device may not exist.
                                         */
+                                       ACPI_ERROR((AE_INFO,
+                                                   "Skip parsing opcode %s",
+                                                   acpi_ps_get_opcode_name
+                                                   (walk_state->opcode)));
                                        walk_state->parser_state.aml =
                                            walk_state->aml + 1;
                                        walk_state->parser_state.aml =
@@ -540,8 +547,6 @@ acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state)
                                            (&walk_state->parser_state);
                                        walk_state->aml =
                                            walk_state->parser_state.aml;
-                                       ACPI_ERROR((AE_INFO,
-                                                   "Skipping Scope block"));
                                }
 
                                continue;
@@ -709,20 +714,20 @@ acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state)
                        } else
                            if ((walk_state->
                                 parse_flags & ACPI_PARSE_MODULE_LEVEL)
-                               && status != AE_CTRL_TRANSFER
-                               && ACPI_FAILURE(status)) {
+                               && (ACPI_AML_EXCEPTION(status)
+                                   || status == AE_ALREADY_EXISTS
+                                   || status == AE_NOT_FOUND)) {
                                /*
-                                * ACPI_PARSE_MODULE_LEVEL flag means that we are currently
-                                * loading a table by executing it as a control method.
-                                * However, if we encounter an error while loading the table,
-                                * we need to keep trying to load the table rather than
-                                * aborting the table load (setting the status to AE_OK
-                                * continues the table load). If we get a failure at this
-                                * point, it means that the dispatcher got an error while
-                                * processing Op (most likely an AML operand error) or a
-                                * control method was called from module level and the
-                                * dispatcher returned AE_CTRL_TRANSFER. In the latter case,
-                                * leave the status alone, there's nothing wrong with it.
+                                * ACPI_PARSE_MODULE_LEVEL flag means that we
+                                * are currently loading a table by executing
+                                * it as a control method. However, if we
+                                * encounter an error while loading the table,
+                                * we need to keep trying to load the table
+                                * rather than aborting the table load (setting
+                                * the status to AE_OK continues the table
+                                * load). If we get a failure at this point, it
+                                * means that the dispatcher got an error while
+                                * trying to execute the Op.
                                 */
                                status = AE_OK;
                        }
index 51891f9..862149c 100644 (file)
@@ -516,9 +516,9 @@ acpi_tb_verify_temp_table(struct acpi_table_desc *table_desc,
                            acpi_tb_check_duplication(table_desc, table_index);
                        if (ACPI_FAILURE(status)) {
                                if (status != AE_CTRL_TERMINATE) {
-                                       ACPI_EXCEPTION((AE_INFO, AE_NO_MEMORY,
+                                       ACPI_EXCEPTION((AE_INFO, status,
                                                        "%4.4s 0x%8.8X%8.8X"
-                                                       " Table is duplicated",
+                                                       " Table is already loaded",
                                                        acpi_ut_valid_nameseg
                                                        (table_desc->signature.
                                                         ascii) ? table_desc->
index 118f3ff..8cc4392 100644 (file)
@@ -355,6 +355,7 @@ acpi_ut_update_ref_count(union acpi_operand_object *object, u32 action)
        u16 original_count;
        u16 new_count = 0;
        acpi_cpu_flags lock_flags;
+       char *message;
 
        ACPI_FUNCTION_NAME(ut_update_ref_count);
 
@@ -391,6 +392,7 @@ acpi_ut_update_ref_count(union acpi_operand_object *object, u32 action)
                                  object, object->common.type,
                                  acpi_ut_get_object_type_name(object),
                                  new_count));
+               message = "Incremement";
                break;
 
        case REF_DECREMENT:
@@ -420,6 +422,7 @@ acpi_ut_update_ref_count(union acpi_operand_object *object, u32 action)
                if (new_count == 0) {
                        acpi_ut_delete_internal_obj(object);
                }
+               message = "Decrement";
                break;
 
        default:
@@ -436,8 +439,8 @@ acpi_ut_update_ref_count(union acpi_operand_object *object, u32 action)
         */
        if (new_count > ACPI_MAX_REFERENCE_COUNT) {
                ACPI_WARNING((AE_INFO,
-                             "Large Reference Count (0x%X) in object %p, Type=0x%.2X",
-                             new_count, object, object->common.type));
+                             "Large Reference Count (0x%X) in object %p, Type=0x%.2X Operation=%s",
+                             new_count, object, object->common.type, message));
        }
 }
 
index 954f8e3..05ff200 100644 (file)
@@ -231,14 +231,34 @@ char acpi_ut_remove_whitespace(char **string)
 
 u8 acpi_ut_detect_hex_prefix(char **string)
 {
+       char *initial_position = *string;
 
+       acpi_ut_remove_hex_prefix(string);
+       if (*string != initial_position) {
+               return (TRUE);  /* String is past leading 0x */
+       }
+
+       return (FALSE);         /* Not a hex string */
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_remove_hex_prefix
+ *
+ * PARAMETERS:  string                  - Pointer to input ASCII string
+ *
+ * RETURN:      none
+ *
+ * DESCRIPTION: Remove a hex "0x" prefix
+ *
+ ******************************************************************************/
+
+void acpi_ut_remove_hex_prefix(char **string)
+{
        if ((**string == ACPI_ASCII_ZERO) &&
            (tolower((int)*(*string + 1)) == 'x')) {
                *string += 2;   /* Go past the leading 0x */
-               return (TRUE);
        }
-
-       return (FALSE);         /* Not a hex string */
 }
 
 /*******************************************************************************
index 8fadad2..5fde619 100644 (file)
@@ -218,7 +218,7 @@ u64 acpi_ut_implicit_strtoul64(char *string)
         * implicit conversions, and the "0x" prefix is "not allowed".
         * However, allow a "0x" prefix as an ACPI extension.
         */
-       acpi_ut_detect_hex_prefix(&string);
+       acpi_ut_remove_hex_prefix(&string);
 
        if (!acpi_ut_remove_leading_zeros(&string)) {
                return_VALUE(0);
index 7c47900..b072cfc 100644 (file)
@@ -1699,7 +1699,7 @@ static int acpi_nfit_add_dimm(struct acpi_nfit_desc *acpi_desc,
 {
        struct acpi_device *adev, *adev_dimm;
        struct device *dev = acpi_desc->dev;
-       unsigned long dsm_mask;
+       unsigned long dsm_mask, label_mask;
        const guid_t *guid;
        int i;
        int family = -1;
@@ -1771,6 +1771,16 @@ static int acpi_nfit_add_dimm(struct acpi_nfit_desc *acpi_desc,
                                        1ULL << i))
                        set_bit(i, &nfit_mem->dsm_mask);
 
+       /*
+        * Prefer the NVDIMM_FAMILY_INTEL label read commands if present
+        * due to their better semantics handling locked capacity.
+        */
+       label_mask = 1 << ND_CMD_GET_CONFIG_SIZE | 1 << ND_CMD_GET_CONFIG_DATA
+               | 1 << ND_CMD_SET_CONFIG_DATA;
+       if (family == NVDIMM_FAMILY_INTEL
+                       && (dsm_mask & label_mask) == label_mask)
+               return 0;
+
        if (acpi_nvdimm_has_method(adev_dimm, "_LSI")
                        && acpi_nvdimm_has_method(adev_dimm, "_LSR")) {
                dev_dbg(dev, "%s: has _LSR\n", dev_name(&adev_dimm->dev));
@@ -2559,7 +2569,12 @@ static void ars_complete(struct acpi_nfit_desc *acpi_desc,
                        test_bit(ARS_SHORT, &nfit_spa->ars_state)
                        ? "short" : "long");
        clear_bit(ARS_SHORT, &nfit_spa->ars_state);
-       set_bit(ARS_DONE, &nfit_spa->ars_state);
+       if (test_and_clear_bit(ARS_REQ_REDO, &nfit_spa->ars_state)) {
+               set_bit(ARS_SHORT, &nfit_spa->ars_state);
+               set_bit(ARS_REQ, &nfit_spa->ars_state);
+               dev_dbg(dev, "ARS: processing scrub request received while in progress\n");
+       } else
+               set_bit(ARS_DONE, &nfit_spa->ars_state);
 }
 
 static int ars_status_process_records(struct acpi_nfit_desc *acpi_desc)
@@ -3256,9 +3271,10 @@ int acpi_nfit_ars_rescan(struct acpi_nfit_desc *acpi_desc, unsigned long flags)
                if (test_bit(ARS_FAILED, &nfit_spa->ars_state))
                        continue;
 
-               if (test_and_set_bit(ARS_REQ, &nfit_spa->ars_state))
+               if (test_and_set_bit(ARS_REQ, &nfit_spa->ars_state)) {
                        busy++;
-               else {
+                       set_bit(ARS_REQ_REDO, &nfit_spa->ars_state);
+               } else {
                        if (test_bit(ARS_SHORT, &flags))
                                set_bit(ARS_SHORT, &nfit_spa->ars_state);
                        scheduled++;
index a97ff42..d1274ea 100644 (file)
@@ -119,6 +119,7 @@ enum nfit_dimm_notifiers {
 
 enum nfit_ars_state {
        ARS_REQ,
+       ARS_REQ_REDO,
        ARS_DONE,
        ARS_SHORT,
        ARS_FAILED,
index 7ffa740..22c9e37 100644 (file)
 #define PMIC_A0LOCK_REG                0xc5
 
 static struct pmic_table power_table[] = {
+/*     {
+               .address = 0x00,
+               .reg = ??,
+               .bit = ??,
+       }, ** VSYS */
+       {
+               .address = 0x04,
+               .reg = 0x63,
+               .bit = 0x00,
+       }, /* SYSX -> VSYS_SX */
+       {
+               .address = 0x08,
+               .reg = 0x62,
+               .bit = 0x00,
+       }, /* SYSU -> VSYS_U */
+       {
+               .address = 0x0c,
+               .reg = 0x64,
+               .bit = 0x00,
+       }, /* SYSS -> VSYS_S */
+       {
+               .address = 0x10,
+               .reg = 0x6a,
+               .bit = 0x00,
+       }, /* V50S -> V5P0S */
+       {
+               .address = 0x14,
+               .reg = 0x6b,
+               .bit = 0x00,
+       }, /* HOST -> VHOST, USB2/3 host */
+       {
+               .address = 0x18,
+               .reg = 0x6c,
+               .bit = 0x00,
+       }, /* VBUS -> VBUS, USB2/3 OTG */
+       {
+               .address = 0x1c,
+               .reg = 0x6d,
+               .bit = 0x00,
+       }, /* HDMI -> VHDMI */
+/*     {
+               .address = 0x20,
+               .reg = ??,
+               .bit = ??,
+       }, ** S285 */
        {
                .address = 0x24,
                .reg = 0x66,
                .bit = 0x00,
-       },
+       }, /* X285 -> V2P85SX, camera */
+/*     {
+               .address = 0x28,
+               .reg = ??,
+               .bit = ??,
+       }, ** V33A */
+       {
+               .address = 0x2c,
+               .reg = 0x69,
+               .bit = 0x00,
+       }, /* V33S -> V3P3S, display/ssd/audio */
+       {
+               .address = 0x30,
+               .reg = 0x68,
+               .bit = 0x00,
+       }, /* V33U -> V3P3U, SDIO wifi&bt */
+/*     {
+               .address = 0x34 .. 0x40,
+               .reg = ??,
+               .bit = ??,
+       }, ** V33I, V18A, REFQ, V12A */
+       {
+               .address = 0x44,
+               .reg = 0x5c,
+               .bit = 0x00,
+       }, /* V18S -> V1P8S, SOC/USB PHY/SIM */
        {
                .address = 0x48,
                .reg = 0x5d,
                .bit = 0x00,
-       },
+       }, /* V18X -> V1P8SX, eMMC/camara/audio */
+       {
+               .address = 0x4c,
+               .reg = 0x5b,
+               .bit = 0x00,
+       }, /* V18U -> V1P8U, LPDDR */
+       {
+               .address = 0x50,
+               .reg = 0x61,
+               .bit = 0x00,
+       }, /* V12X -> V1P2SX, SOC SFR */
+       {
+               .address = 0x54,
+               .reg = 0x60,
+               .bit = 0x00,
+       }, /* V12S -> V1P2S, MIPI */
+/*     {
+               .address = 0x58,
+               .reg = ??,
+               .bit = ??,
+       }, ** V10A */
+       {
+               .address = 0x5c,
+               .reg = 0x56,
+               .bit = 0x00,
+       }, /* V10S -> V1P0S, SOC GFX */
+       {
+               .address = 0x60,
+               .reg = 0x57,
+               .bit = 0x00,
+       }, /* V10X -> V1P0SX, SOC display/DDR IO/PCIe */
+       {
+               .address = 0x64,
+               .reg = 0x59,
+               .bit = 0x00,
+       }, /* V105 -> V1P05S, L2 SRAM */
 };
 
 static struct pmic_table thermal_table[] = {
index b933061..8c0a54d 100644 (file)
@@ -205,6 +205,7 @@ phys_cpuid_t acpi_get_phys_id(acpi_handle handle, int type, u32 acpi_id)
 
        return phys_id;
 }
+EXPORT_SYMBOL_GPL(acpi_get_phys_id);
 
 int acpi_map_cpuid(phys_cpuid_t phys_id, u32 acpi_id)
 {
index b2b9eba..021ce46 100644 (file)
@@ -610,7 +610,7 @@ static int marvell_enable = 1;
 module_param(marvell_enable, int, 0644);
 MODULE_PARM_DESC(marvell_enable, "Marvell SATA via AHCI (1 = enabled)");
 
-static int mobile_lpm_policy = CONFIG_SATA_MOBILE_LPM_POLICY;
+static int mobile_lpm_policy = -1;
 module_param(mobile_lpm_policy, int, 0644);
 MODULE_PARM_DESC(mobile_lpm_policy, "Default LPM policy for mobile chipsets");
 
@@ -1604,6 +1604,37 @@ static int ahci_init_msi(struct pci_dev *pdev, unsigned int n_ports,
        return pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_MSIX);
 }
 
+static void ahci_update_initial_lpm_policy(struct ata_port *ap,
+                                          struct ahci_host_priv *hpriv)
+{
+       int policy = CONFIG_SATA_MOBILE_LPM_POLICY;
+
+
+       /* Ignore processing for non mobile platforms */
+       if (!(hpriv->flags & AHCI_HFLAG_IS_MOBILE))
+               return;
+
+       /* user modified policy via module param */
+       if (mobile_lpm_policy != -1) {
+               policy = mobile_lpm_policy;
+               goto update_policy;
+       }
+
+#ifdef CONFIG_ACPI
+       if (policy > ATA_LPM_MED_POWER &&
+           (acpi_gbl_FADT.flags & ACPI_FADT_LOW_POWER_S0)) {
+               if (hpriv->cap & HOST_CAP_PART)
+                       policy = ATA_LPM_MIN_POWER_WITH_PARTIAL;
+               else if (hpriv->cap & HOST_CAP_SSC)
+                       policy = ATA_LPM_MIN_POWER;
+       }
+#endif
+
+update_policy:
+       if (policy >= ATA_LPM_UNKNOWN && policy <= ATA_LPM_MIN_POWER)
+               ap->target_lpm_policy = policy;
+}
+
 static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        unsigned int board_id = ent->driver_data;
@@ -1807,10 +1838,7 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
                if (ap->flags & ATA_FLAG_EM)
                        ap->em_message_type = hpriv->em_msg_type;
 
-               if ((hpriv->flags & AHCI_HFLAG_IS_MOBILE) &&
-                   mobile_lpm_policy >= ATA_LPM_UNKNOWN &&
-                   mobile_lpm_policy <= ATA_LPM_MIN_POWER)
-                       ap->target_lpm_policy = mobile_lpm_policy;
+               ahci_update_initial_lpm_policy(ap, hpriv);
 
                /* disabled/not-implemented port */
                if (!(hpriv->port_map & (1 << i)))
index 1609eba..6a1515f 100644 (file)
@@ -350,6 +350,7 @@ struct ahci_host_priv {
        u32                     em_msg_type;    /* EM message type */
        bool                    got_runtime_pm; /* Did we do pm_runtime_get? */
        struct clk              *clks[AHCI_MAX_CLKS]; /* Optional */
+       struct reset_control    *rsts;          /* Optional */
        struct regulator        **target_pwrs;  /* Optional */
        /*
         * If platform uses PHYs. There is a 1:1 relation between the port number and
index ea43081..f3d5577 100644 (file)
@@ -425,7 +425,7 @@ static int brcm_ahci_probe(struct platform_device *pdev)
 
        brcm_sata_phys_enable(priv);
 
-       hpriv = ahci_platform_get_resources(pdev);
+       hpriv = ahci_platform_get_resources(pdev, 0);
        if (IS_ERR(hpriv))
                return PTR_ERR(hpriv);
        hpriv->plat_data = priv;
index 5ecc9d4..dc78c98 100644 (file)
@@ -213,7 +213,7 @@ static int ceva_ahci_probe(struct platform_device *pdev)
 
        cevapriv->ahci_pdev = pdev;
 
-       hpriv = ahci_platform_get_resources(pdev);
+       hpriv = ahci_platform_get_resources(pdev, 0);
        if (IS_ERR(hpriv))
                return PTR_ERR(hpriv);
 
index 9b34dff..ebaa657 100644 (file)
@@ -171,7 +171,7 @@ static int ahci_da850_probe(struct platform_device *pdev)
        u32 mpy;
        int rc;
 
-       hpriv = ahci_platform_get_resources(pdev);
+       hpriv = ahci_platform_get_resources(pdev, 0);
        if (IS_ERR(hpriv))
                return PTR_ERR(hpriv);
 
index fbd827c..89509c3 100644 (file)
@@ -148,7 +148,7 @@ static int ahci_dm816_probe(struct platform_device *pdev)
        struct ahci_host_priv *hpriv;
        int rc;
 
-       hpriv = ahci_platform_get_resources(pdev);
+       hpriv = ahci_platform_get_resources(pdev, 0);
        if (IS_ERR(hpriv))
                return PTR_ERR(hpriv);
 
index 6822e2f..b00799d 100644 (file)
@@ -1127,7 +1127,7 @@ static int imx_ahci_probe(struct platform_device *pdev)
                        return ret;
        }
 
-       hpriv = ahci_platform_get_resources(pdev);
+       hpriv = ahci_platform_get_resources(pdev, 0);
        if (IS_ERR(hpriv))
                return PTR_ERR(hpriv);
 
index 0ae6971..8bc1a26 100644 (file)
@@ -142,7 +142,7 @@ static int mtk_ahci_probe(struct platform_device *pdev)
        if (!plat)
                return -ENOMEM;
 
-       hpriv = ahci_platform_get_resources(pdev);
+       hpriv = ahci_platform_get_resources(pdev, 0);
        if (IS_ERR(hpriv))
                return PTR_ERR(hpriv);
 
index 72d90b4..f9cb51b 100644 (file)
@@ -158,7 +158,7 @@ static int ahci_mvebu_probe(struct platform_device *pdev)
        const struct mbus_dram_target_info *dram;
        int rc;
 
-       hpriv = ahci_platform_get_resources(pdev);
+       hpriv = ahci_platform_get_resources(pdev, 0);
        if (IS_ERR(hpriv))
                return PTR_ERR(hpriv);
 
index 99f9a89..46f0bd7 100644 (file)
@@ -43,7 +43,8 @@ static int ahci_probe(struct platform_device *pdev)
        struct ahci_host_priv *hpriv;
        int rc;
 
-       hpriv = ahci_platform_get_resources(pdev);
+       hpriv = ahci_platform_get_resources(pdev,
+                                           AHCI_PLATFORM_GET_RESETS);
        if (IS_ERR(hpriv))
                return PTR_ERR(hpriv);
 
@@ -75,7 +76,6 @@ static const struct of_device_id ahci_of_match[] = {
        { .compatible = "generic-ahci", },
        /* Keep the following compatibles for device tree compatibility */
        { .compatible = "snps,spear-ahci", },
-       { .compatible = "snps,exynos5440-ahci", },
        { .compatible = "ibm,476gtr-ahci", },
        { .compatible = "snps,dwc-ahci", },
        { .compatible = "hisilicon,hisi-ahci", },
index cfdef4d..ce59253 100644 (file)
@@ -250,7 +250,7 @@ static int ahci_qoriq_probe(struct platform_device *pdev)
        struct resource *res;
        int rc;
 
-       hpriv = ahci_platform_get_resources(pdev);
+       hpriv = ahci_platform_get_resources(pdev, 0);
        if (IS_ERR(hpriv))
                return PTR_ERR(hpriv);
 
index 1d31c0c..e57b6f9 100644 (file)
@@ -164,7 +164,7 @@ static int ahci_seattle_probe(struct platform_device *pdev)
        int rc;
        struct ahci_host_priv *hpriv;
 
-       hpriv = ahci_platform_get_resources(pdev);
+       hpriv = ahci_platform_get_resources(pdev, 0);
        if (IS_ERR(hpriv))
                return PTR_ERR(hpriv);
 
index bc345f2..21c5c44 100644 (file)
@@ -156,7 +156,7 @@ static int st_ahci_probe(struct platform_device *pdev)
        if (!drv_data)
                return -ENOMEM;
 
-       hpriv = ahci_platform_get_resources(pdev);
+       hpriv = ahci_platform_get_resources(pdev, 0);
        if (IS_ERR(hpriv))
                return PTR_ERR(hpriv);
        hpriv->plat_data = drv_data;
index b264374..631610b 100644 (file)
@@ -181,7 +181,7 @@ static int ahci_sunxi_probe(struct platform_device *pdev)
        struct ahci_host_priv *hpriv;
        int rc;
 
-       hpriv = ahci_platform_get_resources(pdev);
+       hpriv = ahci_platform_get_resources(pdev, 0);
        if (IS_ERR(hpriv))
                return PTR_ERR(hpriv);
 
index 64d8484..004f260 100644 (file)
@@ -494,7 +494,7 @@ static int tegra_ahci_probe(struct platform_device *pdev)
        int ret;
        unsigned int i;
 
-       hpriv = ahci_platform_get_resources(pdev);
+       hpriv = ahci_platform_get_resources(pdev, 0);
        if (IS_ERR(hpriv))
                return PTR_ERR(hpriv);
 
index ad58da7..7e157e1 100644 (file)
@@ -759,7 +759,7 @@ static int xgene_ahci_probe(struct platform_device *pdev)
                                              &xgene_ahci_v2_port_info };
        int rc;
 
-       hpriv = ahci_platform_get_resources(pdev);
+       hpriv = ahci_platform_get_resources(pdev, 0);
        if (IS_ERR(hpriv))
                return PTR_ERR(hpriv);
 
index 09620c2..b5f57c6 100644 (file)
@@ -801,6 +801,8 @@ static int ahci_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,
                        cmd |= PORT_CMD_ALPE;
                        if (policy == ATA_LPM_MIN_POWER)
                                cmd |= PORT_CMD_ASP;
+                       else if (policy == ATA_LPM_MIN_POWER_WITH_PARTIAL)
+                               cmd &= ~PORT_CMD_ASP;
 
                        /* write out new cmd value */
                        writel(cmd, port_mmio + PORT_CMD);
@@ -811,7 +813,8 @@ static int ahci_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,
        if ((hpriv->cap2 & HOST_CAP2_SDS) &&
            (hpriv->cap2 & HOST_CAP2_SADM) &&
            (link->device->flags & ATA_DFLAG_DEVSLP)) {
-               if (policy == ATA_LPM_MIN_POWER)
+               if (policy == ATA_LPM_MIN_POWER ||
+                   policy == ATA_LPM_MIN_POWER_WITH_PARTIAL)
                        ahci_set_aggressive_devslp(ap, true);
                else
                        ahci_set_aggressive_devslp(ap, false);
@@ -2107,7 +2110,7 @@ static void ahci_set_aggressive_devslp(struct ata_port *ap, bool sleep)
        struct ahci_host_priv *hpriv = ap->host->private_data;
        void __iomem *port_mmio = ahci_port_base(ap);
        struct ata_device *dev = ap->link.device;
-       u32 devslp, dm, dito, mdat, deto;
+       u32 devslp, dm, dito, mdat, deto, dito_conf;
        int rc;
        unsigned int err_mask;
 
@@ -2131,8 +2134,15 @@ static void ahci_set_aggressive_devslp(struct ata_port *ap, bool sleep)
                return;
        }
 
-       /* device sleep was already enabled */
-       if (devslp & PORT_DEVSLP_ADSE)
+       dm = (devslp & PORT_DEVSLP_DM_MASK) >> PORT_DEVSLP_DM_OFFSET;
+       dito = devslp_idle_timeout / (dm + 1);
+       if (dito > 0x3ff)
+               dito = 0x3ff;
+
+       dito_conf = (devslp >> PORT_DEVSLP_DITO_OFFSET) & 0x3FF;
+
+       /* device sleep was already enabled and same dito */
+       if ((devslp & PORT_DEVSLP_ADSE) && (dito_conf == dito))
                return;
 
        /* set DITO, MDAT, DETO and enable DevSlp, need to stop engine first */
@@ -2140,11 +2150,6 @@ static void ahci_set_aggressive_devslp(struct ata_port *ap, bool sleep)
        if (rc)
                return;
 
-       dm = (devslp & PORT_DEVSLP_DM_MASK) >> PORT_DEVSLP_DM_OFFSET;
-       dito = devslp_idle_timeout / (dm + 1);
-       if (dito > 0x3ff)
-               dito = 0x3ff;
-
        /* Use the nominal value 10 ms if the read MDAT is zero,
         * the nominal value of DETO is 20 ms.
         */
@@ -2162,6 +2167,8 @@ static void ahci_set_aggressive_devslp(struct ata_port *ap, bool sleep)
                deto = 20;
        }
 
+       /* Make dito, mdat, deto bits to 0s */
+       devslp &= ~GENMASK_ULL(24, 2);
        devslp |= ((dito << PORT_DEVSLP_DITO_OFFSET) |
                   (mdat << PORT_DEVSLP_MDAT_OFFSET) |
                   (deto << PORT_DEVSLP_DETO_OFFSET) |
@@ -2439,6 +2446,8 @@ static void ahci_port_stop(struct ata_port *ap)
         * re-enabling INTx.
         */
        writel(1 << ap->port_no, host_mmio + HOST_IRQ_STAT);
+
+       ahci_rpm_put_port(ap);
 }
 
 void ahci_print_info(struct ata_host *host, const char *scc_s)
index 30cc8f1..c92c10d 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/phy/phy.h>
 #include <linux/pm_runtime.h>
 #include <linux/of_platform.h>
+#include <linux/reset.h>
 #include "ahci.h"
 
 static void ahci_host_stop(struct ata_host *host);
@@ -195,7 +196,8 @@ EXPORT_SYMBOL_GPL(ahci_platform_disable_regulators);
  * following order:
  * 1) Regulator
  * 2) Clocks (through ahci_platform_enable_clks)
- * 3) Phys
+ * 3) Resets
+ * 4) Phys
  *
  * If resource enabling fails at any point the previous enabled resources
  * are disabled in reverse order.
@@ -215,12 +217,19 @@ int ahci_platform_enable_resources(struct ahci_host_priv *hpriv)
        if (rc)
                goto disable_regulator;
 
-       rc = ahci_platform_enable_phys(hpriv);
+       rc = reset_control_deassert(hpriv->rsts);
        if (rc)
                goto disable_clks;
 
+       rc = ahci_platform_enable_phys(hpriv);
+       if (rc)
+               goto disable_resets;
+
        return 0;
 
+disable_resets:
+       reset_control_assert(hpriv->rsts);
+
 disable_clks:
        ahci_platform_disable_clks(hpriv);
 
@@ -238,13 +247,16 @@ EXPORT_SYMBOL_GPL(ahci_platform_enable_resources);
  * This function disables all ahci_platform managed resources in the
  * following order:
  * 1) Phys
- * 2) Clocks (through ahci_platform_disable_clks)
- * 3) Regulator
+ * 2) Resets
+ * 3) Clocks (through ahci_platform_disable_clks)
+ * 4) Regulator
  */
 void ahci_platform_disable_resources(struct ahci_host_priv *hpriv)
 {
        ahci_platform_disable_phys(hpriv);
 
+       reset_control_assert(hpriv->rsts);
+
        ahci_platform_disable_clks(hpriv);
 
        ahci_platform_disable_regulators(hpriv);
@@ -332,6 +344,7 @@ static int ahci_platform_get_regulator(struct ahci_host_priv *hpriv, u32 port,
 /**
  * ahci_platform_get_resources - Get platform resources
  * @pdev: platform device to get resources for
+ * @flags: bitmap representing the resource to get
  *
  * This function allocates an ahci_host_priv struct, and gets the following
  * resources, storing a reference to them inside the returned struct:
@@ -340,18 +353,20 @@ static int ahci_platform_get_regulator(struct ahci_host_priv *hpriv, u32 port,
  * 2) regulator for controlling the targets power (optional)
  * 3) 0 - AHCI_MAX_CLKS clocks, as specified in the devs devicetree node,
  *    or for non devicetree enabled platforms a single clock
- * 4) phys (optional)
+ * 4) resets, if flags has AHCI_PLATFORM_GET_RESETS (optional)
+ * 5) phys (optional)
  *
  * RETURNS:
  * The allocated ahci_host_priv on success, otherwise an ERR_PTR value
  */
-struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev)
+struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev,
+                                                  unsigned int flags)
 {
        struct device *dev = &pdev->dev;
        struct ahci_host_priv *hpriv;
        struct clk *clk;
        struct device_node *child;
-       int i, sz, enabled_ports = 0, rc = -ENOMEM, child_nodes;
+       int i, enabled_ports = 0, rc = -ENOMEM, child_nodes;
        u32 mask_port_map = 0;
 
        if (!devres_open_group(dev, NULL, GFP_KERNEL))
@@ -393,6 +408,14 @@ struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev)
                hpriv->clks[i] = clk;
        }
 
+       if (flags & AHCI_PLATFORM_GET_RESETS) {
+               hpriv->rsts = devm_reset_control_array_get_optional_shared(dev);
+               if (IS_ERR(hpriv->rsts)) {
+                       rc = PTR_ERR(hpriv->rsts);
+                       goto err_out;
+               }
+       }
+
        hpriv->nports = child_nodes = of_get_child_count(dev->of_node);
 
        /*
@@ -403,14 +426,16 @@ struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev)
        if (!child_nodes)
                hpriv->nports = 1;
 
-       sz = hpriv->nports * sizeof(*hpriv->phys);
-       hpriv->phys = devm_kzalloc(dev, sz, GFP_KERNEL);
+       hpriv->phys = devm_kcalloc(dev, hpriv->nports, sizeof(*hpriv->phys), GFP_KERNEL);
        if (!hpriv->phys) {
                rc = -ENOMEM;
                goto err_out;
        }
-       sz = hpriv->nports * sizeof(*hpriv->target_pwrs);
-       hpriv->target_pwrs = kzalloc(sz, GFP_KERNEL);
+       /*
+        * We cannot use devm_ here, since ahci_platform_put_resources() uses
+        * target_pwrs after devm_ have freed memory
+        */
+       hpriv->target_pwrs = kcalloc(hpriv->nports, sizeof(*hpriv->target_pwrs), GFP_KERNEL);
        if (!hpriv->target_pwrs) {
                rc = -ENOMEM;
                goto err_out;
@@ -605,7 +630,7 @@ static void ahci_host_stop(struct ata_host *host)
 
 /**
  * ahci_platform_shutdown - Disable interrupts and stop DMA for host ports
- * @dev: platform device pointer for the host
+ * @pdev: platform device pointer for the host
  *
  * This function is called during system shutdown and performs the minimal
  * deconfiguration required to ensure that an ahci_platform host cannot
index 984b376..172e328 100644 (file)
@@ -3970,6 +3970,7 @@ int sata_link_scr_lpm(struct ata_link *link, enum ata_lpm_policy policy,
                scontrol |= (0x6 << 8);
                break;
        case ATA_LPM_MED_POWER_WITH_DIPM:
+       case ATA_LPM_MIN_POWER_WITH_PARTIAL:
        case ATA_LPM_MIN_POWER:
                if (ata_link_nr_enabled(link) > 0)
                        /* no restrictions on LPM transitions */
@@ -5066,7 +5067,7 @@ static int ata_sg_setup(struct ata_queued_cmd *qc)
        if (n_elem < 1)
                return -1;
 
-       DPRINTK("%d sg elements mapped\n", n_elem);
+       VPRINTK("%d sg elements mapped\n", n_elem);
        qc->orig_n_elem = qc->n_elem;
        qc->n_elem = n_elem;
        qc->flags |= ATA_QCFLAG_DMAMAP;
index 8e27096..1984fc7 100644 (file)
@@ -110,6 +110,7 @@ static const char *ata_lpm_policy_names[] = {
        [ATA_LPM_MAX_POWER]             = "max_performance",
        [ATA_LPM_MED_POWER]             = "medium_power",
        [ATA_LPM_MED_POWER_WITH_DIPM]   = "med_power_with_dipm",
+       [ATA_LPM_MIN_POWER_WITH_PARTIAL] = "min_power_with_partial",
        [ATA_LPM_MIN_POWER]             = "min_power",
 };
 
@@ -4288,10 +4289,10 @@ static inline ata_xlat_func_t ata_get_xlat_func(struct ata_device *dev, u8 cmd)
 static inline void ata_scsi_dump_cdb(struct ata_port *ap,
                                     struct scsi_cmnd *cmd)
 {
-#ifdef ATA_DEBUG
+#ifdef ATA_VERBOSE_DEBUG
        struct scsi_device *scsidev = cmd->device;
 
-       DPRINTK("CDB (%u:%d,%d,%lld) %9ph\n",
+       VPRINTK("CDB (%u:%d,%d,%lld) %9ph\n",
                ap->print_id,
                scsidev->channel, scsidev->id, scsidev->lun,
                cmd->cmnd);
index cc2f2e3..c5ea0fc 100644 (file)
@@ -658,36 +658,6 @@ unsigned int ata_sff_data_xfer32(struct ata_queued_cmd *qc, unsigned char *buf,
 EXPORT_SYMBOL_GPL(ata_sff_data_xfer32);
 
 /**
- *     ata_sff_data_xfer_noirq - Transfer data by PIO
- *     @qc: queued command
- *     @buf: data buffer
- *     @buflen: buffer length
- *     @rw: read/write
- *
- *     Transfer data from/to the device data register by PIO. Do the
- *     transfer with interrupts disabled.
- *
- *     LOCKING:
- *     Inherited from caller.
- *
- *     RETURNS:
- *     Bytes consumed.
- */
-unsigned int ata_sff_data_xfer_noirq(struct ata_queued_cmd *qc, unsigned char *buf,
-                                    unsigned int buflen, int rw)
-{
-       unsigned long flags;
-       unsigned int consumed;
-
-       local_irq_save(flags);
-       consumed = ata_sff_data_xfer32(qc, buf, buflen, rw);
-       local_irq_restore(flags);
-
-       return consumed;
-}
-EXPORT_SYMBOL_GPL(ata_sff_data_xfer_noirq);
-
-/**
  *     ata_pio_sector - Transfer a sector of data.
  *     @qc: Command on going
  *
index c47caa8..e3532ed 100644 (file)
@@ -178,7 +178,7 @@ static struct scsi_host_template cmd640_sht = {
 static struct ata_port_operations cmd640_port_ops = {
        .inherits       = &ata_sff_port_ops,
        /* In theory xfer_noirq is not needed once we kill the prefetcher */
-       .sff_data_xfer  = ata_sff_data_xfer_noirq,
+       .sff_data_xfer  = ata_sff_data_xfer32,
        .sff_irq_check  = cmd640_sff_irq_check,
        .qc_issue       = cmd640_qc_issue,
        .cable_detect   = ata_cable_40wire,
index 188f2f2..c272f2c 100644 (file)
@@ -324,7 +324,7 @@ static struct ata_port_operations pata_icside_port_ops = {
        .inherits               = &ata_bmdma_port_ops,
        /* no need to build any PRD tables for DMA */
        .qc_prep                = ata_noop_qc_prep,
-       .sff_data_xfer          = ata_sff_data_xfer_noirq,
+       .sff_data_xfer          = ata_sff_data_xfer32,
        .bmdma_setup            = pata_icside_bmdma_setup,
        .bmdma_start            = pata_icside_bmdma_start,
        .bmdma_stop             = pata_icside_bmdma_stop,
index 6f05340..2e53872 100644 (file)
@@ -103,7 +103,7 @@ static struct scsi_host_template pata_imx_sht = {
 
 static struct ata_port_operations pata_imx_port_ops = {
        .inherits               = &ata_sff_port_ops,
-       .sff_data_xfer          = ata_sff_data_xfer_noirq,
+       .sff_data_xfer          = ata_sff_data_xfer32,
        .cable_detect           = ata_cable_unknown,
        .set_piomode            = pata_imx_set_piomode,
 };
index 53828b6..8ea4b84 100644 (file)
@@ -246,12 +246,12 @@ static const struct ata_port_operations legacy_base_port_ops = {
 
 static struct ata_port_operations simple_port_ops = {
        .inherits       = &legacy_base_port_ops,
-       .sff_data_xfer  = ata_sff_data_xfer_noirq,
+       .sff_data_xfer  = ata_sff_data_xfer32,
 };
 
 static struct ata_port_operations legacy_port_ops = {
        .inherits       = &legacy_base_port_ops,
-       .sff_data_xfer  = ata_sff_data_xfer_noirq,
+       .sff_data_xfer  = ata_sff_data_xfer32,
        .set_mode       = legacy_set_mode,
 };
 
@@ -341,7 +341,7 @@ static unsigned int pdc_data_xfer_vlb(struct ata_queued_cmd *qc,
                }
                local_irq_restore(flags);
        } else
-               buflen = ata_sff_data_xfer_noirq(qc, buf, buflen, rw);
+               buflen = ata_sff_data_xfer32(qc, buf, buflen, rw);
 
        return buflen;
 }
index 8c0d7d7..d071ab6 100644 (file)
@@ -44,7 +44,7 @@ static struct scsi_host_template palmld_sht = {
 
 static struct ata_port_operations palmld_port_ops = {
        .inherits               = &ata_sff_port_ops,
-       .sff_data_xfer          = ata_sff_data_xfer_noirq,
+       .sff_data_xfer          = ata_sff_data_xfer32,
        .cable_detect           = ata_cable_40wire,
 };
 
index a541eac..9b0e6c7 100644 (file)
@@ -151,7 +151,7 @@ static struct scsi_host_template pcmcia_sht = {
 
 static struct ata_port_operations pcmcia_port_ops = {
        .inherits       = &ata_sff_port_ops,
-       .sff_data_xfer  = ata_sff_data_xfer_noirq,
+       .sff_data_xfer  = ata_sff_data_xfer32,
        .cable_detect   = ata_cable_40wire,
        .set_mode       = pcmcia_set_mode,
 };
index c503ded..d6f8f54 100644 (file)
@@ -49,7 +49,7 @@ static struct scsi_host_template pata_platform_sht = {
 
 static struct ata_port_operations pata_platform_port_ops = {
        .inherits               = &ata_sff_port_ops,
-       .sff_data_xfer          = ata_sff_data_xfer_noirq,
+       .sff_data_xfer          = ata_sff_data_xfer32,
        .cable_detect           = ata_cable_unknown,
        .set_mode               = pata_platform_set_mode,
 };
index 1ca6bca..fd19f1c 100644 (file)
@@ -471,7 +471,7 @@ static struct ata_port_operations via_port_ops = {
 
 static struct ata_port_operations via_port_ops_noirq = {
        .inherits       = &via_port_ops,
-       .sff_data_xfer  = ata_sff_data_xfer_noirq,
+       .sff_data_xfer  = ata_sff_data_xfer32,
 };
 
 /**
index 6456e07..10ecb23 100644 (file)
@@ -17,7 +17,7 @@
 #include <linux/libata.h>
 #include <linux/of_device.h>
 #include <linux/platform_device.h>
-#include <linux/clk.h>
+#include <linux/pm_runtime.h>
 #include <linux/err.h>
 
 #define DRV_NAME "sata_rcar"
 #define SATAINTMASK_ERRMSK             BIT(2)
 #define SATAINTMASK_ERRCRTMSK          BIT(1)
 #define SATAINTMASK_ATAMSK             BIT(0)
+#define SATAINTMASK_ALL_GEN1           0x7ff
+#define SATAINTMASK_ALL_GEN2           0xfff
 
 #define SATA_RCAR_INT_MASK             (SATAINTMASK_SERRMSK | \
                                         SATAINTMASK_ATAMSK)
@@ -152,7 +154,7 @@ enum sata_rcar_type {
 
 struct sata_rcar_priv {
        void __iomem *base;
-       struct clk *clk;
+       u32 sataint_mask;
        enum sata_rcar_type type;
 };
 
@@ -226,7 +228,7 @@ static void sata_rcar_freeze(struct ata_port *ap)
        struct sata_rcar_priv *priv = ap->host->private_data;
 
        /* mask */
-       iowrite32(0x7ff, priv->base + SATAINTMASK_REG);
+       iowrite32(priv->sataint_mask, priv->base + SATAINTMASK_REG);
 
        ata_sff_freeze(ap);
 }
@@ -242,7 +244,7 @@ static void sata_rcar_thaw(struct ata_port *ap)
        ata_sff_thaw(ap);
 
        /* unmask */
-       iowrite32(0x7ff & ~SATA_RCAR_INT_MASK, base + SATAINTMASK_REG);
+       iowrite32(priv->sataint_mask & ~SATA_RCAR_INT_MASK, base + SATAINTMASK_REG);
 }
 
 static void sata_rcar_ioread16_rep(void __iomem *reg, void *buffer, int count)
@@ -736,7 +738,7 @@ static irqreturn_t sata_rcar_interrupt(int irq, void *dev_instance)
        if (!sataintstat)
                goto done;
        /* ack */
-       iowrite32(~sataintstat & 0x7ff, base + SATAINTSTAT_REG);
+       iowrite32(~sataintstat & priv->sataint_mask, base + SATAINTSTAT_REG);
 
        ap = host->ports[0];
 
@@ -809,7 +811,7 @@ static void sata_rcar_init_module(struct sata_rcar_priv *priv)
 
        /* ack and mask */
        iowrite32(0, base + SATAINTSTAT_REG);
-       iowrite32(0x7ff, base + SATAINTMASK_REG);
+       iowrite32(priv->sataint_mask, base + SATAINTMASK_REG);
 
        /* enable interrupts */
        iowrite32(ATAPI_INT_ENABLE_SATAINT, base + ATAPI_INT_ENABLE_REG);
@@ -819,16 +821,20 @@ static void sata_rcar_init_controller(struct ata_host *host)
 {
        struct sata_rcar_priv *priv = host->private_data;
 
+       priv->sataint_mask = SATAINTMASK_ALL_GEN2;
+
        /* reset and setup phy */
        switch (priv->type) {
        case RCAR_GEN1_SATA:
+               priv->sataint_mask = SATAINTMASK_ALL_GEN1;
                sata_rcar_gen1_phy_init(priv);
                break;
        case RCAR_GEN2_SATA:
-       case RCAR_GEN3_SATA:
        case RCAR_R8A7790_ES1_SATA:
                sata_rcar_gen2_phy_init(priv);
                break;
+       case RCAR_GEN3_SATA:
+               break;
        default:
                dev_warn(host->dev, "SATA phy is not initialized\n");
                break;
@@ -881,6 +887,7 @@ MODULE_DEVICE_TABLE(of, sata_rcar_match);
 
 static int sata_rcar_probe(struct platform_device *pdev)
 {
+       struct device *dev = &pdev->dev;
        struct ata_host *host;
        struct sata_rcar_priv *priv;
        struct resource *mem;
@@ -891,36 +898,31 @@ static int sata_rcar_probe(struct platform_device *pdev)
        if (irq <= 0)
                return -EINVAL;
 
-       priv = devm_kzalloc(&pdev->dev, sizeof(struct sata_rcar_priv),
-                          GFP_KERNEL);
+       priv = devm_kzalloc(dev, sizeof(struct sata_rcar_priv), GFP_KERNEL);
        if (!priv)
                return -ENOMEM;
 
-       priv->type = (enum sata_rcar_type)of_device_get_match_data(&pdev->dev);
-       priv->clk = devm_clk_get(&pdev->dev, NULL);
-       if (IS_ERR(priv->clk)) {
-               dev_err(&pdev->dev, "failed to get access to sata clock\n");
-               return PTR_ERR(priv->clk);
-       }
+       priv->type = (enum sata_rcar_type)of_device_get_match_data(dev);
 
-       ret = clk_prepare_enable(priv->clk);
-       if (ret)
-               return ret;
+       pm_runtime_enable(dev);
+       ret = pm_runtime_get_sync(dev);
+       if (ret < 0)
+               goto err_pm_disable;
 
-       host = ata_host_alloc(&pdev->dev, 1);
+       host = ata_host_alloc(dev, 1);
        if (!host) {
-               dev_err(&pdev->dev, "ata_host_alloc failed\n");
+               dev_err(dev, "ata_host_alloc failed\n");
                ret = -ENOMEM;
-               goto cleanup;
+               goto err_pm_put;
        }
 
        host->private_data = priv;
 
        mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       priv->base = devm_ioremap_resource(&pdev->dev, mem);
+       priv->base = devm_ioremap_resource(dev, mem);
        if (IS_ERR(priv->base)) {
                ret = PTR_ERR(priv->base);
-               goto cleanup;
+               goto err_pm_put;
        }
 
        /* setup port */
@@ -934,9 +936,10 @@ static int sata_rcar_probe(struct platform_device *pdev)
        if (!ret)
                return 0;
 
-cleanup:
-       clk_disable_unprepare(priv->clk);
-
+err_pm_put:
+       pm_runtime_put(dev);
+err_pm_disable:
+       pm_runtime_disable(dev);
        return ret;
 }
 
@@ -952,9 +955,10 @@ static int sata_rcar_remove(struct platform_device *pdev)
        iowrite32(0, base + ATAPI_INT_ENABLE_REG);
        /* ack and mask */
        iowrite32(0, base + SATAINTSTAT_REG);
-       iowrite32(0x7ff, base + SATAINTMASK_REG);
+       iowrite32(priv->sataint_mask, base + SATAINTMASK_REG);
 
-       clk_disable_unprepare(priv->clk);
+       pm_runtime_put(&pdev->dev);
+       pm_runtime_disable(&pdev->dev);
 
        return 0;
 }
@@ -972,9 +976,9 @@ static int sata_rcar_suspend(struct device *dev)
                /* disable interrupts */
                iowrite32(0, base + ATAPI_INT_ENABLE_REG);
                /* mask */
-               iowrite32(0x7ff, base + SATAINTMASK_REG);
+               iowrite32(priv->sataint_mask, base + SATAINTMASK_REG);
 
-               clk_disable_unprepare(priv->clk);
+               pm_runtime_put(dev);
        }
 
        return ret;
@@ -987,17 +991,16 @@ static int sata_rcar_resume(struct device *dev)
        void __iomem *base = priv->base;
        int ret;
 
-       ret = clk_prepare_enable(priv->clk);
-       if (ret)
+       ret = pm_runtime_get_sync(dev);
+       if (ret < 0)
                return ret;
 
        if (priv->type == RCAR_GEN3_SATA) {
-               sata_rcar_gen2_phy_init(priv);
                sata_rcar_init_module(priv);
        } else {
                /* ack and mask */
                iowrite32(0, base + SATAINTSTAT_REG);
-               iowrite32(0x7ff, base + SATAINTMASK_REG);
+               iowrite32(priv->sataint_mask, base + SATAINTMASK_REG);
 
                /* enable interrupts */
                iowrite32(ATAPI_INT_ENABLE_SATAINT,
@@ -1012,11 +1015,10 @@ static int sata_rcar_resume(struct device *dev)
 static int sata_rcar_restore(struct device *dev)
 {
        struct ata_host *host = dev_get_drvdata(dev);
-       struct sata_rcar_priv *priv = host->private_data;
        int ret;
 
-       ret = clk_prepare_enable(priv->clk);
-       if (ret)
+       ret = pm_runtime_get_sync(dev);
+       if (ret < 0)
                return ret;
 
        sata_rcar_setup_port(host);
index f99e5c8..581312a 100644 (file)
@@ -2428,16 +2428,20 @@ static bool DAC960_V2_ReportDeviceConfiguration(DAC960_Controller_T
     {
       DAC960_V2_LogicalDeviceInfo_T *LogicalDeviceInfo =
        Controller->V2.LogicalDeviceInformation[LogicalDriveNumber];
-      unsigned char *ReadCacheStatus[] = { "Read Cache Disabled",
-                                          "Read Cache Enabled",
-                                          "Read Ahead Enabled",
-                                          "Intelligent Read Ahead Enabled",
-                                          "-", "-", "-", "-" };
-      unsigned char *WriteCacheStatus[] = { "Write Cache Disabled",
-                                           "Logical Device Read Only",
-                                           "Write Cache Enabled",
-                                           "Intelligent Write Cache Enabled",
-                                           "-", "-", "-", "-" };
+      static const unsigned char *ReadCacheStatus[] = {
+        "Read Cache Disabled",
+        "Read Cache Enabled",
+        "Read Ahead Enabled",
+        "Intelligent Read Ahead Enabled",
+        "-", "-", "-", "-"
+      };
+      static const unsigned char *WriteCacheStatus[] = {
+        "Write Cache Disabled",
+        "Logical Device Read Only",
+        "Write Cache Enabled",
+        "Intelligent Write Cache Enabled",
+        "-", "-", "-", "-"
+      };
       unsigned char *GeometryTranslation;
       if (LogicalDeviceInfo == NULL) continue;
       switch (LogicalDeviceInfo->DriveGeometry)
@@ -4339,14 +4343,16 @@ static void DAC960_V1_ProcessCompletedCommand(DAC960_Command_T *Command)
 static void DAC960_V2_ReadWriteError(DAC960_Command_T *Command)
 {
   DAC960_Controller_T *Controller = Command->Controller;
-  unsigned char *SenseErrors[] = { "NO SENSE", "RECOVERED ERROR",
-                                  "NOT READY", "MEDIUM ERROR",
-                                  "HARDWARE ERROR", "ILLEGAL REQUEST",
-                                  "UNIT ATTENTION", "DATA PROTECT",
-                                  "BLANK CHECK", "VENDOR-SPECIFIC",
-                                  "COPY ABORTED", "ABORTED COMMAND",
-                                  "EQUAL", "VOLUME OVERFLOW",
-                                  "MISCOMPARE", "RESERVED" };
+  static const unsigned char *SenseErrors[] = {
+    "NO SENSE", "RECOVERED ERROR",
+    "NOT READY", "MEDIUM ERROR",
+    "HARDWARE ERROR", "ILLEGAL REQUEST",
+    "UNIT ATTENTION", "DATA PROTECT",
+    "BLANK CHECK", "VENDOR-SPECIFIC",
+    "COPY ABORTED", "ABORTED COMMAND",
+    "EQUAL", "VOLUME OVERFLOW",
+    "MISCOMPARE", "RESERVED"
+  };
   unsigned char *CommandName = "UNKNOWN";
   switch (Command->CommandType)
     {
index db253cd..d0666f5 100644 (file)
@@ -118,7 +118,6 @@ static struct dentry *dfs_device_status;
 
 static u32 cpu_use[NR_CPUS];
 
-static DEFINE_SPINLOCK(rssd_index_lock);
 static DEFINE_IDA(rssd_index_ida);
 
 static int mtip_block_initialize(struct driver_data *dd);
@@ -3767,20 +3766,10 @@ static int mtip_block_initialize(struct driver_data *dd)
                goto alloc_disk_error;
        }
 
-       /* Generate the disk name, implemented same as in sd.c */
-       do {
-               if (!ida_pre_get(&rssd_index_ida, GFP_KERNEL)) {
-                       rv = -ENOMEM;
-                       goto ida_get_error;
-               }
-
-               spin_lock(&rssd_index_lock);
-               rv = ida_get_new(&rssd_index_ida, &index);
-               spin_unlock(&rssd_index_lock);
-       } while (rv == -EAGAIN);
-
-       if (rv)
+       rv = ida_alloc(&rssd_index_ida, GFP_KERNEL);
+       if (rv < 0)
                goto ida_get_error;
+       index = rv;
 
        rv = rssd_disk_name_format("rssd",
                                index,
@@ -3922,9 +3911,7 @@ block_queue_alloc_init_error:
 block_queue_alloc_tag_error:
        mtip_hw_debugfs_exit(dd);
 disk_index_error:
-       spin_lock(&rssd_index_lock);
-       ida_remove(&rssd_index_ida, index);
-       spin_unlock(&rssd_index_lock);
+       ida_free(&rssd_index_ida, index);
 
 ida_get_error:
        put_disk(dd->disk);
@@ -4012,9 +3999,7 @@ static int mtip_block_remove(struct driver_data *dd)
        }
        dd->disk  = NULL;
 
-       spin_lock(&rssd_index_lock);
-       ida_remove(&rssd_index_ida, dd->index);
-       spin_unlock(&rssd_index_lock);
+       ida_free(&rssd_index_ida, dd->index);
 
        /* De-initialize the protocol layer. */
        mtip_hw_exit(dd);
@@ -4054,9 +4039,7 @@ static int mtip_block_shutdown(struct driver_data *dd)
                dd->queue = NULL;
        }
 
-       spin_lock(&rssd_index_lock);
-       ida_remove(&rssd_index_ida, dd->index);
-       spin_unlock(&rssd_index_lock);
+       ida_free(&rssd_index_ida, dd->index);
        return 0;
 }
 
index e285413..6f1d25c 100644 (file)
@@ -2740,6 +2740,7 @@ static int pkt_setup_dev(dev_t dev, dev_t* pkt_dev)
        pd->write_congestion_on  = write_congestion_on;
        pd->write_congestion_off = write_congestion_off;
 
+       ret = -ENOMEM;
        disk = alloc_disk(1);
        if (!disk)
                goto out_mem;
index d81c653..7915f3b 100644 (file)
@@ -181,6 +181,7 @@ struct rbd_image_header {
 struct rbd_spec {
        u64             pool_id;
        const char      *pool_name;
+       const char      *pool_ns;       /* NULL if default, never "" */
 
        const char      *image_id;
        const char      *image_name;
@@ -735,6 +736,7 @@ enum {
        Opt_lock_timeout,
        Opt_last_int,
        /* int args above */
+       Opt_pool_ns,
        Opt_last_string,
        /* string args above */
        Opt_read_only,
@@ -749,6 +751,7 @@ static match_table_t rbd_opts_tokens = {
        {Opt_queue_depth, "queue_depth=%d"},
        {Opt_lock_timeout, "lock_timeout=%d"},
        /* int args above */
+       {Opt_pool_ns, "_pool_ns=%s"},
        /* string args above */
        {Opt_read_only, "read_only"},
        {Opt_read_only, "ro"},          /* Alternate spelling */
@@ -776,9 +779,14 @@ struct rbd_options {
 #define RBD_EXCLUSIVE_DEFAULT  false
 #define RBD_TRIM_DEFAULT       true
 
+struct parse_rbd_opts_ctx {
+       struct rbd_spec         *spec;
+       struct rbd_options      *opts;
+};
+
 static int parse_rbd_opts_token(char *c, void *private)
 {
-       struct rbd_options *rbd_opts = private;
+       struct parse_rbd_opts_ctx *pctx = private;
        substring_t argstr[MAX_OPT_ARGS];
        int token, intval, ret;
 
@@ -786,7 +794,7 @@ static int parse_rbd_opts_token(char *c, void *private)
        if (token < Opt_last_int) {
                ret = match_int(&argstr[0], &intval);
                if (ret < 0) {
-                       pr_err("bad mount option arg (not int) at '%s'\n", c);
+                       pr_err("bad option arg (not int) at '%s'\n", c);
                        return ret;
                }
                dout("got int token %d val %d\n", token, intval);
@@ -802,7 +810,7 @@ static int parse_rbd_opts_token(char *c, void *private)
                        pr_err("queue_depth out of range\n");
                        return -EINVAL;
                }
-               rbd_opts->queue_depth = intval;
+               pctx->opts->queue_depth = intval;
                break;
        case Opt_lock_timeout:
                /* 0 is "wait forever" (i.e. infinite timeout) */
@@ -810,22 +818,28 @@ static int parse_rbd_opts_token(char *c, void *private)
                        pr_err("lock_timeout out of range\n");
                        return -EINVAL;
                }
-               rbd_opts->lock_timeout = msecs_to_jiffies(intval * 1000);
+               pctx->opts->lock_timeout = msecs_to_jiffies(intval * 1000);
+               break;
+       case Opt_pool_ns:
+               kfree(pctx->spec->pool_ns);
+               pctx->spec->pool_ns = match_strdup(argstr);
+               if (!pctx->spec->pool_ns)
+                       return -ENOMEM;
                break;
        case Opt_read_only:
-               rbd_opts->read_only = true;
+               pctx->opts->read_only = true;
                break;
        case Opt_read_write:
-               rbd_opts->read_only = false;
+               pctx->opts->read_only = false;
                break;
        case Opt_lock_on_read:
-               rbd_opts->lock_on_read = true;
+               pctx->opts->lock_on_read = true;
                break;
        case Opt_exclusive:
-               rbd_opts->exclusive = true;
+               pctx->opts->exclusive = true;
                break;
        case Opt_notrim:
-               rbd_opts->trim = false;
+               pctx->opts->trim = false;
                break;
        default:
                /* libceph prints "bad option" msg */
@@ -1452,7 +1466,7 @@ static void rbd_osd_req_format_write(struct rbd_obj_request *obj_request)
        struct ceph_osd_request *osd_req = obj_request->osd_req;
 
        osd_req->r_flags = CEPH_OSD_FLAG_WRITE;
-       ktime_get_real_ts(&osd_req->r_mtime);
+       ktime_get_real_ts64(&osd_req->r_mtime);
        osd_req->r_data_offset = obj_request->ex.oe_off;
 }
 
@@ -1475,7 +1489,13 @@ rbd_osd_req_create(struct rbd_obj_request *obj_req, unsigned int num_ops)
        req->r_callback = rbd_osd_req_callback;
        req->r_priv = obj_req;
 
+       /*
+        * Data objects may be stored in a separate pool, but always in
+        * the same namespace in that pool as the header in its pool.
+        */
+       ceph_oloc_copy(&req->r_base_oloc, &rbd_dev->header_oloc);
        req->r_base_oloc.pool = rbd_dev->layout.pool_id;
+
        if (ceph_oid_aprintf(&req->r_base_oid, GFP_NOIO, name_format,
                        rbd_dev->header.object_prefix, obj_req->ex.oe_objno))
                goto err_req;
@@ -4119,6 +4139,14 @@ static ssize_t rbd_pool_id_show(struct device *dev,
                        (unsigned long long) rbd_dev->spec->pool_id);
 }
 
+static ssize_t rbd_pool_ns_show(struct device *dev,
+                               struct device_attribute *attr, char *buf)
+{
+       struct rbd_device *rbd_dev = dev_to_rbd_dev(dev);
+
+       return sprintf(buf, "%s\n", rbd_dev->spec->pool_ns ?: "");
+}
+
 static ssize_t rbd_name_show(struct device *dev,
                             struct device_attribute *attr, char *buf)
 {
@@ -4217,6 +4245,7 @@ static DEVICE_ATTR(cluster_fsid, 0444, rbd_cluster_fsid_show, NULL);
 static DEVICE_ATTR(config_info, 0400, rbd_config_info_show, NULL);
 static DEVICE_ATTR(pool, 0444, rbd_pool_show, NULL);
 static DEVICE_ATTR(pool_id, 0444, rbd_pool_id_show, NULL);
+static DEVICE_ATTR(pool_ns, 0444, rbd_pool_ns_show, NULL);
 static DEVICE_ATTR(name, 0444, rbd_name_show, NULL);
 static DEVICE_ATTR(image_id, 0444, rbd_image_id_show, NULL);
 static DEVICE_ATTR(refresh, 0200, NULL, rbd_image_refresh);
@@ -4235,6 +4264,7 @@ static struct attribute *rbd_attrs[] = {
        &dev_attr_config_info.attr,
        &dev_attr_pool.attr,
        &dev_attr_pool_id.attr,
+       &dev_attr_pool_ns.attr,
        &dev_attr_name.attr,
        &dev_attr_image_id.attr,
        &dev_attr_current_snap.attr,
@@ -4295,6 +4325,7 @@ static void rbd_spec_free(struct kref *kref)
        struct rbd_spec *spec = container_of(kref, struct rbd_spec, kref);
 
        kfree(spec->pool_name);
+       kfree(spec->pool_ns);
        kfree(spec->image_id);
        kfree(spec->image_name);
        kfree(spec->snap_name);
@@ -4353,6 +4384,12 @@ static struct rbd_device *__rbd_dev_create(struct rbd_client *rbdc,
        rbd_dev->header.data_pool_id = CEPH_NOPOOL;
        ceph_oid_init(&rbd_dev->header_oid);
        rbd_dev->header_oloc.pool = spec->pool_id;
+       if (spec->pool_ns) {
+               WARN_ON(!*spec->pool_ns);
+               rbd_dev->header_oloc.pool_ns =
+                   ceph_find_or_create_string(spec->pool_ns,
+                                              strlen(spec->pool_ns));
+       }
 
        mutex_init(&rbd_dev->watch_mutex);
        rbd_dev->watch_state = RBD_WATCH_STATE_UNREGISTERED;
@@ -4633,6 +4670,17 @@ static int rbd_dev_v2_parent_info(struct rbd_device *rbd_dev)
                parent_spec->pool_id = pool_id;
                parent_spec->image_id = image_id;
                parent_spec->snap_id = snap_id;
+
+               /* TODO: support cloning across namespaces */
+               if (rbd_dev->spec->pool_ns) {
+                       parent_spec->pool_ns = kstrdup(rbd_dev->spec->pool_ns,
+                                                      GFP_KERNEL);
+                       if (!parent_spec->pool_ns) {
+                               ret = -ENOMEM;
+                               goto out_err;
+                       }
+               }
+
                rbd_dev->parent_spec = parent_spec;
                parent_spec = NULL;     /* rbd_dev now owns this */
        } else {
@@ -5146,8 +5194,7 @@ static int rbd_add_parse_args(const char *buf,
        const char *mon_addrs;
        char *snap_name;
        size_t mon_addrs_size;
-       struct rbd_spec *spec = NULL;
-       struct rbd_options *rbd_opts = NULL;
+       struct parse_rbd_opts_ctx pctx = { 0 };
        struct ceph_options *copts;
        int ret;
 
@@ -5171,22 +5218,22 @@ static int rbd_add_parse_args(const char *buf,
                goto out_err;
        }
 
-       spec = rbd_spec_alloc();
-       if (!spec)
+       pctx.spec = rbd_spec_alloc();
+       if (!pctx.spec)
                goto out_mem;
 
-       spec->pool_name = dup_token(&buf, NULL);
-       if (!spec->pool_name)
+       pctx.spec->pool_name = dup_token(&buf, NULL);
+       if (!pctx.spec->pool_name)
                goto out_mem;
-       if (!*spec->pool_name) {
+       if (!*pctx.spec->pool_name) {
                rbd_warn(NULL, "no pool name provided");
                goto out_err;
        }
 
-       spec->image_name = dup_token(&buf, NULL);
-       if (!spec->image_name)
+       pctx.spec->image_name = dup_token(&buf, NULL);
+       if (!pctx.spec->image_name)
                goto out_mem;
-       if (!*spec->image_name) {
+       if (!*pctx.spec->image_name) {
                rbd_warn(NULL, "no image name provided");
                goto out_err;
        }
@@ -5207,24 +5254,24 @@ static int rbd_add_parse_args(const char *buf,
        if (!snap_name)
                goto out_mem;
        *(snap_name + len) = '\0';
-       spec->snap_name = snap_name;
+       pctx.spec->snap_name = snap_name;
 
        /* Initialize all rbd options to the defaults */
 
-       rbd_opts = kzalloc(sizeof (*rbd_opts), GFP_KERNEL);
-       if (!rbd_opts)
+       pctx.opts = kzalloc(sizeof(*pctx.opts), GFP_KERNEL);
+       if (!pctx.opts)
                goto out_mem;
 
-       rbd_opts->read_only = RBD_READ_ONLY_DEFAULT;
-       rbd_opts->queue_depth = RBD_QUEUE_DEPTH_DEFAULT;
-       rbd_opts->lock_timeout = RBD_LOCK_TIMEOUT_DEFAULT;
-       rbd_opts->lock_on_read = RBD_LOCK_ON_READ_DEFAULT;
-       rbd_opts->exclusive = RBD_EXCLUSIVE_DEFAULT;
-       rbd_opts->trim = RBD_TRIM_DEFAULT;
+       pctx.opts->read_only = RBD_READ_ONLY_DEFAULT;
+       pctx.opts->queue_depth = RBD_QUEUE_DEPTH_DEFAULT;
+       pctx.opts->lock_timeout = RBD_LOCK_TIMEOUT_DEFAULT;
+       pctx.opts->lock_on_read = RBD_LOCK_ON_READ_DEFAULT;
+       pctx.opts->exclusive = RBD_EXCLUSIVE_DEFAULT;
+       pctx.opts->trim = RBD_TRIM_DEFAULT;
 
        copts = ceph_parse_options(options, mon_addrs,
-                                       mon_addrs + mon_addrs_size - 1,
-                                       parse_rbd_opts_token, rbd_opts);
+                                  mon_addrs + mon_addrs_size - 1,
+                                  parse_rbd_opts_token, &pctx);
        if (IS_ERR(copts)) {
                ret = PTR_ERR(copts);
                goto out_err;
@@ -5232,15 +5279,15 @@ static int rbd_add_parse_args(const char *buf,
        kfree(options);
 
        *ceph_opts = copts;
-       *opts = rbd_opts;
-       *rbd_spec = spec;
+       *opts = pctx.opts;
+       *rbd_spec = pctx.spec;
 
        return 0;
 out_mem:
        ret = -ENOMEM;
 out_err:
-       kfree(rbd_opts);
-       rbd_spec_put(spec);
+       kfree(pctx.opts);
+       rbd_spec_put(pctx.spec);
        kfree(options);
 
        return ret;
@@ -5586,8 +5633,10 @@ static int rbd_dev_image_probe(struct rbd_device *rbd_dev, int depth)
                ret = rbd_register_watch(rbd_dev);
                if (ret) {
                        if (ret == -ENOENT)
-                               pr_info("image %s/%s does not exist\n",
+                               pr_info("image %s/%s%s%s does not exist\n",
                                        rbd_dev->spec->pool_name,
+                                       rbd_dev->spec->pool_ns ?: "",
+                                       rbd_dev->spec->pool_ns ? "/" : "",
                                        rbd_dev->spec->image_name);
                        goto err_out_format;
                }
@@ -5609,8 +5658,10 @@ static int rbd_dev_image_probe(struct rbd_device *rbd_dev, int depth)
                ret = rbd_spec_fill_names(rbd_dev);
        if (ret) {
                if (ret == -ENOENT)
-                       pr_info("snap %s/%s@%s does not exist\n",
+                       pr_info("snap %s/%s%s%s@%s does not exist\n",
                                rbd_dev->spec->pool_name,
+                               rbd_dev->spec->pool_ns ?: "",
+                               rbd_dev->spec->pool_ns ? "/" : "",
                                rbd_dev->spec->image_name,
                                rbd_dev->spec->snap_name);
                goto err_out_probe;
index b7d7191..f2c631c 100644 (file)
@@ -58,7 +58,6 @@ MODULE_PARM_DESC(sync_start, "On by Default: Driver load will not complete "
                             "until the card startup has completed.");
 
 static DEFINE_IDA(rsxx_disk_ida);
-static DEFINE_SPINLOCK(rsxx_ida_lock);
 
 /* --------------------Debugfs Setup ------------------- */
 
@@ -771,19 +770,10 @@ static int rsxx_pci_probe(struct pci_dev *dev,
        card->dev = dev;
        pci_set_drvdata(dev, card);
 
-       do {
-               if (!ida_pre_get(&rsxx_disk_ida, GFP_KERNEL)) {
-                       st = -ENOMEM;
-                       goto failed_ida_get;
-               }
-
-               spin_lock(&rsxx_ida_lock);
-               st = ida_get_new(&rsxx_disk_ida, &card->disk_id);
-               spin_unlock(&rsxx_ida_lock);
-       } while (st == -EAGAIN);
-
-       if (st)
+       st = ida_alloc(&rsxx_disk_ida, GFP_KERNEL);
+       if (st < 0)
                goto failed_ida_get;
+       card->disk_id = st;
 
        st = pci_enable_device(dev);
        if (st)
@@ -985,9 +975,7 @@ failed_request_regions:
 failed_dma_mask:
        pci_disable_device(dev);
 failed_enable:
-       spin_lock(&rsxx_ida_lock);
-       ida_remove(&rsxx_disk_ida, card->disk_id);
-       spin_unlock(&rsxx_ida_lock);
+       ida_free(&rsxx_disk_ida, card->disk_id);
 failed_ida_get:
        kfree(card);
 
@@ -1050,6 +1038,7 @@ static void rsxx_pci_remove(struct pci_dev *dev)
        pci_disable_device(dev);
        pci_release_regions(dev);
 
+       ida_free(&rsxx_disk_ida, card->disk_id);
        kfree(card);
 }
 
index c7acf74..a1d6b55 100644 (file)
@@ -337,6 +337,7 @@ static ssize_t backing_dev_store(struct device *dev,
                struct device_attribute *attr, const char *buf, size_t len)
 {
        char *file_name;
+       size_t sz;
        struct file *backing_dev = NULL;
        struct inode *inode;
        struct address_space *mapping;
@@ -357,7 +358,11 @@ static ssize_t backing_dev_store(struct device *dev,
                goto out;
        }
 
-       strlcpy(file_name, buf, len);
+       strlcpy(file_name, buf, PATH_MAX);
+       /* ignore trailing newline */
+       sz = strlen(file_name);
+       if (sz > 0 && file_name[sz - 1] == '\n')
+               file_name[sz - 1] = 0x00;
 
        backing_dev = filp_open(file_name, O_RDWR|O_LARGEFILE, 0);
        if (IS_ERR(backing_dev)) {
index d1c0b60..1851112 100644 (file)
@@ -103,6 +103,16 @@ config SIMPLE_PM_BUS
          Controller (BSC, sometimes called "LBSC within Bus Bridge", or
          "External Bus Interface") as found on several Renesas ARM SoCs.
 
+config SUN50I_DE2_BUS
+       bool "Allwinner A64 DE2 Bus Driver"
+         default ARM64
+         depends on ARCH_SUNXI
+         select SUNXI_SRAM
+         help
+         Say y here to enable support for Allwinner A64 DE2 bus driver. It's
+         mostly transparent, but a SRAM region needs to be claimed in the SRAM
+         controller to make the all blocks in the DE2 part accessible.
+
 config SUNXI_RSB
        tristate "Allwinner sunXi Reduced Serial Bus Driver"
          default MACH_SUN8I || MACH_SUN9I || ARM64
index b8f036c..ca300b1 100644 (file)
@@ -21,6 +21,7 @@ obj-$(CONFIG_OMAP_INTERCONNECT)       += omap_l3_smx.o omap_l3_noc.o
 
 obj-$(CONFIG_OMAP_OCP2SCP)     += omap-ocp2scp.o
 obj-$(CONFIG_QCOM_EBI2)                += qcom-ebi2.o
+obj-$(CONFIG_SUN50I_DE2_BUS)   += sun50i-de2.o
 obj-$(CONFIG_SUNXI_RSB)                += sunxi-rsb.o
 obj-$(CONFIG_SIMPLE_PM_BUS)    += simple-pm-bus.o
 obj-$(CONFIG_TEGRA_ACONNECT)   += tegra-aconnect.o
diff --git a/drivers/bus/sun50i-de2.c b/drivers/bus/sun50i-de2.c
new file mode 100644 (file)
index 0000000..6725187
--- /dev/null
@@ -0,0 +1,48 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Allwinner A64 Display Engine 2.0 Bus Driver
+ *
+ * Copyright (C) 2018 Icenowy Zheng <icenowy@aosc.io>
+ */
+
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/soc/sunxi/sunxi_sram.h>
+
+static int sun50i_de2_bus_probe(struct platform_device *pdev)
+{
+       struct device_node *np = pdev->dev.of_node;
+       int ret;
+
+       ret = sunxi_sram_claim(&pdev->dev);
+       if (ret) {
+               dev_err(&pdev->dev, "Error couldn't map SRAM to device\n");
+               return ret;
+       }
+
+       of_platform_populate(np, NULL, NULL, &pdev->dev);
+
+       return 0;
+}
+
+static int sun50i_de2_bus_remove(struct platform_device *pdev)
+{
+       sunxi_sram_release(&pdev->dev);
+       return 0;
+}
+
+static const struct of_device_id sun50i_de2_bus_of_match[] = {
+       { .compatible = "allwinner,sun50i-a64-de2", },
+       { /* sentinel */ }
+};
+
+static struct platform_driver sun50i_de2_bus_driver = {
+       .probe = sun50i_de2_bus_probe,
+       .remove = sun50i_de2_bus_remove,
+       .driver = {
+               .name = "sun50i-de2-bus",
+               .of_match_table = sun50i_de2_bus_of_match,
+       },
+};
+
+builtin_platform_driver(sun50i_de2_bus_driver);
index 80d60f4..c9bac9d 100644 (file)
 #include <linux/of_address.h>
 #include <linux/of_platform.h>
 #include <linux/slab.h>
+#include <linux/iopoll.h>
 
 #include <linux/platform_data/ti-sysc.h>
 
 #include <dt-bindings/bus/ti-sysc.h>
 
+#define MAX_MODULE_SOFTRESET_WAIT              10000
+
 static const char * const reg_names[] = { "rev", "sysc", "syss", };
 
 enum sysc_clocks {
@@ -88,6 +91,11 @@ struct sysc {
        struct delayed_work idle_work;
 };
 
+void sysc_write(struct sysc *ddata, int offset, u32 value)
+{
+       writel_relaxed(value, ddata->module_va + offset);
+}
+
 static u32 sysc_read(struct sysc *ddata, int offset)
 {
        if (ddata->cfg.quirks & SYSC_QUIRK_16BIT) {
@@ -943,6 +951,36 @@ static void sysc_init_revision_quirks(struct sysc *ddata)
        }
 }
 
+static int sysc_reset(struct sysc *ddata)
+{
+       int offset = ddata->offsets[SYSC_SYSCONFIG];
+       int val;
+
+       if (ddata->legacy_mode || offset < 0 ||
+           ddata->cfg.quirks & SYSC_QUIRK_NO_RESET_ON_INIT)
+               return 0;
+
+       /*
+        * Currently only support reset status in sysstatus.
+        * Warn and return error in all other cases
+        */
+       if (!ddata->cfg.syss_mask) {
+               dev_err(ddata->dev, "No ti,syss-mask. Reset failed\n");
+               return -EINVAL;
+       }
+
+       val = sysc_read(ddata, offset);
+       val |= (0x1 << ddata->cap->regbits->srst_shift);
+       sysc_write(ddata, offset, val);
+
+       /* Poll on reset status */
+       offset = ddata->offsets[SYSC_SYSSTATUS];
+
+       return readl_poll_timeout(ddata->module_va + offset, val,
+                                 (val & ddata->cfg.syss_mask) == 0x0,
+                                 100, MAX_MODULE_SOFTRESET_WAIT);
+}
+
 /* At this point the module is configured enough to read the revision */
 static int sysc_init_module(struct sysc *ddata)
 {
@@ -960,6 +998,14 @@ static int sysc_init_module(struct sysc *ddata)
                return 0;
        }
 
+       error = sysc_reset(ddata);
+       if (error) {
+               dev_err(ddata->dev, "Reset failed with %d\n", error);
+               pm_runtime_put_sync(ddata->dev);
+
+               return error;
+       }
+
        ddata->revision = sysc_read_revision(ddata);
        pm_runtime_put_sync(ddata->dev);
 
@@ -1552,6 +1598,23 @@ static const struct sysc_capabilities sysc_omap4_usb_host_fs = {
        .regbits = &sysc_regbits_omap4_usb_host_fs,
 };
 
+static const struct sysc_regbits sysc_regbits_dra7_mcan = {
+       .dmadisable_shift = -ENODEV,
+       .midle_shift = -ENODEV,
+       .sidle_shift = -ENODEV,
+       .clkact_shift = -ENODEV,
+       .enwkup_shift = 4,
+       .srst_shift = 0,
+       .emufree_shift = -ENODEV,
+       .autoidle_shift = -ENODEV,
+};
+
+static const struct sysc_capabilities sysc_dra7_mcan = {
+       .type = TI_SYSC_DRA7_MCAN,
+       .sysc_mask = SYSC_DRA7_MCAN_ENAWAKEUP | SYSC_OMAP4_SOFTRESET,
+       .regbits = &sysc_regbits_dra7_mcan,
+};
+
 static int sysc_init_pdata(struct sysc *ddata)
 {
        struct ti_sysc_platform_data *pdata = dev_get_platdata(ddata->dev);
@@ -1743,6 +1806,7 @@ static const struct of_device_id sysc_match[] = {
        { .compatible = "ti,sysc-mcasp", .data = &sysc_omap4_mcasp, },
        { .compatible = "ti,sysc-usb-host-fs",
          .data = &sysc_omap4_usb_host_fs, },
+       { .compatible = "ti,sysc-dra7-mcan", .data = &sysc_dra7_mcan, },
        {  },
 };
 MODULE_DEVICE_TABLE(of, sysc_match);
index 94fedee..4948c8b 100644 (file)
@@ -193,14 +193,6 @@ static unsigned long rtc_freq;             /* Current periodic IRQ rate    */
 static unsigned long rtc_irq_data;     /* our output to the world      */
 static unsigned long rtc_max_user_freq = 64; /* > this, need CAP_SYS_RESOURCE */
 
-#ifdef RTC_IRQ
-/*
- * rtc_task_lock nests inside rtc_lock.
- */
-static DEFINE_SPINLOCK(rtc_task_lock);
-static rtc_task_t *rtc_callback;
-#endif
-
 /*
  *     If this driver ever becomes modularised, it will be really nice
  *     to make the epoch retain its value across module reload...
@@ -264,11 +256,6 @@ static irqreturn_t rtc_interrupt(int irq, void *dev_id)
 
        spin_unlock(&rtc_lock);
 
-       /* Now do the rest of the actions */
-       spin_lock(&rtc_task_lock);
-       if (rtc_callback)
-               rtc_callback->func(rtc_callback->private_data);
-       spin_unlock(&rtc_task_lock);
        wake_up_interruptible(&rtc_wait);
 
        kill_fasync(&rtc_async_queue, SIGIO, POLL_IN);
index 081b039..6481337 100644 (file)
@@ -14,6 +14,7 @@
 
 #include "psc.h"
 
+LPSC_CLKDEV1(aemif_clkdev,     NULL,   "ti-aemif");
 LPSC_CLKDEV1(spi0_clkdev,      NULL,   "spi_davinci.0");
 LPSC_CLKDEV1(mmcsd_clkdev,     NULL,   "da830-mmc.0");
 LPSC_CLKDEV1(uart0_clkdev,     NULL,   "serial8250.0");
@@ -22,7 +23,7 @@ static const struct davinci_lpsc_clk_info da830_psc0_info[] = {
        LPSC(0,  0, tpcc,     pll0_sysclk2, NULL,         LPSC_ALWAYS_ENABLED),
        LPSC(1,  0, tptc0,    pll0_sysclk2, NULL,         LPSC_ALWAYS_ENABLED),
        LPSC(2,  0, tptc1,    pll0_sysclk2, NULL,         LPSC_ALWAYS_ENABLED),
-       LPSC(3,  0, aemif,    pll0_sysclk3, NULL,         LPSC_ALWAYS_ENABLED),
+       LPSC(3,  0, aemif,    pll0_sysclk3, aemif_clkdev, LPSC_ALWAYS_ENABLED),
        LPSC(4,  0, spi0,     pll0_sysclk2, spi0_clkdev,  0),
        LPSC(5,  0, mmcsd,    pll0_sysclk2, mmcsd_clkdev, 0),
        LPSC(6,  0, aintc,    pll0_sysclk4, NULL,         LPSC_ALWAYS_ENABLED),
index d196dcb..5a18bca 100644 (file)
@@ -16,8 +16,7 @@
 
 #include "psc.h"
 
-LPSC_CLKDEV2(emifa_clkdev,     NULL,           "ti-aemif",
-                               "aemif",        "davinci_nand.0");
+LPSC_CLKDEV1(emifa_clkdev,     NULL,           "ti-aemif");
 LPSC_CLKDEV1(spi0_clkdev,      NULL,           "spi_davinci.0");
 LPSC_CLKDEV1(mmcsd0_clkdev,    NULL,           "da830-mmc.0");
 LPSC_CLKDEV1(uart0_clkdev,     NULL,           "serial8250.0");
index 8c73086..c75424f 100644 (file)
@@ -21,7 +21,8 @@ LPSC_CLKDEV1(mmcsd1_clkdev,           NULL,           "da830-mmc.1");
 LPSC_CLKDEV1(asp0_clkdev,              NULL,           "davinci-mcbsp");
 LPSC_CLKDEV1(usb_clkdev,               "usb",          NULL);
 LPSC_CLKDEV1(spi2_clkdev,              NULL,           "spi_davinci.2");
-LPSC_CLKDEV1(aemif_clkdev,             "aemif",        NULL);
+LPSC_CLKDEV2(aemif_clkdev,             "aemif",        NULL,
+                                       NULL,           "ti-aemif");
 LPSC_CLKDEV1(mmcsd0_clkdev,            NULL,           "da830-mmc.0");
 LPSC_CLKDEV1(i2c_clkdev,               NULL,           "i2c_davinci.1");
 LPSC_CLKDEV1(uart0_clkdev,             NULL,           "serial8250.0");
index fc0230e..0cea6e0 100644 (file)
@@ -21,7 +21,8 @@ LPSC_CLKDEV2(emac_clkdev,             NULL,           "davinci_emac.1",
                                        "fck",          "davinci_mdio.0");
 LPSC_CLKDEV1(usb_clkdev,               "usb",          NULL);
 LPSC_CLKDEV1(ide_clkdev,               NULL,           "palm_bk3710");
-LPSC_CLKDEV1(aemif_clkdev,             "aemif",        NULL);
+LPSC_CLKDEV2(aemif_clkdev,             "aemif",        NULL,
+                                       NULL,           "ti-aemif");
 LPSC_CLKDEV1(mmcsd_clkdev,             NULL,           "dm6441-mmc.0");
 LPSC_CLKDEV1(asp0_clkdev,              NULL,           "davinci-mcbsp");
 LPSC_CLKDEV1(i2c_clkdev,               NULL,           "i2c_davinci.1");
index c3f82ed..20012dc 100644 (file)
@@ -18,7 +18,8 @@
 LPSC_CLKDEV1(ide_clkdev,       NULL,           "palm_bk3710");
 LPSC_CLKDEV2(emac_clkdev,      NULL,           "davinci_emac.1",
                                "fck",          "davinci_mdio.0");
-LPSC_CLKDEV1(aemif_clkdev,     "aemif",        NULL);
+LPSC_CLKDEV2(aemif_clkdev,     "aemif",        NULL,
+                               NULL,           "ti-aemif");
 LPSC_CLKDEV1(mcasp0_clkdev,    NULL,           "davinci-mcasp.0");
 LPSC_CLKDEV1(mcasp1_clkdev,    NULL,           "davinci-mcasp.1");
 LPSC_CLKDEV1(uart0_clkdev,     NULL,           "serial8250.0");
index 5138263..1a4e6b7 100644 (file)
@@ -14,7 +14,6 @@ obj-$(CONFIG_SOC_EXYNOS5410)  += clk-exynos5410.o
 obj-$(CONFIG_SOC_EXYNOS5420)   += clk-exynos5420.o
 obj-$(CONFIG_SOC_EXYNOS5420)   += clk-exynos5-subcmu.o
 obj-$(CONFIG_EXYNOS_ARM64_COMMON_CLK)  += clk-exynos5433.o
-obj-$(CONFIG_SOC_EXYNOS5440)   += clk-exynos5440.o
 obj-$(CONFIG_EXYNOS_AUDSS_CLK_CON) += clk-exynos-audss.o
 obj-$(CONFIG_ARCH_EXYNOS)      += clk-exynos-clkout.o
 obj-$(CONFIG_EXYNOS_ARM64_COMMON_CLK)  += clk-exynos7.o
diff --git a/drivers/clk/samsung/clk-exynos5440.c b/drivers/clk/samsung/clk-exynos5440.c
deleted file mode 100644 (file)
index b08bd54..0000000
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * Copyright (c) 2013 Samsung Electronics Co., Ltd.
- * Author: Thomas Abraham <thomas.ab@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Common Clock Framework support for Exynos5440 SoC.
-*/
-
-#include <dt-bindings/clock/exynos5440.h>
-#include <linux/clk-provider.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/notifier.h>
-#include <linux/reboot.h>
-
-#include "clk.h"
-#include "clk-pll.h"
-
-#define CLKEN_OV_VAL           0xf8
-#define CPU_CLK_STATUS         0xfc
-#define MISC_DOUT1             0x558
-
-static void __iomem *reg_base;
-
-/* parent clock name list */
-PNAME(mout_armclk_p)   = { "cplla", "cpllb" };
-PNAME(mout_spi_p)      = { "div125", "div200" };
-
-/* fixed rate clocks generated outside the soc */
-static struct samsung_fixed_rate_clock exynos5440_fixed_rate_ext_clks[] __initdata = {
-       FRATE(0, "xtal", NULL, 0, 0),
-};
-
-/* fixed rate clocks */
-static const struct samsung_fixed_rate_clock exynos5440_fixed_rate_clks[] __initconst = {
-       FRATE(0, "ppll", NULL, 0, 1000000000),
-       FRATE(0, "usb_phy0", NULL, 0, 60000000),
-       FRATE(0, "usb_phy1", NULL, 0, 60000000),
-       FRATE(0, "usb_ohci12", NULL, 0, 12000000),
-       FRATE(0, "usb_ohci48", NULL, 0, 48000000),
-};
-
-/* fixed factor clocks */
-static const struct samsung_fixed_factor_clock exynos5440_fixed_factor_clks[] __initconst = {
-       FFACTOR(0, "div250", "ppll", 1, 4, 0),
-       FFACTOR(0, "div200", "ppll", 1, 5, 0),
-       FFACTOR(0, "div125", "div250", 1, 2, 0),
-};
-
-/* mux clocks */
-static const struct samsung_mux_clock exynos5440_mux_clks[] __initconst = {
-       MUX(0, "mout_spi", mout_spi_p, MISC_DOUT1, 5, 1),
-       MUX(CLK_ARM_CLK, "arm_clk", mout_armclk_p, CPU_CLK_STATUS, 0, 1),
-};
-
-/* divider clocks */
-static const struct samsung_div_clock exynos5440_div_clks[] __initconst = {
-       DIV(CLK_SPI_BAUD, "div_spi", "mout_spi", MISC_DOUT1, 3, 2),
-};
-
-/* gate clocks */
-static const struct samsung_gate_clock exynos5440_gate_clks[] __initconst = {
-       GATE(CLK_PB0_250, "pb0_250", "div250", CLKEN_OV_VAL, 3, 0, 0),
-       GATE(CLK_PR0_250, "pr0_250", "div250", CLKEN_OV_VAL, 4, 0, 0),
-       GATE(CLK_PR1_250, "pr1_250", "div250", CLKEN_OV_VAL, 5, 0, 0),
-       GATE(CLK_B_250, "b_250", "div250", CLKEN_OV_VAL, 9, 0, 0),
-       GATE(CLK_B_125, "b_125", "div125", CLKEN_OV_VAL, 10, 0, 0),
-       GATE(CLK_B_200, "b_200", "div200", CLKEN_OV_VAL, 11, 0, 0),
-       GATE(CLK_SATA, "sata", "div200", CLKEN_OV_VAL, 12, 0, 0),
-       GATE(CLK_USB, "usb", "div200", CLKEN_OV_VAL, 13, 0, 0),
-       GATE(CLK_GMAC0, "gmac0", "div200", CLKEN_OV_VAL, 14, 0, 0),
-       GATE(CLK_CS250, "cs250", "div250", CLKEN_OV_VAL, 19, 0, 0),
-       GATE(CLK_PB0_250_O, "pb0_250_o", "pb0_250", CLKEN_OV_VAL, 3, 0, 0),
-       GATE(CLK_PR0_250_O, "pr0_250_o", "pr0_250", CLKEN_OV_VAL, 4, 0, 0),
-       GATE(CLK_PR1_250_O, "pr1_250_o", "pr1_250", CLKEN_OV_VAL, 5, 0, 0),
-       GATE(CLK_B_250_O, "b_250_o", "b_250", CLKEN_OV_VAL, 9, 0, 0),
-       GATE(CLK_B_125_O, "b_125_o", "b_125", CLKEN_OV_VAL, 10, 0, 0),
-       GATE(CLK_B_200_O, "b_200_o", "b_200", CLKEN_OV_VAL, 11, 0, 0),
-       GATE(CLK_SATA_O, "sata_o", "sata", CLKEN_OV_VAL, 12, 0, 0),
-       GATE(CLK_USB_O, "usb_o", "usb", CLKEN_OV_VAL, 13, 0, 0),
-       GATE(CLK_GMAC0_O, "gmac0_o", "gmac", CLKEN_OV_VAL, 14, 0, 0),
-       GATE(CLK_CS250_O, "cs250_o", "cs250", CLKEN_OV_VAL, 19, 0, 0),
-};
-
-static const struct of_device_id ext_clk_match[] __initconst = {
-       { .compatible = "samsung,clock-xtal", .data = (void *)0, },
-       {},
-};
-
-static int exynos5440_clk_restart_notify(struct notifier_block *this,
-               unsigned long code, void *unused)
-{
-       u32 val, status;
-
-       status = readl_relaxed(reg_base + 0xbc);
-       val = readl_relaxed(reg_base + 0xcc);
-       val = (val & 0xffff0000) | (status & 0xffff);
-       writel_relaxed(val, reg_base + 0xcc);
-
-       return NOTIFY_DONE;
-}
-
-/*
- * Exynos5440 Clock restart notifier, handles restart functionality
- */
-static struct notifier_block exynos5440_clk_restart_handler = {
-       .notifier_call = exynos5440_clk_restart_notify,
-       .priority = 128,
-};
-
-static const struct samsung_pll_clock exynos5440_plls[] __initconst = {
-       PLL(pll_2550x, CLK_CPLLA, "cplla", "xtal", 0, 0x4c, NULL),
-       PLL(pll_2550x, CLK_CPLLB, "cpllb", "xtal", 0, 0x50, NULL),
-};
-
-/*
- * Clock aliases for legacy clkdev look-up.
- */
-static const struct samsung_clock_alias exynos5440_aliases[] __initconst = {
-       ALIAS(CLK_ARM_CLK, NULL, "armclk"),
-};
-
-/* register exynos5440 clocks */
-static void __init exynos5440_clk_init(struct device_node *np)
-{
-       struct samsung_clk_provider *ctx;
-
-       reg_base = of_iomap(np, 0);
-       if (!reg_base) {
-               pr_err("%s: failed to map clock controller registers,"
-                       " aborting clock initialization\n", __func__);
-               return;
-       }
-
-       ctx = samsung_clk_init(np, reg_base, CLK_NR_CLKS);
-
-       samsung_clk_of_register_fixed_ext(ctx, exynos5440_fixed_rate_ext_clks,
-               ARRAY_SIZE(exynos5440_fixed_rate_ext_clks), ext_clk_match);
-
-       samsung_clk_register_pll(ctx, exynos5440_plls,
-                       ARRAY_SIZE(exynos5440_plls), ctx->reg_base);
-
-       samsung_clk_register_fixed_rate(ctx, exynos5440_fixed_rate_clks,
-                       ARRAY_SIZE(exynos5440_fixed_rate_clks));
-       samsung_clk_register_fixed_factor(ctx, exynos5440_fixed_factor_clks,
-                       ARRAY_SIZE(exynos5440_fixed_factor_clks));
-       samsung_clk_register_mux(ctx, exynos5440_mux_clks,
-                       ARRAY_SIZE(exynos5440_mux_clks));
-       samsung_clk_register_div(ctx, exynos5440_div_clks,
-                       ARRAY_SIZE(exynos5440_div_clks));
-       samsung_clk_register_gate(ctx, exynos5440_gate_clks,
-                       ARRAY_SIZE(exynos5440_gate_clks));
-       samsung_clk_register_alias(ctx, exynos5440_aliases,
-                                               ARRAY_SIZE(exynos5440_aliases));
-
-       samsung_clk_of_add_provider(np, ctx);
-
-       if (register_restart_handler(&exynos5440_clk_restart_handler))
-               pr_warn("exynos5440 clock can't register restart handler\n");
-
-       pr_info("Exynos5440: arm_clk = %ldHz\n", _get_rate("arm_clk"));
-       pr_info("exynos5440 clock initialization complete\n");
-}
-CLK_OF_DECLARE(exynos5440_clk, "samsung,exynos5440-clock", exynos5440_clk_init);
index fb249a1..71a122b 100644 (file)
@@ -708,6 +708,7 @@ static const struct omap_clkctrl_reg_data dra7_wkupaon_clkctrl_regs[] __initcons
        { DRA7_COUNTER_32K_CLKCTRL, NULL, 0, "wkupaon_iclk_mux" },
        { DRA7_UART10_CLKCTRL, dra7_uart10_bit_data, CLKF_SW_SUP, "wkupaon_cm:clk:0060:24" },
        { DRA7_DCAN1_CLKCTRL, dra7_dcan1_bit_data, CLKF_SW_SUP, "wkupaon_cm:clk:0068:24" },
+       { DRA7_ADC_CLKCTRL, NULL, CLKF_SW_SUP, "mcan_clk"},
        { 0 },
 };
 
index 52f5f1a..0cd8eb7 100644 (file)
@@ -71,20 +71,6 @@ config ARM_BRCMSTB_AVS_CPUFREQ
 
          Say Y, if you have a Broadcom SoC with AVS support for DFS or DVFS.
 
-config ARM_EXYNOS5440_CPUFREQ
-       tristate "SAMSUNG EXYNOS5440"
-       depends on SOC_EXYNOS5440
-       depends on HAVE_CLK && OF
-       select PM_OPP
-       default y
-       help
-         This adds the CPUFreq driver for Samsung EXYNOS5440
-         SoC. The nature of exynos5440 clock controller is
-         different than previous exynos controllers so not using
-         the common exynos framework.
-
-         If in doubt, say N.
-
 config ARM_HIGHBANK_CPUFREQ
        tristate "Calxeda Highbank-based"
        depends on ARCH_HIGHBANK && CPUFREQ_DT && REGULATOR
index fb4a2ec..c1ffeab 100644 (file)
@@ -56,7 +56,6 @@ obj-$(CONFIG_ARM_ARMADA_37XX_CPUFREQ) += armada-37xx-cpufreq.o
 obj-$(CONFIG_ARM_BRCMSTB_AVS_CPUFREQ)  += brcmstb-avs-cpufreq.o
 obj-$(CONFIG_ACPI_CPPC_CPUFREQ)                += cppc_cpufreq.o
 obj-$(CONFIG_ARCH_DAVINCI)             += davinci-cpufreq.o
-obj-$(CONFIG_ARM_EXYNOS5440_CPUFREQ)   += exynos5440-cpufreq.o
 obj-$(CONFIG_ARM_HIGHBANK_CPUFREQ)     += highbank-cpufreq.o
 obj-$(CONFIG_ARM_IMX6Q_CPUFREQ)                += imx6q-cpufreq.o
 obj-$(CONFIG_ARM_KIRKWOOD_CPUFREQ)     += kirkwood-cpufreq.o
index 1d50e97..6d53f7d 100644 (file)
@@ -555,12 +555,20 @@ EXPORT_SYMBOL_GPL(cpufreq_dbs_governor_stop);
 
 void cpufreq_dbs_governor_limits(struct cpufreq_policy *policy)
 {
-       struct policy_dbs_info *policy_dbs = policy->governor_data;
+       struct policy_dbs_info *policy_dbs;
+
+       /* Protect gov->gdbs_data against cpufreq_dbs_governor_exit() */
+       mutex_lock(&gov_dbs_data_mutex);
+       policy_dbs = policy->governor_data;
+       if (!policy_dbs)
+               goto out;
 
        mutex_lock(&policy_dbs->update_mutex);
        cpufreq_policy_apply_limits(policy);
        gov_update_sample_delay(policy_dbs, 0);
-
        mutex_unlock(&policy_dbs->update_mutex);
+
+out:
+       mutex_unlock(&gov_dbs_data_mutex);
 }
 EXPORT_SYMBOL_GPL(cpufreq_dbs_governor_limits);
diff --git a/drivers/cpufreq/exynos5440-cpufreq.c b/drivers/cpufreq/exynos5440-cpufreq.c
deleted file mode 100644 (file)
index 932caa3..0000000
+++ /dev/null
@@ -1,452 +0,0 @@
-/*
- * Copyright (c) 2013 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com
- *
- * Amit Daniel Kachhap <amit.daniel@samsung.com>
- *
- * EXYNOS5440 - CPU frequency scaling support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/clk.h>
-#include <linux/cpu.h>
-#include <linux/cpufreq.h>
-#include <linux/err.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/module.h>
-#include <linux/of_address.h>
-#include <linux/of_irq.h>
-#include <linux/pm_opp.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-
-/* Register definitions */
-#define XMU_DVFS_CTRL          0x0060
-#define XMU_PMU_P0_7           0x0064
-#define XMU_C0_3_PSTATE                0x0090
-#define XMU_P_LIMIT            0x00a0
-#define XMU_P_STATUS           0x00a4
-#define XMU_PMUEVTEN           0x00d0
-#define XMU_PMUIRQEN           0x00d4
-#define XMU_PMUIRQ             0x00d8
-
-/* PMU mask and shift definations */
-#define P_VALUE_MASK           0x7
-
-#define XMU_DVFS_CTRL_EN_SHIFT 0
-
-#define P0_7_CPUCLKDEV_SHIFT   21
-#define P0_7_CPUCLKDEV_MASK    0x7
-#define P0_7_ATBCLKDEV_SHIFT   18
-#define P0_7_ATBCLKDEV_MASK    0x7
-#define P0_7_CSCLKDEV_SHIFT    15
-#define P0_7_CSCLKDEV_MASK     0x7
-#define P0_7_CPUEMA_SHIFT      28
-#define P0_7_CPUEMA_MASK       0xf
-#define P0_7_L2EMA_SHIFT       24
-#define P0_7_L2EMA_MASK                0xf
-#define P0_7_VDD_SHIFT         8
-#define P0_7_VDD_MASK          0x7f
-#define P0_7_FREQ_SHIFT                0
-#define P0_7_FREQ_MASK         0xff
-
-#define C0_3_PSTATE_VALID_SHIFT        8
-#define C0_3_PSTATE_CURR_SHIFT 4
-#define C0_3_PSTATE_NEW_SHIFT  0
-
-#define PSTATE_CHANGED_EVTEN_SHIFT     0
-
-#define PSTATE_CHANGED_IRQEN_SHIFT     0
-
-#define PSTATE_CHANGED_SHIFT           0
-
-/* some constant values for clock divider calculation */
-#define CPU_DIV_FREQ_MAX       500
-#define CPU_DBG_FREQ_MAX       375
-#define CPU_ATB_FREQ_MAX       500
-
-#define PMIC_LOW_VOLT          0x30
-#define PMIC_HIGH_VOLT         0x28
-
-#define CPUEMA_HIGH            0x2
-#define CPUEMA_MID             0x4
-#define CPUEMA_LOW             0x7
-
-#define L2EMA_HIGH             0x1
-#define L2EMA_MID              0x3
-#define L2EMA_LOW              0x4
-
-#define DIV_TAB_MAX    2
-/* frequency unit is 20MHZ */
-#define FREQ_UNIT      20
-#define MAX_VOLTAGE    1550000 /* In microvolt */
-#define VOLTAGE_STEP   12500   /* In microvolt */
-
-#define CPUFREQ_NAME           "exynos5440_dvfs"
-#define DEF_TRANS_LATENCY      100000
-
-enum cpufreq_level_index {
-       L0, L1, L2, L3, L4,
-       L5, L6, L7, L8, L9,
-};
-#define CPUFREQ_LEVEL_END      (L7 + 1)
-
-struct exynos_dvfs_data {
-       void __iomem *base;
-       struct resource *mem;
-       int irq;
-       struct clk *cpu_clk;
-       unsigned int latency;
-       struct cpufreq_frequency_table *freq_table;
-       unsigned int freq_count;
-       struct device *dev;
-       bool dvfs_enabled;
-       struct work_struct irq_work;
-};
-
-static struct exynos_dvfs_data *dvfs_info;
-static DEFINE_MUTEX(cpufreq_lock);
-static struct cpufreq_freqs freqs;
-
-static int init_div_table(void)
-{
-       struct cpufreq_frequency_table *pos, *freq_tbl = dvfs_info->freq_table;
-       unsigned int tmp, clk_div, ema_div, freq, volt_id, idx;
-       struct dev_pm_opp *opp;
-
-       cpufreq_for_each_entry_idx(pos, freq_tbl, idx) {
-               opp = dev_pm_opp_find_freq_exact(dvfs_info->dev,
-                                       pos->frequency * 1000, true);
-               if (IS_ERR(opp)) {
-                       dev_err(dvfs_info->dev,
-                               "failed to find valid OPP for %u KHZ\n",
-                               pos->frequency);
-                       return PTR_ERR(opp);
-               }
-
-               freq = pos->frequency / 1000; /* In MHZ */
-               clk_div = ((freq / CPU_DIV_FREQ_MAX) & P0_7_CPUCLKDEV_MASK)
-                                       << P0_7_CPUCLKDEV_SHIFT;
-               clk_div |= ((freq / CPU_ATB_FREQ_MAX) & P0_7_ATBCLKDEV_MASK)
-                                       << P0_7_ATBCLKDEV_SHIFT;
-               clk_div |= ((freq / CPU_DBG_FREQ_MAX) & P0_7_CSCLKDEV_MASK)
-                                       << P0_7_CSCLKDEV_SHIFT;
-
-               /* Calculate EMA */
-               volt_id = dev_pm_opp_get_voltage(opp);
-
-               volt_id = (MAX_VOLTAGE - volt_id) / VOLTAGE_STEP;
-               if (volt_id < PMIC_HIGH_VOLT) {
-                       ema_div = (CPUEMA_HIGH << P0_7_CPUEMA_SHIFT) |
-                               (L2EMA_HIGH << P0_7_L2EMA_SHIFT);
-               } else if (volt_id > PMIC_LOW_VOLT) {
-                       ema_div = (CPUEMA_LOW << P0_7_CPUEMA_SHIFT) |
-                               (L2EMA_LOW << P0_7_L2EMA_SHIFT);
-               } else {
-                       ema_div = (CPUEMA_MID << P0_7_CPUEMA_SHIFT) |
-                               (L2EMA_MID << P0_7_L2EMA_SHIFT);
-               }
-
-               tmp = (clk_div | ema_div | (volt_id << P0_7_VDD_SHIFT)
-                       | ((freq / FREQ_UNIT) << P0_7_FREQ_SHIFT));
-
-               __raw_writel(tmp, dvfs_info->base + XMU_PMU_P0_7 + 4 * idx);
-               dev_pm_opp_put(opp);
-       }
-
-       return 0;
-}
-
-static void exynos_enable_dvfs(unsigned int cur_frequency)
-{
-       unsigned int tmp, cpu;
-       struct cpufreq_frequency_table *freq_table = dvfs_info->freq_table;
-       struct cpufreq_frequency_table *pos;
-       /* Disable DVFS */
-       __raw_writel(0, dvfs_info->base + XMU_DVFS_CTRL);
-
-       /* Enable PSTATE Change Event */
-       tmp = __raw_readl(dvfs_info->base + XMU_PMUEVTEN);
-       tmp |= (1 << PSTATE_CHANGED_EVTEN_SHIFT);
-       __raw_writel(tmp, dvfs_info->base + XMU_PMUEVTEN);
-
-       /* Enable PSTATE Change IRQ */
-       tmp = __raw_readl(dvfs_info->base + XMU_PMUIRQEN);
-       tmp |= (1 << PSTATE_CHANGED_IRQEN_SHIFT);
-       __raw_writel(tmp, dvfs_info->base + XMU_PMUIRQEN);
-
-       /* Set initial performance index */
-       cpufreq_for_each_entry(pos, freq_table)
-               if (pos->frequency == cur_frequency)
-                       break;
-
-       if (pos->frequency == CPUFREQ_TABLE_END) {
-               dev_crit(dvfs_info->dev, "Boot up frequency not supported\n");
-               /* Assign the highest frequency */
-               pos = freq_table;
-               cur_frequency = pos->frequency;
-       }
-
-       dev_info(dvfs_info->dev, "Setting dvfs initial frequency = %uKHZ",
-                                               cur_frequency);
-
-       for (cpu = 0; cpu < CONFIG_NR_CPUS; cpu++) {
-               tmp = __raw_readl(dvfs_info->base + XMU_C0_3_PSTATE + cpu * 4);
-               tmp &= ~(P_VALUE_MASK << C0_3_PSTATE_NEW_SHIFT);
-               tmp |= ((pos - freq_table) << C0_3_PSTATE_NEW_SHIFT);
-               __raw_writel(tmp, dvfs_info->base + XMU_C0_3_PSTATE + cpu * 4);
-       }
-
-       /* Enable DVFS */
-       __raw_writel(1 << XMU_DVFS_CTRL_EN_SHIFT,
-                               dvfs_info->base + XMU_DVFS_CTRL);
-}
-
-static int exynos_target(struct cpufreq_policy *policy, unsigned int index)
-{
-       unsigned int tmp;
-       int i;
-       struct cpufreq_frequency_table *freq_table = dvfs_info->freq_table;
-
-       mutex_lock(&cpufreq_lock);
-
-       freqs.old = policy->cur;
-       freqs.new = freq_table[index].frequency;
-
-       cpufreq_freq_transition_begin(policy, &freqs);
-
-       /* Set the target frequency in all C0_3_PSTATE register */
-       for_each_cpu(i, policy->cpus) {
-               tmp = __raw_readl(dvfs_info->base + XMU_C0_3_PSTATE + i * 4);
-               tmp &= ~(P_VALUE_MASK << C0_3_PSTATE_NEW_SHIFT);
-               tmp |= (index << C0_3_PSTATE_NEW_SHIFT);
-
-               __raw_writel(tmp, dvfs_info->base + XMU_C0_3_PSTATE + i * 4);
-       }
-       mutex_unlock(&cpufreq_lock);
-       return 0;
-}
-
-static void exynos_cpufreq_work(struct work_struct *work)
-{
-       unsigned int cur_pstate, index;
-       struct cpufreq_policy *policy = cpufreq_cpu_get(0); /* boot CPU */
-       struct cpufreq_frequency_table *freq_table = dvfs_info->freq_table;
-
-       /* Ensure we can access cpufreq structures */
-       if (unlikely(dvfs_info->dvfs_enabled == false))
-               goto skip_work;
-
-       mutex_lock(&cpufreq_lock);
-       freqs.old = policy->cur;
-
-       cur_pstate = __raw_readl(dvfs_info->base + XMU_P_STATUS);
-       if (cur_pstate >> C0_3_PSTATE_VALID_SHIFT & 0x1)
-               index = (cur_pstate >> C0_3_PSTATE_CURR_SHIFT) & P_VALUE_MASK;
-       else
-               index = (cur_pstate >> C0_3_PSTATE_NEW_SHIFT) & P_VALUE_MASK;
-
-       if (likely(index < dvfs_info->freq_count)) {
-               freqs.new = freq_table[index].frequency;
-       } else {
-               dev_crit(dvfs_info->dev, "New frequency out of range\n");
-               freqs.new = freqs.old;
-       }
-       cpufreq_freq_transition_end(policy, &freqs, 0);
-
-       cpufreq_cpu_put(policy);
-       mutex_unlock(&cpufreq_lock);
-skip_work:
-       enable_irq(dvfs_info->irq);
-}
-
-static irqreturn_t exynos_cpufreq_irq(int irq, void *id)
-{
-       unsigned int tmp;
-
-       tmp = __raw_readl(dvfs_info->base + XMU_PMUIRQ);
-       if (tmp >> PSTATE_CHANGED_SHIFT & 0x1) {
-               __raw_writel(tmp, dvfs_info->base + XMU_PMUIRQ);
-               disable_irq_nosync(irq);
-               schedule_work(&dvfs_info->irq_work);
-       }
-       return IRQ_HANDLED;
-}
-
-static void exynos_sort_descend_freq_table(void)
-{
-       struct cpufreq_frequency_table *freq_tbl = dvfs_info->freq_table;
-       int i = 0, index;
-       unsigned int tmp_freq;
-       /*
-        * Exynos5440 clock controller state logic expects the cpufreq table to
-        * be in descending order. But the OPP library constructs the table in
-        * ascending order. So to make the table descending we just need to
-        * swap the i element with the N - i element.
-        */
-       for (i = 0; i < dvfs_info->freq_count / 2; i++) {
-               index = dvfs_info->freq_count - i - 1;
-               tmp_freq = freq_tbl[i].frequency;
-               freq_tbl[i].frequency = freq_tbl[index].frequency;
-               freq_tbl[index].frequency = tmp_freq;
-       }
-}
-
-static int exynos_cpufreq_cpu_init(struct cpufreq_policy *policy)
-{
-       policy->clk = dvfs_info->cpu_clk;
-       return cpufreq_generic_init(policy, dvfs_info->freq_table,
-                       dvfs_info->latency);
-}
-
-static struct cpufreq_driver exynos_driver = {
-       .flags          = CPUFREQ_STICKY | CPUFREQ_ASYNC_NOTIFICATION |
-                               CPUFREQ_NEED_INITIAL_FREQ_CHECK,
-       .verify         = cpufreq_generic_frequency_table_verify,
-       .target_index   = exynos_target,
-       .get            = cpufreq_generic_get,
-       .init           = exynos_cpufreq_cpu_init,
-       .name           = CPUFREQ_NAME,
-       .attr           = cpufreq_generic_attr,
-};
-
-static const struct of_device_id exynos_cpufreq_match[] = {
-       {
-               .compatible = "samsung,exynos5440-cpufreq",
-       },
-       {},
-};
-MODULE_DEVICE_TABLE(of, exynos_cpufreq_match);
-
-static int exynos_cpufreq_probe(struct platform_device *pdev)
-{
-       int ret = -EINVAL;
-       struct device_node *np;
-       struct resource res;
-       unsigned int cur_frequency;
-
-       np = pdev->dev.of_node;
-       if (!np)
-               return -ENODEV;
-
-       dvfs_info = devm_kzalloc(&pdev->dev, sizeof(*dvfs_info), GFP_KERNEL);
-       if (!dvfs_info) {
-               ret = -ENOMEM;
-               goto err_put_node;
-       }
-
-       dvfs_info->dev = &pdev->dev;
-
-       ret = of_address_to_resource(np, 0, &res);
-       if (ret)
-               goto err_put_node;
-
-       dvfs_info->base = devm_ioremap_resource(dvfs_info->dev, &res);
-       if (IS_ERR(dvfs_info->base)) {
-               ret = PTR_ERR(dvfs_info->base);
-               goto err_put_node;
-       }
-
-       dvfs_info->irq = irq_of_parse_and_map(np, 0);
-       if (!dvfs_info->irq) {
-               dev_err(dvfs_info->dev, "No cpufreq irq found\n");
-               ret = -ENODEV;
-               goto err_put_node;
-       }
-
-       ret = dev_pm_opp_of_add_table(dvfs_info->dev);
-       if (ret) {
-               dev_err(dvfs_info->dev, "failed to init OPP table: %d\n", ret);
-               goto err_put_node;
-       }
-
-       ret = dev_pm_opp_init_cpufreq_table(dvfs_info->dev,
-                                           &dvfs_info->freq_table);
-       if (ret) {
-               dev_err(dvfs_info->dev,
-                       "failed to init cpufreq table: %d\n", ret);
-               goto err_free_opp;
-       }
-       dvfs_info->freq_count = dev_pm_opp_get_opp_count(dvfs_info->dev);
-       exynos_sort_descend_freq_table();
-
-       if (of_property_read_u32(np, "clock-latency", &dvfs_info->latency))
-               dvfs_info->latency = DEF_TRANS_LATENCY;
-
-       dvfs_info->cpu_clk = devm_clk_get(dvfs_info->dev, "armclk");
-       if (IS_ERR(dvfs_info->cpu_clk)) {
-               dev_err(dvfs_info->dev, "Failed to get cpu clock\n");
-               ret = PTR_ERR(dvfs_info->cpu_clk);
-               goto err_free_table;
-       }
-
-       cur_frequency = clk_get_rate(dvfs_info->cpu_clk);
-       if (!cur_frequency) {
-               dev_err(dvfs_info->dev, "Failed to get clock rate\n");
-               ret = -EINVAL;
-               goto err_free_table;
-       }
-       cur_frequency /= 1000;
-
-       INIT_WORK(&dvfs_info->irq_work, exynos_cpufreq_work);
-       ret = devm_request_irq(dvfs_info->dev, dvfs_info->irq,
-                               exynos_cpufreq_irq, IRQF_TRIGGER_NONE,
-                               CPUFREQ_NAME, dvfs_info);
-       if (ret) {
-               dev_err(dvfs_info->dev, "Failed to register IRQ\n");
-               goto err_free_table;
-       }
-
-       ret = init_div_table();
-       if (ret) {
-               dev_err(dvfs_info->dev, "Failed to initialise div table\n");
-               goto err_free_table;
-       }
-
-       exynos_enable_dvfs(cur_frequency);
-       ret = cpufreq_register_driver(&exynos_driver);
-       if (ret) {
-               dev_err(dvfs_info->dev,
-                       "%s: failed to register cpufreq driver\n", __func__);
-               goto err_free_table;
-       }
-
-       of_node_put(np);
-       dvfs_info->dvfs_enabled = true;
-       return 0;
-
-err_free_table:
-       dev_pm_opp_free_cpufreq_table(dvfs_info->dev, &dvfs_info->freq_table);
-err_free_opp:
-       dev_pm_opp_of_remove_table(dvfs_info->dev);
-err_put_node:
-       of_node_put(np);
-       dev_err(&pdev->dev, "%s: failed initialization\n", __func__);
-       return ret;
-}
-
-static int exynos_cpufreq_remove(struct platform_device *pdev)
-{
-       cpufreq_unregister_driver(&exynos_driver);
-       dev_pm_opp_free_cpufreq_table(dvfs_info->dev, &dvfs_info->freq_table);
-       dev_pm_opp_of_remove_table(dvfs_info->dev);
-       return 0;
-}
-
-static struct platform_driver exynos_cpufreq_platdrv = {
-       .driver = {
-               .name   = "exynos5440-cpufreq",
-               .of_match_table = exynos_cpufreq_match,
-       },
-       .probe          = exynos_cpufreq_probe,
-       .remove         = exynos_cpufreq_remove,
-};
-module_platform_driver(exynos_cpufreq_platdrv);
-
-MODULE_AUTHOR("Amit Daniel Kachhap <amit.daniel@samsung.com>");
-MODULE_DESCRIPTION("Exynos5440 cpufreq driver");
-MODULE_LICENSE("GPL");
index 1aef60d..110483f 100644 (file)
@@ -328,9 +328,8 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
                unsigned int polling_threshold;
 
                /*
-                * We want to default to C1 (hlt), not to busy polling
-                * unless the timer is happening really really soon, or
-                * C1's exit latency exceeds the user configured limit.
+                * Default to a physical idle state, not to busy polling, unless
+                * a timer is going to trigger really really soon.
                 */
                polling_threshold = max_t(unsigned int, 20, s->target_residency);
                if (data->next_timer_us > polling_threshold &&
@@ -349,14 +348,12 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
                 * If the tick is already stopped, the cost of possible short
                 * idle duration misprediction is much higher, because the CPU
                 * may be stuck in a shallow idle state for a long time as a
-                * result of it.  In that case say we might mispredict and try
-                * to force the CPU into a state for which we would have stopped
-                * the tick, unless a timer is going to expire really soon
-                * anyway.
+                * result of it.  In that case say we might mispredict and use
+                * the known time till the closest timer event for the idle
+                * state selection.
                 */
                if (data->predicted_us < TICK_USEC)
-                       data->predicted_us = min_t(unsigned int, TICK_USEC,
-                                                  ktime_to_us(delta_next));
+                       data->predicted_us = ktime_to_us(delta_next);
        } else {
                /*
                 * Use the performance multiplier and the user-configurable
@@ -381,8 +378,22 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
                        continue;
                if (idx == -1)
                        idx = i; /* first enabled state */
-               if (s->target_residency > data->predicted_us)
-                       break;
+               if (s->target_residency > data->predicted_us) {
+                       if (!tick_nohz_tick_stopped())
+                               break;
+
+                       /*
+                        * If the state selected so far is shallow and this
+                        * state's target residency matches the time till the
+                        * closest timer event, select this one to avoid getting
+                        * stuck in the shallow one for too long.
+                        */
+                       if (drv->states[idx].target_residency < TICK_USEC &&
+                           s->target_residency <= ktime_to_us(delta_next))
+                               idx = i;
+
+                       goto out;
+               }
                if (s->exit_latency > latency_req) {
                        /*
                         * If we break out of the loop for latency reasons, use
@@ -403,14 +414,13 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
         * Don't stop the tick if the selected state is a polling one or if the
         * expected idle duration is shorter than the tick period length.
         */
-       if ((drv->states[idx].flags & CPUIDLE_FLAG_POLLING) ||
-           expected_interval < TICK_USEC) {
+       if (((drv->states[idx].flags & CPUIDLE_FLAG_POLLING) ||
+            expected_interval < TICK_USEC) && !tick_nohz_tick_stopped()) {
                unsigned int delta_next_us = ktime_to_us(delta_next);
 
                *stop_tick = false;
 
-               if (!tick_nohz_tick_stopped() && idx > 0 &&
-                   drv->states[idx].target_residency > delta_next_us) {
+               if (idx > 0 && drv->states[idx].target_residency > delta_next_us) {
                        /*
                         * The tick is not going to be stopped and the target
                         * residency of the state to be returned is not within
@@ -418,8 +428,8 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
                         * tick, so try to correct that.
                         */
                        for (i = idx - 1; i >= 0; i--) {
-                           if (drv->states[i].disabled ||
-                               dev->states_usage[i].disable)
+                               if (drv->states[i].disabled ||
+                                   dev->states_usage[i].disable)
                                        continue;
 
                                idx = i;
@@ -429,6 +439,7 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
                }
        }
 
+out:
        data->last_state_idx = idx;
 
        return data->last_state_idx;
index 31b4407..b5b4c12 100644 (file)
@@ -35,7 +35,7 @@
 #ifndef _SG_SW_QM2_H_
 #define _SG_SW_QM2_H_
 
-#include "../../../drivers/staging/fsl-mc/include/dpaa2-fd.h"
+#include <soc/fsl/dpaa2-fd.h>
 
 static inline void dma_to_qm_sg_one(struct dpaa2_sg_entry *qm_sg_ptr,
                                    dma_addr_t dma, u32 len, u16 offset)
index e586ffa..dbfa9fc 100644 (file)
@@ -12,7 +12,7 @@
 #include "ctrl.h"
 #include "regs.h"
 #include "sg_sw_qm2.h"
-#include "../../../drivers/staging/fsl-mc/include/dpaa2-fd.h"
+#include <soc/fsl/dpaa2-fd.h>
 
 struct sec4_sg_entry {
        u64 ptr;
index f746af2..38b0650 100644 (file)
@@ -129,9 +129,9 @@ $code=<<___;
         le?vperm       $IN,$IN,$IN,$lemask
        vxor            $zero,$zero,$zero
 
-       vpmsumd         $Xl,$IN,$Hl             # H.lo·Xi.lo
-       vpmsumd         $Xm,$IN,$H              # H.hi·Xi.lo+H.lo·Xi.hi
-       vpmsumd         $Xh,$IN,$Hh             # H.hi·Xi.hi
+       vpmsumd         $Xl,$IN,$Hl             # H.lo·Xi.lo
+       vpmsumd         $Xm,$IN,$H              # H.hi·Xi.lo+H.lo·Xi.hi
+       vpmsumd         $Xh,$IN,$Hh             # H.hi·Xi.hi
 
        vpmsumd         $t2,$Xl,$xC2            # 1st phase
 
@@ -187,11 +187,11 @@ $code=<<___;
 .align 5
 Loop:
         subic          $len,$len,16
-       vpmsumd         $Xl,$IN,$Hl             # H.lo·Xi.lo
+       vpmsumd         $Xl,$IN,$Hl             # H.lo·Xi.lo
         subfe.         r0,r0,r0                # borrow?-1:0
-       vpmsumd         $Xm,$IN,$H              # H.hi·Xi.lo+H.lo·Xi.hi
+       vpmsumd         $Xm,$IN,$H              # H.hi·Xi.lo+H.lo·Xi.hi
         and            r0,r0,$len
-       vpmsumd         $Xh,$IN,$Hh             # H.hi·Xi.hi
+       vpmsumd         $Xh,$IN,$Hh             # H.hi·Xi.hi
         add            $inp,$inp,r0
 
        vpmsumd         $t2,$Xl,$xC2            # 1st phase
index 0a2acd7..6fd4608 100644 (file)
@@ -248,13 +248,12 @@ __weak phys_addr_t dax_pgoff_to_phys(struct dev_dax *dev_dax, pgoff_t pgoff,
        return -1;
 }
 
-static int __dev_dax_pte_fault(struct dev_dax *dev_dax, struct vm_fault *vmf)
+static vm_fault_t __dev_dax_pte_fault(struct dev_dax *dev_dax,
+                               struct vm_fault *vmf, pfn_t *pfn)
 {
        struct device *dev = &dev_dax->dev;
        struct dax_region *dax_region;
-       int rc = VM_FAULT_SIGBUS;
        phys_addr_t phys;
-       pfn_t pfn;
        unsigned int fault_size = PAGE_SIZE;
 
        if (check_vma(dev_dax, vmf->vma, __func__))
@@ -276,26 +275,19 @@ static int __dev_dax_pte_fault(struct dev_dax *dev_dax, struct vm_fault *vmf)
                return VM_FAULT_SIGBUS;
        }
 
-       pfn = phys_to_pfn_t(phys, dax_region->pfn_flags);
-
-       rc = vm_insert_mixed(vmf->vma, vmf->address, pfn);
-
-       if (rc == -ENOMEM)
-               return VM_FAULT_OOM;
-       if (rc < 0 && rc != -EBUSY)
-               return VM_FAULT_SIGBUS;
+       *pfn = phys_to_pfn_t(phys, dax_region->pfn_flags);
 
-       return VM_FAULT_NOPAGE;
+       return vmf_insert_mixed(vmf->vma, vmf->address, *pfn);
 }
 
-static int __dev_dax_pmd_fault(struct dev_dax *dev_dax, struct vm_fault *vmf)
+static vm_fault_t __dev_dax_pmd_fault(struct dev_dax *dev_dax,
+                               struct vm_fault *vmf, pfn_t *pfn)
 {
        unsigned long pmd_addr = vmf->address & PMD_MASK;
        struct device *dev = &dev_dax->dev;
        struct dax_region *dax_region;
        phys_addr_t phys;
        pgoff_t pgoff;
-       pfn_t pfn;
        unsigned int fault_size = PMD_SIZE;
 
        if (check_vma(dev_dax, vmf->vma, __func__))
@@ -331,21 +323,21 @@ static int __dev_dax_pmd_fault(struct dev_dax *dev_dax, struct vm_fault *vmf)
                return VM_FAULT_SIGBUS;
        }
 
-       pfn = phys_to_pfn_t(phys, dax_region->pfn_flags);
+       *pfn = phys_to_pfn_t(phys, dax_region->pfn_flags);
 
-       return vmf_insert_pfn_pmd(vmf->vma, vmf->address, vmf->pmd, pfn,
+       return vmf_insert_pfn_pmd(vmf->vma, vmf->address, vmf->pmd, *pfn,
                        vmf->flags & FAULT_FLAG_WRITE);
 }
 
 #ifdef CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD
-static int __dev_dax_pud_fault(struct dev_dax *dev_dax, struct vm_fault *vmf)
+static vm_fault_t __dev_dax_pud_fault(struct dev_dax *dev_dax,
+                               struct vm_fault *vmf, pfn_t *pfn)
 {
        unsigned long pud_addr = vmf->address & PUD_MASK;
        struct device *dev = &dev_dax->dev;
        struct dax_region *dax_region;
        phys_addr_t phys;
        pgoff_t pgoff;
-       pfn_t pfn;
        unsigned int fault_size = PUD_SIZE;
 
 
@@ -382,23 +374,26 @@ static int __dev_dax_pud_fault(struct dev_dax *dev_dax, struct vm_fault *vmf)
                return VM_FAULT_SIGBUS;
        }
 
-       pfn = phys_to_pfn_t(phys, dax_region->pfn_flags);
+       *pfn = phys_to_pfn_t(phys, dax_region->pfn_flags);
 
-       return vmf_insert_pfn_pud(vmf->vma, vmf->address, vmf->pud, pfn,
+       return vmf_insert_pfn_pud(vmf->vma, vmf->address, vmf->pud, *pfn,
                        vmf->flags & FAULT_FLAG_WRITE);
 }
 #else
-static int __dev_dax_pud_fault(struct dev_dax *dev_dax, struct vm_fault *vmf)
+static vm_fault_t __dev_dax_pud_fault(struct dev_dax *dev_dax,
+                               struct vm_fault *vmf, pfn_t *pfn)
 {
        return VM_FAULT_FALLBACK;
 }
 #endif /* !CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD */
 
-static int dev_dax_huge_fault(struct vm_fault *vmf,
+static vm_fault_t dev_dax_huge_fault(struct vm_fault *vmf,
                enum page_entry_size pe_size)
 {
-       int rc, id;
        struct file *filp = vmf->vma->vm_file;
+       unsigned long fault_size;
+       int rc, id;
+       pfn_t pfn;
        struct dev_dax *dev_dax = filp->private_data;
 
        dev_dbg(&dev_dax->dev, "%s: %s (%#lx - %#lx) size = %d\n", current->comm,
@@ -408,23 +403,49 @@ static int dev_dax_huge_fault(struct vm_fault *vmf,
        id = dax_read_lock();
        switch (pe_size) {
        case PE_SIZE_PTE:
-               rc = __dev_dax_pte_fault(dev_dax, vmf);
+               fault_size = PAGE_SIZE;
+               rc = __dev_dax_pte_fault(dev_dax, vmf, &pfn);
                break;
        case PE_SIZE_PMD:
-               rc = __dev_dax_pmd_fault(dev_dax, vmf);
+               fault_size = PMD_SIZE;
+               rc = __dev_dax_pmd_fault(dev_dax, vmf, &pfn);
                break;
        case PE_SIZE_PUD:
-               rc = __dev_dax_pud_fault(dev_dax, vmf);
+               fault_size = PUD_SIZE;
+               rc = __dev_dax_pud_fault(dev_dax, vmf, &pfn);
                break;
        default:
                rc = VM_FAULT_SIGBUS;
        }
+
+       if (rc == VM_FAULT_NOPAGE) {
+               unsigned long i;
+               pgoff_t pgoff;
+
+               /*
+                * In the device-dax case the only possibility for a
+                * VM_FAULT_NOPAGE result is when device-dax capacity is
+                * mapped. No need to consider the zero page, or racing
+                * conflicting mappings.
+                */
+               pgoff = linear_page_index(vmf->vma, vmf->address
+                               & ~(fault_size - 1));
+               for (i = 0; i < fault_size / PAGE_SIZE; i++) {
+                       struct page *page;
+
+                       page = pfn_to_page(pfn_t_to_pfn(pfn) + i);
+                       if (page->mapping)
+                               continue;
+                       page->mapping = filp->f_mapping;
+                       page->index = pgoff + i;
+               }
+       }
        dax_read_unlock(id);
 
        return rc;
 }
 
-static int dev_dax_fault(struct vm_fault *vmf)
+static vm_fault_t dev_dax_fault(struct vm_fault *vmf)
 {
        return dev_dax_huge_fault(vmf, PE_SIZE_PTE);
 }
index fd49b24..99e2aac 100644 (file)
@@ -105,15 +105,19 @@ static int dax_pmem_probe(struct device *dev)
        if (rc)
                return rc;
 
-       rc = devm_add_action_or_reset(dev, dax_pmem_percpu_exit,
-                                                       &dax_pmem->ref);
-       if (rc)
+       rc = devm_add_action(dev, dax_pmem_percpu_exit, &dax_pmem->ref);
+       if (rc) {
+               percpu_ref_exit(&dax_pmem->ref);
                return rc;
+       }
 
        dax_pmem->pgmap.ref = &dax_pmem->ref;
        addr = devm_memremap_pages(dev, &dax_pmem->pgmap);
-       if (IS_ERR(addr))
+       if (IS_ERR(addr)) {
+               devm_remove_action(dev, dax_pmem_percpu_exit, &dax_pmem->ref);
+               percpu_ref_exit(&dax_pmem->ref);
                return PTR_ERR(addr);
+       }
 
        rc = devm_add_action_or_reset(dev, dax_pmem_percpu_kill,
                                                        &dax_pmem->ref);
index 45276ab..6e928f3 100644 (file)
@@ -89,7 +89,6 @@ bool __bdev_dax_supported(struct block_device *bdev, int blocksize)
        struct request_queue *q;
        pgoff_t pgoff;
        int err, id;
-       void *kaddr;
        pfn_t pfn;
        long len;
        char buf[BDEVNAME_SIZE];
@@ -122,7 +121,7 @@ bool __bdev_dax_supported(struct block_device *bdev, int blocksize)
        }
 
        id = dax_read_lock();
-       len = dax_direct_access(dax_dev, pgoff, 1, &kaddr, &pfn);
+       len = dax_direct_access(dax_dev, pgoff, 1, NULL, &pfn);
        dax_read_unlock(id);
 
        put_dax(dax_dev);
index 272bed6..f1a441a 100644 (file)
@@ -161,9 +161,7 @@ static void chan_dev_release(struct device *dev)
 
        chan_dev = container_of(dev, typeof(*chan_dev), device);
        if (atomic_dec_and_test(chan_dev->idr_ref)) {
-               mutex_lock(&dma_list_mutex);
-               ida_remove(&dma_ida, chan_dev->dev_id);
-               mutex_unlock(&dma_list_mutex);
+               ida_free(&dma_ida, chan_dev->dev_id);
                kfree(chan_dev->idr_ref);
        }
        kfree(chan_dev);
@@ -898,17 +896,12 @@ static bool device_has_all_tx_types(struct dma_device *device)
 
 static int get_dma_id(struct dma_device *device)
 {
-       int rc;
-
-       do {
-               if (!ida_pre_get(&dma_ida, GFP_KERNEL))
-                       return -ENOMEM;
-               mutex_lock(&dma_list_mutex);
-               rc = ida_get_new(&dma_ida, &device->dev_id);
-               mutex_unlock(&dma_list_mutex);
-       } while (rc == -EAGAIN);
+       int rc = ida_alloc(&dma_ida, GFP_KERNEL);
 
-       return rc;
+       if (rc < 0)
+               return rc;
+       device->dev_id = rc;
+       return 0;
 }
 
 /**
@@ -1092,9 +1085,7 @@ int dma_async_device_register(struct dma_device *device)
 err_out:
        /* if we never registered a channel just release the idr */
        if (atomic_read(idr_ref) == 0) {
-               mutex_lock(&dma_list_mutex);
-               ida_remove(&dma_ida, device->dev_id);
-               mutex_unlock(&dma_list_mutex);
+               ida_free(&dma_ida, device->dev_id);
                kfree(idr_ref);
                return rc;
        }
index 3bb82e5..7d3edd7 100644 (file)
@@ -215,6 +215,7 @@ const char * const edac_mem_types[] = {
        [MEM_LRDDR3]    = "Load-Reduced-DDR3-RAM",
        [MEM_DDR4]      = "Unbuffered-DDR4",
        [MEM_RDDR4]     = "Registered-DDR4",
+       [MEM_LRDDR4]    = "Load-Reduced-DDR4-RAM",
        [MEM_NVDIMM]    = "Non-volatile-RAM",
 };
 EXPORT_SYMBOL_GPL(edac_mem_types);
index 2a219b1..721e6c5 100644 (file)
@@ -363,8 +363,6 @@ static int scmi_dvfs_device_opps_add(const struct scmi_handle *handle,
                return domain;
 
        dom = pi->dom_info + domain;
-       if (!dom)
-               return -EIO;
 
        for (opp = dom->opp, idx = 0; idx < dom->opp_count; idx++, opp++) {
                freq = opp->perf * dom->mult_factor;
@@ -394,9 +392,6 @@ static int scmi_dvfs_transition_latency_get(const struct scmi_handle *handle,
                return domain;
 
        dom = pi->dom_info + domain;
-       if (!dom)
-               return -EIO;
-
        /* uS to nS */
        return dom->opp[dom->opp_count - 1].trans_latency_us * 1000;
 }
index 50793fd..b22ccfb 100644 (file)
@@ -20,7 +20,7 @@
 #include <linux/efi-bgrt.h>
 
 struct acpi_table_bgrt bgrt_tab;
-size_t __initdata bgrt_image_size;
+size_t bgrt_image_size;
 
 struct bmp_header {
        u16 id;
index 88c322d..14c40a7 100644 (file)
@@ -24,6 +24,7 @@ KBUILD_CFLAGS                 := $(cflags-y) -DDISABLE_BRANCH_PROFILING \
                                   -D__NO_FORTIFY \
                                   $(call cc-option,-ffreestanding) \
                                   $(call cc-option,-fno-stack-protector) \
+                                  -D__DISABLE_EXPORTS
 
 GCOV_PROFILE                   := n
 KASAN_SANITIZE                 := n
index bb1c068..3469436 100644 (file)
@@ -77,28 +77,6 @@ static int psci_ops_check(void)
        return 0;
 }
 
-static int find_cpu_groups(const struct cpumask *cpus,
-                          const struct cpumask **cpu_groups)
-{
-       unsigned int nb = 0;
-       cpumask_var_t tmp;
-
-       if (!alloc_cpumask_var(&tmp, GFP_KERNEL))
-               return -ENOMEM;
-       cpumask_copy(tmp, cpus);
-
-       while (!cpumask_empty(tmp)) {
-               const struct cpumask *cpu_group =
-                       topology_core_cpumask(cpumask_any(tmp));
-
-               cpu_groups[nb++] = cpu_group;
-               cpumask_andnot(tmp, tmp, cpu_group);
-       }
-
-       free_cpumask_var(tmp);
-       return nb;
-}
-
 /*
  * offlined_cpus is a temporary array but passing it as an argument avoids
  * multiple allocations.
@@ -166,29 +144,66 @@ static unsigned int down_and_up_cpus(const struct cpumask *cpus,
        return err;
 }
 
+static void free_cpu_groups(int num, cpumask_var_t **pcpu_groups)
+{
+       int i;
+       cpumask_var_t *cpu_groups = *pcpu_groups;
+
+       for (i = 0; i < num; ++i)
+               free_cpumask_var(cpu_groups[i]);
+       kfree(cpu_groups);
+}
+
+static int alloc_init_cpu_groups(cpumask_var_t **pcpu_groups)
+{
+       int num_groups = 0;
+       cpumask_var_t tmp, *cpu_groups;
+
+       if (!alloc_cpumask_var(&tmp, GFP_KERNEL))
+               return -ENOMEM;
+
+       cpu_groups = kcalloc(nb_available_cpus, sizeof(cpu_groups),
+                            GFP_KERNEL);
+       if (!cpu_groups)
+               return -ENOMEM;
+
+       cpumask_copy(tmp, cpu_online_mask);
+
+       while (!cpumask_empty(tmp)) {
+               const struct cpumask *cpu_group =
+                       topology_core_cpumask(cpumask_any(tmp));
+
+               if (!alloc_cpumask_var(&cpu_groups[num_groups], GFP_KERNEL)) {
+                       free_cpu_groups(num_groups, &cpu_groups);
+                       return -ENOMEM;
+               }
+               cpumask_copy(cpu_groups[num_groups++], cpu_group);
+               cpumask_andnot(tmp, tmp, cpu_group);
+       }
+
+       free_cpumask_var(tmp);
+       *pcpu_groups = cpu_groups;
+
+       return num_groups;
+}
+
 static int hotplug_tests(void)
 {
-       int err;
-       cpumask_var_t offlined_cpus;
-       int i, nb_cpu_group;
-       const struct cpumask **cpu_groups;
+       int i, nb_cpu_group, err = -ENOMEM;
+       cpumask_var_t offlined_cpus, *cpu_groups;
        char *page_buf;
 
-       err = -ENOMEM;
        if (!alloc_cpumask_var(&offlined_cpus, GFP_KERNEL))
                return err;
-       /* We may have up to nb_available_cpus cpu_groups. */
-       cpu_groups = kmalloc_array(nb_available_cpus, sizeof(*cpu_groups),
-                                  GFP_KERNEL);
-       if (!cpu_groups)
+
+       nb_cpu_group = alloc_init_cpu_groups(&cpu_groups);
+       if (nb_cpu_group < 0)
                goto out_free_cpus;
        page_buf = (char *)__get_free_page(GFP_KERNEL);
        if (!page_buf)
                goto out_free_cpu_groups;
 
        err = 0;
-       nb_cpu_group = find_cpu_groups(cpu_online_mask, cpu_groups);
-
        /*
         * Of course the last CPU cannot be powered down and cpu_down() should
         * refuse doing that.
@@ -212,7 +227,7 @@ static int hotplug_tests(void)
 
        free_page((unsigned long)page_buf);
 out_free_cpu_groups:
-       kfree(cpu_groups);
+       free_cpu_groups(nb_cpu_group, &cpu_groups);
 out_free_cpus:
        free_cpumask_var(offlined_cpus);
        return err;
index 6692888..a200a21 100644 (file)
 #define MBOX_DATA28(msg)               ((msg) & ~0xf)
 #define MBOX_CHAN_PROPERTY             8
 
+#define MAX_RPI_FW_PROP_BUF_SIZE       32
+
+static struct platform_device *rpi_hwmon;
+
 struct rpi_firmware {
        struct mbox_client cl;
        struct mbox_chan *chan; /* The property channel. */
@@ -143,18 +147,22 @@ int rpi_firmware_property(struct rpi_firmware *fw,
        /* Single tags are very small (generally 8 bytes), so the
         * stack should be safe.
         */
-       u8 data[buf_size + sizeof(struct rpi_firmware_property_tag_header)];
+       u8 data[sizeof(struct rpi_firmware_property_tag_header) +
+               MAX_RPI_FW_PROP_BUF_SIZE];
        struct rpi_firmware_property_tag_header *header =
                (struct rpi_firmware_property_tag_header *)data;
        int ret;
 
+       if (WARN_ON(buf_size > sizeof(data) - sizeof(*header)))
+               return -EINVAL;
+
        header->tag = tag;
        header->buf_size = buf_size;
        header->req_resp_size = 0;
        memcpy(data + sizeof(struct rpi_firmware_property_tag_header),
               tag_data, buf_size);
 
-       ret = rpi_firmware_property_list(fw, &data, sizeof(data));
+       ret = rpi_firmware_property_list(fw, &data, buf_size + sizeof(*header));
        memcpy(tag_data,
               data + sizeof(struct rpi_firmware_property_tag_header),
               buf_size);
@@ -183,6 +191,20 @@ rpi_firmware_print_firmware_revision(struct rpi_firmware *fw)
        }
 }
 
+static void
+rpi_register_hwmon_driver(struct device *dev, struct rpi_firmware *fw)
+{
+       u32 packet;
+       int ret = rpi_firmware_property(fw, RPI_FIRMWARE_GET_THROTTLED,
+                                       &packet, sizeof(packet));
+
+       if (ret)
+               return;
+
+       rpi_hwmon = platform_device_register_data(dev, "raspberrypi-hwmon",
+                                                 -1, NULL, 0);
+}
+
 static int rpi_firmware_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
@@ -209,6 +231,7 @@ static int rpi_firmware_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, fw);
 
        rpi_firmware_print_firmware_revision(fw);
+       rpi_register_hwmon_driver(dev, fw);
 
        return 0;
 }
@@ -217,6 +240,8 @@ static int rpi_firmware_remove(struct platform_device *pdev)
 {
        struct rpi_firmware *fw = platform_get_drvdata(pdev);
 
+       platform_device_unregister(rpi_hwmon);
+       rpi_hwmon = NULL;
        mbox_free_channel(fw->chan);
 
        return 0;
index f7a0f57..4f52c3a 100644 (file)
@@ -1049,6 +1049,12 @@ config GPIO_LP87565
          This driver can also be built as a module. If so, the module will be
          called gpio-lp87565.
 
+config GPIO_MADERA
+       tristate "Cirrus Logic Madera class codecs"
+       depends on PINCTRL_MADERA
+       help
+         Support for GPIOs on Cirrus Logic Madera class codecs.
+
 config GPIO_MAX77620
        tristate "GPIO support for PMIC MAX77620 and MAX20024"
        depends on MFD_MAX77620
index fc77989..c256aff 100644 (file)
@@ -71,6 +71,7 @@ obj-$(CONFIG_ARCH_LPC32XX)    += gpio-lpc32xx.o
 obj-$(CONFIG_GPIO_LP873X)      += gpio-lp873x.o
 obj-$(CONFIG_GPIO_LP87565)     += gpio-lp87565.o
 obj-$(CONFIG_GPIO_LYNXPOINT)   += gpio-lynxpoint.o
+obj-$(CONFIG_GPIO_MADERA)      += gpio-madera.o
 obj-$(CONFIG_GPIO_MAX3191X)    += gpio-max3191x.o
 obj-$(CONFIG_GPIO_MAX730X)     += gpio-max730x.o
 obj-$(CONFIG_GPIO_MAX7300)     += gpio-max7300.o
diff --git a/drivers/gpio/gpio-madera.c b/drivers/gpio/gpio-madera.c
new file mode 100644 (file)
index 0000000..7ba68d1
--- /dev/null
@@ -0,0 +1,206 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * GPIO support for Cirrus Logic Madera codecs
+ *
+ * Copyright (C) 2015-2018 Cirrus Logic
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2.
+ */
+
+#include <linux/gpio/driver.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include <linux/mfd/madera/core.h>
+#include <linux/mfd/madera/pdata.h>
+#include <linux/mfd/madera/registers.h>
+
+struct madera_gpio {
+       struct madera *madera;
+       /* storage space for the gpio_chip we're using */
+       struct gpio_chip gpio_chip;
+};
+
+static int madera_gpio_get_direction(struct gpio_chip *chip,
+                                    unsigned int offset)
+{
+       struct madera_gpio *madera_gpio = gpiochip_get_data(chip);
+       struct madera *madera = madera_gpio->madera;
+       unsigned int reg_offset = 2 * offset;
+       unsigned int val;
+       int ret;
+
+       ret = regmap_read(madera->regmap, MADERA_GPIO1_CTRL_2 + reg_offset,
+                         &val);
+       if (ret < 0)
+               return ret;
+
+       return !!(val & MADERA_GP1_DIR_MASK);
+}
+
+static int madera_gpio_direction_in(struct gpio_chip *chip, unsigned int offset)
+{
+       struct madera_gpio *madera_gpio = gpiochip_get_data(chip);
+       struct madera *madera = madera_gpio->madera;
+       unsigned int reg_offset = 2 * offset;
+
+       return regmap_update_bits(madera->regmap,
+                                 MADERA_GPIO1_CTRL_2 + reg_offset,
+                                 MADERA_GP1_DIR_MASK, MADERA_GP1_DIR);
+}
+
+static int madera_gpio_get(struct gpio_chip *chip, unsigned int offset)
+{
+       struct madera_gpio *madera_gpio = gpiochip_get_data(chip);
+       struct madera *madera = madera_gpio->madera;
+       unsigned int reg_offset = 2 * offset;
+       unsigned int val;
+       int ret;
+
+       ret = regmap_read(madera->regmap, MADERA_GPIO1_CTRL_1 + reg_offset,
+                         &val);
+       if (ret < 0)
+               return ret;
+
+       return !!(val & MADERA_GP1_LVL_MASK);
+}
+
+static int madera_gpio_direction_out(struct gpio_chip *chip,
+                                    unsigned int offset, int value)
+{
+       struct madera_gpio *madera_gpio = gpiochip_get_data(chip);
+       struct madera *madera = madera_gpio->madera;
+       unsigned int reg_offset = 2 * offset;
+       unsigned int reg_val = value ? MADERA_GP1_LVL : 0;
+       int ret;
+
+       ret = regmap_update_bits(madera->regmap,
+                                MADERA_GPIO1_CTRL_2 + reg_offset,
+                                MADERA_GP1_DIR_MASK, 0);
+       if (ret < 0)
+               return ret;
+
+       return regmap_update_bits(madera->regmap,
+                                 MADERA_GPIO1_CTRL_1 + reg_offset,
+                                 MADERA_GP1_LVL_MASK, reg_val);
+}
+
+static void madera_gpio_set(struct gpio_chip *chip, unsigned int offset,
+                           int value)
+{
+       struct madera_gpio *madera_gpio = gpiochip_get_data(chip);
+       struct madera *madera = madera_gpio->madera;
+       unsigned int reg_offset = 2 * offset;
+       unsigned int reg_val = value ? MADERA_GP1_LVL : 0;
+       int ret;
+
+       ret = regmap_update_bits(madera->regmap,
+                                MADERA_GPIO1_CTRL_1 + reg_offset,
+                                MADERA_GP1_LVL_MASK, reg_val);
+
+       /* set() doesn't return an error so log a warning */
+       if (ret)
+               dev_warn(madera->dev, "Failed to write to 0x%x (%d)\n",
+                        MADERA_GPIO1_CTRL_1 + reg_offset, ret);
+}
+
+static struct gpio_chip madera_gpio_chip = {
+       .label                  = "madera",
+       .owner                  = THIS_MODULE,
+       .request                = gpiochip_generic_request,
+       .free                   = gpiochip_generic_free,
+       .get_direction          = madera_gpio_get_direction,
+       .direction_input        = madera_gpio_direction_in,
+       .get                    = madera_gpio_get,
+       .direction_output       = madera_gpio_direction_out,
+       .set                    = madera_gpio_set,
+       .set_config             = gpiochip_generic_config,
+       .can_sleep              = true,
+};
+
+static int madera_gpio_probe(struct platform_device *pdev)
+{
+       struct madera *madera = dev_get_drvdata(pdev->dev.parent);
+       struct madera_pdata *pdata = dev_get_platdata(madera->dev);
+       struct madera_gpio *madera_gpio;
+       int ret;
+
+       madera_gpio = devm_kzalloc(&pdev->dev, sizeof(*madera_gpio),
+                                  GFP_KERNEL);
+       if (!madera_gpio)
+               return -ENOMEM;
+
+       madera_gpio->madera = madera;
+
+       /* Construct suitable gpio_chip from the template in madera_gpio_chip */
+       madera_gpio->gpio_chip = madera_gpio_chip;
+       madera_gpio->gpio_chip.parent = pdev->dev.parent;
+
+       switch (madera->type) {
+       case CS47L35:
+               madera_gpio->gpio_chip.ngpio = CS47L35_NUM_GPIOS;
+               break;
+       case CS47L85:
+       case WM1840:
+               madera_gpio->gpio_chip.ngpio = CS47L85_NUM_GPIOS;
+               break;
+       case CS47L90:
+       case CS47L91:
+               madera_gpio->gpio_chip.ngpio = CS47L90_NUM_GPIOS;
+               break;
+       default:
+               dev_err(&pdev->dev, "Unknown chip variant %d\n", madera->type);
+               return -EINVAL;
+       }
+
+       /* We want to be usable on systems that don't use devicetree or acpi */
+       if (pdata && pdata->gpio_base)
+               madera_gpio->gpio_chip.base = pdata->gpio_base;
+       else
+               madera_gpio->gpio_chip.base = -1;
+
+       ret = devm_gpiochip_add_data(&pdev->dev,
+                                    &madera_gpio->gpio_chip,
+                                    madera_gpio);
+       if (ret < 0) {
+               dev_dbg(&pdev->dev, "Could not register gpiochip, %d\n", ret);
+               return ret;
+       }
+
+       /*
+        * This is part of a composite MFD device which can only be used with
+        * the corresponding pinctrl driver. On all supported silicon the GPIO
+        * to pinctrl mapping is fixed in the silicon, so we register it
+        * explicitly instead of requiring a redundant gpio-ranges in the
+        * devicetree.
+        * In any case we also want to work on systems that don't use devicetree
+        * or acpi.
+        */
+       ret = gpiochip_add_pin_range(&madera_gpio->gpio_chip, "madera-pinctrl",
+                                    0, 0, madera_gpio->gpio_chip.ngpio);
+       if (ret) {
+               dev_dbg(&pdev->dev, "Failed to add pin range (%d)\n", ret);
+               return ret;
+       }
+
+       return 0;
+}
+
+static struct platform_driver madera_gpio_driver = {
+       .driver = {
+               .name   = "madera-gpio",
+       },
+       .probe          = madera_gpio_probe,
+};
+
+module_platform_driver(madera_gpio_driver);
+
+MODULE_SOFTDEP("pre: pinctrl-madera");
+MODULE_DESCRIPTION("GPIO interface for Madera codecs");
+MODULE_AUTHOR("Nariman Poushin <nariman@opensource.cirrus.com>");
+MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:madera-gpio");
index 8a707d8..f92597c 100644 (file)
@@ -206,11 +206,9 @@ static int amdgpu_amdkfd_remove_eviction_fence(struct amdgpu_bo *bo,
                                        struct amdgpu_amdkfd_fence ***ef_list,
                                        unsigned int *ef_count)
 {
-       struct reservation_object_list *fobj;
-       struct reservation_object *resv;
-       unsigned int i = 0, j = 0, k = 0, shared_count;
-       unsigned int count = 0;
-       struct amdgpu_amdkfd_fence **fence_list;
+       struct reservation_object *resv = bo->tbo.resv;
+       struct reservation_object_list *old, *new;
+       unsigned int i, j, k;
 
        if (!ef && !ef_list)
                return -EINVAL;
@@ -220,76 +218,67 @@ static int amdgpu_amdkfd_remove_eviction_fence(struct amdgpu_bo *bo,
                *ef_count = 0;
        }
 
-       resv = bo->tbo.resv;
-       fobj = reservation_object_get_list(resv);
-
-       if (!fobj)
+       old = reservation_object_get_list(resv);
+       if (!old)
                return 0;
 
-       preempt_disable();
-       write_seqcount_begin(&resv->seq);
+       new = kmalloc(offsetof(typeof(*new), shared[old->shared_max]),
+                     GFP_KERNEL);
+       if (!new)
+               return -ENOMEM;
 
-       /* Go through all the shared fences in the resevation object. If
-        * ef is specified and it exists in the list, remove it and reduce the
-        * count. If ef is not specified, then get the count of eviction fences
-        * present.
+       /* Go through all the shared fences in the resevation object and sort
+        * the interesting ones to the end of the list.
         */
-       shared_count = fobj->shared_count;
-       for (i = 0; i < shared_count; ++i) {
+       for (i = 0, j = old->shared_count, k = 0; i < old->shared_count; ++i) {
                struct dma_fence *f;
 
-               f = rcu_dereference_protected(fobj->shared[i],
+               f = rcu_dereference_protected(old->shared[i],
                                              reservation_object_held(resv));
 
-               if (ef) {
-                       if (f->context == ef->base.context) {
-                               dma_fence_put(f);
-                               fobj->shared_count--;
-                       } else {
-                               RCU_INIT_POINTER(fobj->shared[j++], f);
-                       }
-               } else if (to_amdgpu_amdkfd_fence(f))
-                       count++;
+               if ((ef && f->context == ef->base.context) ||
+                   (!ef && to_amdgpu_amdkfd_fence(f)))
+                       RCU_INIT_POINTER(new->shared[--j], f);
+               else
+                       RCU_INIT_POINTER(new->shared[k++], f);
        }
-       write_seqcount_end(&resv->seq);
-       preempt_enable();
-
-       if (ef || !count)
-               return 0;
-
-       /* Alloc memory for count number of eviction fence pointers. Fill the
-        * ef_list array and ef_count
-        */
-       fence_list = kcalloc(count, sizeof(struct amdgpu_amdkfd_fence *),
-                            GFP_KERNEL);
-       if (!fence_list)
-               return -ENOMEM;
+       new->shared_max = old->shared_max;
+       new->shared_count = k;
 
-       preempt_disable();
-       write_seqcount_begin(&resv->seq);
+       if (!ef) {
+               unsigned int count = old->shared_count - j;
 
-       j = 0;
-       for (i = 0; i < shared_count; ++i) {
-               struct dma_fence *f;
-               struct amdgpu_amdkfd_fence *efence;
-
-               f = rcu_dereference_protected(fobj->shared[i],
-                       reservation_object_held(resv));
+               /* Alloc memory for count number of eviction fence pointers.
+                * Fill the ef_list array and ef_count
+                */
+               *ef_list = kcalloc(count, sizeof(**ef_list), GFP_KERNEL);
+               *ef_count = count;
 
-               efence = to_amdgpu_amdkfd_fence(f);
-               if (efence) {
-                       fence_list[k++] = efence;
-                       fobj->shared_count--;
-               } else {
-                       RCU_INIT_POINTER(fobj->shared[j++], f);
+               if (!*ef_list) {
+                       kfree(new);
+                       return -ENOMEM;
                }
        }
 
+       /* Install the new fence list, seqcount provides the barriers */
+       preempt_disable();
+       write_seqcount_begin(&resv->seq);
+       RCU_INIT_POINTER(resv->fence, new);
        write_seqcount_end(&resv->seq);
        preempt_enable();
 
-       *ef_list = fence_list;
-       *ef_count = k;
+       /* Drop the references to the removed fences or move them to ef_list */
+       for (i = j, k = 0; i < old->shared_count; ++i) {
+               struct dma_fence *f;
+
+               f = rcu_dereference_protected(new->shared[i],
+                                             reservation_object_held(resv));
+               if (!ef)
+                       (*ef_list)[k++] = to_amdgpu_amdkfd_fence(f);
+               else
+                       dma_fence_put(f);
+       }
+       kfree_rcu(old, rcu);
 
        return 0;
 }
index 1e66dfd..8ab5ccb 100644 (file)
@@ -2274,7 +2274,7 @@ bool amdgpu_device_asic_has_dc_support(enum amd_asic_type asic_type)
        case CHIP_VEGA10:
        case CHIP_VEGA12:
        case CHIP_VEGA20:
-#ifdef CONFIG_X86
+#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
        case CHIP_RAVEN:
 #endif
                return amdgpu_dc != 0;
index a365ea2..e55508b 100644 (file)
@@ -178,12 +178,18 @@ void amdgpu_mn_unlock(struct amdgpu_mn *mn)
  *
  * @amn: our notifier
  */
-static void amdgpu_mn_read_lock(struct amdgpu_mn *amn)
+static int amdgpu_mn_read_lock(struct amdgpu_mn *amn, bool blockable)
 {
-       mutex_lock(&amn->read_lock);
+       if (blockable)
+               mutex_lock(&amn->read_lock);
+       else if (!mutex_trylock(&amn->read_lock))
+               return -EAGAIN;
+
        if (atomic_inc_return(&amn->recursion) == 1)
                down_read_non_owner(&amn->lock);
        mutex_unlock(&amn->read_lock);
+
+       return 0;
 }
 
 /**
@@ -239,10 +245,11 @@ static void amdgpu_mn_invalidate_node(struct amdgpu_mn_node *node,
  * Block for operations on BOs to finish and mark pages as accessed and
  * potentially dirty.
  */
-static void amdgpu_mn_invalidate_range_start_gfx(struct mmu_notifier *mn,
+static int amdgpu_mn_invalidate_range_start_gfx(struct mmu_notifier *mn,
                                                 struct mm_struct *mm,
                                                 unsigned long start,
-                                                unsigned long end)
+                                                unsigned long end,
+                                                bool blockable)
 {
        struct amdgpu_mn *amn = container_of(mn, struct amdgpu_mn, mn);
        struct interval_tree_node *it;
@@ -250,17 +257,28 @@ static void amdgpu_mn_invalidate_range_start_gfx(struct mmu_notifier *mn,
        /* notification is exclusive, but interval is inclusive */
        end -= 1;
 
-       amdgpu_mn_read_lock(amn);
+       /* TODO we should be able to split locking for interval tree and
+        * amdgpu_mn_invalidate_node
+        */
+       if (amdgpu_mn_read_lock(amn, blockable))
+               return -EAGAIN;
 
        it = interval_tree_iter_first(&amn->objects, start, end);
        while (it) {
                struct amdgpu_mn_node *node;
 
+               if (!blockable) {
+                       amdgpu_mn_read_unlock(amn);
+                       return -EAGAIN;
+               }
+
                node = container_of(it, struct amdgpu_mn_node, it);
                it = interval_tree_iter_next(it, start, end);
 
                amdgpu_mn_invalidate_node(node, start, end);
        }
+
+       return 0;
 }
 
 /**
@@ -275,10 +293,11 @@ static void amdgpu_mn_invalidate_range_start_gfx(struct mmu_notifier *mn,
  * necessitates evicting all user-mode queues of the process. The BOs
  * are restorted in amdgpu_mn_invalidate_range_end_hsa.
  */
-static void amdgpu_mn_invalidate_range_start_hsa(struct mmu_notifier *mn,
+static int amdgpu_mn_invalidate_range_start_hsa(struct mmu_notifier *mn,
                                                 struct mm_struct *mm,
                                                 unsigned long start,
-                                                unsigned long end)
+                                                unsigned long end,
+                                                bool blockable)
 {
        struct amdgpu_mn *amn = container_of(mn, struct amdgpu_mn, mn);
        struct interval_tree_node *it;
@@ -286,13 +305,19 @@ static void amdgpu_mn_invalidate_range_start_hsa(struct mmu_notifier *mn,
        /* notification is exclusive, but interval is inclusive */
        end -= 1;
 
-       amdgpu_mn_read_lock(amn);
+       if (amdgpu_mn_read_lock(amn, blockable))
+               return -EAGAIN;
 
        it = interval_tree_iter_first(&amn->objects, start, end);
        while (it) {
                struct amdgpu_mn_node *node;
                struct amdgpu_bo *bo;
 
+               if (!blockable) {
+                       amdgpu_mn_read_unlock(amn);
+                       return -EAGAIN;
+               }
+
                node = container_of(it, struct amdgpu_mn_node, it);
                it = interval_tree_iter_next(it, start, end);
 
@@ -304,6 +329,8 @@ static void amdgpu_mn_invalidate_range_start_hsa(struct mmu_notifier *mn,
                                amdgpu_amdkfd_evict_userptr(mem, mm);
                }
        }
+
+       return 0;
 }
 
 /**
index 86a0715..1cafe8d 100644 (file)
@@ -53,9 +53,8 @@ static int amdgpu_sched_process_priority_override(struct amdgpu_device *adev,
                                                  int fd,
                                                  enum drm_sched_priority priority)
 {
-       struct file *filp = fcheck(fd);
+       struct file *filp = fget(fd);
        struct drm_file *file;
-       struct pid *pid;
        struct amdgpu_fpriv *fpriv;
        struct amdgpu_ctx *ctx;
        uint32_t id;
@@ -63,20 +62,12 @@ static int amdgpu_sched_process_priority_override(struct amdgpu_device *adev,
        if (!filp)
                return -EINVAL;
 
-       pid = get_pid(((struct drm_file *)filp->private_data)->pid);
+       file = filp->private_data;
+       fpriv = file->driver_priv;
+       idr_for_each_entry(&fpriv->ctx_mgr.ctx_handles, ctx, id)
+               amdgpu_ctx_priority_override(ctx, priority);
 
-       mutex_lock(&adev->ddev->filelist_mutex);
-       list_for_each_entry(file, &adev->ddev->filelist, lhead) {
-               if (file->pid != pid)
-                       continue;
-
-               fpriv = file->driver_priv;
-               idr_for_each_entry(&fpriv->ctx_mgr.ctx_handles, ctx, id)
-                               amdgpu_ctx_priority_override(ctx, priority);
-       }
-       mutex_unlock(&adev->ddev->filelist_mutex);
-
-       put_pid(pid);
+       fput(filp);
 
        return 0;
 }
index 52778de..2d44735 100644 (file)
@@ -38,6 +38,7 @@ int vega20_reg_base_init(struct amdgpu_device *adev)
                adev->reg_offset[ATHUB_HWIP][i] = (uint32_t *)(&(ATHUB_BASE.instance[i]));
                adev->reg_offset[NBIO_HWIP][i] = (uint32_t *)(&(NBIO_BASE.instance[i]));
                adev->reg_offset[MP0_HWIP][i] = (uint32_t *)(&(MP0_BASE.instance[i]));
+               adev->reg_offset[MP1_HWIP][i] = (uint32_t *)(&(MP1_BASE.instance[i]));
                adev->reg_offset[UVD_HWIP][i] = (uint32_t *)(&(UVD_BASE.instance[i]));
                adev->reg_offset[VCE_HWIP][i] = (uint32_t *)(&(VCE_BASE.instance[i]));
                adev->reg_offset[DF_HWIP][i] = (uint32_t *)(&(DF_BASE.instance[i]));
@@ -46,6 +47,8 @@ int vega20_reg_base_init(struct amdgpu_device *adev)
                adev->reg_offset[SDMA0_HWIP][i] = (uint32_t *)(&(SDMA0_BASE.instance[i]));
                adev->reg_offset[SDMA1_HWIP][i] = (uint32_t *)(&(SDMA1_BASE.instance[i]));
                adev->reg_offset[SMUIO_HWIP][i] = (uint32_t *)(&(SMUIO_BASE.instance[i]));
+               adev->reg_offset[NBIF_HWIP][i] = (uint32_t *)(&(NBIO_BASE.instance[i]));
+               adev->reg_offset[THM_HWIP][i] = (uint32_t *)(&(THM_BASE.instance[i]));
        }
        return 0;
 }
index 42c8ad1..88b57a5 100644 (file)
@@ -112,8 +112,8 @@ static u32 vi_smc_rreg(struct amdgpu_device *adev, u32 reg)
        u32 r;
 
        spin_lock_irqsave(&adev->smc_idx_lock, flags);
-       WREG32(mmSMC_IND_INDEX_11, (reg));
-       r = RREG32(mmSMC_IND_DATA_11);
+       WREG32_NO_KIQ(mmSMC_IND_INDEX_11, (reg));
+       r = RREG32_NO_KIQ(mmSMC_IND_DATA_11);
        spin_unlock_irqrestore(&adev->smc_idx_lock, flags);
        return r;
 }
index 325083b..ed654a7 100644 (file)
@@ -4,11 +4,17 @@ menu "Display Engine Configuration"
 config DRM_AMD_DC
        bool "AMD DC - Enable new display engine"
        default y
+       select DRM_AMD_DC_DCN1_0 if X86 && !(KCOV_INSTRUMENT_ALL && KCOV_ENABLE_COMPARISONS)
        help
          Choose this option if you want to use the new display engine
          support for AMDGPU. This adds required support for Vega and
          Raven ASICs.
 
+config DRM_AMD_DC_DCN1_0
+       def_bool n
+       help
+         RV family support for display engine
+
 config DEBUG_KERNEL_DC
        bool "Enable kgdb break in DC"
        depends on DRM_AMD_DC
index 34f3482..800f481 100644 (file)
@@ -58,9 +58,7 @@
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_edid.h>
 
-#include "modules/inc/mod_freesync.h"
-
-#ifdef CONFIG_X86
+#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
 #include "ivsrcid/irqsrcs_dcn_1_0.h"
 
 #include "dcn/dcn_1_0_offset.h"
@@ -1192,7 +1190,7 @@ static int dce110_register_irq_handlers(struct amdgpu_device *adev)
        return 0;
 }
 
-#ifdef CONFIG_X86
+#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
 /* Register IRQ sources and initialize IRQ callbacks */
 static int dcn10_register_irq_handlers(struct amdgpu_device *adev)
 {
@@ -1532,7 +1530,7 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)
                        goto fail;
                }
                break;
-#ifdef CONFIG_X86
+#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
        case CHIP_RAVEN:
                if (dcn10_register_irq_handlers(dm->adev)) {
                        DRM_ERROR("DM: Failed to initialize IRQ\n");
@@ -1716,7 +1714,7 @@ static int dm_early_init(void *handle)
                adev->mode_info.num_dig = 6;
                adev->mode_info.plane_type = dm_plane_type_default;
                break;
-#ifdef CONFIG_X86
+#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
        case CHIP_RAVEN:
                adev->mode_info.num_crtc = 4;
                adev->mode_info.num_hpd = 4;
index 532a515..aed538a 100644 (file)
@@ -25,7 +25,7 @@
 
 DC_LIBS = basics bios calcs dce gpio i2caux irq virtual
 
-ifdef CONFIG_X86
+ifdef CONFIG_DRM_AMD_DC_DCN1_0
 DC_LIBS += dcn10 dml
 endif
 
index 770ff89..bbbcef5 100644 (file)
@@ -55,7 +55,7 @@ bool dal_bios_parser_init_cmd_tbl_helper2(
        case DCE_VERSION_11_22:
                *h = dal_cmd_tbl_helper_dce112_get_table2();
                return true;
-#ifdef CONFIG_X86
+#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
        case DCN_VERSION_1_0:
                *h = dal_cmd_tbl_helper_dce112_get_table2();
                return true;
index 416500e..95f332e 100644 (file)
@@ -38,7 +38,7 @@ CFLAGS_dcn_calc_math.o := $(calcs_ccflags) -Wno-tautological-compare
 
 BW_CALCS = dce_calcs.o bw_fixed.o custom_float.o
 
-ifdef CONFIG_X86
+ifdef CONFIG_DRM_AMD_DC_DCN1_0
 BW_CALCS += dcn_calcs.o dcn_calc_math.o dcn_calc_auto.o
 endif
 
index 733ac22..6ae050d 100644 (file)
@@ -52,6 +52,8 @@
 #include "dm_helpers.h"
 #include "mem_input.h"
 #include "hubp.h"
+
+#include "dc_link_dp.h"
 #define DC_LOGGER \
        dc->ctx->logger
 
@@ -419,8 +421,17 @@ void dc_link_set_preferred_link_settings(struct dc *dc,
                                         struct dc_link_settings *link_setting,
                                         struct dc_link *link)
 {
-       link->preferred_link_setting = *link_setting;
-       dp_retrain_link_dp_test(link, link_setting, false);
+       struct dc_link_settings store_settings = *link_setting;
+       struct dc_stream_state *link_stream =
+               link->dc->current_state->res_ctx.pipe_ctx[0].stream;
+
+       link->preferred_link_setting = store_settings;
+       if (link_stream)
+               decide_link_settings(link_stream, &store_settings);
+
+       if ((store_settings.lane_count != LANE_COUNT_UNKNOWN) &&
+               (store_settings.link_rate != LINK_RATE_UNKNOWN))
+               dp_retrain_link_dp_test(link, &store_settings, false);
 }
 
 void dc_link_enable_hpd(const struct dc_link *link)
@@ -476,7 +487,7 @@ static void destruct(struct dc *dc)
        kfree(dc->bw_dceip);
        dc->bw_dceip = NULL;
 
-#ifdef CONFIG_X86
+#ifdef CONFIG_DRM_AMD_DC_DCN1_0
        kfree(dc->dcn_soc);
        dc->dcn_soc = NULL;
 
@@ -492,7 +503,7 @@ static bool construct(struct dc *dc,
        struct dc_context *dc_ctx;
        struct bw_calcs_dceip *dc_dceip;
        struct bw_calcs_vbios *dc_vbios;
-#ifdef CONFIG_X86
+#ifdef CONFIG_DRM_AMD_DC_DCN1_0
        struct dcn_soc_bounding_box *dcn_soc;
        struct dcn_ip_params *dcn_ip;
 #endif
@@ -514,7 +525,7 @@ static bool construct(struct dc *dc,
        }
 
        dc->bw_vbios = dc_vbios;
-#ifdef CONFIG_X86
+#ifdef CONFIG_DRM_AMD_DC_DCN1_0
        dcn_soc = kzalloc(sizeof(*dcn_soc), GFP_KERNEL);
        if (!dcn_soc) {
                dm_error("%s: failed to create dcn_soc\n", __func__);
index caece7c..e1ebdf7 100644 (file)
@@ -348,7 +348,7 @@ void context_clock_trace(
                struct dc *dc,
                struct dc_state *context)
 {
-#ifdef CONFIG_X86
+#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
        DC_LOGGER_INIT(dc->ctx->logger);
        CLOCK_TRACE("Current: dispclk_khz:%d  max_dppclk_khz:%d  dcfclk_khz:%d\n"
                        "dcfclk_deep_sleep_khz:%d  fclk_khz:%d  socclk_khz:%d\n",
index 326b3e9..5678679 100644 (file)
@@ -1039,9 +1039,6 @@ static bool construct(
 
        link->link_id = bios->funcs->get_connector_id(bios, init_params->connector_index);
 
-       if (dc_ctx->dc_bios->integrated_info)
-               link->dp_ss_off = !!dc_ctx->dc_bios->integrated_info->dp_ss_control;
-
        if (link->link_id.type != OBJECT_TYPE_CONNECTOR) {
                dm_error("%s: Invalid Connector ObjectID from Adapter Service for connector index:%d! type %d expected %d\n",
                         __func__, init_params->connector_index,
@@ -1049,6 +1046,9 @@ static bool construct(
                goto create_fail;
        }
 
+       if (link->dc->res_pool->funcs->link_init)
+               link->dc->res_pool->funcs->link_init(link);
+
        hpd_gpio = get_hpd_gpio(link->ctx->dc_bios, link->link_id, link->ctx->gpio_service);
 
        if (hpd_gpio != NULL)
index 1644f2a..ea6becc 100644 (file)
@@ -41,7 +41,7 @@
 #include "dce100/dce100_resource.h"
 #include "dce110/dce110_resource.h"
 #include "dce112/dce112_resource.h"
-#ifdef CONFIG_X86
+#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
 #include "dcn10/dcn10_resource.h"
 #endif
 #include "dce120/dce120_resource.h"
@@ -85,7 +85,7 @@ enum dce_version resource_parse_asic_id(struct hw_asic_id asic_id)
        case FAMILY_AI:
                dc_version = DCE_VERSION_12_0;
                break;
-#ifdef CONFIG_X86
+#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
        case FAMILY_RV:
                dc_version = DCN_VERSION_1_0;
                break;
@@ -136,7 +136,7 @@ struct resource_pool *dc_create_resource_pool(
                        num_virtual_links, dc);
                break;
 
-#ifdef CONFIG_X86
+#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
        case DCN_VERSION_1_0:
                res_pool = dcn10_create_resource_pool(
                                num_virtual_links, dc);
@@ -1251,7 +1251,7 @@ static struct pipe_ctx *acquire_free_pipe_for_stream(
 
 }
 
-#ifdef CONFIG_X86
+#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
 static int acquire_first_split_pipe(
                struct resource_context *res_ctx,
                const struct resource_pool *pool,
@@ -1322,7 +1322,7 @@ bool dc_add_plane_to_context(
 
        free_pipe = acquire_free_pipe_for_stream(context, pool, stream);
 
-#ifdef CONFIG_X86
+#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
        if (!free_pipe) {
                int pipe_idx = acquire_first_split_pipe(&context->res_ctx, pool, stream);
                if (pipe_idx >= 0)
@@ -1920,7 +1920,7 @@ enum dc_status resource_map_pool_resources(
        /* acquire new resources */
        pipe_idx = acquire_first_free_pipe(&context->res_ctx, pool, stream);
 
-#ifdef CONFIG_X86
+#ifdef CONFIG_DRM_AMD_DC_DCN1_0
        if (pipe_idx < 0)
                pipe_idx = acquire_first_split_pipe(&context->res_ctx, pool, stream);
 #endif
index e2f033d..6c9990b 100644 (file)
@@ -294,7 +294,7 @@ struct dc {
        /* Inputs into BW and WM calculations. */
        struct bw_calcs_dceip *bw_dceip;
        struct bw_calcs_vbios *bw_vbios;
-#ifdef CONFIG_X86
+#ifdef CONFIG_DRM_AMD_DC_DCN1_0
        struct dcn_soc_bounding_box *dcn_soc;
        struct dcn_ip_params *dcn_ip;
        struct display_mode_lib dml;
index 439dcf3..ca13775 100644 (file)
@@ -592,7 +592,7 @@ static uint32_t dce110_get_pix_clk_dividers(
        case DCE_VERSION_11_2:
        case DCE_VERSION_11_22:
        case DCE_VERSION_12_0:
-#ifdef CONFIG_X86
+#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
        case DCN_VERSION_1_0:
 #endif
 
@@ -909,7 +909,7 @@ static bool dce110_program_pix_clk(
        struct dce110_clk_src *clk_src = TO_DCE110_CLK_SRC(clock_source);
        struct bp_pixel_clock_parameters bp_pc_params = {0};
 
-#ifdef CONFIG_X86
+#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
        if (IS_FPGA_MAXIMUS_DC(clock_source->ctx->dce_environment)) {
                unsigned int inst = pix_clk_params->controller_id - CONTROLLER_ID_D0;
                unsigned dp_dto_ref_kHz = 700000;
@@ -982,7 +982,7 @@ static bool dce110_program_pix_clk(
        case DCE_VERSION_11_2:
        case DCE_VERSION_11_22:
        case DCE_VERSION_12_0:
-#ifdef CONFIG_X86
+#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
        case DCN_VERSION_1_0:
 #endif
 
index 801bb65..c45e2f7 100644 (file)
@@ -55,7 +55,7 @@
        CS_SF(PHYPLLA_PIXCLK_RESYNC_CNTL, PHYPLLA_DCCG_DEEP_COLOR_CNTL, mask_sh),\
        CS_SF(PHYPLLA_PIXCLK_RESYNC_CNTL, PHYPLLA_PIXCLK_DOUBLE_RATE_ENABLE, mask_sh)
 
-#ifdef CONFIG_X86
+#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
 
 #define CS_COMMON_REG_LIST_DCN1_0(index, pllid) \
                SRI(PIXCLK_RESYNC_CNTL, PHYPLL, pllid),\
index 684da3d..fb1f373 100644 (file)
@@ -30,7 +30,7 @@
 #include "bios_parser_interface.h"
 #include "dc.h"
 #include "dmcu.h"
-#ifdef CONFIG_X86
+#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
 #include "dcn_calcs.h"
 #endif
 #include "core_types.h"
@@ -106,7 +106,8 @@ enum dentist_base_divider_id {
        DENTIST_BASE_DID_1 = 0x08,
        DENTIST_BASE_DID_2 = 0x40,
        DENTIST_BASE_DID_3 = 0x60,
-       DENTIST_MAX_DID    = 0x80
+       DENTIST_BASE_DID_4 = 0x7e,
+       DENTIST_MAX_DID = 0x7f
 };
 
 /* Starting point and step size for each divider range.*/
@@ -117,6 +118,8 @@ enum dentist_divider_range {
        DENTIST_DIVIDER_RANGE_2_STEP  = 2,   /* 0.50  */
        DENTIST_DIVIDER_RANGE_3_START = 128, /* 32.00 */
        DENTIST_DIVIDER_RANGE_3_STEP  = 4,   /* 1.00  */
+       DENTIST_DIVIDER_RANGE_4_START = 248, /* 62.00 */
+       DENTIST_DIVIDER_RANGE_4_STEP  = 264, /* 66.00 */
        DENTIST_DIVIDER_RANGE_SCALE_FACTOR = 4
 };
 
@@ -133,9 +136,12 @@ static int dentist_get_divider_from_did(int did)
        } else if (did < DENTIST_BASE_DID_3) {
                return DENTIST_DIVIDER_RANGE_2_START + DENTIST_DIVIDER_RANGE_2_STEP
                                                        * (did - DENTIST_BASE_DID_2);
-       } else {
+       } else if (did < DENTIST_BASE_DID_4) {
                return DENTIST_DIVIDER_RANGE_3_START + DENTIST_DIVIDER_RANGE_3_STEP
                                                        * (did - DENTIST_BASE_DID_3);
+       } else {
+               return DENTIST_DIVIDER_RANGE_4_START + DENTIST_DIVIDER_RANGE_4_STEP
+                                                       * (did - DENTIST_BASE_DID_4);
        }
 }
 
@@ -478,7 +484,7 @@ static void dce12_update_clocks(struct dccg *dccg,
        }
 }
 
-#ifdef CONFIG_X86
+#ifdef CONFIG_DRM_AMD_DC_DCN1_0
 static int dcn1_determine_dppclk_threshold(struct dccg *dccg, struct dc_clocks *new_clocks)
 {
        bool request_dpp_div = new_clocks->dispclk_khz > new_clocks->dppclk_khz;
@@ -668,7 +674,7 @@ static void dce_update_clocks(struct dccg *dccg,
        }
 }
 
-#ifdef CONFIG_X86
+#ifdef CONFIG_DRM_AMD_DC_DCN1_0
 static const struct display_clock_funcs dcn1_funcs = {
        .get_dp_ref_clk_frequency = dce12_get_dp_ref_freq_khz,
        .set_dispclk = dce112_set_clock,
@@ -823,7 +829,7 @@ struct dccg *dce120_dccg_create(struct dc_context *ctx)
        return &clk_dce->base;
 }
 
-#ifdef CONFIG_X86
+#ifdef CONFIG_DRM_AMD_DC_DCN1_0
 struct dccg *dcn1_dccg_create(struct dc_context *ctx)
 {
        struct dc_debug_options *debug = &ctx->dc->debug;
index e5e44ad..8a6b2d3 100644 (file)
@@ -111,7 +111,7 @@ struct dccg *dce112_dccg_create(
 
 struct dccg *dce120_dccg_create(struct dc_context *ctx);
 
-#ifdef CONFIG_X86
+#ifdef CONFIG_DRM_AMD_DC_DCN1_0
 struct dccg *dcn1_dccg_create(struct dc_context *ctx);
 #endif
 
index ca7989e..dea40b3 100644 (file)
@@ -316,7 +316,7 @@ static void dce_get_psr_wait_loop(
        return;
 }
 
-#ifdef CONFIG_X86
+#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
 static void dcn10_get_dmcu_state(struct dmcu *dmcu)
 {
        struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(dmcu);
@@ -743,7 +743,7 @@ static const struct dmcu_funcs dce_funcs = {
        .is_dmcu_initialized = dce_is_dmcu_initialized
 };
 
-#ifdef CONFIG_X86
+#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
 static const struct dmcu_funcs dcn10_funcs = {
        .dmcu_init = dcn10_dmcu_init,
        .load_iram = dcn10_dmcu_load_iram,
@@ -795,7 +795,7 @@ struct dmcu *dce_dmcu_create(
        return &dmcu_dce->base;
 }
 
-#ifdef CONFIG_X86
+#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
 struct dmcu *dcn10_dmcu_create(
        struct dc_context *ctx,
        const struct dce_dmcu_registers *regs,
index b139b40..91642e6 100644 (file)
@@ -135,7 +135,7 @@ static void dce110_update_generic_info_packet(
                        AFMT_GENERIC0_UPDATE, (packet_index == 0),
                        AFMT_GENERIC2_UPDATE, (packet_index == 2));
        }
-#ifdef CONFIG_X86
+#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
        if (REG(AFMT_VBI_PACKET_CONTROL1)) {
                switch (packet_index) {
                case 0:
@@ -229,7 +229,7 @@ static void dce110_update_hdmi_info_packet(
                                HDMI_GENERIC1_SEND, send,
                                HDMI_GENERIC1_LINE, line);
                break;
-#ifdef CONFIG_X86
+#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
        case 4:
                if (REG(HDMI_GENERIC_PACKET_CONTROL2))
                        REG_UPDATE_3(HDMI_GENERIC_PACKET_CONTROL2,
@@ -274,7 +274,7 @@ static void dce110_stream_encoder_dp_set_stream_attribute(
        struct dc_crtc_timing *crtc_timing,
        enum dc_color_space output_color_space)
 {
-#ifdef CONFIG_X86
+#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
        uint32_t h_active_start;
        uint32_t v_active_start;
        uint32_t misc0 = 0;
@@ -317,7 +317,7 @@ static void dce110_stream_encoder_dp_set_stream_attribute(
                if (enc110->se_mask->DP_VID_M_DOUBLE_VALUE_EN)
                        REG_UPDATE(DP_VID_TIMING, DP_VID_M_DOUBLE_VALUE_EN, 1);
 
-#ifdef CONFIG_X86
+#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
                if (enc110->se_mask->DP_VID_N_MUL)
                        REG_UPDATE(DP_VID_TIMING, DP_VID_N_MUL, 1);
 #endif
@@ -328,7 +328,7 @@ static void dce110_stream_encoder_dp_set_stream_attribute(
                break;
        }
 
-#ifdef CONFIG_X86
+#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
        if (REG(DP_MSA_MISC))
                misc1 = REG_READ(DP_MSA_MISC);
 #endif
@@ -362,7 +362,7 @@ static void dce110_stream_encoder_dp_set_stream_attribute(
        /* set dynamic range and YCbCr range */
 
 
-#ifdef CONFIG_X86
+#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
        switch (crtc_timing->display_color_depth) {
        case COLOR_DEPTH_666:
                colorimetry_bpc = 0;
@@ -441,7 +441,7 @@ static void dce110_stream_encoder_dp_set_stream_attribute(
                                DP_DYN_RANGE, dynamic_range_rgb,
                                DP_YCBCR_RANGE, dynamic_range_ycbcr);
 
-#ifdef CONFIG_X86
+#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
                if (REG(DP_MSA_COLORIMETRY))
                        REG_SET(DP_MSA_COLORIMETRY, 0, DP_MSA_MISC0, misc0);
 
@@ -476,7 +476,7 @@ static void dce110_stream_encoder_dp_set_stream_attribute(
                                crtc_timing->v_front_porch;
 
 
-#ifdef CONFIG_X86
+#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
                /* start at begining of left border */
                if (REG(DP_MSA_TIMING_PARAM2))
                        REG_SET_2(DP_MSA_TIMING_PARAM2, 0,
@@ -751,7 +751,7 @@ static void dce110_stream_encoder_update_hdmi_info_packets(
                dce110_update_hdmi_info_packet(enc110, 3, &info_frame->hdrsmd);
        }
 
-#ifdef CONFIG_X86
+#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
        if (enc110->se_mask->HDMI_DB_DISABLE) {
                /* for bring up, disable dp double  TODO */
                if (REG(HDMI_DB_CONTROL))
@@ -789,7 +789,7 @@ static void dce110_stream_encoder_stop_hdmi_info_packets(
                HDMI_GENERIC1_LINE, 0,
                HDMI_GENERIC1_SEND, 0);
 
-#ifdef CONFIG_X86
+#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
        /* stop generic packets 2 & 3 on HDMI */
        if (REG(HDMI_GENERIC_PACKET_CONTROL2))
                REG_SET_6(HDMI_GENERIC_PACKET_CONTROL2, 0,
index 5450d4d..14384d9 100644 (file)
@@ -1250,7 +1250,7 @@ static void program_scaler(const struct dc *dc,
 {
        struct tg_color color = {0};
 
-#ifdef CONFIG_X86
+#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
        /* TOFPGA */
        if (pipe_ctx->plane_res.xfm->funcs->transform_set_pixel_storage_depth == NULL)
                return;
@@ -1588,7 +1588,13 @@ void dce110_enable_accelerated_mode(struct dc *dc, struct dc_state *context)
        bool can_eDP_fast_boot_optimize = false;
 
        if (edp_link) {
-               can_eDP_fast_boot_optimize =
+               /* this seems to cause blank screens on DCE8 */
+               if ((dc->ctx->dce_version == DCE_VERSION_8_0) ||
+                   (dc->ctx->dce_version == DCE_VERSION_8_1) ||
+                   (dc->ctx->dce_version == DCE_VERSION_8_3))
+                       can_eDP_fast_boot_optimize = false;
+               else
+                       can_eDP_fast_boot_optimize =
                                edp_link->link_enc->funcs->is_dig_enabled(edp_link->link_enc);
        }
 
index b9d9930..562ee18 100644 (file)
@@ -61,7 +61,7 @@ AMD_DISPLAY_FILES += $(AMD_DAL_GPIO_DCE120)
 ###############################################################################
 # DCN 1x
 ###############################################################################
-ifdef CONFIG_X86
+ifdef CONFIG_DRM_AMD_DC_DCN1_0
 GPIO_DCN10 = hw_translate_dcn10.o hw_factory_dcn10.o
 
 AMD_DAL_GPIO_DCN10 = $(addprefix $(AMDDALPATH)/dc/gpio/dcn10/,$(GPIO_DCN10))
index 83df779..0caee35 100644 (file)
@@ -43,7 +43,7 @@
 #include "dce80/hw_factory_dce80.h"
 #include "dce110/hw_factory_dce110.h"
 #include "dce120/hw_factory_dce120.h"
-#ifdef CONFIG_X86
+#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
 #include "dcn10/hw_factory_dcn10.h"
 #endif
 
@@ -81,7 +81,7 @@ bool dal_hw_factory_init(
        case DCE_VERSION_12_0:
                dal_hw_factory_dce120_init(factory);
                return true;
-#ifdef CONFIG_X86
+#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
        case DCN_VERSION_1_0:
                dal_hw_factory_dcn10_init(factory);
                return true;
index e754131..55c7074 100644 (file)
@@ -43,7 +43,7 @@
 #include "dce80/hw_translate_dce80.h"
 #include "dce110/hw_translate_dce110.h"
 #include "dce120/hw_translate_dce120.h"
-#ifdef CONFIG_X86
+#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
 #include "dcn10/hw_translate_dcn10.h"
 #endif
 
@@ -78,7 +78,7 @@ bool dal_hw_translate_init(
        case DCE_VERSION_12_0:
                dal_hw_translate_dce120_init(translate);
                return true;
-#ifdef CONFIG_X86
+#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
        case DCN_VERSION_1_0:
                dal_hw_translate_dcn10_init(translate);
                return true;
index a851d07..352885c 100644 (file)
@@ -71,7 +71,7 @@ AMD_DISPLAY_FILES += $(AMD_DAL_I2CAUX_DCE112)
 ###############################################################################
 # DCN 1.0 family
 ###############################################################################
-ifdef CONFIG_X86
+ifdef CONFIG_DRM_AMD_DC_DCN1_0
 I2CAUX_DCN1 = i2caux_dcn10.o
 
 AMD_DAL_I2CAUX_DCN1 = $(addprefix $(AMDDALPATH)/dc/i2caux/dcn10/,$(I2CAUX_DCN1))
index f7ed355..9b0bcc6 100644 (file)
@@ -59,7 +59,7 @@
 
 #include "dce120/i2caux_dce120.h"
 
-#ifdef CONFIG_X86
+#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
 #include "dcn10/i2caux_dcn10.h"
 #endif
 
@@ -91,7 +91,7 @@ struct i2caux *dal_i2caux_create(
                return dal_i2caux_dce100_create(ctx);
        case DCE_VERSION_12_0:
                return dal_i2caux_dce120_create(ctx);
-#ifdef CONFIG_X86
+#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
        case DCN_VERSION_1_0:
                return dal_i2caux_dcn10_create(ctx);
 #endif
index 9f33306..c0b9ca1 100644 (file)
@@ -33,7 +33,7 @@
 #include "dc_bios_types.h"
 #include "mem_input.h"
 #include "hubp.h"
-#ifdef CONFIG_X86
+#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
 #include "mpc.h"
 #endif
 
@@ -92,6 +92,7 @@ struct resource_context;
 
 struct resource_funcs {
        void (*destroy)(struct resource_pool **pool);
+       void (*link_init)(struct dc_link *link);
        struct link_encoder *(*link_enc_create)(
                        const struct encoder_init_data *init);
 
@@ -221,7 +222,7 @@ struct pipe_ctx {
        struct pipe_ctx *top_pipe;
        struct pipe_ctx *bottom_pipe;
 
-#ifdef CONFIG_X86
+#ifdef CONFIG_DRM_AMD_DC_DCN1_0
        struct _vcs_dpi_display_dlg_regs_st dlg_regs;
        struct _vcs_dpi_display_ttu_regs_st ttu_regs;
        struct _vcs_dpi_display_rq_regs_st rq_regs;
@@ -276,7 +277,7 @@ struct dc_state {
 
        /* Note: these are big structures, do *not* put on stack! */
        struct dm_pp_display_configuration pp_display_cfg;
-#ifdef CONFIG_X86
+#ifdef CONFIG_DRM_AMD_DC_DCN1_0
        struct dcn_bw_internal_vars dcn_bw_vars;
 #endif
 
index a76ee60..498515a 100644 (file)
@@ -60,7 +60,7 @@ AMD_DISPLAY_FILES += $(AMD_DAL_IRQ_DCE12)
 ###############################################################################
 # DCN 1x
 ###############################################################################
-ifdef CONFIG_X86
+ifdef CONFIG_DRM_AMD_DC_DCN1_0
 IRQ_DCN1 = irq_service_dcn10.o
 
 AMD_DAL_IRQ_DCN1 = $(addprefix $(AMDDALPATH)/dc/irq/dcn10/,$(IRQ_DCN1))
index ae3fd0a..604bea0 100644 (file)
@@ -36,7 +36,7 @@
 #include "dce120/irq_service_dce120.h"
 
 
-#ifdef CONFIG_X86
+#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
 #include "dcn10/irq_service_dcn10.h"
 #endif
 
index c9fce90..a407892 100644 (file)
@@ -48,7 +48,7 @@
 
 #define dm_error(fmt, ...) DRM_ERROR(fmt, ##__VA_ARGS__)
 
-#ifdef CONFIG_X86
+#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
 #include <asm/fpu/api.h>
 #endif
 
index 53207e7..6ef3c87 100644 (file)
@@ -75,10 +75,12 @@ int phm_set_power_state(struct pp_hwmgr *hwmgr,
 
 int phm_enable_dynamic_state_management(struct pp_hwmgr *hwmgr)
 {
+       struct amdgpu_device *adev = NULL;
        int ret = -EINVAL;;
        PHM_FUNC_CHECK(hwmgr);
+       adev = hwmgr->adev;
 
-       if (smum_is_dpm_running(hwmgr)) {
+       if (smum_is_dpm_running(hwmgr) && !amdgpu_passthrough(adev)) {
                pr_info("dpm has been enabled\n");
                return 0;
        }
index 5dc742b..3c9fc99 100644 (file)
@@ -116,6 +116,9 @@ static const struct edid_quirk {
        /* CPT panel of Asus UX303LA reports 8 bpc, but is a 6 bpc panel */
        { "CPT", 0x17df, EDID_QUIRK_FORCE_6BPC },
 
+       /* SDC panel of Lenovo B50-80 reports 8 bpc, but is a 6 bpc panel */
+       { "SDC", 0x3652, EDID_QUIRK_FORCE_6BPC },
+
        /* Belinea 10 15 55 */
        { "MAX", 1516, EDID_QUIRK_PREFER_LARGE_60 },
        { "MAX", 0x77e, EDID_QUIRK_PREFER_LARGE_60 },
index 2f00a37..adefae5 100644 (file)
@@ -108,7 +108,7 @@ static int psbfb_pan(struct fb_var_screeninfo *var, struct fb_info *info)
         return 0;
 }
 
-static int psbfb_vm_fault(struct vm_fault *vmf)
+static vm_fault_t psbfb_vm_fault(struct vm_fault *vmf)
 {
        struct vm_area_struct *vma = vmf->vma;
        struct psb_framebuffer *psbfb = vma->vm_private_data;
@@ -118,7 +118,7 @@ static int psbfb_vm_fault(struct vm_fault *vmf)
        int page_num;
        int i;
        unsigned long address;
-       int ret;
+       vm_fault_t ret = VM_FAULT_SIGBUS;
        unsigned long pfn;
        unsigned long phys_addr = (unsigned long)dev_priv->stolen_base +
                                  gtt->offset;
@@ -131,18 +131,14 @@ static int psbfb_vm_fault(struct vm_fault *vmf)
        for (i = 0; i < page_num; i++) {
                pfn = (phys_addr >> PAGE_SHIFT);
 
-               ret = vm_insert_mixed(vma, address,
+               ret = vmf_insert_mixed(vma, address,
                                __pfn_to_pfn_t(pfn, PFN_DEV));
-               if (unlikely((ret == -EBUSY) || (ret != 0 && i > 0)))
+               if (unlikely(ret & VM_FAULT_ERROR))
                        break;
-               else if (unlikely(ret != 0)) {
-                       ret = (ret == -ENOMEM) ? VM_FAULT_OOM : VM_FAULT_SIGBUS;
-                       return ret;
-               }
                address += PAGE_SIZE;
                phys_addr += PAGE_SIZE;
        }
-       return VM_FAULT_NOPAGE;
+       return ret;
 }
 
 static void psbfb_vm_open(struct vm_area_struct *vma)
index 913bf4c..576f1b2 100644 (file)
@@ -134,12 +134,13 @@ int psb_gem_dumb_create(struct drm_file *file, struct drm_device *dev,
  *     vma->vm_private_data points to the GEM object that is backing this
  *     mapping.
  */
-int psb_gem_fault(struct vm_fault *vmf)
+vm_fault_t psb_gem_fault(struct vm_fault *vmf)
 {
        struct vm_area_struct *vma = vmf->vma;
        struct drm_gem_object *obj;
        struct gtt_range *r;
-       int ret;
+       int err;
+       vm_fault_t ret;
        unsigned long pfn;
        pgoff_t page_offset;
        struct drm_device *dev;
@@ -158,9 +159,10 @@ int psb_gem_fault(struct vm_fault *vmf)
        /* For now the mmap pins the object and it stays pinned. As things
           stand that will do us no harm */
        if (r->mmapping == 0) {
-               ret = psb_gtt_pin(r);
-               if (ret < 0) {
-                       dev_err(dev->dev, "gma500: pin failed: %d\n", ret);
+               err = psb_gtt_pin(r);
+               if (err < 0) {
+                       dev_err(dev->dev, "gma500: pin failed: %d\n", err);
+                       ret = vmf_error(err);
                        goto fail;
                }
                r->mmapping = 1;
@@ -175,18 +177,9 @@ int psb_gem_fault(struct vm_fault *vmf)
                pfn = (dev_priv->stolen_base + r->offset) >> PAGE_SHIFT;
        else
                pfn = page_to_pfn(r->pages[page_offset]);
-       ret = vm_insert_pfn(vma, vmf->address, pfn);
-
+       ret = vmf_insert_pfn(vma, vmf->address, pfn);
 fail:
        mutex_unlock(&dev_priv->mmap_mutex);
-       switch (ret) {
-       case 0:
-       case -ERESTARTSYS:
-       case -EINTR:
-               return VM_FAULT_NOPAGE;
-       case -ENOMEM:
-               return VM_FAULT_OOM;
-       default:
-               return VM_FAULT_SIGBUS;
-       }
+
+       return ret;
 }
index e8300f5..93d2f40 100644 (file)
@@ -21,6 +21,7 @@
 #define _PSB_DRV_H_
 
 #include <linux/kref.h>
+#include <linux/mm_types.h>
 
 #include <drm/drmP.h>
 #include <drm/drm_global.h>
@@ -749,7 +750,7 @@ extern int psb_gem_get_aperture(struct drm_device *dev, void *data,
                        struct drm_file *file);
 extern int psb_gem_dumb_create(struct drm_file *file, struct drm_device *dev,
                        struct drm_mode_create_dumb *args);
-extern int psb_gem_fault(struct vm_fault *vmf);
+extern vm_fault_t psb_gem_fault(struct vm_fault *vmf);
 
 /* psb_device.c */
 extern const struct psb_ops psb_chip_ops;
index 5c607f2..33a458b 100644 (file)
@@ -24,6 +24,7 @@ config DRM_I915
        select IOSF_MBI
        select CRC32
        select SND_HDA_I915 if SND_HDA_CORE
+       select CEC_CORE if CEC_NOTIFIER
        help
          Choose this option if you have a system that has "Intel Graphics
          Media Accelerator" or "HD Graphics" integrated graphics,
index dcd6e23..2c9b284 100644 (file)
@@ -112,10 +112,11 @@ static void del_object(struct i915_mmu_object *mo)
        mo->attached = false;
 }
 
-static void i915_gem_userptr_mn_invalidate_range_start(struct mmu_notifier *_mn,
+static int i915_gem_userptr_mn_invalidate_range_start(struct mmu_notifier *_mn,
                                                       struct mm_struct *mm,
                                                       unsigned long start,
-                                                      unsigned long end)
+                                                      unsigned long end,
+                                                      bool blockable)
 {
        struct i915_mmu_notifier *mn =
                container_of(_mn, struct i915_mmu_notifier, mn);
@@ -124,7 +125,7 @@ static void i915_gem_userptr_mn_invalidate_range_start(struct mmu_notifier *_mn,
        LIST_HEAD(cancelled);
 
        if (RB_EMPTY_ROOT(&mn->objects.rb_root))
-               return;
+               return 0;
 
        /* interval ranges are inclusive, but invalidate range is exclusive */
        end--;
@@ -132,6 +133,10 @@ static void i915_gem_userptr_mn_invalidate_range_start(struct mmu_notifier *_mn,
        spin_lock(&mn->lock);
        it = interval_tree_iter_first(&mn->objects, start, end);
        while (it) {
+               if (!blockable) {
+                       spin_unlock(&mn->lock);
+                       return -EAGAIN;
+               }
                /* The mmu_object is released late when destroying the
                 * GEM object so it is entirely possible to gain a
                 * reference on an object in the process of being freed
@@ -154,6 +159,8 @@ static void i915_gem_userptr_mn_invalidate_range_start(struct mmu_notifier *_mn,
 
        if (!list_empty(&cancelled))
                flush_workqueue(mn->wq);
+
+       return 0;
 }
 
 static const struct mmu_notifier_ops i915_gem_userptr_notifier = {
index 00165ad..395dd25 100644 (file)
@@ -43,7 +43,7 @@
 #define MISSING_CASE(x) WARN(1, "Missing case (%s == %ld)\n", \
                             __stringify(x), (long)(x))
 
-#if GCC_VERSION >= 70000
+#if defined(GCC_VERSION) && GCC_VERSION >= 70000
 #define add_overflows(A, B) \
        __builtin_add_overflow_p((A), (B), (typeof((A) + (B)))0)
 #else
index 9292001..138a1bc 100644 (file)
@@ -126,6 +126,30 @@ enum port {
 
 #define port_name(p) ((p) + 'A')
 
+/*
+ * Ports identifier referenced from other drivers.
+ * Expected to remain stable over time
+ */
+static inline const char *port_identifier(enum port port)
+{
+       switch (port) {
+       case PORT_A:
+               return "Port A";
+       case PORT_B:
+               return "Port B";
+       case PORT_C:
+               return "Port C";
+       case PORT_D:
+               return "Port D";
+       case PORT_E:
+               return "Port E";
+       case PORT_F:
+               return "Port F";
+       default:
+               return "<invalid>";
+       }
+}
+
 enum tc_port {
        PORT_TC_NONE = -1,
 
index 17af06d..8fc61e9 100644 (file)
@@ -39,6 +39,7 @@
 #include <drm/drm_dp_mst_helper.h>
 #include <drm/drm_rect.h>
 #include <drm/drm_atomic.h>
+#include <media/cec-notifier.h>
 
 /**
  * __wait_for - magic wait macro
@@ -1016,6 +1017,7 @@ struct intel_hdmi {
        bool has_audio;
        bool rgb_quant_range_selectable;
        struct intel_connector *attached_connector;
+       struct cec_notifier *cec_notifier;
 };
 
 struct intel_dp_mst_encoder;
index 8363fbd..a907640 100644 (file)
@@ -1899,6 +1899,8 @@ intel_hdmi_set_edid(struct drm_connector *connector)
                connected = true;
        }
 
+       cec_notifier_set_phys_addr_from_edid(intel_hdmi->cec_notifier, edid);
+
        return connected;
 }
 
@@ -1907,6 +1909,7 @@ intel_hdmi_detect(struct drm_connector *connector, bool force)
 {
        enum drm_connector_status status;
        struct drm_i915_private *dev_priv = to_i915(connector->dev);
+       struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);
 
        DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
                      connector->base.id, connector->name);
@@ -1922,6 +1925,9 @@ intel_hdmi_detect(struct drm_connector *connector, bool force)
 
        intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS);
 
+       if (status != connector_status_connected)
+               cec_notifier_phys_addr_invalidate(intel_hdmi->cec_notifier);
+
        return status;
 }
 
@@ -2062,6 +2068,8 @@ static void chv_hdmi_pre_enable(struct intel_encoder *encoder,
 
 static void intel_hdmi_destroy(struct drm_connector *connector)
 {
+       if (intel_attached_hdmi(connector)->cec_notifier)
+               cec_notifier_put(intel_attached_hdmi(connector)->cec_notifier);
        kfree(to_intel_connector(connector)->detect_edid);
        drm_connector_cleanup(connector);
        kfree(connector);
@@ -2382,6 +2390,11 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,
                u32 temp = I915_READ(PEG_BAND_GAP_DATA);
                I915_WRITE(PEG_BAND_GAP_DATA, (temp & ~0xf) | 0xd);
        }
+
+       intel_hdmi->cec_notifier = cec_notifier_get_conn(dev->dev,
+                                                        port_identifier(port));
+       if (!intel_hdmi->cec_notifier)
+               DRM_DEBUG_KMS("CEC notifier get failed\n");
 }
 
 void intel_hdmi_init(struct drm_i915_private *dev_priv,
index 5b5d0a2..97964f7 100644 (file)
@@ -1385,6 +1385,9 @@ static const struct panel_desc innolux_tv123wam = {
                .width = 259,
                .height = 173,
        },
+       .delay = {
+               .unprepare = 500,
+       },
 };
 
 static const struct drm_display_mode innolux_zj070na_01p_mode = {
index abd2497..f8b35df 100644 (file)
@@ -118,19 +118,27 @@ static void radeon_mn_release(struct mmu_notifier *mn,
  * We block for all BOs between start and end to be idle and
  * unmap them by move them into system domain again.
  */
-static void radeon_mn_invalidate_range_start(struct mmu_notifier *mn,
+static int radeon_mn_invalidate_range_start(struct mmu_notifier *mn,
                                             struct mm_struct *mm,
                                             unsigned long start,
-                                            unsigned long end)
+                                            unsigned long end,
+                                            bool blockable)
 {
        struct radeon_mn *rmn = container_of(mn, struct radeon_mn, mn);
        struct ttm_operation_ctx ctx = { false, false };
        struct interval_tree_node *it;
+       int ret = 0;
 
        /* notification is exclusive, but interval is inclusive */
        end -= 1;
 
-       mutex_lock(&rmn->lock);
+       /* TODO we should be able to split locking for interval tree and
+        * the tear down.
+        */
+       if (blockable)
+               mutex_lock(&rmn->lock);
+       else if (!mutex_trylock(&rmn->lock))
+               return -EAGAIN;
 
        it = interval_tree_iter_first(&rmn->objects, start, end);
        while (it) {
@@ -138,6 +146,11 @@ static void radeon_mn_invalidate_range_start(struct mmu_notifier *mn,
                struct radeon_bo *bo;
                long r;
 
+               if (!blockable) {
+                       ret = -EAGAIN;
+                       goto out_unlock;
+               }
+
                node = container_of(it, struct radeon_mn_node, it);
                it = interval_tree_iter_next(it, start, end);
 
@@ -166,7 +179,10 @@ static void radeon_mn_invalidate_range_start(struct mmu_notifier *mn,
                }
        }
        
+out_unlock:
        mutex_unlock(&rmn->lock);
+
+       return ret;
 }
 
 static const struct mmu_notifier_ops radeon_mn_ops = {
index ddb1e93..b93c558 100644 (file)
@@ -51,51 +51,34 @@ static int vmw_gmrid_man_get_node(struct ttm_mem_type_manager *man,
 {
        struct vmwgfx_gmrid_man *gman =
                (struct vmwgfx_gmrid_man *)man->priv;
-       int ret = 0;
        int id;
 
        mem->mm_node = NULL;
 
+       id = ida_alloc_max(&gman->gmr_ida, gman->max_gmr_ids - 1, GFP_KERNEL);
+       if (id < 0)
+               return id;
+
        spin_lock(&gman->lock);
 
        if (gman->max_gmr_pages > 0) {
                gman->used_gmr_pages += bo->num_pages;
                if (unlikely(gman->used_gmr_pages > gman->max_gmr_pages))
-                       goto out_err_locked;
+                       goto nospace;
        }
 
-       do {
-               spin_unlock(&gman->lock);
-               if (unlikely(ida_pre_get(&gman->gmr_ida, GFP_KERNEL) == 0)) {
-                       ret = -ENOMEM;
-                       goto out_err;
-               }
-               spin_lock(&gman->lock);
-
-               ret = ida_get_new(&gman->gmr_ida, &id);
-               if (unlikely(ret == 0 && id >= gman->max_gmr_ids)) {
-                       ida_remove(&gman->gmr_ida, id);
-                       ret = 0;
-                       goto out_err_locked;
-               }
-       } while (ret == -EAGAIN);
-
-       if (likely(ret == 0)) {
-               mem->mm_node = gman;
-               mem->start = id;
-               mem->num_pages = bo->num_pages;
-       } else
-               goto out_err_locked;
+       mem->mm_node = gman;
+       mem->start = id;
+       mem->num_pages = bo->num_pages;
 
        spin_unlock(&gman->lock);
        return 0;
 
-out_err:
-       spin_lock(&gman->lock);
-out_err_locked:
+nospace:
        gman->used_gmr_pages -= bo->num_pages;
        spin_unlock(&gman->lock);
-       return ret;
+       ida_free(&gman->gmr_ida, id);
+       return 0;
 }
 
 static void vmw_gmrid_man_put_node(struct ttm_mem_type_manager *man,
@@ -105,8 +88,8 @@ static void vmw_gmrid_man_put_node(struct ttm_mem_type_manager *man,
                (struct vmwgfx_gmrid_man *)man->priv;
 
        if (mem->mm_node) {
+               ida_free(&gman->gmr_ida, mem->start);
                spin_lock(&gman->lock);
-               ida_remove(&gman->gmr_ida, mem->start);
                gman->used_gmr_pages -= mem->num_pages;
                spin_unlock(&gman->lock);
                mem->mm_node = NULL;
index a49a104..61e1953 100644 (file)
@@ -207,6 +207,16 @@ config HID_CORSAIR
        - Vengeance K90
        - Scimitar PRO RGB
 
+config HID_COUGAR
+       tristate "Cougar devices"
+       depends on HID
+       help
+       Support for Cougar devices that are not fully compliant with the
+       HID standard.
+
+       Supported devices:
+       - Cougar 500k Gaming Keyboard
+
 config HID_PRODIKEYS
        tristate "Prodikeys PC-MIDI Keyboard support"
        depends on HID && SND
index 511e1cb..bd7ac53 100644 (file)
@@ -35,6 +35,7 @@ obj-$(CONFIG_HID_CHERRY)      += hid-cherry.o
 obj-$(CONFIG_HID_CHICONY)      += hid-chicony.o
 obj-$(CONFIG_HID_CMEDIA)       += hid-cmedia.o
 obj-$(CONFIG_HID_CORSAIR)      += hid-corsair.o
+obj-$(CONFIG_HID_COUGAR)       += hid-cougar.o
 obj-$(CONFIG_HID_CP2112)       += hid-cp2112.o
 obj-$(CONFIG_HID_CYPRESS)      += hid-cypress.o
 obj-$(CONFIG_HID_DRAGONRISE)   += hid-dr.o
index 3942ee6..3da354a 100644 (file)
@@ -128,9 +128,19 @@ static int open_collection(struct hid_parser *parser, unsigned type)
 
        usage = parser->local.usage[0];
 
-       if (parser->collection_stack_ptr == HID_COLLECTION_STACK_SIZE) {
-               hid_err(parser->device, "collection stack overflow\n");
-               return -EINVAL;
+       if (parser->collection_stack_ptr == parser->collection_stack_size) {
+               unsigned int *collection_stack;
+               unsigned int new_size = parser->collection_stack_size +
+                                       HID_COLLECTION_STACK_SIZE;
+
+               collection_stack = krealloc(parser->collection_stack,
+                                           new_size * sizeof(unsigned int),
+                                           GFP_KERNEL);
+               if (!collection_stack)
+                       return -ENOMEM;
+
+               parser->collection_stack = collection_stack;
+               parser->collection_stack_size = new_size;
        }
 
        if (parser->device->maxcollection == parser->device->collection_size) {
@@ -840,6 +850,7 @@ static int hid_scan_report(struct hid_device *hid)
                break;
        }
 
+       kfree(parser->collection_stack);
        vfree(parser);
        return 0;
 }
@@ -1939,6 +1950,29 @@ static int hid_bus_match(struct device *dev, struct device_driver *drv)
        return hid_match_device(hdev, hdrv) != NULL;
 }
 
+/**
+ * hid_compare_device_paths - check if both devices share the same path
+ * @hdev_a: hid device
+ * @hdev_b: hid device
+ * @separator: char to use as separator
+ *
+ * Check if two devices share the same path up to the last occurrence of
+ * the separator char. Both paths must exist (i.e., zero-length paths
+ * don't match).
+ */
+bool hid_compare_device_paths(struct hid_device *hdev_a,
+                             struct hid_device *hdev_b, char separator)
+{
+       int n1 = strrchr(hdev_a->phys, separator) - hdev_a->phys;
+       int n2 = strrchr(hdev_b->phys, separator) - hdev_b->phys;
+
+       if (n1 != n2 || n1 <= 0 || n2 <= 0)
+               return false;
+
+       return !strncmp(hdev_a->phys, hdev_b->phys, n1);
+}
+EXPORT_SYMBOL_GPL(hid_compare_device_paths);
+
 static int hid_device_probe(struct device *dev)
 {
        struct hid_driver *hdrv = to_hid_driver(dev->driver);
diff --git a/drivers/hid/hid-cougar.c b/drivers/hid/hid-cougar.c
new file mode 100644 (file)
index 0000000..ad2e87d
--- /dev/null
@@ -0,0 +1,312 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ *  HID driver for Cougar 500k Gaming Keyboard
+ *
+ *  Copyright (c) 2018 Daniel M. Lambea <dmlambea@gmail.com>
+ */
+
+#include <linux/hid.h>
+#include <linux/module.h>
+
+#include "hid-ids.h"
+
+MODULE_AUTHOR("Daniel M. Lambea <dmlambea@gmail.com>");
+MODULE_DESCRIPTION("Cougar 500k Gaming Keyboard");
+MODULE_LICENSE("GPL");
+MODULE_INFO(key_mappings, "G1-G6 are mapped to F13-F18");
+
+static int cougar_g6_is_space = 1;
+module_param_named(g6_is_space, cougar_g6_is_space, int, 0600);
+MODULE_PARM_DESC(g6_is_space,
+       "If set, G6 programmable key sends SPACE instead of F18 (0=off, 1=on) (default=1)");
+
+
+#define COUGAR_VENDOR_USAGE    0xff00ff00
+
+#define COUGAR_FIELD_CODE      1
+#define COUGAR_FIELD_ACTION    2
+
+#define COUGAR_KEY_G1          0x83
+#define COUGAR_KEY_G2          0x84
+#define COUGAR_KEY_G3          0x85
+#define COUGAR_KEY_G4          0x86
+#define COUGAR_KEY_G5          0x87
+#define COUGAR_KEY_G6          0x78
+#define COUGAR_KEY_FN          0x0d
+#define COUGAR_KEY_MR          0x6f
+#define COUGAR_KEY_M1          0x80
+#define COUGAR_KEY_M2          0x81
+#define COUGAR_KEY_M3          0x82
+#define COUGAR_KEY_LEDS                0x67
+#define COUGAR_KEY_LOCK                0x6e
+
+
+/* Default key mappings. The special key COUGAR_KEY_G6 is defined first
+ * because it is more frequent to use the spacebar rather than any other
+ * special keys. Depending on the value of the parameter 'g6_is_space',
+ * the mapping will be updated in the probe function.
+ */
+static unsigned char cougar_mapping[][2] = {
+       { COUGAR_KEY_G6,   KEY_SPACE },
+       { COUGAR_KEY_G1,   KEY_F13 },
+       { COUGAR_KEY_G2,   KEY_F14 },
+       { COUGAR_KEY_G3,   KEY_F15 },
+       { COUGAR_KEY_G4,   KEY_F16 },
+       { COUGAR_KEY_G5,   KEY_F17 },
+       { COUGAR_KEY_LOCK, KEY_SCREENLOCK },
+/* The following keys are handled by the hardware itself, so no special
+ * treatment is required:
+       { COUGAR_KEY_FN, KEY_RESERVED },
+       { COUGAR_KEY_MR, KEY_RESERVED },
+       { COUGAR_KEY_M1, KEY_RESERVED },
+       { COUGAR_KEY_M2, KEY_RESERVED },
+       { COUGAR_KEY_M3, KEY_RESERVED },
+       { COUGAR_KEY_LEDS, KEY_RESERVED },
+*/
+       { 0, 0 },
+};
+
+struct cougar_shared {
+       struct list_head list;
+       struct kref kref;
+       bool enabled;
+       struct hid_device *dev;
+       struct input_dev *input;
+};
+
+struct cougar {
+       bool special_intf;
+       struct cougar_shared *shared;
+};
+
+static LIST_HEAD(cougar_udev_list);
+static DEFINE_MUTEX(cougar_udev_list_lock);
+
+static void cougar_fix_g6_mapping(struct hid_device *hdev)
+{
+       int i;
+
+       for (i = 0; cougar_mapping[i][0]; i++) {
+               if (cougar_mapping[i][0] == COUGAR_KEY_G6) {
+                       cougar_mapping[i][1] =
+                               cougar_g6_is_space ? KEY_SPACE : KEY_F18;
+                       hid_info(hdev, "G6 mapped to %s\n",
+                                cougar_g6_is_space ? "space" : "F18");
+                       return;
+               }
+       }
+       hid_warn(hdev, "no mapping defined for G6/spacebar");
+}
+
+/*
+ * Constant-friendly rdesc fixup for mouse interface
+ */
+static __u8 *cougar_report_fixup(struct hid_device *hdev, __u8 *rdesc,
+                                unsigned int *rsize)
+{
+       if (rdesc[2] == 0x09 && rdesc[3] == 0x02 &&
+           (rdesc[115] | rdesc[116] << 8) >= HID_MAX_USAGES) {
+               hid_info(hdev,
+                       "usage count exceeds max: fixing up report descriptor\n");
+               rdesc[115] = ((HID_MAX_USAGES-1) & 0xff);
+               rdesc[116] = ((HID_MAX_USAGES-1) >> 8);
+       }
+       return rdesc;
+}
+
+static struct cougar_shared *cougar_get_shared_data(struct hid_device *hdev)
+{
+       struct cougar_shared *shared;
+
+       /* Try to find an already-probed interface from the same device */
+       list_for_each_entry(shared, &cougar_udev_list, list) {
+               if (hid_compare_device_paths(hdev, shared->dev, '/')) {
+                       kref_get(&shared->kref);
+                       return shared;
+               }
+       }
+       return NULL;
+}
+
+static void cougar_release_shared_data(struct kref *kref)
+{
+       struct cougar_shared *shared = container_of(kref,
+                                                   struct cougar_shared, kref);
+
+       mutex_lock(&cougar_udev_list_lock);
+       list_del(&shared->list);
+       mutex_unlock(&cougar_udev_list_lock);
+
+       kfree(shared);
+}
+
+static void cougar_remove_shared_data(void *resource)
+{
+       struct cougar *cougar = resource;
+
+       if (cougar->shared) {
+               kref_put(&cougar->shared->kref, cougar_release_shared_data);
+               cougar->shared = NULL;
+       }
+}
+
+/*
+ * Bind the device group's shared data to this cougar struct.
+ * If no shared data exists for this group, create and initialize it.
+ */
+static int cougar_bind_shared_data(struct hid_device *hdev, struct cougar *cougar)
+{
+       struct cougar_shared *shared;
+       int error = 0;
+
+       mutex_lock(&cougar_udev_list_lock);
+
+       shared = cougar_get_shared_data(hdev);
+       if (!shared) {
+               shared = kzalloc(sizeof(*shared), GFP_KERNEL);
+               if (!shared) {
+                       error = -ENOMEM;
+                       goto out;
+               }
+
+               kref_init(&shared->kref);
+               shared->dev = hdev;
+               list_add_tail(&shared->list, &cougar_udev_list);
+       }
+
+       cougar->shared = shared;
+
+       error = devm_add_action(&hdev->dev, cougar_remove_shared_data, cougar);
+       if (error) {
+               mutex_unlock(&cougar_udev_list_lock);
+               cougar_remove_shared_data(cougar);
+               return error;
+       }
+
+out:
+       mutex_unlock(&cougar_udev_list_lock);
+       return error;
+}
+
+static int cougar_probe(struct hid_device *hdev,
+                       const struct hid_device_id *id)
+{
+       struct cougar *cougar;
+       struct hid_input *next, *hidinput = NULL;
+       unsigned int connect_mask;
+       int error;
+
+       cougar = devm_kzalloc(&hdev->dev, sizeof(*cougar), GFP_KERNEL);
+       if (!cougar)
+               return -ENOMEM;
+       hid_set_drvdata(hdev, cougar);
+
+       error = hid_parse(hdev);
+       if (error) {
+               hid_err(hdev, "parse failed\n");
+               goto fail;
+       }
+
+       if (hdev->collection->usage == COUGAR_VENDOR_USAGE) {
+               cougar->special_intf = true;
+               connect_mask = HID_CONNECT_HIDRAW;
+       } else
+               connect_mask = HID_CONNECT_DEFAULT;
+
+       error = hid_hw_start(hdev, connect_mask);
+       if (error) {
+               hid_err(hdev, "hw start failed\n");
+               goto fail;
+       }
+
+       error = cougar_bind_shared_data(hdev, cougar);
+       if (error)
+               goto fail_stop_and_cleanup;
+
+       /* The custom vendor interface will use the hid_input registered
+        * for the keyboard interface, in order to send translated key codes
+        * to it.
+        */
+       if (hdev->collection->usage == HID_GD_KEYBOARD) {
+               cougar_fix_g6_mapping(hdev);
+               list_for_each_entry_safe(hidinput, next, &hdev->inputs, list) {
+                       if (hidinput->registered && hidinput->input != NULL) {
+                               cougar->shared->input = hidinput->input;
+                               cougar->shared->enabled = true;
+                               break;
+                       }
+               }
+       } else if (hdev->collection->usage == COUGAR_VENDOR_USAGE) {
+               error = hid_hw_open(hdev);
+               if (error)
+                       goto fail_stop_and_cleanup;
+       }
+       return 0;
+
+fail_stop_and_cleanup:
+       hid_hw_stop(hdev);
+fail:
+       hid_set_drvdata(hdev, NULL);
+       return error;
+}
+
+/*
+ * Convert events from vendor intf to input key events
+ */
+static int cougar_raw_event(struct hid_device *hdev, struct hid_report *report,
+                           u8 *data, int size)
+{
+       struct cougar *cougar;
+       unsigned char code, action;
+       int i;
+
+       cougar = hid_get_drvdata(hdev);
+       if (!cougar->special_intf || !cougar->shared ||
+           !cougar->shared->input || !cougar->shared->enabled)
+               return 0;
+
+       code = data[COUGAR_FIELD_CODE];
+       action = data[COUGAR_FIELD_ACTION];
+       for (i = 0; cougar_mapping[i][0]; i++) {
+               if (code == cougar_mapping[i][0]) {
+                       input_event(cougar->shared->input, EV_KEY,
+                                   cougar_mapping[i][1], action);
+                       input_sync(cougar->shared->input);
+                       return 0;
+               }
+       }
+       hid_warn(hdev, "unmapped special key code %x: ignoring\n", code);
+       return 0;
+}
+
+static void cougar_remove(struct hid_device *hdev)
+{
+       struct cougar *cougar = hid_get_drvdata(hdev);
+
+       if (cougar) {
+               /* Stop the vendor intf to process more events */
+               if (cougar->shared)
+                       cougar->shared->enabled = false;
+               if (cougar->special_intf)
+                       hid_hw_close(hdev);
+       }
+       hid_hw_stop(hdev);
+}
+
+static struct hid_device_id cougar_id_table[] = {
+       { HID_USB_DEVICE(USB_VENDOR_ID_SOLID_YEAR,
+                        USB_DEVICE_ID_COUGAR_500K_GAMING_KEYBOARD) },
+       {}
+};
+MODULE_DEVICE_TABLE(hid, cougar_id_table);
+
+static struct hid_driver cougar_driver = {
+       .name                   = "cougar",
+       .id_table               = cougar_id_table,
+       .report_fixup           = cougar_report_fixup,
+       .probe                  = cougar_probe,
+       .remove                 = cougar_remove,
+       .raw_event              = cougar_raw_event,
+};
+
+module_hid_driver(cougar_driver);
index 803a725..07e26c3 100644 (file)
 
 #include "hid-ids.h"
 
+#define ELAN_MT_I2C            0x5d
 #define ELAN_SINGLE_FINGER     0x81
 #define ELAN_MT_FIRST_FINGER   0x82
 #define ELAN_MT_SECOND_FINGER  0x83
 #define ELAN_INPUT_REPORT_SIZE 8
+#define ELAN_I2C_REPORT_SIZE   32
+#define ELAN_FINGER_DATA_LEN   5
+#define ELAN_MAX_FINGERS       5
+#define ELAN_MAX_PRESSURE      255
+#define ELAN_TP_USB_INTF       1
+
+#define ELAN_FEATURE_REPORT    0x0d
+#define ELAN_FEATURE_SIZE      5
+#define ELAN_PARAM_MAX_X       6
+#define ELAN_PARAM_MAX_Y       7
+#define ELAN_PARAM_RES         8
 
 #define ELAN_MUTE_LED_REPORT   0xBC
 #define ELAN_LED_REPORT_SIZE   8
 
-struct elan_touchpad_settings {
-       u8 max_fingers;
-       u16 max_x;
-       u16 max_y;
-       u8 max_area_x;
-       u8 max_area_y;
-       u8 max_w;
-       int usb_bInterfaceNumber;
-};
+#define ELAN_HAS_LED           BIT(0)
 
 struct elan_drvdata {
        struct input_dev *input;
        u8 prev_report[ELAN_INPUT_REPORT_SIZE];
        struct led_classdev mute_led;
        u8 mute_led_state;
-       struct elan_touchpad_settings *settings;
+       u16 max_x;
+       u16 max_y;
+       u16 res_x;
+       u16 res_y;
 };
 
 static int is_not_elan_touchpad(struct hid_device *hdev)
 {
-       struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
-       struct elan_drvdata *drvdata = hid_get_drvdata(hdev);
+       if (hdev->bus == BUS_USB) {
+               struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
+
+               return (intf->altsetting->desc.bInterfaceNumber !=
+                       ELAN_TP_USB_INTF);
+       }
 
-       return (intf->altsetting->desc.bInterfaceNumber != drvdata->settings->usb_bInterfaceNumber);
+       return 0;
 }
 
 static int elan_input_mapping(struct hid_device *hdev, struct hid_input *hi,
@@ -62,12 +73,86 @@ static int elan_input_mapping(struct hid_device *hdev, struct hid_input *hi,
 
        if (field->report->id == ELAN_SINGLE_FINGER ||
            field->report->id == ELAN_MT_FIRST_FINGER ||
-           field->report->id == ELAN_MT_SECOND_FINGER)
+           field->report->id == ELAN_MT_SECOND_FINGER ||
+           field->report->id == ELAN_MT_I2C)
                return -1;
 
        return 0;
 }
 
+static int elan_get_device_param(struct hid_device *hdev,
+                                unsigned char *dmabuf, unsigned char param)
+{
+       int ret;
+
+       dmabuf[0] = ELAN_FEATURE_REPORT;
+       dmabuf[1] = 0x05;
+       dmabuf[2] = 0x03;
+       dmabuf[3] = param;
+       dmabuf[4] = 0x01;
+
+       ret = hid_hw_raw_request(hdev, ELAN_FEATURE_REPORT, dmabuf,
+                                ELAN_FEATURE_SIZE, HID_FEATURE_REPORT,
+                                HID_REQ_SET_REPORT);
+       if (ret != ELAN_FEATURE_SIZE) {
+               hid_err(hdev, "Set report error for parm %d: %d\n", param, ret);
+               return ret;
+       }
+
+       ret = hid_hw_raw_request(hdev, ELAN_FEATURE_REPORT, dmabuf,
+                                ELAN_FEATURE_SIZE, HID_FEATURE_REPORT,
+                                HID_REQ_GET_REPORT);
+       if (ret != ELAN_FEATURE_SIZE) {
+               hid_err(hdev, "Get report error for parm %d: %d\n", param, ret);
+               return ret;
+       }
+
+       return 0;
+}
+
+static unsigned int elan_convert_res(char val)
+{
+       /*
+        * (value from firmware) * 10 + 790 = dpi
+        * dpi * 10 / 254 = dots/mm
+        */
+       return (val * 10 + 790) * 10 / 254;
+}
+
+static int elan_get_device_params(struct hid_device *hdev)
+{
+       struct elan_drvdata *drvdata = hid_get_drvdata(hdev);
+       unsigned char *dmabuf;
+       int ret;
+
+       dmabuf = kmalloc(ELAN_FEATURE_SIZE, GFP_KERNEL);
+       if (!dmabuf)
+               return -ENOMEM;
+
+       ret = elan_get_device_param(hdev, dmabuf, ELAN_PARAM_MAX_X);
+       if (ret)
+               goto err;
+
+       drvdata->max_x = (dmabuf[4] << 8) | dmabuf[3];
+
+       ret = elan_get_device_param(hdev, dmabuf, ELAN_PARAM_MAX_Y);
+       if (ret)
+               goto err;
+
+       drvdata->max_y = (dmabuf[4] << 8) | dmabuf[3];
+
+       ret = elan_get_device_param(hdev, dmabuf, ELAN_PARAM_RES);
+       if (ret)
+               goto err;
+
+       drvdata->res_x = elan_convert_res(dmabuf[3]);
+       drvdata->res_y = elan_convert_res(dmabuf[4]);
+
+err:
+       kfree(dmabuf);
+       return ret;
+}
+
 static int elan_input_configured(struct hid_device *hdev, struct hid_input *hi)
 {
        int ret;
@@ -77,6 +162,10 @@ static int elan_input_configured(struct hid_device *hdev, struct hid_input *hi)
        if (is_not_elan_touchpad(hdev))
                return 0;
 
+       ret = elan_get_device_params(hdev);
+       if (ret)
+               return ret;
+
        input = devm_input_allocate_device(&hdev->dev);
        if (!input)
                return -ENOMEM;
@@ -90,25 +179,25 @@ static int elan_input_configured(struct hid_device *hdev, struct hid_input *hi)
        input->id.version = hdev->version;
        input->dev.parent = &hdev->dev;
 
-       input_set_abs_params(input, ABS_MT_POSITION_X, 0,
-                            drvdata->settings->max_x, 0, 0);
-       input_set_abs_params(input, ABS_MT_POSITION_Y, 0,
-                            drvdata->settings->max_y, 0, 0);
-       input_set_abs_params(input, ABS_MT_TOUCH_MAJOR, 0,
-                            drvdata->settings->max_fingers, 0, 0);
-       input_set_abs_params(input, ABS_TOOL_WIDTH, 0,
-                            drvdata->settings->max_w, 0, 0);
+       input_set_abs_params(input, ABS_MT_POSITION_X, 0, drvdata->max_x,
+                            0, 0);
+       input_set_abs_params(input, ABS_MT_POSITION_Y, 0, drvdata->max_y,
+                            0, 0);
+       input_set_abs_params(input, ABS_MT_PRESSURE, 0, ELAN_MAX_PRESSURE,
+                            0, 0);
 
        __set_bit(BTN_LEFT, input->keybit);
        __set_bit(INPUT_PROP_BUTTONPAD, input->propbit);
 
-       ret = input_mt_init_slots(input, drvdata->settings->max_fingers,
-                                 INPUT_MT_POINTER);
+       ret = input_mt_init_slots(input, ELAN_MAX_FINGERS, INPUT_MT_POINTER);
        if (ret) {
                hid_err(hdev, "Failed to init elan MT slots: %d\n", ret);
                return ret;
        }
 
+       input_abs_set_res(input, ABS_X, drvdata->res_x);
+       input_abs_set_res(input, ABS_Y, drvdata->res_y);
+
        ret = input_register_device(input);
        if (ret) {
                hid_err(hdev, "Failed to register elan input device: %d\n",
@@ -126,7 +215,7 @@ static void elan_report_mt_slot(struct elan_drvdata *drvdata, u8 *data,
                                unsigned int slot_num)
 {
        struct input_dev *input = drvdata->input;
-       int x, y, w;
+       int x, y, p;
 
        bool active = !!data;
 
@@ -134,17 +223,17 @@ static void elan_report_mt_slot(struct elan_drvdata *drvdata, u8 *data,
        input_mt_report_slot_state(input, MT_TOOL_FINGER, active);
        if (active) {
                x = ((data[0] & 0xF0) << 4) | data[1];
-               y = drvdata->settings->max_y -
+               y = drvdata->max_y -
                    (((data[0] & 0x07) << 8) | data[2]);
-               w = data[4];
+               p = data[4];
 
                input_report_abs(input, ABS_MT_POSITION_X, x);
                input_report_abs(input, ABS_MT_POSITION_Y, y);
-               input_report_abs(input, ABS_TOOL_WIDTH, w);
+               input_report_abs(input, ABS_MT_PRESSURE, p);
        }
 }
 
-static void elan_report_input(struct elan_drvdata *drvdata, u8 *data)
+static void elan_usb_report_input(struct elan_drvdata *drvdata, u8 *data)
 {
        int i;
        struct input_dev *input = drvdata->input;
@@ -162,7 +251,7 @@ static void elan_report_input(struct elan_drvdata *drvdata, u8 *data)
         * byte 5: x8  x7  x6  x5  x4  x3  x2  x1
         * byte 6: y8  y7  y6  y5  y4  y3  y2  y1
         * byte 7: sy4 sy3 sy2 sy1 sx4 sx3 sx2 sx1
-        * byte 8: w8  w7  w6  w5  w4  w3  w2  w1
+        * byte 8: p8  p7  p6  p5  p4  p3  p2  p1
         *
         * packet structure for ELAN_MT_SECOND_FINGER:
         *
@@ -171,19 +260,21 @@ static void elan_report_input(struct elan_drvdata *drvdata, u8 *data)
         * byte 3: x8  x7  x6  x5  x4  x3  x2  x1
         * byte 4: y8  y7  y6  y5  y4  y3  y2  y1
         * byte 5: sy4 sy3 sy2 sy1 sx4 sx3 sx2 sx1
-        * byte 6: w8  w7  w6  w5  w4  w3  w2  w1
+        * byte 6: p8  p7  p6  p5  p4  p3  p2  p1
         * byte 7: 0   0   0   0   0   0   0   0
         * byte 8: 0   0   0   0   0   0   0   0
         *
         * f5-f1: finger touch bits
         * L: clickpad button
-        * sy / sx: not sure yet, but this looks like rectangular
-        * area for finger
-        * w: looks like finger width
+        * sy / sx: finger width / height expressed in traces, the total number
+        *          of traces can be queried by doing a HID_REQ_SET_REPORT
+        *          { 0x0d, 0x05, 0x03, 0x05, 0x01 } followed by a GET, in the
+        *          returned buf, buf[3]=no-x-traces, buf[4]=no-y-traces.
+        * p: pressure
         */
 
        if (data[0] == ELAN_SINGLE_FINGER) {
-               for (i = 0; i < drvdata->settings->max_fingers; i++) {
+               for (i = 0; i < ELAN_MAX_FINGERS; i++) {
                        if (data[2] & BIT(i + 3))
                                elan_report_mt_slot(drvdata, data + 3, i);
                        else
@@ -210,7 +301,7 @@ static void elan_report_input(struct elan_drvdata *drvdata, u8 *data)
                if (prev_report[0] != ELAN_MT_FIRST_FINGER)
                        return;
 
-               for (i = 0; i < drvdata->settings->max_fingers; i++) {
+               for (i = 0; i < ELAN_MAX_FINGERS; i++) {
                        if (prev_report[2] & BIT(i + 3)) {
                                if (!first) {
                                        first = 1;
@@ -229,6 +320,46 @@ static void elan_report_input(struct elan_drvdata *drvdata, u8 *data)
        input_sync(input);
 }
 
+static void elan_i2c_report_input(struct elan_drvdata *drvdata, u8 *data)
+{
+       struct input_dev *input = drvdata->input;
+       u8 *finger_data;
+       int i;
+
+       /*
+        * Elan MT touchpads in i2c mode send finger data in the same format
+        * as in USB mode, but then with all fingers in a single packet.
+        *
+        * packet structure for ELAN_MT_I2C:
+        *
+        * byte     1: 1   0   0   1   1   1   0   1   // 0x5d
+        * byte     2: f5  f4  f3  f2  f1  0   0   L
+        * byte     3: x12 x11 x10 x9  0?  y11 y10 y9
+        * byte     4: x8  x7  x6  x5  x4  x3  x2  x1
+        * byte     5: y8  y7  y6  y5  y4  y3  y2  y1
+        * byte     6: sy4 sy3 sy2 sy1 sx4 sx3 sx2 sx1
+        * byte     7: p8  p7  p6  p5  p4  p3  p2  p1
+        * byte  8-12: Same as byte 3-7 for second finger down
+        * byte 13-17: Same as byte 3-7 for third finger down
+        * byte 18-22: Same as byte 3-7 for fourth finger down
+        * byte 23-27: Same as byte 3-7 for fifth finger down
+        */
+
+       finger_data = data + 2;
+       for (i = 0; i < ELAN_MAX_FINGERS; i++) {
+               if (data[1] & BIT(i + 3)) {
+                       elan_report_mt_slot(drvdata, finger_data, i);
+                       finger_data += ELAN_FINGER_DATA_LEN;
+               } else {
+                       elan_report_mt_slot(drvdata, NULL, i);
+               }
+       }
+
+       input_report_key(input, BTN_LEFT, data[1] & 0x01);
+       input_mt_sync_frame(input);
+       input_sync(input);
+}
+
 static int elan_raw_event(struct hid_device *hdev,
                          struct hid_report *report, u8 *data, int size)
 {
@@ -241,11 +372,16 @@ static int elan_raw_event(struct hid_device *hdev,
            data[0] == ELAN_MT_FIRST_FINGER ||
            data[0] == ELAN_MT_SECOND_FINGER) {
                if (size == ELAN_INPUT_REPORT_SIZE) {
-                       elan_report_input(drvdata, data);
+                       elan_usb_report_input(drvdata, data);
                        return 1;
                }
        }
 
+       if (data[0] == ELAN_MT_I2C && size == ELAN_I2C_REPORT_SIZE) {
+               elan_i2c_report_input(drvdata, data);
+               return 1;
+       }
+
        return 0;
 }
 
@@ -343,7 +479,6 @@ static int elan_probe(struct hid_device *hdev, const struct hid_device_id *id)
        if (!drvdata)
                return -ENOMEM;
 
-       drvdata->settings = (struct elan_touchpad_settings *)id->driver_data;
        hid_set_drvdata(hdev, drvdata);
 
        ret = hid_parse(hdev);
@@ -371,9 +506,11 @@ static int elan_probe(struct hid_device *hdev, const struct hid_device_id *id)
        if (ret)
                goto err;
 
-       ret = elan_init_mute_led(hdev);
-       if (ret)
-               goto err;
+       if (id->driver_data & ELAN_HAS_LED) {
+               ret = elan_init_mute_led(hdev);
+               if (ret)
+                       goto err;
+       }
 
        return 0;
 err:
@@ -386,22 +523,14 @@ static void elan_remove(struct hid_device *hdev)
        hid_hw_stop(hdev);
 }
 
-static const struct elan_touchpad_settings hp_x2_10_touchpad_data = {
-       .max_fingers = 5,
-       .max_x = 2930,
-       .max_y = 1250,
-       .max_area_x = 15,
-       .max_area_y = 15,
-       .max_w = 255,
-       .usb_bInterfaceNumber = 1,
-};
-
 static const struct hid_device_id elan_devices[] = {
+       { HID_USB_DEVICE(USB_VENDOR_ID_ELAN, USB_DEVICE_ID_HP_X2),
+         .driver_data = ELAN_HAS_LED },
        { HID_USB_DEVICE(USB_VENDOR_ID_ELAN, USB_DEVICE_ID_HP_X2_10_COVER),
-               (kernel_ulong_t)&hp_x2_10_touchpad_data},
+         .driver_data = ELAN_HAS_LED },
+       { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, USB_DEVICE_ID_TOSHIBA_CLICK_L9W) },
        { }
 };
-
 MODULE_DEVICE_TABLE(hid, elan_devices);
 
 static struct hid_driver elan_driver = {
index c7981dd..79bdf0c 100644 (file)
 #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_A001      0xa001
 
 #define USB_VENDOR_ID_ELAN             0x04f3
+#define USB_DEVICE_ID_TOSHIBA_CLICK_L9W        0x0401
+#define USB_DEVICE_ID_HP_X2            0x074d
 #define USB_DEVICE_ID_HP_X2_10_COVER   0x0755
 
 #define USB_VENDOR_ID_ELECOM           0x056e
 #define USB_VENDOR_ID_SINO_LITE                        0x1345
 #define USB_DEVICE_ID_SINO_LITE_CONTROLLER     0x3008
 
+#define USB_VENDOR_ID_SOLID_YEAR                       0x060b
+#define USB_DEVICE_ID_COUGAR_500K_GAMING_KEYBOARD      0x500a
+
 #define USB_VENDOR_ID_SOUNDGRAPH       0x15c2
 #define USB_DEVICE_ID_SOUNDGRAPH_IMON_FIRST    0x0034
 #define USB_DEVICE_ID_SOUNDGRAPH_IMON_LAST     0x0046
index ab93dd5..4e94ea3 100644 (file)
@@ -1550,6 +1550,9 @@ static struct hid_input *hidinput_allocate(struct hid_device *hid,
                case HID_GD_WIRELESS_RADIO_CTLS:
                        suffix = "Wireless Radio Control";
                        break;
+               case HID_GD_SYSTEM_MULTIAXIS:
+                       suffix = "System Multi Axis";
+                       break;
                default:
                        break;
                }
index 96e7d32..72d9836 100644 (file)
 
 #include "hid-ids.h"
 
-#define MS_HIDINPUT            0x01
-#define MS_ERGONOMY            0x02
-#define MS_PRESENTER           0x04
-#define MS_RDESC               0x08
-#define MS_NOGET               0x10
-#define MS_DUPLICATE_USAGES    0x20
+#define MS_HIDINPUT            BIT(0)
+#define MS_ERGONOMY            BIT(1)
+#define MS_PRESENTER           BIT(2)
+#define MS_RDESC               BIT(3)
+#define MS_NOGET               BIT(4)
+#define MS_DUPLICATE_USAGES    BIT(5)
+#define MS_SURFACE_DIAL                BIT(6)
 
 static __u8 *ms_report_fixup(struct hid_device *hdev, __u8 *rdesc,
                unsigned int *rsize)
@@ -130,6 +131,30 @@ static int ms_presenter_8k_quirk(struct hid_input *hi, struct hid_usage *usage,
        return 1;
 }
 
+static int ms_surface_dial_quirk(struct hid_input *hi, struct hid_field *field,
+               struct hid_usage *usage, unsigned long **bit, int *max)
+{
+       switch (usage->hid & HID_USAGE_PAGE) {
+       case 0xff070000:
+               /* fall-through */
+       case HID_UP_DIGITIZER:
+               /* ignore those axis */
+               return -1;
+       case HID_UP_GENDESK:
+               switch (usage->hid) {
+               case HID_GD_X:
+                       /* fall-through */
+               case HID_GD_Y:
+                       /* fall-through */
+               case HID_GD_RFKILL_BTN:
+                       /* ignore those axis */
+                       return -1;
+               }
+       }
+
+       return 0;
+}
+
 static int ms_input_mapping(struct hid_device *hdev, struct hid_input *hi,
                struct hid_field *field, struct hid_usage *usage,
                unsigned long **bit, int *max)
@@ -146,6 +171,13 @@ static int ms_input_mapping(struct hid_device *hdev, struct hid_input *hi,
                        ms_presenter_8k_quirk(hi, usage, bit, max))
                return 1;
 
+       if (quirks & MS_SURFACE_DIAL) {
+               int ret = ms_surface_dial_quirk(hi, field, usage, bit, max);
+
+               if (ret)
+                       return ret;
+       }
+
        return 0;
 }
 
@@ -229,6 +261,9 @@ static int ms_probe(struct hid_device *hdev, const struct hid_device_id *id)
        if (quirks & MS_NOGET)
                hdev->quirks |= HID_QUIRK_NOGET;
 
+       if (quirks & MS_SURFACE_DIAL)
+               hdev->quirks |= HID_QUIRK_INPUT_PER_APP;
+
        ret = hid_parse(hdev);
        if (ret) {
                hid_err(hdev, "parse failed\n");
@@ -281,6 +316,8 @@ static const struct hid_device_id ms_devices[] = {
 
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_BT),
                .driver_data = MS_PRESENTER },
+       { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, 0x091B),
+               .driver_data = MS_SURFACE_DIAL },
        { }
 };
 MODULE_DEVICE_TABLE(hid, ms_devices);
index 45968f7..40fbb7c 100644 (file)
  */
 
 /*
- * This driver is regularly tested thanks to the tool hid-test[1].
- * This tool relies on hid-replay[2] and a database of hid devices[3].
+ * This driver is regularly tested thanks to the test suite in hid-tools[1].
  * Please run these regression tests before patching this module so that
  * your patch won't break existing known devices.
  *
- * [1] https://github.com/bentiss/hid-test
- * [2] https://github.com/bentiss/hid-replay
- * [3] https://github.com/bentiss/hid-devices
+ * [1] https://gitlab.freedesktop.org/libevdev/hid-tools
  */
 
 #include <linux/device.h>
@@ -90,13 +87,54 @@ enum latency_mode {
 #define MT_IO_FLAGS_ACTIVE_SLOTS       1
 #define MT_IO_FLAGS_PENDING_SLOTS      2
 
-struct mt_slot {
-       __s32 x, y, cx, cy, p, w, h, a;
-       __s32 contactid;        /* the device ContactID assigned to this slot */
-       bool touch_state;       /* is the touch valid? */
-       bool inrange_state;     /* is the finger in proximity of the sensor? */
-       bool confidence_state;  /* is the touch made by a finger? */
-       bool has_azimuth;       /* the contact reports azimuth */
+static const bool mtrue = true;                /* default for true */
+static const bool mfalse;              /* default for false */
+static const __s32 mzero;              /* default for 0 */
+
+#define DEFAULT_TRUE   ((void *)&mtrue)
+#define DEFAULT_FALSE  ((void *)&mfalse)
+#define DEFAULT_ZERO   ((void *)&mzero)
+
+struct mt_usages {
+       struct list_head list;
+       __s32 *x, *y, *cx, *cy, *p, *w, *h, *a;
+       __s32 *contactid;       /* the device ContactID assigned to this slot */
+       bool *tip_state;        /* is the touch valid? */
+       bool *inrange_state;    /* is the finger in proximity of the sensor? */
+       bool *confidence_state; /* is the touch made by a finger? */
+};
+
+struct mt_application {
+       struct list_head list;
+       unsigned int application;
+       struct list_head mt_usages;     /* mt usages list */
+
+       __s32 quirks;
+
+       __s32 *scantime;                /* scantime reported */
+       __s32 scantime_logical_max;     /* max value for raw scantime */
+
+       __s32 *raw_cc;                  /* contact count in the report */
+       int left_button_state;          /* left button state */
+       unsigned int mt_flags;          /* flags to pass to input-mt */
+
+       unsigned long *pending_palm_slots;      /* slots where we reported palm
+                                                * and need to release */
+
+       __u8 num_received;      /* how many contacts we received */
+       __u8 num_expected;      /* expected last contact index */
+       __u8 buttons_count;     /* number of physical buttons per touchpad */
+       __u8 touches_by_report; /* how many touches are present in one report:
+                                * 1 means we should use a serial protocol
+                                * > 1 means hybrid (multitouch) protocol
+                                */
+
+       __s32 dev_time;         /* the scan time provided by the device */
+       unsigned long jiffies;  /* the frame's jiffies */
+       int timestamp;          /* the timestamp to be sent */
+       int prev_scantime;              /* scantime reported previously */
+
+       bool have_contact_count;
 };
 
 struct mt_class {
@@ -111,46 +149,30 @@ struct mt_class {
        bool export_all_inputs; /* do not ignore mouse, keyboards, etc... */
 };
 
-struct mt_fields {
-       unsigned usages[HID_MAX_FIELDS];
-       unsigned int length;
+struct mt_report_data {
+       struct list_head list;
+       struct hid_report *report;
+       struct mt_application *application;
+       bool is_mt_collection;
 };
 
 struct mt_device {
-       struct mt_slot curdata; /* placeholder of incoming data */
        struct mt_class mtclass;        /* our mt device class */
        struct timer_list release_timer;        /* to release sticky fingers */
        struct hid_device *hdev;        /* hid_device we're attached to */
-       struct mt_fields *fields;       /* temporary placeholder for storing the
-                                          multitouch fields */
        unsigned long mt_io_flags;      /* mt flags (MT_IO_FLAGS_*) */
-       int cc_index;   /* contact count field index in the report */
-       int cc_value_index;     /* contact count value index in the field */
-       int scantime_index;     /* scantime field index in the report */
-       int scantime_val_index; /* scantime value index in the field */
-       int prev_scantime;      /* scantime reported in the previous packet */
-       int left_button_state;  /* left button state */
-       unsigned last_slot_field;       /* the last field of a slot */
-       unsigned mt_report_id;  /* the report ID of the multitouch device */
        __u8 inputmode_value;   /* InputMode HID feature value */
-       __u8 num_received;      /* how many contacts we received */
-       __u8 num_expected;      /* expected last contact index */
        __u8 maxcontacts;
-       __u8 touches_by_report; /* how many touches are present in one report:
-                               * 1 means we should use a serial protocol
-                               * > 1 means hybrid (multitouch) protocol */
-       __u8 buttons_count;     /* number of physical buttons per touchpad */
        bool is_buttonpad;      /* is this device a button pad? */
        bool serial_maybe;      /* need to check for serial protocol */
-       bool curvalid;          /* is the current contact valid? */
-       unsigned mt_flags;      /* flags to pass to input-mt */
-       __s32 dev_time;         /* the scan time provided by the device */
-       unsigned long jiffies;  /* the frame's jiffies */
-       int timestamp;          /* the timestamp to be sent */
+
+       struct list_head applications;
+       struct list_head reports;
 };
 
-static void mt_post_parse_default_settings(struct mt_device *td);
-static void mt_post_parse(struct mt_device *td);
+static void mt_post_parse_default_settings(struct mt_device *td,
+                                          struct mt_application *app);
+static void mt_post_parse(struct mt_device *td, struct mt_application *app);
 
 /* classes of device behavior */
 #define MT_CLS_DEFAULT                         0x0001
@@ -203,15 +225,16 @@ static void mt_post_parse(struct mt_device *td);
  * to a valid contact that was just read.
  */
 
-static int cypress_compute_slot(struct mt_device *td)
+static int cypress_compute_slot(struct mt_application *application,
+                               struct mt_usages *slot)
 {
-       if (td->curdata.contactid != 0 || td->num_received == 0)
-               return td->curdata.contactid;
+       if (*slot->contactid != 0 || application->num_received == 0)
+               return *slot->contactid;
        else
                return -1;
 }
 
-static struct mt_class mt_classes[] = {
+static const struct mt_class mt_classes[] = {
        { .name = MT_CLS_DEFAULT,
                .quirks = MT_QUIRK_ALWAYS_VALID |
                        MT_QUIRK_CONTACT_CNT_ACCURATE },
@@ -353,6 +376,7 @@ static ssize_t mt_set_quirks(struct device *dev,
 {
        struct hid_device *hdev = to_hid_device(dev);
        struct mt_device *td = hid_get_drvdata(hdev);
+       struct mt_application *application;
 
        unsigned long val;
 
@@ -361,8 +385,11 @@ static ssize_t mt_set_quirks(struct device *dev,
 
        td->mtclass.quirks = val;
 
-       if (td->cc_index < 0)
-               td->mtclass.quirks &= ~MT_QUIRK_CONTACT_CNT_ACCURATE;
+       list_for_each_entry(application, &td->applications, list) {
+               application->quirks = val;
+               if (!application->have_contact_count)
+                       application->quirks &= ~MT_QUIRK_CONTACT_CNT_ACCURATE;
+       }
 
        return count;
 }
@@ -457,41 +484,199 @@ static void set_abs(struct input_dev *input, unsigned int code,
        input_abs_set_res(input, code, hidinput_calc_abs_res(field, code));
 }
 
-static void mt_store_field(struct hid_usage *usage, struct mt_device *td,
-               struct hid_input *hi)
+static struct mt_usages *mt_allocate_usage(struct hid_device *hdev,
+                                          struct mt_application *application)
+{
+       struct mt_usages *usage;
+
+       usage = devm_kzalloc(&hdev->dev, sizeof(*usage), GFP_KERNEL);
+       if (!usage)
+               return NULL;
+
+       /* set some defaults so we do not need to check for null pointers */
+       usage->x = DEFAULT_ZERO;
+       usage->y = DEFAULT_ZERO;
+       usage->cx = DEFAULT_ZERO;
+       usage->cy = DEFAULT_ZERO;
+       usage->p = DEFAULT_ZERO;
+       usage->w = DEFAULT_ZERO;
+       usage->h = DEFAULT_ZERO;
+       usage->a = DEFAULT_ZERO;
+       usage->contactid = DEFAULT_ZERO;
+       usage->tip_state = DEFAULT_FALSE;
+       usage->inrange_state = DEFAULT_FALSE;
+       usage->confidence_state = DEFAULT_TRUE;
+
+       list_add_tail(&usage->list, &application->mt_usages);
+
+       return usage;
+}
+
+static struct mt_application *mt_allocate_application(struct mt_device *td,
+                                                     unsigned int application)
+{
+       struct mt_application *mt_application;
+
+       mt_application = devm_kzalloc(&td->hdev->dev, sizeof(*mt_application),
+                                     GFP_KERNEL);
+       if (!mt_application)
+               return NULL;
+
+       mt_application->application = application;
+       INIT_LIST_HEAD(&mt_application->mt_usages);
+
+       if (application == HID_DG_TOUCHSCREEN)
+               mt_application->mt_flags |= INPUT_MT_DIRECT;
+
+       /*
+        * Model touchscreens providing buttons as touchpads.
+        */
+       if (application == HID_DG_TOUCHPAD) {
+               mt_application->mt_flags |= INPUT_MT_POINTER;
+               td->inputmode_value = MT_INPUTMODE_TOUCHPAD;
+       }
+
+       mt_application->scantime = DEFAULT_ZERO;
+       mt_application->raw_cc = DEFAULT_ZERO;
+       mt_application->quirks = td->mtclass.quirks;
+
+       list_add_tail(&mt_application->list, &td->applications);
+
+       return mt_application;
+}
+
+static struct mt_application *mt_find_application(struct mt_device *td,
+                                                 unsigned int application)
+{
+       struct mt_application *tmp, *mt_application = NULL;
+
+       list_for_each_entry(tmp, &td->applications, list) {
+               if (application == tmp->application) {
+                       mt_application = tmp;
+                       break;
+               }
+       }
+
+       if (!mt_application)
+               mt_application = mt_allocate_application(td, application);
+
+       return mt_application;
+}
+
+static struct mt_report_data *mt_allocate_report_data(struct mt_device *td,
+                                                     struct hid_report *report)
+{
+       struct mt_report_data *rdata;
+       struct hid_field *field;
+       int r, n;
+
+       rdata = devm_kzalloc(&td->hdev->dev, sizeof(*rdata), GFP_KERNEL);
+       if (!rdata)
+               return NULL;
+
+       rdata->report = report;
+       rdata->application = mt_find_application(td, report->application);
+
+       if (!rdata->application) {
+               devm_kfree(&td->hdev->dev, rdata);
+               return NULL;
+       }
+
+       for (r = 0; r < report->maxfield; r++) {
+               field = report->field[r];
+
+               if (!(HID_MAIN_ITEM_VARIABLE & field->flags))
+                       continue;
+
+               for (n = 0; n < field->report_count; n++) {
+                       if (field->usage[n].hid == HID_DG_CONTACTID)
+                               rdata->is_mt_collection = true;
+               }
+       }
+
+       list_add_tail(&rdata->list, &td->reports);
+
+       return rdata;
+}
+
+static struct mt_report_data *mt_find_report_data(struct mt_device *td,
+                                                 struct hid_report *report)
 {
-       struct mt_fields *f = td->fields;
+       struct mt_report_data *tmp, *rdata = NULL;
 
-       if (f->length >= HID_MAX_FIELDS)
+       list_for_each_entry(tmp, &td->reports, list) {
+               if (report == tmp->report) {
+                       rdata = tmp;
+                       break;
+               }
+       }
+
+       if (!rdata)
+               rdata = mt_allocate_report_data(td, report);
+
+       return rdata;
+}
+
+static void mt_store_field(struct hid_device *hdev,
+                          struct mt_application *application,
+                          __s32 *value,
+                          size_t offset)
+{
+       struct mt_usages *usage;
+       __s32 **target;
+
+       if (list_empty(&application->mt_usages))
+               usage = mt_allocate_usage(hdev, application);
+       else
+               usage = list_last_entry(&application->mt_usages,
+                                       struct mt_usages,
+                                       list);
+
+       if (!usage)
                return;
 
-       f->usages[f->length++] = usage->hid;
+       target = (__s32 **)((char *)usage + offset);
+
+       /* the value has already been filled, create a new slot */
+       if (*target != DEFAULT_TRUE &&
+           *target != DEFAULT_FALSE &&
+           *target != DEFAULT_ZERO) {
+               usage = mt_allocate_usage(hdev, application);
+               if (!usage)
+                       return;
+
+               target = (__s32 **)((char *)usage + offset);
+       }
+
+       *target = value;
 }
 
+#define MT_STORE_FIELD(__name)                                         \
+       mt_store_field(hdev, app,                                       \
+                      &field->value[usage->usage_index],               \
+                      offsetof(struct mt_usages, __name))
+
 static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
                struct hid_field *field, struct hid_usage *usage,
-               unsigned long **bit, int *max)
+               unsigned long **bit, int *max, struct mt_application *app)
 {
        struct mt_device *td = hid_get_drvdata(hdev);
        struct mt_class *cls = &td->mtclass;
        int code;
        struct hid_usage *prev_usage = NULL;
 
-       if (field->application == HID_DG_TOUCHSCREEN)
-               td->mt_flags |= INPUT_MT_DIRECT;
-
        /*
         * Model touchscreens providing buttons as touchpads.
         */
-       if (field->application == HID_DG_TOUCHPAD ||
+       if (field->application == HID_DG_TOUCHSCREEN &&
            (usage->hid & HID_USAGE_PAGE) == HID_UP_BUTTON) {
-               td->mt_flags |= INPUT_MT_POINTER;
+               app->mt_flags |= INPUT_MT_POINTER;
                td->inputmode_value = MT_INPUTMODE_TOUCHPAD;
        }
 
        /* count the buttons on touchpads */
        if ((usage->hid & HID_USAGE_PAGE) == HID_UP_BUTTON)
-               td->buttons_count++;
+               app->buttons_count++;
 
        if (usage->usage_index)
                prev_usage = &field->usage[usage->usage_index - 1];
@@ -502,33 +687,40 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
                switch (usage->hid) {
                case HID_GD_X:
                        if (prev_usage && (prev_usage->hid == usage->hid)) {
-                               hid_map_usage(hi, usage, bit, max,
-                                       EV_ABS, ABS_MT_TOOL_X);
-                               set_abs(hi->input, ABS_MT_TOOL_X, field,
-                                       cls->sn_move);
+                               code = ABS_MT_TOOL_X;
+                               MT_STORE_FIELD(cx);
                        } else {
-                               hid_map_usage(hi, usage, bit, max,
-                                       EV_ABS, ABS_MT_POSITION_X);
-                               set_abs(hi->input, ABS_MT_POSITION_X, field,
-                                       cls->sn_move);
+                               code = ABS_MT_POSITION_X;
+                               MT_STORE_FIELD(x);
+                       }
+
+                       set_abs(hi->input, code, field, cls->sn_move);
+
+                       /*
+                        * A system multi-axis that exports X and Y has a high
+                        * chance of being used directly on a surface
+                        */
+                       if (field->application == HID_GD_SYSTEM_MULTIAXIS) {
+                               __set_bit(INPUT_PROP_DIRECT,
+                                         hi->input->propbit);
+                               input_set_abs_params(hi->input,
+                                                    ABS_MT_TOOL_TYPE,
+                                                    MT_TOOL_DIAL,
+                                                    MT_TOOL_DIAL, 0, 0);
                        }
 
-                       mt_store_field(usage, td, hi);
                        return 1;
                case HID_GD_Y:
                        if (prev_usage && (prev_usage->hid == usage->hid)) {
-                               hid_map_usage(hi, usage, bit, max,
-                                       EV_ABS, ABS_MT_TOOL_Y);
-                               set_abs(hi->input, ABS_MT_TOOL_Y, field,
-                                       cls->sn_move);
+                               code = ABS_MT_TOOL_Y;
+                               MT_STORE_FIELD(cy);
                        } else {
-                               hid_map_usage(hi, usage, bit, max,
-                                       EV_ABS, ABS_MT_POSITION_Y);
-                               set_abs(hi->input, ABS_MT_POSITION_Y, field,
-                                       cls->sn_move);
+                               code = ABS_MT_POSITION_Y;
+                               MT_STORE_FIELD(y);
                        }
 
-                       mt_store_field(usage, td, hi);
+                       set_abs(hi->input, code, field, cls->sn_move);
+
                        return 1;
                }
                return 0;
@@ -536,43 +728,45 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
        case HID_UP_DIGITIZER:
                switch (usage->hid) {
                case HID_DG_INRANGE:
-                       if (cls->quirks & MT_QUIRK_HOVERING) {
-                               hid_map_usage(hi, usage, bit, max,
-                                       EV_ABS, ABS_MT_DISTANCE);
+                       if (app->quirks & MT_QUIRK_HOVERING) {
                                input_set_abs_params(hi->input,
                                        ABS_MT_DISTANCE, 0, 1, 0, 0);
                        }
-                       mt_store_field(usage, td, hi);
+                       MT_STORE_FIELD(inrange_state);
                        return 1;
                case HID_DG_CONFIDENCE:
                        if ((cls->name == MT_CLS_WIN_8 ||
                                cls->name == MT_CLS_WIN_8_DUAL) &&
-                               field->application == HID_DG_TOUCHPAD)
-                               cls->quirks |= MT_QUIRK_CONFIDENCE;
-                       mt_store_field(usage, td, hi);
+                               (field->application == HID_DG_TOUCHPAD ||
+                                field->application == HID_DG_TOUCHSCREEN))
+                               app->quirks |= MT_QUIRK_CONFIDENCE;
+
+                       if (app->quirks & MT_QUIRK_CONFIDENCE)
+                               input_set_abs_params(hi->input,
+                                                    ABS_MT_TOOL_TYPE,
+                                                    MT_TOOL_FINGER,
+                                                    MT_TOOL_PALM, 0, 0);
+
+                       MT_STORE_FIELD(confidence_state);
                        return 1;
                case HID_DG_TIPSWITCH:
-                       hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH);
-                       input_set_capability(hi->input, EV_KEY, BTN_TOUCH);
-                       mt_store_field(usage, td, hi);
+                       if (field->application != HID_GD_SYSTEM_MULTIAXIS)
+                               input_set_capability(hi->input,
+                                                    EV_KEY, BTN_TOUCH);
+                       MT_STORE_FIELD(tip_state);
                        return 1;
                case HID_DG_CONTACTID:
-                       mt_store_field(usage, td, hi);
-                       td->touches_by_report++;
-                       td->mt_report_id = field->report->id;
+                       MT_STORE_FIELD(contactid);
+                       app->touches_by_report++;
                        return 1;
                case HID_DG_WIDTH:
-                       hid_map_usage(hi, usage, bit, max,
-                                       EV_ABS, ABS_MT_TOUCH_MAJOR);
-                       if (!(cls->quirks & MT_QUIRK_NO_AREA))
+                       if (!(app->quirks & MT_QUIRK_NO_AREA))
                                set_abs(hi->input, ABS_MT_TOUCH_MAJOR, field,
                                        cls->sn_width);
-                       mt_store_field(usage, td, hi);
+                       MT_STORE_FIELD(w);
                        return 1;
                case HID_DG_HEIGHT:
-                       hid_map_usage(hi, usage, bit, max,
-                                       EV_ABS, ABS_MT_TOUCH_MINOR);
-                       if (!(cls->quirks & MT_QUIRK_NO_AREA)) {
+                       if (!(app->quirks & MT_QUIRK_NO_AREA)) {
                                set_abs(hi->input, ABS_MT_TOUCH_MINOR, field,
                                        cls->sn_height);
 
@@ -585,41 +779,23 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
                                        input_set_abs_params(hi->input,
                                                ABS_MT_ORIENTATION, 0, 1, 0, 0);
                        }
-                       mt_store_field(usage, td, hi);
+                       MT_STORE_FIELD(h);
                        return 1;
                case HID_DG_TIPPRESSURE:
-                       hid_map_usage(hi, usage, bit, max,
-                                       EV_ABS, ABS_MT_PRESSURE);
                        set_abs(hi->input, ABS_MT_PRESSURE, field,
                                cls->sn_pressure);
-                       mt_store_field(usage, td, hi);
+                       MT_STORE_FIELD(p);
                        return 1;
                case HID_DG_SCANTIME:
-                       hid_map_usage(hi, usage, bit, max,
-                               EV_MSC, MSC_TIMESTAMP);
                        input_set_capability(hi->input, EV_MSC, MSC_TIMESTAMP);
-                       /* Ignore if indexes are out of bounds. */
-                       if (field->index >= field->report->maxfield ||
-                           usage->usage_index >= field->report_count)
-                               return 1;
-                       td->scantime_index = field->index;
-                       td->scantime_val_index = usage->usage_index;
-                       /*
-                        * We don't set td->last_slot_field as scan time is
-                        * global to the report.
-                        */
+                       app->scantime = &field->value[usage->usage_index];
+                       app->scantime_logical_max = field->logical_maximum;
                        return 1;
                case HID_DG_CONTACTCOUNT:
-                       /* Ignore if indexes are out of bounds. */
-                       if (field->index >= field->report->maxfield ||
-                           usage->usage_index >= field->report_count)
-                               return 1;
-                       td->cc_index = field->index;
-                       td->cc_value_index = usage->usage_index;
+                       app->have_contact_count = true;
+                       app->raw_cc = &field->value[usage->usage_index];
                        return 1;
                case HID_DG_AZIMUTH:
-                       hid_map_usage(hi, usage, bit, max,
-                               EV_ABS, ABS_MT_ORIENTATION);
                        /*
                         * Azimuth has the range of [0, MAX) representing a full
                         * revolution. Set ABS_MT_ORIENTATION to a quarter of
@@ -630,11 +806,10 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
                                field->logical_maximum / 4,
                                cls->sn_move ?
                                field->logical_maximum / cls->sn_move : 0, 0);
-                       mt_store_field(usage, td, hi);
+                       MT_STORE_FIELD(a);
                        return 1;
                case HID_DG_CONTACTMAX:
-                       /* we don't set td->last_slot_field as contactcount and
-                        * contact max are global to the report */
+                       /* contact max are global to the report */
                        return -1;
                case HID_DG_TOUCH:
                        /* Legacy devices use TIPSWITCH and not TOUCH.
@@ -650,10 +825,14 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
                 * MS PTP spec says that external buttons left and right have
                 * usages 2 and 3.
                 */
-               if ((cls->quirks & MT_QUIRK_WIN8_PTP_BUTTONS) &&
+               if ((app->quirks & MT_QUIRK_WIN8_PTP_BUTTONS) &&
                    field->application == HID_DG_TOUCHPAD &&
                    (usage->hid & HID_USAGE) > 1)
                        code--;
+
+               if (field->application == HID_GD_SYSTEM_MULTIAXIS)
+                       code = BTN_0  + ((usage->hid - 1) & HID_USAGE);
+
                hid_map_usage(hi, usage, bit, max, EV_KEY, code);
                input_set_capability(hi->input, EV_KEY, code);
                return 1;
@@ -666,110 +845,68 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
        return 0;
 }
 
-static int mt_compute_slot(struct mt_device *td, struct input_dev *input)
+static int mt_compute_slot(struct mt_device *td, struct mt_application *app,
+                          struct mt_usages *slot,
+                          struct input_dev *input)
 {
-       __s32 quirks = td->mtclass.quirks;
+       __s32 quirks = app->quirks;
 
        if (quirks & MT_QUIRK_SLOT_IS_CONTACTID)
-               return td->curdata.contactid;
+               return *slot->contactid;
 
        if (quirks & MT_QUIRK_CYPRESS)
-               return cypress_compute_slot(td);
+               return cypress_compute_slot(app, slot);
 
        if (quirks & MT_QUIRK_SLOT_IS_CONTACTNUMBER)
-               return td->num_received;
+               return app->num_received;
 
        if (quirks & MT_QUIRK_SLOT_IS_CONTACTID_MINUS_ONE)
-               return td->curdata.contactid - 1;
+               return *slot->contactid - 1;
 
-       return input_mt_get_slot_by_key(input, td->curdata.contactid);
+       return input_mt_get_slot_by_key(input, *slot->contactid);
 }
 
-/*
- * this function is called when a whole contact has been processed,
- * so that it can assign it to a slot and store the data there
- */
-static void mt_complete_slot(struct mt_device *td, struct input_dev *input)
+static void mt_release_pending_palms(struct mt_device *td,
+                                    struct mt_application *app,
+                                    struct input_dev *input)
 {
-       if ((td->mtclass.quirks & MT_QUIRK_CONTACT_CNT_ACCURATE) &&
-           td->num_received >= td->num_expected)
-               return;
-
-       if (td->curvalid || (td->mtclass.quirks & MT_QUIRK_ALWAYS_VALID)) {
-               int active;
-               int slotnum = mt_compute_slot(td, input);
-               struct mt_slot *s = &td->curdata;
-               struct input_mt *mt = input->mt;
+       int slotnum;
+       bool need_sync = false;
 
-               if (slotnum < 0 || slotnum >= td->maxcontacts)
-                       return;
-
-               if ((td->mtclass.quirks & MT_QUIRK_IGNORE_DUPLICATES) && mt) {
-                       struct input_mt_slot *slot = &mt->slots[slotnum];
-                       if (input_mt_is_active(slot) &&
-                           input_mt_is_used(mt, slot))
-                               return;
-               }
-
-               if (!(td->mtclass.quirks & MT_QUIRK_CONFIDENCE))
-                       s->confidence_state = true;
-               active = (s->touch_state || s->inrange_state) &&
-                                                       s->confidence_state;
+       for_each_set_bit(slotnum, app->pending_palm_slots, td->maxcontacts) {
+               clear_bit(slotnum, app->pending_palm_slots);
 
                input_mt_slot(input, slotnum);
-               input_mt_report_slot_state(input, MT_TOOL_FINGER, active);
-               if (active) {
-                       /* this finger is in proximity of the sensor */
-                       int wide = (s->w > s->h);
-                       int major = max(s->w, s->h);
-                       int minor = min(s->w, s->h);
-                       int orientation = wide;
+               input_mt_report_slot_state(input, MT_TOOL_PALM, false);
 
-                       if (s->has_azimuth)
-                               orientation = s->a;
-
-                       /*
-                        * divided by two to match visual scale of touch
-                        * for devices with this quirk
-                        */
-                       if (td->mtclass.quirks & MT_QUIRK_TOUCH_SIZE_SCALING) {
-                               major = major >> 1;
-                               minor = minor >> 1;
-                       }
-
-                       input_event(input, EV_ABS, ABS_MT_POSITION_X, s->x);
-                       input_event(input, EV_ABS, ABS_MT_POSITION_Y, s->y);
-                       input_event(input, EV_ABS, ABS_MT_TOOL_X, s->cx);
-                       input_event(input, EV_ABS, ABS_MT_TOOL_Y, s->cy);
-                       input_event(input, EV_ABS, ABS_MT_DISTANCE,
-                               !s->touch_state);
-                       input_event(input, EV_ABS, ABS_MT_ORIENTATION,
-                               orientation);
-                       input_event(input, EV_ABS, ABS_MT_PRESSURE, s->p);
-                       input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, major);
-                       input_event(input, EV_ABS, ABS_MT_TOUCH_MINOR, minor);
-
-                       set_bit(MT_IO_FLAGS_ACTIVE_SLOTS, &td->mt_io_flags);
-               }
+               need_sync = true;
        }
 
-       td->num_received++;
+       if (need_sync) {
+               input_mt_sync_frame(input);
+               input_sync(input);
+       }
 }
 
 /*
  * this function is called when a whole packet has been received and processed,
  * so that it can decide what to send to the input layer.
  */
-static void mt_sync_frame(struct mt_device *td, struct input_dev *input)
+static void mt_sync_frame(struct mt_device *td, struct mt_application *app,
+                         struct input_dev *input)
 {
-       if (td->mtclass.quirks & MT_QUIRK_WIN8_PTP_BUTTONS)
-               input_event(input, EV_KEY, BTN_LEFT, td->left_button_state);
+       if (app->quirks & MT_QUIRK_WIN8_PTP_BUTTONS)
+               input_event(input, EV_KEY, BTN_LEFT, app->left_button_state);
 
        input_mt_sync_frame(input);
-       input_event(input, EV_MSC, MSC_TIMESTAMP, td->timestamp);
+       input_event(input, EV_MSC, MSC_TIMESTAMP, app->timestamp);
        input_sync(input);
-       td->num_received = 0;
-       td->left_button_state = 0;
+
+       mt_release_pending_palms(td, app, input);
+
+       app->num_received = 0;
+       app->left_button_state = 0;
+
        if (test_bit(MT_IO_FLAGS_ACTIVE_SLOTS, &td->mt_io_flags))
                set_bit(MT_IO_FLAGS_PENDING_SLOTS, &td->mt_io_flags);
        else
@@ -777,17 +914,15 @@ static void mt_sync_frame(struct mt_device *td, struct input_dev *input)
        clear_bit(MT_IO_FLAGS_ACTIVE_SLOTS, &td->mt_io_flags);
 }
 
-static int mt_compute_timestamp(struct mt_device *td, struct hid_field *field,
-               __s32 value)
+static int mt_compute_timestamp(struct mt_application *app, __s32 value)
 {
-       long delta = value - td->dev_time;
-       unsigned long jdelta = jiffies_to_usecs(jiffies - td->jiffies);
+       long delta = value - app->prev_scantime;
+       unsigned long jdelta = jiffies_to_usecs(jiffies - app->jiffies);
 
-       td->jiffies = jiffies;
-       td->dev_time = value;
+       app->jiffies = jiffies;
 
        if (delta < 0)
-               delta += field->logical_maximum;
+               delta += app->scantime_logical_max;
 
        /* HID_DG_SCANTIME is expressed in 100us, we want it in us. */
        delta *= 100;
@@ -796,7 +931,7 @@ static int mt_compute_timestamp(struct mt_device *td, struct hid_field *field,
                /* No data received for a while, resync the timestamp. */
                return 0;
        else
-               return td->timestamp + delta;
+               return app->timestamp + delta;
 }
 
 static int mt_touch_event(struct hid_device *hid, struct hid_field *field,
@@ -809,63 +944,90 @@ static int mt_touch_event(struct hid_device *hid, struct hid_field *field,
        return 1;
 }
 
-static void mt_process_mt_event(struct hid_device *hid, struct hid_field *field,
-                               struct hid_usage *usage, __s32 value,
-                               bool first_packet)
+static int mt_process_slot(struct mt_device *td, struct input_dev *input,
+                           struct mt_application *app,
+                           struct mt_usages *slot)
 {
-       struct mt_device *td = hid_get_drvdata(hid);
-       __s32 quirks = td->mtclass.quirks;
-       struct input_dev *input = field->hidinput->input;
+       struct input_mt *mt = input->mt;
+       __s32 quirks = app->quirks;
+       bool valid = true;
+       bool confidence_state = true;
+       bool inrange_state = false;
+       int active;
+       int slotnum;
+       int tool = MT_TOOL_FINGER;
+
+       if (!slot)
+               return -EINVAL;
 
-       if (hid->claimed & HID_CLAIMED_INPUT) {
-               switch (usage->hid) {
-               case HID_DG_INRANGE:
-                       if (quirks & MT_QUIRK_VALID_IS_INRANGE)
-                               td->curvalid = value;
-                       if (quirks & MT_QUIRK_HOVERING)
-                               td->curdata.inrange_state = value;
-                       break;
-               case HID_DG_TIPSWITCH:
-                       if (quirks & MT_QUIRK_NOT_SEEN_MEANS_UP)
-                               td->curvalid = value;
-                       td->curdata.touch_state = value;
-                       break;
-               case HID_DG_CONFIDENCE:
-                       if (quirks & MT_QUIRK_CONFIDENCE)
-                               td->curdata.confidence_state = value;
-                       if (quirks & MT_QUIRK_VALID_IS_CONFIDENCE)
-                               td->curvalid = value;
-                       break;
-               case HID_DG_CONTACTID:
-                       td->curdata.contactid = value;
-                       break;
-               case HID_DG_TIPPRESSURE:
-                       td->curdata.p = value;
-                       break;
-               case HID_GD_X:
-                       if (usage->code == ABS_MT_TOOL_X)
-                               td->curdata.cx = value;
-                       else
-                               td->curdata.x = value;
-                       break;
-               case HID_GD_Y:
-                       if (usage->code == ABS_MT_TOOL_Y)
-                               td->curdata.cy = value;
-                       else
-                               td->curdata.y = value;
-                       break;
-               case HID_DG_WIDTH:
-                       td->curdata.w = value;
-                       break;
-               case HID_DG_HEIGHT:
-                       td->curdata.h = value;
-                       break;
-               case HID_DG_SCANTIME:
-                       td->timestamp = mt_compute_timestamp(td, field, value);
-                       break;
-               case HID_DG_CONTACTCOUNT:
-                       break;
-               case HID_DG_AZIMUTH:
+       if ((quirks & MT_QUIRK_CONTACT_CNT_ACCURATE) &&
+           app->num_received >= app->num_expected)
+               return -EAGAIN;
+
+       if (!(quirks & MT_QUIRK_ALWAYS_VALID)) {
+               if (quirks & MT_QUIRK_VALID_IS_INRANGE)
+                       valid = *slot->inrange_state;
+               if (quirks & MT_QUIRK_NOT_SEEN_MEANS_UP)
+                       valid = *slot->tip_state;
+               if (quirks & MT_QUIRK_VALID_IS_CONFIDENCE)
+                       valid = *slot->confidence_state;
+
+               if (!valid)
+                       return 0;
+       }
+
+       slotnum = mt_compute_slot(td, app, slot, input);
+       if (slotnum < 0 || slotnum >= td->maxcontacts)
+               return 0;
+
+       if ((quirks & MT_QUIRK_IGNORE_DUPLICATES) && mt) {
+               struct input_mt_slot *i_slot = &mt->slots[slotnum];
+
+               if (input_mt_is_active(i_slot) &&
+                   input_mt_is_used(mt, i_slot))
+                       return -EAGAIN;
+       }
+
+       if (quirks & MT_QUIRK_CONFIDENCE)
+               confidence_state = *slot->confidence_state;
+
+       if (quirks & MT_QUIRK_HOVERING)
+               inrange_state = *slot->inrange_state;
+
+       active = *slot->tip_state || inrange_state;
+
+       if (app->application == HID_GD_SYSTEM_MULTIAXIS)
+               tool = MT_TOOL_DIAL;
+       else if (unlikely(!confidence_state)) {
+               tool = MT_TOOL_PALM;
+               if (!active &&
+                   input_mt_is_active(&mt->slots[slotnum])) {
+                       /*
+                        * The non-confidence was reported for
+                        * previously valid contact that is also no
+                        * longer valid. We can't simply report
+                        * lift-off as userspace will not be aware
+                        * of non-confidence, so we need to split
+                        * it into 2 events: active MT_TOOL_PALM
+                        * and a separate liftoff.
+                        */
+                       active = true;
+                       set_bit(slotnum, app->pending_palm_slots);
+               }
+       }
+
+       input_mt_slot(input, slotnum);
+       input_mt_report_slot_state(input, tool, active);
+       if (active) {
+               /* this finger is in proximity of the sensor */
+               int wide = (*slot->w > *slot->h);
+               int major = max(*slot->w, *slot->h);
+               int minor = min(*slot->w, *slot->h);
+               int orientation = wide;
+               int max_azimuth;
+               int azimuth;
+
+               if (slot->a != DEFAULT_ZERO) {
                        /*
                         * Azimuth is counter-clockwise and ranges from [0, MAX)
                         * (a full revolution). Convert it to clockwise ranging
@@ -876,77 +1038,107 @@ static void mt_process_mt_event(struct hid_device *hid, struct hid_field *field,
                         * out of range to [-MAX/2, MAX/2] to report an upside
                         * down ellipsis.
                         */
-                       if (value > field->logical_maximum / 2)
-                               value -= field->logical_maximum;
-                       td->curdata.a = -value;
-                       td->curdata.has_azimuth = true;
-                       break;
-               case HID_DG_TOUCH:
-                       /* do nothing */
-                       break;
+                       azimuth = *slot->a;
+                       max_azimuth = input_abs_get_max(input,
+                                                       ABS_MT_ORIENTATION);
+                       if (azimuth > max_azimuth * 2)
+                               azimuth -= max_azimuth * 4;
+                       orientation = -azimuth;
+               }
 
-               default:
+               if (quirks & MT_QUIRK_TOUCH_SIZE_SCALING) {
                        /*
-                        * For Win8 PTP touchpads we should only look at
-                        * non finger/touch events in the first_packet of
-                        * a (possible) multi-packet frame.
+                        * divided by two to match visual scale of touch
+                        * for devices with this quirk
                         */
-                       if ((quirks & MT_QUIRK_WIN8_PTP_BUTTONS) &&
-                           !first_packet)
-                               return;
+                       major = major >> 1;
+                       minor = minor >> 1;
+               }
 
-                       /*
-                        * For Win8 PTP touchpads we map both the clickpad click
-                        * and any "external" left buttons to BTN_LEFT if a
-                        * device claims to have both we need to report 1 for
-                        * BTN_LEFT if either is pressed, so we or all values
-                        * together and report the result in mt_sync_frame().
-                        */
-                       if ((quirks & MT_QUIRK_WIN8_PTP_BUTTONS) &&
-                           usage->type == EV_KEY && usage->code == BTN_LEFT) {
-                               td->left_button_state |= value;
-                               return;
-                       }
+               input_event(input, EV_ABS, ABS_MT_POSITION_X, *slot->x);
+               input_event(input, EV_ABS, ABS_MT_POSITION_Y, *slot->y);
+               input_event(input, EV_ABS, ABS_MT_TOOL_X, *slot->cx);
+               input_event(input, EV_ABS, ABS_MT_TOOL_Y, *slot->cy);
+               input_event(input, EV_ABS, ABS_MT_DISTANCE, !*slot->tip_state);
+               input_event(input, EV_ABS, ABS_MT_ORIENTATION, orientation);
+               input_event(input, EV_ABS, ABS_MT_PRESSURE, *slot->p);
+               input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, major);
+               input_event(input, EV_ABS, ABS_MT_TOUCH_MINOR, minor);
+
+               set_bit(MT_IO_FLAGS_ACTIVE_SLOTS, &td->mt_io_flags);
+       }
 
-                       if (usage->type)
-                               input_event(input, usage->type, usage->code,
-                                               value);
+       return 0;
+}
+
+static void mt_process_mt_event(struct hid_device *hid,
+                               struct mt_application *app,
+                               struct hid_field *field,
+                               struct hid_usage *usage,
+                               __s32 value,
+                               bool first_packet)
+{
+       __s32 quirks = app->quirks;
+       struct input_dev *input = field->hidinput->input;
+
+       if (!usage->type || !(hid->claimed & HID_CLAIMED_INPUT))
+               return;
+
+       if (quirks & MT_QUIRK_WIN8_PTP_BUTTONS) {
+
+               /*
+                * For Win8 PTP touchpads we should only look at
+                * non finger/touch events in the first_packet of a
+                * (possible) multi-packet frame.
+                */
+               if (!first_packet)
                        return;
-               }
 
-               if (usage->usage_index + 1 == field->report_count) {
-                       /* we only take into account the last report. */
-                       if (usage->hid == td->last_slot_field)
-                               mt_complete_slot(td, field->hidinput->input);
+               /*
+                * For Win8 PTP touchpads we map both the clickpad click
+                * and any "external" left buttons to BTN_LEFT if a
+                * device claims to have both we need to report 1 for
+                * BTN_LEFT if either is pressed, so we or all values
+                * together and report the result in mt_sync_frame().
+                */
+               if (usage->type == EV_KEY && usage->code == BTN_LEFT) {
+                       app->left_button_state |= value;
+                       return;
                }
-
        }
+
+       input_event(input, usage->type, usage->code, value);
 }
 
-static void mt_touch_report(struct hid_device *hid, struct hid_report *report)
+static void mt_touch_report(struct hid_device *hid,
+                           struct mt_report_data *rdata)
 {
        struct mt_device *td = hid_get_drvdata(hid);
+       struct hid_report *report = rdata->report;
+       struct mt_application *app = rdata->application;
        struct hid_field *field;
+       struct input_dev *input;
+       struct mt_usages *slot;
        bool first_packet;
        unsigned count;
-       int r, n, scantime = 0;
+       int r, n;
+       int scantime = 0;
+       int contact_count = -1;
 
        /* sticky fingers release in progress, abort */
        if (test_and_set_bit(MT_IO_FLAGS_RUNNING, &td->mt_io_flags))
                return;
 
+       scantime = *app->scantime;
+       app->timestamp = mt_compute_timestamp(app, scantime);
+       if (app->raw_cc != DEFAULT_ZERO)
+               contact_count = *app->raw_cc;
+
        /*
         * Includes multi-packet support where subsequent
         * packets are sent with zero contactcount.
         */
-       if (td->scantime_index >= 0) {
-               field = report->field[td->scantime_index];
-               scantime = field->value[td->scantime_val_index];
-       }
-       if (td->cc_index >= 0) {
-               struct hid_field *field = report->field[td->cc_index];
-               int value = field->value[td->cc_value_index];
-
+       if (contact_count >= 0) {
                /*
                 * For Win8 PTPs the first packet (td->num_received == 0) may
                 * have a contactcount of 0 if there only is a button event.
@@ -954,16 +1146,25 @@ static void mt_touch_report(struct hid_device *hid, struct hid_report *report)
                 * of a possible multi-packet frame be checking that the
                 * timestamp has changed.
                 */
-               if ((td->mtclass.quirks & MT_QUIRK_WIN8_PTP_BUTTONS) &&
-                   td->num_received == 0 && td->prev_scantime != scantime)
-                       td->num_expected = value;
+               if ((app->quirks & MT_QUIRK_WIN8_PTP_BUTTONS) &&
+                   app->num_received == 0 &&
+                   app->prev_scantime != scantime)
+                       app->num_expected = contact_count;
                /* A non 0 contact count always indicates a first packet */
-               else if (value)
-                       td->num_expected = value;
+               else if (contact_count)
+                       app->num_expected = contact_count;
+       }
+       app->prev_scantime = scantime;
+
+       first_packet = app->num_received == 0;
+
+       input = report->field[0]->hidinput->input;
+
+       list_for_each_entry(slot, &app->mt_usages, list) {
+               if (!mt_process_slot(td, input, app, slot))
+                       app->num_received++;
        }
-       td->prev_scantime = scantime;
 
-       first_packet = td->num_received == 0;
        for (r = 0; r < report->maxfield; r++) {
                field = report->field[r];
                count = field->report_count;
@@ -972,12 +1173,13 @@ static void mt_touch_report(struct hid_device *hid, struct hid_report *report)
                        continue;
 
                for (n = 0; n < count; n++)
-                       mt_process_mt_event(hid, field, &field->usage[n],
-                                           field->value[n], first_packet);
+                       mt_process_mt_event(hid, app, field,
+                                           &field->usage[n], field->value[n],
+                                           first_packet);
        }
 
-       if (td->num_received >= td->num_expected)
-               mt_sync_frame(td, report->field[0]->hidinput->input);
+       if (app->num_received >= app->num_expected)
+               mt_sync_frame(td, app, input);
 
        /*
         * Windows 8 specs says 2 things:
@@ -997,7 +1199,7 @@ static void mt_touch_report(struct hid_device *hid, struct hid_report *report)
         * only affect laggish machines and the ones that have a firmware
         * defect.
         */
-       if (td->mtclass.quirks & MT_QUIRK_STICKY_FINGERS) {
+       if (app->quirks & MT_QUIRK_STICKY_FINGERS) {
                if (test_bit(MT_IO_FLAGS_PENDING_SLOTS, &td->mt_io_flags))
                        mod_timer(&td->release_timer,
                                  jiffies + msecs_to_jiffies(100));
@@ -1009,7 +1211,8 @@ static void mt_touch_report(struct hid_device *hid, struct hid_report *report)
 }
 
 static int mt_touch_input_configured(struct hid_device *hdev,
-                                       struct hid_input *hi)
+                                    struct hid_input *hi,
+                                    struct mt_application *app)
 {
        struct mt_device *td = hid_get_drvdata(hdev);
        struct mt_class *cls = &td->mtclass;
@@ -1019,28 +1222,36 @@ static int mt_touch_input_configured(struct hid_device *hdev,
        if (!td->maxcontacts)
                td->maxcontacts = MT_DEFAULT_MAXCONTACT;
 
-       mt_post_parse(td);
+       mt_post_parse(td, app);
        if (td->serial_maybe)
-               mt_post_parse_default_settings(td);
+               mt_post_parse_default_settings(td, app);
 
        if (cls->is_indirect)
-               td->mt_flags |= INPUT_MT_POINTER;
+               app->mt_flags |= INPUT_MT_POINTER;
 
-       if (cls->quirks & MT_QUIRK_NOT_SEEN_MEANS_UP)
-               td->mt_flags |= INPUT_MT_DROP_UNUSED;
+       if (app->quirks & MT_QUIRK_NOT_SEEN_MEANS_UP)
+               app->mt_flags |= INPUT_MT_DROP_UNUSED;
 
        /* check for clickpads */
-       if ((td->mt_flags & INPUT_MT_POINTER) && (td->buttons_count == 1))
+       if ((app->mt_flags & INPUT_MT_POINTER) &&
+           (app->buttons_count == 1))
                td->is_buttonpad = true;
 
        if (td->is_buttonpad)
                __set_bit(INPUT_PROP_BUTTONPAD, input->propbit);
 
-       ret = input_mt_init_slots(input, td->maxcontacts, td->mt_flags);
+       app->pending_palm_slots = devm_kcalloc(&hi->input->dev,
+                                              BITS_TO_LONGS(td->maxcontacts),
+                                              sizeof(long),
+                                              GFP_KERNEL);
+       if (!app->pending_palm_slots)
+               return -ENOMEM;
+
+       ret = input_mt_init_slots(input, td->maxcontacts, app->mt_flags);
        if (ret)
                return ret;
 
-       td->mt_flags = 0;
+       app->mt_flags = 0;
        return 0;
 }
 
@@ -1051,6 +1262,16 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
                unsigned long **bit, int *max)
 {
        struct mt_device *td = hid_get_drvdata(hdev);
+       struct mt_application *application;
+       struct mt_report_data *rdata;
+
+       rdata = mt_find_report_data(td, field->report);
+       if (!rdata) {
+               hid_err(hdev, "failed to allocate data for report\n");
+               return 0;
+       }
+
+       application = rdata->application;
 
        /*
         * If mtclass.export_all_inputs is not set, only map fields from
@@ -1066,8 +1287,9 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
            field->application != HID_GD_SYSTEM_CONTROL &&
            field->application != HID_CP_CONSUMER_CONTROL &&
            field->application != HID_GD_WIRELESS_RADIO_CTLS &&
+           field->application != HID_GD_SYSTEM_MULTIAXIS &&
            !(field->application == HID_VD_ASUS_CUSTOM_MEDIA_KEYS &&
-             td->mtclass.quirks & MT_QUIRK_ASUS_CUSTOM_UP))
+             application->quirks & MT_QUIRK_ASUS_CUSTOM_UP))
                return -1;
 
        /*
@@ -1076,7 +1298,7 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
         * map usages to input keys.
         */
        if (field->application == HID_VD_ASUS_CUSTOM_MEDIA_KEYS &&
-           td->mtclass.quirks & MT_QUIRK_ASUS_CUSTOM_UP &&
+           application->quirks & MT_QUIRK_ASUS_CUSTOM_UP &&
            (usage->hid & HID_USAGE_PAGE) == HID_UP_CUSTOM) {
                set_bit(EV_REP, hi->input->evbit);
                if (field->flags & HID_MAIN_ITEM_VARIABLE)
@@ -1093,23 +1315,9 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
                return 1;
        }
 
-       /*
-        * some egalax touchscreens have "application == HID_DG_TOUCHSCREEN"
-        * for the stylus.
-        * The check for mt_report_id ensures we don't process
-        * HID_DG_CONTACTCOUNT from the pen report as it is outside the physical
-        * collection, but within the report ID.
-        */
-       if (field->physical == HID_DG_STYLUS)
-               return 0;
-       else if ((field->physical == 0) &&
-                (field->report->id != td->mt_report_id) &&
-                (td->mt_report_id != -1))
-               return 0;
-
-       if (field->application == HID_DG_TOUCHSCREEN ||
-           field->application == HID_DG_TOUCHPAD)
-               return mt_touch_input_mapping(hdev, hi, field, usage, bit, max);
+       if (rdata->is_mt_collection)
+               return mt_touch_input_mapping(hdev, hi, field, usage, bit, max,
+                                             application);
 
        /* let hid-core decide for the others */
        return 0;
@@ -1119,15 +1327,11 @@ static int mt_input_mapped(struct hid_device *hdev, struct hid_input *hi,
                struct hid_field *field, struct hid_usage *usage,
                unsigned long **bit, int *max)
 {
-       /*
-        * some egalax touchscreens have "application == HID_DG_TOUCHSCREEN"
-        * for the stylus.
-        */
-       if (field->physical == HID_DG_STYLUS)
-               return 0;
+       struct mt_device *td = hid_get_drvdata(hdev);
+       struct mt_report_data *rdata;
 
-       if (field->application == HID_DG_TOUCHSCREEN ||
-           field->application == HID_DG_TOUCHPAD) {
+       rdata = mt_find_report_data(td, field->report);
+       if (rdata && rdata->is_mt_collection) {
                /* We own these mappings, tell hid-input to ignore them */
                return -1;
        }
@@ -1140,8 +1344,10 @@ static int mt_event(struct hid_device *hid, struct hid_field *field,
                                struct hid_usage *usage, __s32 value)
 {
        struct mt_device *td = hid_get_drvdata(hid);
+       struct mt_report_data *rdata;
 
-       if (field->report->id == td->mt_report_id)
+       rdata = mt_find_report_data(td, field->report);
+       if (rdata && rdata->is_mt_collection)
                return mt_touch_event(hid, field, usage, value);
 
        return 0;
@@ -1151,12 +1357,14 @@ static void mt_report(struct hid_device *hid, struct hid_report *report)
 {
        struct mt_device *td = hid_get_drvdata(hid);
        struct hid_field *field = report->field[0];
+       struct mt_report_data *rdata;
 
        if (!(hid->claimed & HID_CLAIMED_INPUT))
                return;
 
-       if (report->id == td->mt_report_id)
-               return mt_touch_report(hid, report);
+       rdata = mt_find_report_data(td, report);
+       if (rdata && rdata->is_mt_collection)
+               return mt_touch_report(hid, rdata);
 
        if (field && field->hidinput && field->hidinput->input)
                input_sync(field->hidinput->input);
@@ -1197,9 +1405,9 @@ static bool mt_need_to_apply_feature(struct hid_device *hdev,
                return true;
 
        case HID_DG_CONTACTMAX:
-               if (td->mtclass.maxcontacts) {
+               if (cls->maxcontacts) {
                        max = min_t(int, field->logical_maximum,
-                                   td->mtclass.maxcontacts);
+                                   cls->maxcontacts);
                        if (field->value[index] != max) {
                                field->value[index] = max;
                                return true;
@@ -1259,12 +1467,13 @@ static void mt_set_modes(struct hid_device *hdev, enum latency_mode latency,
        }
 }
 
-static void mt_post_parse_default_settings(struct mt_device *td)
+static void mt_post_parse_default_settings(struct mt_device *td,
+                                          struct mt_application *app)
 {
-       __s32 quirks = td->mtclass.quirks;
+       __s32 quirks = app->quirks;
 
        /* unknown serial device needs special quirks */
-       if (td->touches_by_report == 1) {
+       if (list_is_singular(&app->mt_usages)) {
                quirks |= MT_QUIRK_ALWAYS_VALID;
                quirks &= ~MT_QUIRK_NOT_SEEN_MEANS_UP;
                quirks &= ~MT_QUIRK_VALID_IS_INRANGE;
@@ -1272,21 +1481,13 @@ static void mt_post_parse_default_settings(struct mt_device *td)
                quirks &= ~MT_QUIRK_CONTACT_CNT_ACCURATE;
        }
 
-       td->mtclass.quirks = quirks;
+       app->quirks = quirks;
 }
 
-static void mt_post_parse(struct mt_device *td)
+static void mt_post_parse(struct mt_device *td, struct mt_application *app)
 {
-       struct mt_fields *f = td->fields;
-       struct mt_class *cls = &td->mtclass;
-
-       if (td->touches_by_report > 0) {
-               int field_count_per_touch = f->length / td->touches_by_report;
-               td->last_slot_field = f->usages[field_count_per_touch - 1];
-       }
-
-       if (td->cc_index < 0)
-               cls->quirks &= ~MT_QUIRK_CONTACT_CNT_ACCURATE;
+       if (!app->have_contact_count)
+               app->quirks &= ~MT_QUIRK_CONTACT_CNT_ACCURATE;
 }
 
 static int mt_input_configured(struct hid_device *hdev, struct hid_input *hi)
@@ -1295,13 +1496,24 @@ static int mt_input_configured(struct hid_device *hdev, struct hid_input *hi)
        char *name;
        const char *suffix = NULL;
        unsigned int application = 0;
+       struct mt_report_data *rdata;
+       struct mt_application *mt_application = NULL;
        struct hid_report *report;
        int ret;
 
        list_for_each_entry(report, &hi->reports, hidinput_list) {
                application = report->application;
-               if (report->id == td->mt_report_id) {
-                       ret = mt_touch_input_configured(hdev, hi);
+               rdata = mt_find_report_data(td, report);
+               if (!rdata) {
+                       hid_err(hdev, "failed to allocate data for report\n");
+                       return -ENOMEM;
+               }
+
+               mt_application = rdata->application;
+
+               if (rdata->is_mt_collection) {
+                       ret = mt_touch_input_configured(hdev, hi,
+                                                       mt_application);
                        if (ret)
                                return ret;
                }
@@ -1327,6 +1539,7 @@ static int mt_input_configured(struct hid_device *hdev, struct hid_input *hi)
                case HID_GD_SYSTEM_CONTROL:
                case HID_CP_CONSUMER_CONTROL:
                case HID_GD_WIRELESS_RADIO_CTLS:
+               case HID_GD_SYSTEM_MULTIAXIS:
                        /* already handled by hid core */
                        break;
                case HID_DG_TOUCHSCREEN:
@@ -1390,6 +1603,7 @@ static void mt_fix_const_fields(struct hid_device *hdev, unsigned int usage)
 static void mt_release_contacts(struct hid_device *hid)
 {
        struct hid_input *hidinput;
+       struct mt_application *application;
        struct mt_device *td = hid_get_drvdata(hid);
 
        list_for_each_entry(hidinput, &hid->inputs, list) {
@@ -1409,7 +1623,9 @@ static void mt_release_contacts(struct hid_device *hid)
                }
        }
 
-       td->num_received = 0;
+       list_for_each_entry(application, &td->applications, list) {
+               application->num_received = 0;
+       }
 }
 
 static void mt_expired_timeout(struct timer_list *t)
@@ -1432,7 +1648,7 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
 {
        int ret, i;
        struct mt_device *td;
-       struct mt_class *mtclass = mt_classes; /* MT_CLS_DEFAULT */
+       const struct mt_class *mtclass = mt_classes; /* MT_CLS_DEFAULT */
 
        for (i = 0; mt_classes[i].name ; i++) {
                if (id->driver_data == mt_classes[i].name) {
@@ -1449,17 +1665,10 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
        td->hdev = hdev;
        td->mtclass = *mtclass;
        td->inputmode_value = MT_INPUTMODE_TOUCHSCREEN;
-       td->cc_index = -1;
-       td->scantime_index = -1;
-       td->mt_report_id = -1;
        hid_set_drvdata(hdev, td);
 
-       td->fields = devm_kzalloc(&hdev->dev, sizeof(struct mt_fields),
-                                 GFP_KERNEL);
-       if (!td->fields) {
-               dev_err(&hdev->dev, "cannot allocate multitouch fields data\n");
-               return -ENOMEM;
-       }
+       INIT_LIST_HEAD(&td->applications);
+       INIT_LIST_HEAD(&td->reports);
 
        if (id->vendor == HID_ANY_ID && id->product == HID_ANY_ID)
                td->serial_maybe = true;
@@ -1496,10 +1705,6 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
 
        mt_set_modes(hdev, HID_LATENCY_NORMAL, true, true);
 
-       /* release .fields memory as it is not used anymore */
-       devm_kfree(&hdev->dev, td->fields);
-       td->fields = NULL;
-
        return 0;
 }
 
index 43b1c72..9bc6f48 100644 (file)
@@ -955,6 +955,8 @@ static int ntrig_probe(struct hid_device *hdev, const struct hid_device_id *id)
 
        ret = sysfs_create_group(&hdev->dev.kobj,
                        &ntrig_attribute_group);
+       if (ret)
+               hid_err(hdev, "cannot create sysfs group\n");
 
        return 0;
 err_free:
index daf5957..73c9d4c 100644 (file)
@@ -44,29 +44,6 @@ static __u8 *redragon_report_fixup(struct hid_device *hdev, __u8 *rdesc,
        return rdesc;
 }
 
-static int redragon_probe(struct hid_device *dev,
-       const struct hid_device_id *id)
-{
-       int ret;
-
-       ret = hid_parse(dev);
-       if (ret) {
-               hid_err(dev, "parse failed\n");
-               return ret;
-       }
-
-       /* do not register unused input device */
-       if (dev->maxapplication == 1)
-               return 0;
-
-       ret = hid_hw_start(dev, HID_CONNECT_DEFAULT);
-       if (ret) {
-               hid_err(dev, "hw start failed\n");
-               return ret;
-       }
-
-       return 0;
-}
 static const struct hid_device_id redragon_devices[] = {
        {HID_USB_DEVICE(USB_VENDOR_ID_JESS, USB_DEVICE_ID_REDRAGON_ASURA)},
        {}
@@ -77,8 +54,7 @@ MODULE_DEVICE_TABLE(hid, redragon_devices);
 static struct hid_driver redragon_driver = {
        .name = "redragon",
        .id_table = redragon_devices,
-       .report_fixup = redragon_report_fixup,
-       .probe = redragon_probe
+       .report_fixup = redragon_report_fixup
 };
 
 module_hid_driver(redragon_driver);
index e475c50..9671a4b 100644 (file)
@@ -1353,7 +1353,7 @@ static int sony_register_touchpad(struct sony_sc *sc, int touch_count,
        char *name;
        int ret;
 
-       sc->touchpad = input_allocate_device();
+       sc->touchpad = devm_input_allocate_device(&sc->hdev->dev);
        if (!sc->touchpad)
                return -ENOMEM;
 
@@ -1370,11 +1370,9 @@ static int sony_register_touchpad(struct sony_sc *sc, int touch_count,
         * DS4 compatible non-Sony devices with different names.
         */
        name_sz = strlen(sc->hdev->name) + sizeof(DS4_TOUCHPAD_SUFFIX);
-       name = kzalloc(name_sz, GFP_KERNEL);
-       if (!name) {
-               ret = -ENOMEM;
-               goto err;
-       }
+       name = devm_kzalloc(&sc->hdev->dev, name_sz, GFP_KERNEL);
+       if (!name)
+               return -ENOMEM;
        snprintf(name, name_sz, "%s" DS4_TOUCHPAD_SUFFIX, sc->hdev->name);
        sc->touchpad->name = name;
 
@@ -1403,34 +1401,13 @@ static int sony_register_touchpad(struct sony_sc *sc, int touch_count,
 
        ret = input_mt_init_slots(sc->touchpad, touch_count, INPUT_MT_POINTER);
        if (ret < 0)
-               goto err;
+               return ret;
 
        ret = input_register_device(sc->touchpad);
        if (ret < 0)
-               goto err;
+               return ret;
 
        return 0;
-
-err:
-       kfree(sc->touchpad->name);
-       sc->touchpad->name = NULL;
-
-       input_free_device(sc->touchpad);
-       sc->touchpad = NULL;
-
-       return ret;
-}
-
-static void sony_unregister_touchpad(struct sony_sc *sc)
-{
-       if (!sc->touchpad)
-               return;
-
-       kfree(sc->touchpad->name);
-       sc->touchpad->name = NULL;
-
-       input_unregister_device(sc->touchpad);
-       sc->touchpad = NULL;
 }
 
 static int sony_register_sensors(struct sony_sc *sc)
@@ -1440,7 +1417,7 @@ static int sony_register_sensors(struct sony_sc *sc)
        int ret;
        int range;
 
-       sc->sensor_dev = input_allocate_device();
+       sc->sensor_dev = devm_input_allocate_device(&sc->hdev->dev);
        if (!sc->sensor_dev)
                return -ENOMEM;
 
@@ -1457,11 +1434,9 @@ static int sony_register_sensors(struct sony_sc *sc)
         * DS4 compatible non-Sony devices with different names.
         */
        name_sz = strlen(sc->hdev->name) + sizeof(SENSOR_SUFFIX);
-       name = kzalloc(name_sz, GFP_KERNEL);
-       if (!name) {
-               ret = -ENOMEM;
-               goto err;
-       }
+       name = devm_kzalloc(&sc->hdev->dev, name_sz, GFP_KERNEL);
+       if (!name)
+               return -ENOMEM;
        snprintf(name, name_sz, "%s" SENSOR_SUFFIX, sc->hdev->name);
        sc->sensor_dev->name = name;
 
@@ -1503,33 +1478,11 @@ static int sony_register_sensors(struct sony_sc *sc)
 
        ret = input_register_device(sc->sensor_dev);
        if (ret < 0)
-               goto err;
+               return ret;
 
        return 0;
-
-err:
-       kfree(sc->sensor_dev->name);
-       sc->sensor_dev->name = NULL;
-
-       input_free_device(sc->sensor_dev);
-       sc->sensor_dev = NULL;
-
-       return ret;
 }
 
-static void sony_unregister_sensors(struct sony_sc *sc)
-{
-       if (!sc->sensor_dev)
-               return;
-
-       kfree(sc->sensor_dev->name);
-       sc->sensor_dev->name = NULL;
-
-       input_unregister_device(sc->sensor_dev);
-       sc->sensor_dev = NULL;
-}
-
-
 /*
  * Sending HID_REQ_GET_REPORT changes the operation mode of the ps3 controller
  * to "operational".  Without this, the ps3 controller will not report any
@@ -1987,25 +1940,6 @@ static int sony_led_blink_set(struct led_classdev *led, unsigned long *delay_on,
        return 0;
 }
 
-static void sony_leds_remove(struct sony_sc *sc)
-{
-       struct led_classdev *led;
-       int n;
-
-       BUG_ON(!(sc->quirks & SONY_LED_SUPPORT));
-
-       for (n = 0; n < sc->led_count; n++) {
-               led = sc->leds[n];
-               sc->leds[n] = NULL;
-               if (!led)
-                       continue;
-               led_classdev_unregister(led);
-               kfree(led);
-       }
-
-       sc->led_count = 0;
-}
-
 static int sony_leds_init(struct sony_sc *sc)
 {
        struct hid_device *hdev = sc->hdev;
@@ -2078,11 +2012,10 @@ static int sony_leds_init(struct sony_sc *sc)
                if (use_ds4_names)
                        name_sz = strlen(dev_name(&hdev->dev)) + strlen(ds4_name_str[n]) + 2;
 
-               led = kzalloc(sizeof(struct led_classdev) + name_sz, GFP_KERNEL);
+               led = devm_kzalloc(&hdev->dev, sizeof(struct led_classdev) + name_sz, GFP_KERNEL);
                if (!led) {
                        hid_err(hdev, "Couldn't allocate memory for LED %d\n", n);
-                       ret = -ENOMEM;
-                       goto error_leds;
+                       return -ENOMEM;
                }
 
                name = (void *)(&led[1]);
@@ -2103,21 +2036,14 @@ static int sony_leds_init(struct sony_sc *sc)
 
                sc->leds[n] = led;
 
-               ret = led_classdev_register(&hdev->dev, led);
+               ret = devm_led_classdev_register(&hdev->dev, led);
                if (ret) {
                        hid_err(hdev, "Failed to register LED %d\n", n);
-                       sc->leds[n] = NULL;
-                       kfree(led);
-                       goto error_leds;
+                       return ret;
                }
        }
 
-       return ret;
-
-error_leds:
-       sony_leds_remove(sc);
-
-       return ret;
+       return 0;
 }
 
 static void sixaxis_send_output_report(struct sony_sc *sc)
@@ -2276,16 +2202,20 @@ static int sony_allocate_output_report(struct sony_sc *sc)
        if ((sc->quirks & SIXAXIS_CONTROLLER) ||
                        (sc->quirks & NAVIGATION_CONTROLLER))
                sc->output_report_dmabuf =
-                       kmalloc(sizeof(union sixaxis_output_report_01),
+                       devm_kmalloc(&sc->hdev->dev,
+                               sizeof(union sixaxis_output_report_01),
                                GFP_KERNEL);
        else if (sc->quirks & DUALSHOCK4_CONTROLLER_BT)
-               sc->output_report_dmabuf = kmalloc(DS4_OUTPUT_REPORT_0x11_SIZE,
+               sc->output_report_dmabuf = devm_kmalloc(&sc->hdev->dev,
+                                               DS4_OUTPUT_REPORT_0x11_SIZE,
                                                GFP_KERNEL);
        else if (sc->quirks & (DUALSHOCK4_CONTROLLER_USB | DUALSHOCK4_DONGLE))
-               sc->output_report_dmabuf = kmalloc(DS4_OUTPUT_REPORT_0x05_SIZE,
+               sc->output_report_dmabuf = devm_kmalloc(&sc->hdev->dev,
+                                               DS4_OUTPUT_REPORT_0x05_SIZE,
                                                GFP_KERNEL);
        else if (sc->quirks & MOTION_CONTROLLER)
-               sc->output_report_dmabuf = kmalloc(MOTION_REPORT_0x02_SIZE,
+               sc->output_report_dmabuf = devm_kmalloc(&sc->hdev->dev,
+                                               MOTION_REPORT_0x02_SIZE,
                                                GFP_KERNEL);
        else
                return 0;
@@ -2392,36 +2322,21 @@ static int sony_battery_probe(struct sony_sc *sc, int append_dev_id)
        sc->battery_desc.get_property = sony_battery_get_property;
        sc->battery_desc.type = POWER_SUPPLY_TYPE_BATTERY;
        sc->battery_desc.use_for_apm = 0;
-       sc->battery_desc.name = kasprintf(GFP_KERNEL, battery_str_fmt,
-                                         sc->mac_address, sc->device_id);
+       sc->battery_desc.name = devm_kasprintf(&hdev->dev, GFP_KERNEL,
+                                         battery_str_fmt, sc->mac_address, sc->device_id);
        if (!sc->battery_desc.name)
                return -ENOMEM;
 
-       sc->battery = power_supply_register(&hdev->dev, &sc->battery_desc,
+       sc->battery = devm_power_supply_register(&hdev->dev, &sc->battery_desc,
                                            &psy_cfg);
        if (IS_ERR(sc->battery)) {
                ret = PTR_ERR(sc->battery);
                hid_err(hdev, "Unable to register battery device\n");
-               goto err_free;
+               return ret;
        }
 
        power_supply_powers(sc->battery, &hdev->dev);
        return 0;
-
-err_free:
-       kfree(sc->battery_desc.name);
-       sc->battery_desc.name = NULL;
-       return ret;
-}
-
-static void sony_battery_remove(struct sony_sc *sc)
-{
-       if (!sc->battery_desc.name)
-               return;
-
-       power_supply_unregister(sc->battery);
-       kfree(sc->battery_desc.name);
-       sc->battery_desc.name = NULL;
 }
 
 /*
@@ -2879,16 +2794,7 @@ err_stop:
                device_remove_file(&sc->hdev->dev, &dev_attr_firmware_version);
        if (sc->hw_version)
                device_remove_file(&sc->hdev->dev, &dev_attr_hardware_version);
-       if (sc->quirks & SONY_LED_SUPPORT)
-               sony_leds_remove(sc);
-       if (sc->quirks & SONY_BATTERY_SUPPORT)
-               sony_battery_remove(sc);
-       if (sc->touchpad)
-               sony_unregister_touchpad(sc);
-       if (sc->sensor_dev)
-               sony_unregister_sensors(sc);
        sony_cancel_work_sync(sc);
-       kfree(sc->output_report_dmabuf);
        sony_remove_dev_list(sc);
        sony_release_device_id(sc);
        hid_hw_stop(hdev);
@@ -2965,18 +2871,6 @@ static void sony_remove(struct hid_device *hdev)
 
        hid_hw_close(hdev);
 
-       if (sc->quirks & SONY_LED_SUPPORT)
-               sony_leds_remove(sc);
-
-       if (sc->quirks & SONY_BATTERY_SUPPORT)
-               sony_battery_remove(sc);
-
-       if (sc->touchpad)
-               sony_unregister_touchpad(sc);
-
-       if (sc->sensor_dev)
-               sony_unregister_sensors(sc);
-
        if (sc->quirks & DUALSHOCK4_CONTROLLER_BT)
                device_remove_file(&sc->hdev->dev, &dev_attr_bt_poll_interval);
 
@@ -2988,8 +2882,6 @@ static void sony_remove(struct hid_device *hdev)
 
        sony_cancel_work_sync(sc);
 
-       kfree(sc->output_report_dmabuf);
-
        sony_remove_dev_list(sc);
 
        sony_release_device_id(sc);
index 579884e..7780da4 100644 (file)
@@ -455,6 +455,12 @@ static __u8 wiimote_cmd_read_ext(struct wiimote_data *wdata, __u8 *rmem)
                return WIIMOTE_EXT_BALANCE_BOARD;
        if (rmem[4] == 0x01 && rmem[5] == 0x20)
                return WIIMOTE_EXT_PRO_CONTROLLER;
+       if (rmem[0] == 0x01 && rmem[1] == 0x00 &&
+           rmem[4] == 0x01 && rmem[5] == 0x03)
+               return WIIMOTE_EXT_DRUMS;
+       if (rmem[0] == 0x00 && rmem[1] == 0x00 &&
+           rmem[4] == 0x01 && rmem[5] == 0x03)
+               return WIIMOTE_EXT_GUITAR;
 
        return WIIMOTE_EXT_UNKNOWN;
 }
@@ -488,6 +494,8 @@ static bool wiimote_cmd_map_mp(struct wiimote_data *wdata, __u8 exttype)
        /* map MP with correct pass-through mode */
        switch (exttype) {
        case WIIMOTE_EXT_CLASSIC_CONTROLLER:
+       case WIIMOTE_EXT_DRUMS:
+       case WIIMOTE_EXT_GUITAR:
                wmem = 0x07;
                break;
        case WIIMOTE_EXT_NUNCHUK:
@@ -1075,6 +1083,8 @@ static const char *wiimote_exttype_names[WIIMOTE_EXT_NUM] = {
        [WIIMOTE_EXT_CLASSIC_CONTROLLER] = "Nintendo Wii Classic Controller",
        [WIIMOTE_EXT_BALANCE_BOARD] = "Nintendo Wii Balance Board",
        [WIIMOTE_EXT_PRO_CONTROLLER] = "Nintendo Wii U Pro Controller",
+       [WIIMOTE_EXT_DRUMS] = "Nintendo Wii Drums",
+       [WIIMOTE_EXT_GUITAR] = "Nintendo Wii Guitar",
 };
 
 /*
@@ -1660,6 +1670,10 @@ static ssize_t wiimote_ext_show(struct device *dev,
                return sprintf(buf, "balanceboard\n");
        case WIIMOTE_EXT_PRO_CONTROLLER:
                return sprintf(buf, "procontroller\n");
+       case WIIMOTE_EXT_DRUMS:
+               return sprintf(buf, "drums\n");
+       case WIIMOTE_EXT_GUITAR:
+               return sprintf(buf, "guitar\n");
        case WIIMOTE_EXT_UNKNOWN:
                /* fallthrough */
        default:
index c830ed3..aa72eb9 100644 (file)
@@ -1950,6 +1950,444 @@ static const struct wiimod_ops wiimod_pro = {
 };
 
 /*
+ * Drums
+ * Guitar-Hero, Rock-Band and other games came bundled with drums which can
+ * be plugged as extension to a Wiimote. Drum-reports are still not entirely
+ * figured out, but the most important information is known.
+ * We create a separate device for drums and report all information via this
+ * input device.
+ */
+
+static inline void wiimod_drums_report_pressure(struct wiimote_data *wdata,
+                                               __u8 none, __u8 which,
+                                               __u8 pressure, __u8 onoff,
+                                               __u8 *store, __u16 code,
+                                               __u8 which_code)
+{
+       static const __u8 default_pressure = 3;
+
+       if (!none && which == which_code) {
+               *store = pressure;
+               input_report_abs(wdata->extension.input, code, *store);
+       } else if (onoff != !!*store) {
+               *store = onoff ? default_pressure : 0;
+               input_report_abs(wdata->extension.input, code, *store);
+       }
+}
+
+static void wiimod_drums_in_ext(struct wiimote_data *wdata, const __u8 *ext)
+{
+       __u8 pressure, which, none, hhp, sx, sy;
+       __u8 o, r, y, g, b, bass, bm, bp;
+
+       /*   Byte |  8  |  7  |  6  |  5  |  4  |  3  |  2  |  1  |
+        *   -----+-----+-----+-----+-----+-----+-----+-----+-----+
+        *    1   |  0  |  0  |              SX <5:0>             |
+        *    2   |  0  |  0  |              SY <5:0>             |
+        *   -----+-----+-----+-----------------------------+-----+
+        *    3   | HPP | NON |         WHICH <5:1>         |  ?  |
+        *   -----+-----+-----+-----+-----+-----+-----+-----+-----+
+        *    4   |   SOFT <7:5>    |  0  |  1  |  1  |  0  |  ?  |
+        *   -----+-----+-----+-----+-----+-----+-----+-----+-----+
+        *    5   |  ?  |  1  |  1  | B-  |  1  | B+  |  1  |  ?  |
+        *   -----+-----+-----+-----+-----+-----+-----+-----+-----+
+        *    6   |  O  |  R  |  Y  |  G  |  B  | BSS |  1  |  1  |
+        *   -----+-----+-----+-----+-----+-----+-----+-----+-----+
+        * All buttons are 0 if pressed
+        *
+        * With Motion+ enabled, the following bits will get invalid:
+        *   Byte |  8  |  7  |  6  |  5  |  4  |  3  |  2  |  1  |
+        *   -----+-----+-----+-----+-----+-----+-----+-----+-----+
+        *    1   |  0  |  0  |              SX <5:1>       |XXXXX|
+        *    2   |  0  |  0  |              SY <5:1>       |XXXXX|
+        *   -----+-----+-----+-----------------------------+-----+
+        *    3   | HPP | NON |         WHICH <5:1>         |  ?  |
+        *   -----+-----+-----+-----+-----+-----+-----+-----+-----+
+        *    4   |   SOFT <7:5>    |  0  |  1  |  1  |  0  |  ?  |
+        *   -----+-----+-----+-----+-----+-----+-----+-----+-----+
+        *    5   |  ?  |  1  |  1  | B-  |  1  | B+  |  1  |XXXXX|
+        *   -----+-----+-----+-----+-----+-----+-----+-----+-----+
+        *    6   |  O  |  R  |  Y  |  G  |  B  | BSS |XXXXX|XXXXX|
+        *   -----+-----+-----+-----+-----+-----+-----+-----+-----+
+        */
+
+       pressure = 7 - (ext[3] >> 5);
+       which = (ext[2] >> 1) & 0x1f;
+       none = !!(ext[2] & 0x40);
+       hhp = !(ext[2] & 0x80);
+       sx = ext[0] & 0x3f;
+       sy = ext[1] & 0x3f;
+       o = !(ext[5] & 0x80);
+       r = !(ext[5] & 0x40);
+       y = !(ext[5] & 0x20);
+       g = !(ext[5] & 0x10);
+       b = !(ext[5] & 0x08);
+       bass = !(ext[5] & 0x04);
+       bm = !(ext[4] & 0x10);
+       bp = !(ext[4] & 0x04);
+
+       if (wdata->state.flags & WIIPROTO_FLAG_MP_ACTIVE) {
+               sx &= 0x3e;
+               sy &= 0x3e;
+       }
+
+       wiimod_drums_report_pressure(wdata, none, which, pressure,
+                                    o, &wdata->state.pressure_drums[0],
+                                    ABS_HAT2Y, 0x0e);
+       wiimod_drums_report_pressure(wdata, none, which, pressure,
+                                    r, &wdata->state.pressure_drums[1],
+                                    ABS_HAT0X, 0x19);
+       wiimod_drums_report_pressure(wdata, none, which, pressure,
+                                    y, &wdata->state.pressure_drums[2],
+                                    ABS_HAT2X, 0x11);
+       wiimod_drums_report_pressure(wdata, none, which, pressure,
+                                    g, &wdata->state.pressure_drums[3],
+                                    ABS_HAT1X, 0x12);
+       wiimod_drums_report_pressure(wdata, none, which, pressure,
+                                    b, &wdata->state.pressure_drums[4],
+                                    ABS_HAT0Y, 0x0f);
+
+       /* Bass shares pressure with hi-hat (set via hhp) */
+       wiimod_drums_report_pressure(wdata, none, hhp ? 0xff : which, pressure,
+                                    bass, &wdata->state.pressure_drums[5],
+                                    ABS_HAT3X, 0x1b);
+       /* Hi-hat has no on/off values, just pressure. Force to off/0. */
+       wiimod_drums_report_pressure(wdata, none, hhp ? which : 0xff, pressure,
+                                    0, &wdata->state.pressure_drums[6],
+                                    ABS_HAT3Y, 0x0e);
+
+       input_report_abs(wdata->extension.input, ABS_X, sx - 0x20);
+       input_report_abs(wdata->extension.input, ABS_Y, sy - 0x20);
+
+       input_report_key(wdata->extension.input, BTN_START, bp);
+       input_report_key(wdata->extension.input, BTN_SELECT, bm);
+
+       input_sync(wdata->extension.input);
+}
+
+static int wiimod_drums_open(struct input_dev *dev)
+{
+       struct wiimote_data *wdata = input_get_drvdata(dev);
+       unsigned long flags;
+
+       spin_lock_irqsave(&wdata->state.lock, flags);
+       wdata->state.flags |= WIIPROTO_FLAG_EXT_USED;
+       wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL);
+       spin_unlock_irqrestore(&wdata->state.lock, flags);
+
+       return 0;
+}
+
+static void wiimod_drums_close(struct input_dev *dev)
+{
+       struct wiimote_data *wdata = input_get_drvdata(dev);
+       unsigned long flags;
+
+       spin_lock_irqsave(&wdata->state.lock, flags);
+       wdata->state.flags &= ~WIIPROTO_FLAG_EXT_USED;
+       wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL);
+       spin_unlock_irqrestore(&wdata->state.lock, flags);
+}
+
+static int wiimod_drums_probe(const struct wiimod_ops *ops,
+                             struct wiimote_data *wdata)
+{
+       int ret;
+
+       wdata->extension.input = input_allocate_device();
+       if (!wdata->extension.input)
+               return -ENOMEM;
+
+       input_set_drvdata(wdata->extension.input, wdata);
+       wdata->extension.input->open = wiimod_drums_open;
+       wdata->extension.input->close = wiimod_drums_close;
+       wdata->extension.input->dev.parent = &wdata->hdev->dev;
+       wdata->extension.input->id.bustype = wdata->hdev->bus;
+       wdata->extension.input->id.vendor = wdata->hdev->vendor;
+       wdata->extension.input->id.product = wdata->hdev->product;
+       wdata->extension.input->id.version = wdata->hdev->version;
+       wdata->extension.input->name = WIIMOTE_NAME " Drums";
+
+       set_bit(EV_KEY, wdata->extension.input->evbit);
+       set_bit(BTN_START, wdata->extension.input->keybit);
+       set_bit(BTN_SELECT, wdata->extension.input->keybit);
+
+       set_bit(EV_ABS, wdata->extension.input->evbit);
+       set_bit(ABS_X, wdata->extension.input->absbit);
+       set_bit(ABS_Y, wdata->extension.input->absbit);
+       set_bit(ABS_HAT0X, wdata->extension.input->absbit);
+       set_bit(ABS_HAT0Y, wdata->extension.input->absbit);
+       set_bit(ABS_HAT1X, wdata->extension.input->absbit);
+       set_bit(ABS_HAT2X, wdata->extension.input->absbit);
+       set_bit(ABS_HAT2Y, wdata->extension.input->absbit);
+       set_bit(ABS_HAT3X, wdata->extension.input->absbit);
+       set_bit(ABS_HAT3Y, wdata->extension.input->absbit);
+       input_set_abs_params(wdata->extension.input,
+                            ABS_X, -32, 31, 1, 1);
+       input_set_abs_params(wdata->extension.input,
+                            ABS_Y, -32, 31, 1, 1);
+       input_set_abs_params(wdata->extension.input,
+                            ABS_HAT0X, 0, 7, 0, 0);
+       input_set_abs_params(wdata->extension.input,
+                            ABS_HAT0Y, 0, 7, 0, 0);
+       input_set_abs_params(wdata->extension.input,
+                            ABS_HAT1X, 0, 7, 0, 0);
+       input_set_abs_params(wdata->extension.input,
+                            ABS_HAT2X, 0, 7, 0, 0);
+       input_set_abs_params(wdata->extension.input,
+                            ABS_HAT2Y, 0, 7, 0, 0);
+       input_set_abs_params(wdata->extension.input,
+                            ABS_HAT3X, 0, 7, 0, 0);
+       input_set_abs_params(wdata->extension.input,
+                            ABS_HAT3Y, 0, 7, 0, 0);
+
+       ret = input_register_device(wdata->extension.input);
+       if (ret)
+               goto err_free;
+
+       return 0;
+
+err_free:
+       input_free_device(wdata->extension.input);
+       wdata->extension.input = NULL;
+       return ret;
+}
+
+static void wiimod_drums_remove(const struct wiimod_ops *ops,
+                               struct wiimote_data *wdata)
+{
+       if (!wdata->extension.input)
+               return;
+
+       input_unregister_device(wdata->extension.input);
+       wdata->extension.input = NULL;
+}
+
+static const struct wiimod_ops wiimod_drums = {
+       .flags = 0,
+       .arg = 0,
+       .probe = wiimod_drums_probe,
+       .remove = wiimod_drums_remove,
+       .in_ext = wiimod_drums_in_ext,
+};
+
+/*
+ * Guitar
+ * Guitar-Hero, Rock-Band and other games came bundled with guitars which can
+ * be plugged as extension to a Wiimote.
+ * We create a separate device for guitars and report all information via this
+ * input device.
+ */
+
+enum wiimod_guitar_keys {
+       WIIMOD_GUITAR_KEY_G,
+       WIIMOD_GUITAR_KEY_R,
+       WIIMOD_GUITAR_KEY_Y,
+       WIIMOD_GUITAR_KEY_B,
+       WIIMOD_GUITAR_KEY_O,
+       WIIMOD_GUITAR_KEY_UP,
+       WIIMOD_GUITAR_KEY_DOWN,
+       WIIMOD_GUITAR_KEY_PLUS,
+       WIIMOD_GUITAR_KEY_MINUS,
+       WIIMOD_GUITAR_KEY_NUM,
+};
+
+static const __u16 wiimod_guitar_map[] = {
+       BTN_1,                  /* WIIMOD_GUITAR_KEY_G */
+       BTN_2,                  /* WIIMOD_GUITAR_KEY_R */
+       BTN_3,                  /* WIIMOD_GUITAR_KEY_Y */
+       BTN_4,                  /* WIIMOD_GUITAR_KEY_B */
+       BTN_5,                  /* WIIMOD_GUITAR_KEY_O */
+       BTN_DPAD_UP,            /* WIIMOD_GUITAR_KEY_UP */
+       BTN_DPAD_DOWN,          /* WIIMOD_GUITAR_KEY_DOWN */
+       BTN_START,              /* WIIMOD_GUITAR_KEY_PLUS */
+       BTN_SELECT,             /* WIIMOD_GUITAR_KEY_MINUS */
+};
+
+static void wiimod_guitar_in_ext(struct wiimote_data *wdata, const __u8 *ext)
+{
+       __u8 sx, sy, tb, wb, bd, bm, bp, bo, br, bb, bg, by, bu;
+
+       /*   Byte |  8  |  7  |  6  |  5  |  4  |  3  |  2  |  1  |
+        *   -----+-----+-----+-----+-----+-----+-----+-----+-----+
+        *    1   |  0  |  0  |              SX <5:0>             |
+        *    2   |  0  |  0  |              SY <5:0>             |
+        *   -----+-----+-----+-----+-----------------------------+
+        *    3   |  0  |  0  |  0  |      TB <4:0>               |
+        *   -----+-----+-----+-----+-----------------------------+
+        *    4   |  0  |  0  |  0  |      WB <4:0>               |
+        *   -----+-----+-----+-----+-----+-----+-----+-----+-----+
+        *    5   |  1  | BD  |  1  | B-  |  1  | B+  |  1  |  1  |
+        *   -----+-----+-----+-----+-----+-----+-----+-----+-----+
+        *    6   | BO  | BR  | BB  | BG  | BY  |  1  |  1  | BU  |
+        *   -----+-----+-----+-----+-----+-----+-----+-----+-----+
+        * All buttons are 0 if pressed
+        *
+        * With Motion+ enabled, it will look like this:
+        *   Byte |  8  |  7  |  6  |  5  |  4  |  3  |  2  |  1  |
+        *   -----+-----+-----+-----+-----+-----+-----+-----+-----+
+        *    1   |  0  |  0  |              SX <5:1>       | BU  |
+        *    2   |  0  |  0  |              SY <5:1>       |  1  |
+        *   -----+-----+-----+-----+-----------------------+-----+
+        *    3   |  0  |  0  |  0  |      TB <4:0>               |
+        *   -----+-----+-----+-----+-----------------------------+
+        *    4   |  0  |  0  |  0  |      WB <4:0>               |
+        *   -----+-----+-----+-----+-----+-----+-----+-----+-----+
+        *    5   |  1  | BD  |  1  | B-  |  1  | B+  |  1  |XXXXX|
+        *   -----+-----+-----+-----+-----+-----+-----+-----+-----+
+        *    6   | BO  | BR  | BB  | BG  | BY  |  1  |XXXXX|XXXXX|
+        *   -----+-----+-----+-----+-----+-----+-----+-----+-----+
+        */
+
+       sx = ext[0] & 0x3f;
+       sy = ext[1] & 0x3f;
+       tb = ext[2] & 0x1f;
+       wb = ext[3] & 0x1f;
+       bd = !(ext[4] & 0x40);
+       bm = !(ext[4] & 0x10);
+       bp = !(ext[4] & 0x04);
+       bo = !(ext[5] & 0x80);
+       br = !(ext[5] & 0x40);
+       bb = !(ext[5] & 0x20);
+       bg = !(ext[5] & 0x10);
+       by = !(ext[5] & 0x08);
+       bu = !(ext[5] & 0x01);
+
+       if (wdata->state.flags & WIIPROTO_FLAG_MP_ACTIVE) {
+               bu = !(ext[0] & 0x01);
+               sx &= 0x3e;
+               sy &= 0x3e;
+       }
+
+       input_report_abs(wdata->extension.input, ABS_X, sx - 0x20);
+       input_report_abs(wdata->extension.input, ABS_Y, sy - 0x20);
+       input_report_abs(wdata->extension.input, ABS_HAT0X, tb);
+       input_report_abs(wdata->extension.input, ABS_HAT1X, wb - 0x10);
+
+       input_report_key(wdata->extension.input,
+                        wiimod_guitar_map[WIIMOD_GUITAR_KEY_G],
+                        bg);
+       input_report_key(wdata->extension.input,
+                        wiimod_guitar_map[WIIMOD_GUITAR_KEY_R],
+                        br);
+       input_report_key(wdata->extension.input,
+                        wiimod_guitar_map[WIIMOD_GUITAR_KEY_Y],
+                        by);
+       input_report_key(wdata->extension.input,
+                        wiimod_guitar_map[WIIMOD_GUITAR_KEY_B],
+                        bb);
+       input_report_key(wdata->extension.input,
+                        wiimod_guitar_map[WIIMOD_GUITAR_KEY_O],
+                        bo);
+       input_report_key(wdata->extension.input,
+                        wiimod_guitar_map[WIIMOD_GUITAR_KEY_UP],
+                        bu);
+       input_report_key(wdata->extension.input,
+                        wiimod_guitar_map[WIIMOD_GUITAR_KEY_DOWN],
+                        bd);
+       input_report_key(wdata->extension.input,
+                        wiimod_guitar_map[WIIMOD_GUITAR_KEY_PLUS],
+                        bp);
+       input_report_key(wdata->extension.input,
+                        wiimod_guitar_map[WIIMOD_GUITAR_KEY_MINUS],
+                        bm);
+
+       input_sync(wdata->extension.input);
+}
+
+static int wiimod_guitar_open(struct input_dev *dev)
+{
+       struct wiimote_data *wdata = input_get_drvdata(dev);
+       unsigned long flags;
+
+       spin_lock_irqsave(&wdata->state.lock, flags);
+       wdata->state.flags |= WIIPROTO_FLAG_EXT_USED;
+       wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL);
+       spin_unlock_irqrestore(&wdata->state.lock, flags);
+
+       return 0;
+}
+
+static void wiimod_guitar_close(struct input_dev *dev)
+{
+       struct wiimote_data *wdata = input_get_drvdata(dev);
+       unsigned long flags;
+
+       spin_lock_irqsave(&wdata->state.lock, flags);
+       wdata->state.flags &= ~WIIPROTO_FLAG_EXT_USED;
+       wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL);
+       spin_unlock_irqrestore(&wdata->state.lock, flags);
+}
+
+static int wiimod_guitar_probe(const struct wiimod_ops *ops,
+                              struct wiimote_data *wdata)
+{
+       int ret, i;
+
+       wdata->extension.input = input_allocate_device();
+       if (!wdata->extension.input)
+               return -ENOMEM;
+
+       input_set_drvdata(wdata->extension.input, wdata);
+       wdata->extension.input->open = wiimod_guitar_open;
+       wdata->extension.input->close = wiimod_guitar_close;
+       wdata->extension.input->dev.parent = &wdata->hdev->dev;
+       wdata->extension.input->id.bustype = wdata->hdev->bus;
+       wdata->extension.input->id.vendor = wdata->hdev->vendor;
+       wdata->extension.input->id.product = wdata->hdev->product;
+       wdata->extension.input->id.version = wdata->hdev->version;
+       wdata->extension.input->name = WIIMOTE_NAME " Guitar";
+
+       set_bit(EV_KEY, wdata->extension.input->evbit);
+       for (i = 0; i < WIIMOD_GUITAR_KEY_NUM; ++i)
+               set_bit(wiimod_guitar_map[i],
+                       wdata->extension.input->keybit);
+
+       set_bit(EV_ABS, wdata->extension.input->evbit);
+       set_bit(ABS_X, wdata->extension.input->absbit);
+       set_bit(ABS_Y, wdata->extension.input->absbit);
+       set_bit(ABS_HAT0X, wdata->extension.input->absbit);
+       set_bit(ABS_HAT1X, wdata->extension.input->absbit);
+       input_set_abs_params(wdata->extension.input,
+                            ABS_X, -32, 31, 1, 1);
+       input_set_abs_params(wdata->extension.input,
+                            ABS_Y, -32, 31, 1, 1);
+       input_set_abs_params(wdata->extension.input,
+                            ABS_HAT0X, 0, 0x1f, 1, 1);
+       input_set_abs_params(wdata->extension.input,
+                            ABS_HAT1X, 0, 0x0f, 1, 1);
+
+       ret = input_register_device(wdata->extension.input);
+       if (ret)
+               goto err_free;
+
+       return 0;
+
+err_free:
+       input_free_device(wdata->extension.input);
+       wdata->extension.input = NULL;
+       return ret;
+}
+
+static void wiimod_guitar_remove(const struct wiimod_ops *ops,
+                                struct wiimote_data *wdata)
+{
+       if (!wdata->extension.input)
+               return;
+
+       input_unregister_device(wdata->extension.input);
+       wdata->extension.input = NULL;
+}
+
+static const struct wiimod_ops wiimod_guitar = {
+       .flags = 0,
+       .arg = 0,
+       .probe = wiimod_guitar_probe,
+       .remove = wiimod_guitar_remove,
+       .in_ext = wiimod_guitar_in_ext,
+};
+
+/*
  * Builtin Motion Plus
  * This module simply sets the WIIPROTO_FLAG_BUILTIN_MP protocol flag which
  * disables polling for Motion-Plus. This should be set only for devices which
@@ -2201,4 +2639,6 @@ const struct wiimod_ops *wiimod_ext_table[WIIMOTE_EXT_NUM] = {
        [WIIMOTE_EXT_CLASSIC_CONTROLLER] = &wiimod_classic,
        [WIIMOTE_EXT_BALANCE_BOARD] = &wiimod_bboard,
        [WIIMOTE_EXT_PRO_CONTROLLER] = &wiimod_pro,
+       [WIIMOTE_EXT_DRUMS] = &wiimod_drums,
+       [WIIMOTE_EXT_GUITAR] = &wiimod_guitar,
 };
index 510ca77..3bf3d3c 100644 (file)
@@ -89,6 +89,8 @@ enum wiimote_exttype {
        WIIMOTE_EXT_CLASSIC_CONTROLLER,
        WIIMOTE_EXT_BALANCE_BOARD,
        WIIMOTE_EXT_PRO_CONTROLLER,
+       WIIMOTE_EXT_DRUMS,
+       WIIMOTE_EXT_GUITAR,
        WIIMOTE_EXT_NUM,
 };
 
@@ -137,6 +139,7 @@ struct wiimote_state {
        /* calibration/cache data */
        __u16 calib_bboard[4][3];
        __s16 calib_pro_sticks[4];
+       __u8 pressure_drums[7];
        __u8 cache_rumble;
 };
 
index eae0cb3..2ce194a 100644 (file)
@@ -1002,18 +1002,18 @@ static int i2c_hid_probe(struct i2c_client *client,
                return client->irq;
        }
 
-       ihid = kzalloc(sizeof(struct i2c_hid), GFP_KERNEL);
+       ihid = devm_kzalloc(&client->dev, sizeof(*ihid), GFP_KERNEL);
        if (!ihid)
                return -ENOMEM;
 
        if (client->dev.of_node) {
                ret = i2c_hid_of_probe(client, &ihid->pdata);
                if (ret)
-                       goto err;
+                       return ret;
        } else if (!platform_data) {
                ret = i2c_hid_acpi_pdata(client, &ihid->pdata);
                if (ret)
-                       goto err;
+                       return ret;
        } else {
                ihid->pdata = *platform_data;
        }
@@ -1021,21 +1021,20 @@ static int i2c_hid_probe(struct i2c_client *client,
        /* Parse platform agnostic common properties from ACPI / device tree */
        i2c_hid_fwnode_probe(client, &ihid->pdata);
 
-       ihid->pdata.supply = devm_regulator_get(&client->dev, "vdd");
-       if (IS_ERR(ihid->pdata.supply)) {
-               ret = PTR_ERR(ihid->pdata.supply);
-               if (ret != -EPROBE_DEFER)
-                       dev_err(&client->dev, "Failed to get regulator: %d\n",
-                               ret);
-               goto err;
-       }
+       ihid->pdata.supplies[0].supply = "vdd";
+       ihid->pdata.supplies[1].supply = "vddl";
+
+       ret = devm_regulator_bulk_get(&client->dev,
+                                     ARRAY_SIZE(ihid->pdata.supplies),
+                                     ihid->pdata.supplies);
+       if (ret)
+               return ret;
+
+       ret = regulator_bulk_enable(ARRAY_SIZE(ihid->pdata.supplies),
+                                   ihid->pdata.supplies);
+       if (ret < 0)
+               return ret;
 
-       ret = regulator_enable(ihid->pdata.supply);
-       if (ret < 0) {
-               dev_err(&client->dev, "Failed to enable regulator: %d\n",
-                       ret);
-               goto err;
-       }
        if (ihid->pdata.post_power_delay_ms)
                msleep(ihid->pdata.post_power_delay_ms);
 
@@ -1122,11 +1121,9 @@ err_pm:
        pm_runtime_disable(&client->dev);
 
 err_regulator:
-       regulator_disable(ihid->pdata.supply);
-
-err:
+       regulator_bulk_disable(ARRAY_SIZE(ihid->pdata.supplies),
+                              ihid->pdata.supplies);
        i2c_hid_free_buffers(ihid);
-       kfree(ihid);
        return ret;
 }
 
@@ -1148,9 +1145,8 @@ static int i2c_hid_remove(struct i2c_client *client)
        if (ihid->bufsize)
                i2c_hid_free_buffers(ihid);
 
-       regulator_disable(ihid->pdata.supply);
-
-       kfree(ihid);
+       regulator_bulk_disable(ARRAY_SIZE(ihid->pdata.supplies),
+                              ihid->pdata.supplies);
 
        return 0;
 }
@@ -1201,9 +1197,8 @@ static int i2c_hid_suspend(struct device *dev)
                        hid_warn(hid, "Failed to enable irq wake: %d\n",
                                wake_status);
        } else {
-               ret = regulator_disable(ihid->pdata.supply);
-               if (ret < 0)
-                       hid_warn(hid, "Failed to disable supply: %d\n", ret);
+               regulator_bulk_disable(ARRAY_SIZE(ihid->pdata.supplies),
+                                      ihid->pdata.supplies);
        }
 
        return 0;
@@ -1218,9 +1213,11 @@ static int i2c_hid_resume(struct device *dev)
        int wake_status;
 
        if (!device_may_wakeup(&client->dev)) {
-               ret = regulator_enable(ihid->pdata.supply);
-               if (ret < 0)
-                       hid_warn(hid, "Failed to enable supply: %d\n", ret);
+               ret = regulator_bulk_enable(ARRAY_SIZE(ihid->pdata.supplies),
+                                           ihid->pdata.supplies);
+               if (ret)
+                       hid_warn(hid, "Failed to enable supplies: %d\n", ret);
+
                if (ihid->pdata.post_power_delay_ms)
                        msleep(ihid->pdata.post_power_delay_ms);
        } else if (ihid->irq_wake_enabled) {
index 9a60ec1..bfbca7e 100644 (file)
@@ -907,8 +907,9 @@ struct ishtp_device *ish_dev_init(struct pci_dev *pdev)
        struct ishtp_device *dev;
        int     i;
 
-       dev = kzalloc(sizeof(struct ishtp_device) + sizeof(struct ish_hw),
-               GFP_KERNEL);
+       dev = devm_kzalloc(&pdev->dev,
+                          sizeof(struct ishtp_device) + sizeof(struct ish_hw),
+                          GFP_KERNEL);
        if (!dev)
                return NULL;
 
@@ -925,7 +926,9 @@ struct ishtp_device *ish_dev_init(struct pci_dev *pdev)
        for (i = 0; i < IPC_TX_FIFO_SIZE; ++i) {
                struct wr_msg_ctl_info  *tx_buf;
 
-               tx_buf = kzalloc(sizeof(struct wr_msg_ctl_info), GFP_KERNEL);
+               tx_buf = devm_kzalloc(&pdev->dev,
+                                     sizeof(struct wr_msg_ctl_info),
+                                     GFP_KERNEL);
                if (!tx_buf) {
                        /*
                         * IPC buffers may be limited or not available
index a2c53ea..050f987 100644 (file)
@@ -95,6 +95,13 @@ static int ish_init(struct ishtp_device *dev)
        return 0;
 }
 
+static const struct pci_device_id ish_invalid_pci_ids[] = {
+       /* Mehlow platform special pci ids */
+       {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xA309)},
+       {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xA30A)},
+       {}
+};
+
 /**
  * ish_probe() - PCI driver probe callback
  * @pdev:      pci device
@@ -110,6 +117,10 @@ static int ish_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        struct ish_hw *hw;
        int     ret;
 
+       /* Check for invalid platforms for ISH support */
+       if (pci_dev_present(ish_invalid_pci_ids))
+               return -ENODEV;
+
        /* enable pci dev */
        ret = pci_enable_device(pdev);
        if (ret) {
@@ -172,7 +183,6 @@ free_irq:
        free_irq(pdev->irq, dev);
 free_device:
        pci_iounmap(pdev, hw->mem_addr);
-       kfree(dev);
 release_regions:
        pci_release_regions(pdev);
 disable_device:
@@ -202,7 +212,6 @@ static void ish_remove(struct pci_dev *pdev)
        pci_release_regions(pdev);
        pci_clear_master(pdev);
        pci_disable_device(pdev);
-       kfree(ishtp_dev);
 }
 
 static struct device __maybe_unused *ish_resume_device;
index ae4a69f..8b5dd58 100644 (file)
@@ -298,7 +298,6 @@ int ishtp_hbm_cl_flow_control_req(struct ishtp_device *dev,
        struct ishtp_msg_hdr *ishtp_hdr = &hdr;
        const size_t len = sizeof(struct hbm_flow_control);
        int     rv;
-       unsigned int    num_frags;
        unsigned long   flags;
 
        spin_lock_irqsave(&cl->fc_spinlock, flags);
@@ -314,7 +313,6 @@ int ishtp_hbm_cl_flow_control_req(struct ishtp_device *dev,
                return  0;
        }
 
-       num_frags = cl->recv_msg_num_frags;
        cl->recv_msg_num_frags = 0;
 
        rv = ishtp_write_message(dev, ishtp_hdr, data);
index af0e0d0..11103ef 100644 (file)
@@ -480,6 +480,7 @@ static void hid_ctrl(struct urb *urb)
 {
        struct hid_device *hid = urb->context;
        struct usbhid_device *usbhid = hid->driver_data;
+       unsigned long flags;
        int unplug = 0, status = urb->status;
 
        switch (status) {
@@ -501,7 +502,7 @@ static void hid_ctrl(struct urb *urb)
                hid_warn(urb->dev, "ctrl urb status %d received\n", status);
        }
 
-       spin_lock(&usbhid->lock);
+       spin_lock_irqsave(&usbhid->lock, flags);
 
        if (unplug) {
                usbhid->ctrltail = usbhid->ctrlhead;
@@ -511,13 +512,13 @@ static void hid_ctrl(struct urb *urb)
                if (usbhid->ctrlhead != usbhid->ctrltail &&
                                hid_submit_ctrl(hid) == 0) {
                        /* Successfully submitted next urb in queue */
-                       spin_unlock(&usbhid->lock);
+                       spin_unlock_irqrestore(&usbhid->lock, flags);
                        return;
                }
        }
 
        clear_bit(HID_CTRL_RUNNING, &usbhid->iofl);
-       spin_unlock(&usbhid->lock);
+       spin_unlock_irqrestore(&usbhid->lock, flags);
        usb_autopm_put_interface_async(usbhid->intf);
        wake_up(&usbhid->wait);
 }
index d679753..0bdd85d 100644 (file)
@@ -210,6 +210,57 @@ static int wacom_calc_hid_res(int logical_extents, int physical_extents,
        return hidinput_calc_abs_res(&field, ABS_X);
 }
 
+static void wacom_hid_usage_quirk(struct hid_device *hdev,
+               struct hid_field *field, struct hid_usage *usage)
+{
+       struct wacom *wacom = hid_get_drvdata(hdev);
+       struct wacom_features *features = &wacom->wacom_wac.features;
+       unsigned int equivalent_usage = wacom_equivalent_usage(usage->hid);
+
+       /*
+        * The Dell Canvas 27 needs to be switched to its vendor-defined
+        * report to provide the best resolution.
+        */
+       if (hdev->vendor == USB_VENDOR_ID_WACOM &&
+           hdev->product == 0x4200 &&
+           field->application == HID_UP_MSVENDOR) {
+               wacom->wacom_wac.mode_report = field->report->id;
+               wacom->wacom_wac.mode_value = 2;
+       }
+
+       /*
+        * ISDv4 devices which predate HID's adoption of the
+        * HID_DG_BARELSWITCH2 usage use 0x000D0000 in its
+        * position instead. We can accurately detect if a
+        * usage with that value should be HID_DG_BARRELSWITCH2
+        * based on the surrounding usages, which have remained
+        * constant across generations.
+        */
+       if (features->type == HID_GENERIC &&
+           usage->hid == 0x000D0000 &&
+           field->application == HID_DG_PEN &&
+           field->physical == HID_DG_STYLUS) {
+               int i = usage->usage_index;
+
+               if (i-4 >= 0 && i+1 < field->maxusage &&
+                   field->usage[i-4].hid == HID_DG_TIPSWITCH &&
+                   field->usage[i-3].hid == HID_DG_BARRELSWITCH &&
+                   field->usage[i-2].hid == HID_DG_ERASER &&
+                   field->usage[i-1].hid == HID_DG_INVERT &&
+                   field->usage[i+1].hid == HID_DG_INRANGE) {
+                       usage->hid = HID_DG_BARRELSWITCH2;
+               }
+       }
+
+       /* 2nd-generation Intuos Pro Large has incorrect Y maximum */
+       if (hdev->vendor == USB_VENDOR_ID_WACOM &&
+           hdev->product == 0x0358 &&
+           WACOM_PEN_FIELD(field) &&
+           equivalent_usage == HID_GD_Y) {
+               field->logical_maximum = 43200;
+       }
+}
+
 static void wacom_feature_mapping(struct hid_device *hdev,
                struct hid_field *field, struct hid_usage *usage)
 {
@@ -221,6 +272,8 @@ static void wacom_feature_mapping(struct hid_device *hdev,
        int ret;
        u32 n;
 
+       wacom_hid_usage_quirk(hdev, field, usage);
+
        switch (equivalent_usage) {
        case HID_DG_CONTACTMAX:
                /* leave touch_max as is if predefined */
@@ -300,13 +353,6 @@ static void wacom_feature_mapping(struct hid_device *hdev,
                kfree(data);
                break;
        }
-
-       if (hdev->vendor == USB_VENDOR_ID_WACOM &&
-           hdev->product == 0x4200 /* Dell Canvas 27 */ &&
-           field->application == HID_UP_MSVENDOR) {
-               wacom->wacom_wac.mode_report = field->report->id;
-               wacom->wacom_wac.mode_value = 2;
-       }
 }
 
 /*
@@ -348,6 +394,7 @@ static void wacom_usage_mapping(struct hid_device *hdev,
        struct wacom_features *features = &wacom->wacom_wac.features;
        bool finger = WACOM_FINGER_FIELD(field);
        bool pen = WACOM_PEN_FIELD(field);
+       unsigned equivalent_usage = wacom_equivalent_usage(usage->hid);
 
        /*
        * Requiring Stylus Usage will ignore boot mouse
@@ -361,49 +408,9 @@ static void wacom_usage_mapping(struct hid_device *hdev,
        else
                return;
 
-       /*
-        * Bamboo models do not support HID_DG_CONTACTMAX.
-        * And, Bamboo Pen only descriptor contains touch.
-        */
-       if (features->type > BAMBOO_PT) {
-               /* ISDv4 touch devices at least supports one touch point */
-               if (finger && !features->touch_max)
-                       features->touch_max = 1;
-       }
-
-       /*
-        * ISDv4 devices which predate HID's adoption of the
-        * HID_DG_BARELSWITCH2 usage use 0x000D0000 in its
-        * position instead. We can accurately detect if a
-        * usage with that value should be HID_DG_BARRELSWITCH2
-        * based on the surrounding usages, which have remained
-        * constant across generations.
-        */
-       if (features->type == HID_GENERIC &&
-           usage->hid == 0x000D0000 &&
-           field->application == HID_DG_PEN &&
-           field->physical == HID_DG_STYLUS) {
-               int i = usage->usage_index;
+       wacom_hid_usage_quirk(hdev, field, usage);
 
-               if (i-4 >= 0 && i+1 < field->maxusage &&
-                   field->usage[i-4].hid == HID_DG_TIPSWITCH &&
-                   field->usage[i-3].hid == HID_DG_BARRELSWITCH &&
-                   field->usage[i-2].hid == HID_DG_ERASER &&
-                   field->usage[i-1].hid == HID_DG_INVERT &&
-                   field->usage[i+1].hid == HID_DG_INRANGE) {
-                       usage->hid = HID_DG_BARRELSWITCH2;
-               }
-       }
-
-       /* 2nd-generation Intuos Pro Large has incorrect Y maximum */
-       if (hdev->vendor == USB_VENDOR_ID_WACOM &&
-           hdev->product == 0x0358 &&
-           WACOM_PEN_FIELD(field) &&
-           wacom_equivalent_usage(usage->hid) == HID_GD_Y) {
-               field->logical_maximum = 43200;
-       }
-
-       switch (usage->hid) {
+       switch (equivalent_usage) {
        case HID_GD_X:
                features->x_max = field->logical_maximum;
                if (finger) {
@@ -703,18 +710,6 @@ struct wacom_hdev_data {
 static LIST_HEAD(wacom_udev_list);
 static DEFINE_MUTEX(wacom_udev_list_lock);
 
-static bool compare_device_paths(struct hid_device *hdev_a,
-               struct hid_device *hdev_b, char separator)
-{
-       int n1 = strrchr(hdev_a->phys, separator) - hdev_a->phys;
-       int n2 = strrchr(hdev_b->phys, separator) - hdev_b->phys;
-
-       if (n1 != n2 || n1 <= 0 || n2 <= 0)
-               return false;
-
-       return !strncmp(hdev_a->phys, hdev_b->phys, n1);
-}
-
 static bool wacom_are_sibling(struct hid_device *hdev,
                struct hid_device *sibling)
 {
@@ -737,10 +732,10 @@ static bool wacom_are_sibling(struct hid_device *hdev,
         * the same physical parent device path.
         */
        if (hdev->vendor == sibling->vendor && hdev->product == sibling->product) {
-               if (!compare_device_paths(hdev, sibling, '/'))
+               if (!hid_compare_device_paths(hdev, sibling, '/'))
                        return false;
        } else {
-               if (!compare_device_paths(hdev, sibling, '.'))
+               if (!hid_compare_device_paths(hdev, sibling, '.'))
                        return false;
        }
 
@@ -787,7 +782,7 @@ static struct wacom_hdev_data *wacom_get_hdev_data(struct hid_device *hdev)
 
        /* Try to find an already-probed interface from the same device */
        list_for_each_entry(data, &wacom_udev_list, list) {
-               if (compare_device_paths(hdev, data->dev, '/')) {
+               if (hid_compare_device_paths(hdev, data->dev, '/')) {
                        kref_get(&data->kref);
                        return data;
                }
index ad7afa7..e0a06be 100644 (file)
@@ -4357,19 +4357,19 @@ static const struct wacom_features wacom_features_0x5E =
          .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE };
 static const struct wacom_features wacom_features_0x90 =
        { "Wacom ISDv4 90", 26202, 16325, 255, 0,
-         TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+         TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; /* Pen-only */
 static const struct wacom_features wacom_features_0x93 =
        { "Wacom ISDv4 93", 26202, 16325, 255, 0,
-         TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+         TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 1 };
 static const struct wacom_features wacom_features_0x97 =
        { "Wacom ISDv4 97", 26202, 16325, 511, 0,
-         TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+         TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; /* Pen-only */
 static const struct wacom_features wacom_features_0x9A =
        { "Wacom ISDv4 9A", 26202, 16325, 255, 0,
-         TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+         TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 1 };
 static const struct wacom_features wacom_features_0x9F =
        { "Wacom ISDv4 9F", 26202, 16325, 255, 0,
-         TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+         TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 1 };
 static const struct wacom_features wacom_features_0xE2 =
        { "Wacom ISDv4 E2", 26202, 16325, 255, 0,
          TABLETPC2FG, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 2 };
@@ -4384,13 +4384,13 @@ static const struct wacom_features wacom_features_0xE6 =
          TABLETPC2FG, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 2 };
 static const struct wacom_features wacom_features_0xEC =
        { "Wacom ISDv4 EC", 25710, 14500, 255, 0,
-         TABLETPC,    WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+         TABLETPC,    WACOM_INTUOS_RES, WACOM_INTUOS_RES }; /* Pen-only */
 static const struct wacom_features wacom_features_0xED =
        { "Wacom ISDv4 ED", 26202, 16325, 255, 0,
-         TABLETPCE, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+         TABLETPCE, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 1 };
 static const struct wacom_features wacom_features_0xEF =
        { "Wacom ISDv4 EF", 26202, 16325, 255, 0,
-         TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+         TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; /* Pen-only */
 static const struct wacom_features wacom_features_0x100 =
        { "Wacom ISDv4 100", 26202, 16325, 255, 0,
          MTTPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
@@ -4408,10 +4408,10 @@ static const struct wacom_features wacom_features_0x10F =
          MTTPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
 static const struct wacom_features wacom_features_0x116 =
        { "Wacom ISDv4 116", 26202, 16325, 255, 0,
-         TABLETPCE, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+         TABLETPCE, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 1 };
 static const struct wacom_features wacom_features_0x12C =
        { "Wacom ISDv4 12C", 27848, 15752, 2047, 0,
-         TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+         TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; /* Pen-only */
 static const struct wacom_features wacom_features_0x4001 =
        { "Wacom ISDv4 4001", 26202, 16325, 255, 0,
          MTTPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
index ccf4266..81da17a 100644 (file)
@@ -1320,6 +1320,16 @@ config SENSORS_PWM_FAN
          This driver can also be built as a module.  If so, the module
          will be called pwm-fan.
 
+config SENSORS_RASPBERRYPI_HWMON
+       tristate "Raspberry Pi voltage monitor"
+       depends on RASPBERRYPI_FIRMWARE || (COMPILE_TEST && !RASPBERRYPI_FIRMWARE)
+       help
+         If you say yes here you get support for voltage sensor on the
+         Raspberry Pi.
+
+         This driver can also be built as a module. If so, the module
+         will be called raspberrypi-hwmon.
+
 config SENSORS_SHT15
        tristate "Sensiron humidity and temperature sensors. SHT15 and compat."
        depends on GPIOLIB || COMPILE_TEST
index 842c92f..93f7f41 100644 (file)
@@ -143,6 +143,7 @@ obj-$(CONFIG_SENSORS_PC87427)       += pc87427.o
 obj-$(CONFIG_SENSORS_PCF8591)  += pcf8591.o
 obj-$(CONFIG_SENSORS_POWR1220)  += powr1220.o
 obj-$(CONFIG_SENSORS_PWM_FAN)  += pwm-fan.o
+obj-$(CONFIG_SENSORS_RASPBERRYPI_HWMON)        += raspberrypi-hwmon.o
 obj-$(CONFIG_SENSORS_S3C)      += s3c-hwmon.o
 obj-$(CONFIG_SENSORS_SCH56XX_COMMON)+= sch56xx-common.o
 obj-$(CONFIG_SENSORS_SCH5627)  += sch5627.o
diff --git a/drivers/hwmon/raspberrypi-hwmon.c b/drivers/hwmon/raspberrypi-hwmon.c
new file mode 100644 (file)
index 0000000..fb4e4a6
--- /dev/null
@@ -0,0 +1,166 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Raspberry Pi voltage sensor driver
+ *
+ * Based on firmware/raspberrypi.c by Noralf Trønnes
+ *
+ * Copyright (C) 2018 Stefan Wahren <stefan.wahren@i2se.com>
+ */
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/hwmon.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/workqueue.h>
+#include <soc/bcm2835/raspberrypi-firmware.h>
+
+#define UNDERVOLTAGE_STICKY_BIT        BIT(16)
+
+struct rpi_hwmon_data {
+       struct device *hwmon_dev;
+       struct rpi_firmware *fw;
+       u32 last_throttled;
+       struct delayed_work get_values_poll_work;
+};
+
+static void rpi_firmware_get_throttled(struct rpi_hwmon_data *data)
+{
+       u32 new_uv, old_uv, value;
+       int ret;
+
+       /* Request firmware to clear sticky bits */
+       value = 0xffff;
+
+       ret = rpi_firmware_property(data->fw, RPI_FIRMWARE_GET_THROTTLED,
+                                   &value, sizeof(value));
+       if (ret) {
+               dev_err_once(data->hwmon_dev, "Failed to get throttled (%d)\n",
+                            ret);
+               return;
+       }
+
+       new_uv = value & UNDERVOLTAGE_STICKY_BIT;
+       old_uv = data->last_throttled & UNDERVOLTAGE_STICKY_BIT;
+       data->last_throttled = value;
+
+       if (new_uv == old_uv)
+               return;
+
+       if (new_uv)
+               dev_crit(data->hwmon_dev, "Undervoltage detected!\n");
+       else
+               dev_info(data->hwmon_dev, "Voltage normalised\n");
+
+       sysfs_notify(&data->hwmon_dev->kobj, NULL, "in0_lcrit_alarm");
+}
+
+static void get_values_poll(struct work_struct *work)
+{
+       struct rpi_hwmon_data *data;
+
+       data = container_of(work, struct rpi_hwmon_data,
+                           get_values_poll_work.work);
+
+       rpi_firmware_get_throttled(data);
+
+       /*
+        * We can't run faster than the sticky shift (100ms) since we get
+        * flipping in the sticky bits that are cleared.
+        */
+       schedule_delayed_work(&data->get_values_poll_work, 2 * HZ);
+}
+
+static int rpi_read(struct device *dev, enum hwmon_sensor_types type,
+                   u32 attr, int channel, long *val)
+{
+       struct rpi_hwmon_data *data = dev_get_drvdata(dev);
+
+       *val = !!(data->last_throttled & UNDERVOLTAGE_STICKY_BIT);
+       return 0;
+}
+
+static umode_t rpi_is_visible(const void *_data, enum hwmon_sensor_types type,
+                             u32 attr, int channel)
+{
+       return 0444;
+}
+
+static const u32 rpi_in_config[] = {
+       HWMON_I_LCRIT_ALARM,
+       0
+};
+
+static const struct hwmon_channel_info rpi_in = {
+       .type = hwmon_in,
+       .config = rpi_in_config,
+};
+
+static const struct hwmon_channel_info *rpi_info[] = {
+       &rpi_in,
+       NULL
+};
+
+static const struct hwmon_ops rpi_hwmon_ops = {
+       .is_visible = rpi_is_visible,
+       .read = rpi_read,
+};
+
+static const struct hwmon_chip_info rpi_chip_info = {
+       .ops = &rpi_hwmon_ops,
+       .info = rpi_info,
+};
+
+static int rpi_hwmon_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct rpi_hwmon_data *data;
+       int ret;
+
+       data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
+       if (!data)
+               return -ENOMEM;
+
+       /* Parent driver assure that firmware is correct */
+       data->fw = dev_get_drvdata(dev->parent);
+
+       /* Init throttled */
+       ret = rpi_firmware_property(data->fw, RPI_FIRMWARE_GET_THROTTLED,
+                                   &data->last_throttled,
+                                   sizeof(data->last_throttled));
+
+       data->hwmon_dev = devm_hwmon_device_register_with_info(dev, "rpi_volt",
+                                                              data,
+                                                              &rpi_chip_info,
+                                                              NULL);
+
+       INIT_DELAYED_WORK(&data->get_values_poll_work, get_values_poll);
+       platform_set_drvdata(pdev, data);
+
+       if (!PTR_ERR_OR_ZERO(data->hwmon_dev))
+               schedule_delayed_work(&data->get_values_poll_work, 2 * HZ);
+
+       return PTR_ERR_OR_ZERO(data->hwmon_dev);
+}
+
+static int rpi_hwmon_remove(struct platform_device *pdev)
+{
+       struct rpi_hwmon_data *data = platform_get_drvdata(pdev);
+
+       cancel_delayed_work_sync(&data->get_values_poll_work);
+
+       return 0;
+}
+
+static struct platform_driver rpi_hwmon_driver = {
+       .probe = rpi_hwmon_probe,
+       .remove = rpi_hwmon_remove,
+       .driver = {
+               .name = "raspberrypi-hwmon",
+       },
+};
+module_platform_driver(rpi_hwmon_driver);
+
+MODULE_AUTHOR("Stefan Wahren <stefan.wahren@i2se.com>");
+MODULE_DESCRIPTION("Raspberry Pi voltage sensor driver");
+MODULE_LICENSE("GPL v2");
index 634f580..d293e55 100644 (file)
@@ -1182,7 +1182,7 @@ static void msc_mmap_close(struct vm_area_struct *vma)
        mutex_unlock(&msc->buf_mutex);
 }
 
-static int msc_mmap_fault(struct vm_fault *vmf)
+static vm_fault_t msc_mmap_fault(struct vm_fault *vmf)
 {
        struct msc_iter *iter = vmf->vma->vm_file->private_data;
        struct msc *msc = iter->msc;
index 72c94c6..bed6ba6 100644 (file)
@@ -18,4 +18,3 @@ obj-$(CONFIG_I2C_STUB)                += i2c-stub.o
 obj-$(CONFIG_I2C_SLAVE_EEPROM) += i2c-slave-eeprom.o
 
 ccflags-$(CONFIG_I2C_DEBUG_CORE) := -DDEBUG
-CFLAGS_i2c-core-base.o := -Wno-deprecated-declarations
index 4f8df2e..451d4ae 100644 (file)
@@ -116,24 +116,21 @@ config I2C_I801
            DH89xxCC (PCH)
            Panther Point (PCH)
            Lynx Point (PCH)
-           Lynx Point-LP (PCH)
            Avoton (SOC)
            Wellsburg (PCH)
            Coleto Creek (PCH)
            Wildcat Point (PCH)
-           Wildcat Point-LP (PCH)
            BayTrail (SOC)
            Braswell (SOC)
-           Sunrise Point-H (PCH)
-           Sunrise Point-LP (PCH)
-           Kaby Lake-H (PCH)
+           Sunrise Point (PCH)
+           Kaby Lake (PCH)
            DNV (SOC)
            Broxton (SOC)
            Lewisburg (PCH)
            Gemini Lake (SOC)
-           Cannon Lake-H (PCH)
-           Cannon Lake-LP (PCH)
+           Cannon Lake (PCH)
            Cedar Fork (PCH)
+           Ice Lake (PCH)
 
          This driver can also be built as a module.  If so, the module
          will be called i2c-i801.
@@ -762,6 +759,13 @@ config I2C_OMAP
          Like OMAP1510/1610/1710/5912 and OMAP242x.
          For details see http://www.ti.com/omap.
 
+config I2C_OWL
+       tristate "Actions Semiconductor Owl I2C Controller"
+       depends on ARCH_ACTIONS || COMPILE_TEST
+       help
+         Say Y here if you want to use the I2C bus controller on
+         the Actions Semiconductor Owl SoC's.
+
 config I2C_PASEMI
        tristate "PA Semi SMBus interface"
        depends on PPC_PASEMI && PCI
@@ -828,6 +832,19 @@ config I2C_PXA_SLAVE
          is necessary for systems where the PXA may be a target on the
          I2C bus.
 
+config I2C_QCOM_GENI
+       tristate "Qualcomm Technologies Inc.'s GENI based I2C controller"
+       depends on ARCH_QCOM || COMPILE_TEST
+       depends on QCOM_GENI_SE
+       help
+         This driver supports GENI serial engine based I2C controller in
+         master mode on the Qualcomm Technologies Inc.'s SoCs. If you say
+         yes to this option, support will be included for the built-in I2C
+         interface on the Qualcomm Technologies Inc.'s SoCs.
+
+         This driver can also be built as a module.  If so, the module
+         will be called i2c-qcom-geni.
+
 config I2C_QUP
        tristate "Qualcomm QUP based I2C controller"
        depends on ARCH_QCOM
@@ -1330,4 +1347,15 @@ config I2C_ZX2967
          This driver can also be built as a module. If so, the module will be
          called i2c-zx2967.
 
+config I2C_FSI
+       tristate "FSI I2C driver"
+       depends on FSI
+       help
+         Driver for FSI bus attached I2C masters. These are I2C masters that
+         are connected to the system over an FSI bus, instead of the more
+         common PCI or MMIO interface.
+
+         This driver can also be built as a module. If so, the module will be
+         called as i2c-fsi.
+
 endmenu
index 5a86914..18b26af 100644 (file)
@@ -76,6 +76,7 @@ obj-$(CONFIG_I2C_MXS)         += i2c-mxs.o
 obj-$(CONFIG_I2C_NOMADIK)      += i2c-nomadik.o
 obj-$(CONFIG_I2C_OCORES)       += i2c-ocores.o
 obj-$(CONFIG_I2C_OMAP)         += i2c-omap.o
+obj-$(CONFIG_I2C_OWL)          += i2c-owl.o
 obj-$(CONFIG_I2C_PASEMI)       += i2c-pasemi.o
 obj-$(CONFIG_I2C_PCA_PLATFORM) += i2c-pca-platform.o
 obj-$(CONFIG_I2C_PMCMSP)       += i2c-pmcmsp.o
@@ -83,6 +84,7 @@ obj-$(CONFIG_I2C_PNX)         += i2c-pnx.o
 obj-$(CONFIG_I2C_PUV3)         += i2c-puv3.o
 obj-$(CONFIG_I2C_PXA)          += i2c-pxa.o
 obj-$(CONFIG_I2C_PXA_PCI)      += i2c-pxa-pci.o
+obj-$(CONFIG_I2C_QCOM_GENI)    += i2c-qcom-geni.o
 obj-$(CONFIG_I2C_QUP)          += i2c-qup.o
 obj-$(CONFIG_I2C_RIIC)         += i2c-riic.o
 obj-$(CONFIG_I2C_RK3X)         += i2c-rk3x.o
@@ -137,5 +139,6 @@ obj-$(CONFIG_I2C_PCA_ISA)   += i2c-pca-isa.o
 obj-$(CONFIG_I2C_SIBYTE)       += i2c-sibyte.o
 obj-$(CONFIG_I2C_XGENE_SLIMPRO) += i2c-xgene-slimpro.o
 obj-$(CONFIG_SCx200_ACB)       += scx200_acb.o
+obj-$(CONFIG_I2C_FSI)          += i2c-fsi.o
 
 ccflags-$(CONFIG_I2C_DEBUG_BUS) := -DDEBUG
index 95a80a8..134567f 100644 (file)
@@ -384,6 +384,7 @@ static s32 amd8111_access(struct i2c_adapter * adap, u16 addr,
                        if (status)
                                return status;
                        len = min_t(u8, len, I2C_SMBUS_BLOCK_MAX);
+                       /* fall through */
                case I2C_SMBUS_I2C_BLOCK_DATA:
                        for (i = 0; i < len; i++) {
                                status = amd_ec_read(smbus, AMD_SMB_DATA + i,
index 60e4d0e..a4f956c 100644 (file)
 #define ASPEED_I2CD_DEV_ADDR_MASK                      GENMASK(6, 0)
 
 enum aspeed_i2c_master_state {
+       ASPEED_I2C_MASTER_INACTIVE,
        ASPEED_I2C_MASTER_START,
        ASPEED_I2C_MASTER_TX_FIRST,
        ASPEED_I2C_MASTER_TX,
        ASPEED_I2C_MASTER_RX_FIRST,
        ASPEED_I2C_MASTER_RX,
        ASPEED_I2C_MASTER_STOP,
-       ASPEED_I2C_MASTER_INACTIVE,
 };
 
 enum aspeed_i2c_slave_state {
+       ASPEED_I2C_SLAVE_STOP,
        ASPEED_I2C_SLAVE_START,
        ASPEED_I2C_SLAVE_READ_REQUESTED,
        ASPEED_I2C_SLAVE_READ_PROCESSED,
        ASPEED_I2C_SLAVE_WRITE_REQUESTED,
        ASPEED_I2C_SLAVE_WRITE_RECEIVED,
-       ASPEED_I2C_SLAVE_STOP,
 };
 
 struct aspeed_i2c_bus {
@@ -234,7 +234,6 @@ static bool aspeed_i2c_slave_irq(struct aspeed_i2c_bus *bus)
        bool irq_handled = true;
        u8 value;
 
-       spin_lock(&bus->lock);
        if (!slave) {
                irq_handled = false;
                goto out;
@@ -325,7 +324,6 @@ static bool aspeed_i2c_slave_irq(struct aspeed_i2c_bus *bus)
        writel(status_ack, bus->base + ASPEED_I2C_INTR_STS_REG);
 
 out:
-       spin_unlock(&bus->lock);
        return irq_handled;
 }
 #endif /* CONFIG_I2C_SLAVE */
@@ -389,7 +387,6 @@ static bool aspeed_i2c_master_irq(struct aspeed_i2c_bus *bus)
        u8 recv_byte;
        int ret;
 
-       spin_lock(&bus->lock);
        irq_status = readl(bus->base + ASPEED_I2C_INTR_STS_REG);
        /* Ack all interrupt bits. */
        writel(irq_status, bus->base + ASPEED_I2C_INTR_STS_REG);
@@ -407,7 +404,7 @@ static bool aspeed_i2c_master_irq(struct aspeed_i2c_bus *bus)
         */
        ret = aspeed_i2c_is_irq_error(irq_status);
        if (ret < 0) {
-               dev_dbg(bus->dev, "received error interrupt: 0x%08x",
+               dev_dbg(bus->dev, "received error interrupt: 0x%08x\n",
                        irq_status);
                bus->cmd_err = ret;
                bus->master_state = ASPEED_I2C_MASTER_INACTIVE;
@@ -416,7 +413,7 @@ static bool aspeed_i2c_master_irq(struct aspeed_i2c_bus *bus)
 
        /* We are in an invalid state; reset bus to a known state. */
        if (!bus->msgs) {
-               dev_err(bus->dev, "bus in unknown state");
+               dev_err(bus->dev, "bus in unknown state\n");
                bus->cmd_err = -EIO;
                if (bus->master_state != ASPEED_I2C_MASTER_STOP)
                        aspeed_i2c_do_stop(bus);
@@ -431,7 +428,7 @@ static bool aspeed_i2c_master_irq(struct aspeed_i2c_bus *bus)
         */
        if (bus->master_state == ASPEED_I2C_MASTER_START) {
                if (unlikely(!(irq_status & ASPEED_I2CD_INTR_TX_ACK))) {
-                       pr_devel("no slave present at %02x", msg->addr);
+                       pr_devel("no slave present at %02x\n", msg->addr);
                        status_ack |= ASPEED_I2CD_INTR_TX_NAK;
                        bus->cmd_err = -ENXIO;
                        aspeed_i2c_do_stop(bus);
@@ -451,11 +448,11 @@ static bool aspeed_i2c_master_irq(struct aspeed_i2c_bus *bus)
        switch (bus->master_state) {
        case ASPEED_I2C_MASTER_TX:
                if (unlikely(irq_status & ASPEED_I2CD_INTR_TX_NAK)) {
-                       dev_dbg(bus->dev, "slave NACKed TX");
+                       dev_dbg(bus->dev, "slave NACKed TX\n");
                        status_ack |= ASPEED_I2CD_INTR_TX_NAK;
                        goto error_and_stop;
                } else if (unlikely(!(irq_status & ASPEED_I2CD_INTR_TX_ACK))) {
-                       dev_err(bus->dev, "slave failed to ACK TX");
+                       dev_err(bus->dev, "slave failed to ACK TX\n");
                        goto error_and_stop;
                }
                status_ack |= ASPEED_I2CD_INTR_TX_ACK;
@@ -478,7 +475,7 @@ static bool aspeed_i2c_master_irq(struct aspeed_i2c_bus *bus)
                /* fallthrough intended */
        case ASPEED_I2C_MASTER_RX:
                if (unlikely(!(irq_status & ASPEED_I2CD_INTR_RX_DONE))) {
-                       dev_err(bus->dev, "master failed to RX");
+                       dev_err(bus->dev, "master failed to RX\n");
                        goto error_and_stop;
                }
                status_ack |= ASPEED_I2CD_INTR_RX_DONE;
@@ -509,7 +506,7 @@ static bool aspeed_i2c_master_irq(struct aspeed_i2c_bus *bus)
                goto out_no_complete;
        case ASPEED_I2C_MASTER_STOP:
                if (unlikely(!(irq_status & ASPEED_I2CD_INTR_NORMAL_STOP))) {
-                       dev_err(bus->dev, "master failed to STOP");
+                       dev_err(bus->dev, "master failed to STOP\n");
                        bus->cmd_err = -EIO;
                        /* Do not STOP as we have already tried. */
                } else {
@@ -520,7 +517,7 @@ static bool aspeed_i2c_master_irq(struct aspeed_i2c_bus *bus)
                goto out_complete;
        case ASPEED_I2C_MASTER_INACTIVE:
                dev_err(bus->dev,
-                       "master received interrupt 0x%08x, but is inactive",
+                       "master received interrupt 0x%08x, but is inactive\n",
                        irq_status);
                bus->cmd_err = -EIO;
                /* Do not STOP as we should be inactive. */
@@ -547,22 +544,29 @@ out_no_complete:
                dev_err(bus->dev,
                        "irq handled != irq. expected 0x%08x, but was 0x%08x\n",
                        irq_status, status_ack);
-       spin_unlock(&bus->lock);
        return !!irq_status;
 }
 
 static irqreturn_t aspeed_i2c_bus_irq(int irq, void *dev_id)
 {
        struct aspeed_i2c_bus *bus = dev_id;
+       bool ret;
+
+       spin_lock(&bus->lock);
 
 #if IS_ENABLED(CONFIG_I2C_SLAVE)
        if (aspeed_i2c_slave_irq(bus)) {
                dev_dbg(bus->dev, "irq handled by slave.\n");
-               return IRQ_HANDLED;
+               ret = true;
+               goto out;
        }
 #endif /* CONFIG_I2C_SLAVE */
 
-       return aspeed_i2c_master_irq(bus) ? IRQ_HANDLED : IRQ_NONE;
+       ret = aspeed_i2c_master_irq(bus);
+
+out:
+       spin_unlock(&bus->lock);
+       return ret ? IRQ_HANDLED : IRQ_NONE;
 }
 
 static int aspeed_i2c_master_xfer(struct i2c_adapter *adap,
@@ -851,7 +855,7 @@ static int aspeed_i2c_probe_bus(struct platform_device *pdev)
        bus->rst = devm_reset_control_get_shared(&pdev->dev, NULL);
        if (IS_ERR(bus->rst)) {
                dev_err(&pdev->dev,
-                       "missing or invalid reset controller device tree entry");
+                       "missing or invalid reset controller device tree entry\n");
                return PTR_ERR(bus->rst);
        }
        reset_control_deassert(bus->rst);
@@ -868,7 +872,7 @@ static int aspeed_i2c_probe_bus(struct platform_device *pdev)
        if (!match)
                bus->get_clk_reg_val = aspeed_i2c_24xx_get_clk_reg_val;
        else
-               bus->get_clk_reg_val = match->data;
+               bus->get_clk_reg_val = (u32 (*)(u32))match->data;
 
        /* Initialize the I2C adapter */
        spin_lock_init(&bus->lock);
index 78792b4..826d320 100644 (file)
@@ -689,9 +689,9 @@ static int brcmstb_i2c_suspend(struct device *dev)
 {
        struct brcmstb_i2c_dev *i2c_dev = dev_get_drvdata(dev);
 
-       i2c_lock_adapter(&i2c_dev->adapter);
+       i2c_lock_bus(&i2c_dev->adapter, I2C_LOCK_ROOT_ADAPTER);
        i2c_dev->is_suspended = true;
-       i2c_unlock_adapter(&i2c_dev->adapter);
+       i2c_unlock_bus(&i2c_dev->adapter, I2C_LOCK_ROOT_ADAPTER);
 
        return 0;
 }
@@ -700,10 +700,10 @@ static int brcmstb_i2c_resume(struct device *dev)
 {
        struct brcmstb_i2c_dev *i2c_dev = dev_get_drvdata(dev);
 
-       i2c_lock_adapter(&i2c_dev->adapter);
+       i2c_lock_bus(&i2c_dev->adapter, I2C_LOCK_ROOT_ADAPTER);
        brcmstb_i2c_set_bsc_reg_defaults(i2c_dev);
        i2c_dev->is_suspended = false;
-       i2c_unlock_adapter(&i2c_dev->adapter);
+       i2c_unlock_bus(&i2c_dev->adapter, I2C_LOCK_ROOT_ADAPTER);
 
        return 0;
 }
index 7379043..11caafa 100644 (file)
@@ -718,14 +718,14 @@ static int i2c_davinci_cpufreq_transition(struct notifier_block *nb,
 
        dev = container_of(nb, struct davinci_i2c_dev, freq_transition);
 
-       i2c_lock_adapter(&dev->adapter);
+       i2c_lock_bus(&dev->adapter, I2C_LOCK_ROOT_ADAPTER);
        if (val == CPUFREQ_PRECHANGE) {
                davinci_i2c_reset_ctrl(dev, 0);
        } else if (val == CPUFREQ_POSTCHANGE) {
                i2c_davinci_calc_clk_dividers(dev);
                davinci_i2c_reset_ctrl(dev, 1);
        }
-       i2c_unlock_adapter(&dev->adapter);
+       i2c_unlock_bus(&dev->adapter, I2C_LOCK_ROOT_ADAPTER);
 
        return 0;
 }
index dbda8c9..a2a275c 100644 (file)
@@ -1,15 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Intel BayTrail PMIC I2C bus semaphore implementaion
  * Copyright (c) 2014, Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
  */
 #include <linux/delay.h>
 #include <linux/device.h>
index 48914df..69ec4a7 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
 /*
  * Synopsys DesignWare I2C adapter driver.
  *
@@ -6,20 +7,6 @@
  * Copyright (C) 2006 Texas Instruments.
  * Copyright (C) 2007 MontaVista Software Inc.
  * Copyright (C) 2009 Provigent Ltd.
- *
- * ----------------------------------------------------------------------------
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- * ----------------------------------------------------------------------------
- *
  */
 #include <linux/clk.h>
 #include <linux/delay.h>
@@ -31,6 +18,7 @@
 #include <linux/io.h>
 #include <linux/module.h>
 #include <linux/pm_runtime.h>
+#include <linux/swab.h>
 
 #include "i2c-designware-core.h"
 
@@ -94,6 +82,40 @@ void dw_writel(struct dw_i2c_dev *dev, u32 b, int offset)
        }
 }
 
+/**
+ * i2c_dw_set_reg_access() - Set register access flags
+ * @dev: device private data
+ *
+ * Autodetects needed register access mode and sets access flags accordingly.
+ * This must be called before doing any other register access.
+ */
+int i2c_dw_set_reg_access(struct dw_i2c_dev *dev)
+{
+       u32 reg;
+       int ret;
+
+       ret = i2c_dw_acquire_lock(dev);
+       if (ret)
+               return ret;
+
+       reg = dw_readl(dev, DW_IC_COMP_TYPE);
+       i2c_dw_release_lock(dev);
+
+       if (reg == swab32(DW_IC_COMP_TYPE_VALUE)) {
+               /* Configure register endianess access */
+               dev->flags |= ACCESS_SWAP;
+       } else if (reg == (DW_IC_COMP_TYPE_VALUE & 0x0000ffff)) {
+               /* Configure register access mode 16bit */
+               dev->flags |= ACCESS_16BIT;
+       } else if (reg != DW_IC_COMP_TYPE_VALUE) {
+               dev_err(dev->dev,
+                       "Unknown Synopsys component type: 0x%08x\n", reg);
+               return -ENODEV;
+       }
+
+       return 0;
+}
+
 u32 i2c_dw_scl_hcnt(u32 ic_clk, u32 tSYMBOL, u32 tf, int cond, int offset)
 {
        /*
@@ -149,6 +171,47 @@ u32 i2c_dw_scl_lcnt(u32 ic_clk, u32 tLOW, u32 tf, int offset)
        return ((ic_clk * (tLOW + tf) + 500000) / 1000000) - 1 + offset;
 }
 
+int i2c_dw_set_sda_hold(struct dw_i2c_dev *dev)
+{
+       u32 reg;
+       int ret;
+
+       ret = i2c_dw_acquire_lock(dev);
+       if (ret)
+               return ret;
+
+       /* Configure SDA Hold Time if required */
+       reg = dw_readl(dev, DW_IC_COMP_VERSION);
+       if (reg >= DW_IC_SDA_HOLD_MIN_VERS) {
+               if (!dev->sda_hold_time) {
+                       /* Keep previous hold time setting if no one set it */
+                       dev->sda_hold_time = dw_readl(dev, DW_IC_SDA_HOLD);
+               }
+
+               /*
+                * Workaround for avoiding TX arbitration lost in case I2C
+                * slave pulls SDA down "too quickly" after falling egde of
+                * SCL by enabling non-zero SDA RX hold. Specification says it
+                * extends incoming SDA low to high transition while SCL is
+                * high but it apprears to help also above issue.
+                */
+               if (!(dev->sda_hold_time & DW_IC_SDA_HOLD_RX_MASK))
+                       dev->sda_hold_time |= 1 << DW_IC_SDA_HOLD_RX_SHIFT;
+
+               dev_dbg(dev->dev, "SDA Hold Time TX:RX = %d:%d\n",
+                       dev->sda_hold_time & ~(u32)DW_IC_SDA_HOLD_RX_MASK,
+                       dev->sda_hold_time >> DW_IC_SDA_HOLD_RX_SHIFT);
+       } else if (dev->sda_hold_time) {
+               dev_warn(dev->dev,
+                       "Hardware too old to adjust SDA hold time.\n");
+               dev->sda_hold_time = 0;
+       }
+
+       i2c_dw_release_lock(dev);
+
+       return 0;
+}
+
 void __i2c_dw_disable(struct dw_i2c_dev *dev)
 {
        int timeout = 100;
index d690e64..e367b1a 100644 (file)
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
 /*
  * Synopsys DesignWare I2C adapter driver.
  *
@@ -6,20 +7,6 @@
  * Copyright (C) 2006 Texas Instruments.
  * Copyright (C) 2007 MontaVista Software Inc.
  * Copyright (C) 2009 Provigent Ltd.
- *
- * ----------------------------------------------------------------------------
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- * ----------------------------------------------------------------------------
- *
  */
 
 #include <linux/i2c.h>
  * @tx_fifo_depth: depth of the hardware tx fifo
  * @rx_fifo_depth: depth of the hardware rx fifo
  * @rx_outstanding: current master-rx elements in tx fifo
- * @clk_freq: bus clock frequency
+ * @timings: bus clock frequency, SDA hold and other timings
+ * @sda_hold_time: SDA hold value
  * @ss_hcnt: standard speed HCNT value
  * @ss_lcnt: standard speed LCNT value
  * @fs_hcnt: fast speed HCNT value
@@ -264,10 +252,8 @@ struct dw_i2c_dev {
        unsigned int            tx_fifo_depth;
        unsigned int            rx_fifo_depth;
        int                     rx_outstanding;
-       u32                     clk_freq;
+       struct i2c_timings      timings;
        u32                     sda_hold_time;
-       u32                     sda_falling_time;
-       u32                     scl_falling_time;
        u16                     ss_hcnt;
        u16                     ss_lcnt;
        u16                     fs_hcnt;
@@ -295,8 +281,10 @@ struct dw_i2c_dev {
 
 u32 dw_readl(struct dw_i2c_dev *dev, int offset);
 void dw_writel(struct dw_i2c_dev *dev, u32 b, int offset);
+int i2c_dw_set_reg_access(struct dw_i2c_dev *dev);
 u32 i2c_dw_scl_hcnt(u32 ic_clk, u32 tSYMBOL, u32 tf, int cond, int offset);
 u32 i2c_dw_scl_lcnt(u32 ic_clk, u32 tLOW, u32 tf, int offset);
+int i2c_dw_set_sda_hold(struct dw_i2c_dev *dev);
 unsigned long i2c_dw_clk_rate(struct dw_i2c_dev *dev);
 int i2c_dw_prepare_clk(struct dw_i2c_dev *dev, bool prepare);
 int i2c_dw_acquire_lock(struct dw_i2c_dev *dev);
index 27436a9..e18442b 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
 /*
  * Synopsys DesignWare I2C adapter driver (master only).
  *
@@ -6,20 +7,6 @@
  * Copyright (C) 2006 Texas Instruments.
  * Copyright (C) 2007 MontaVista Software Inc.
  * Copyright (C) 2009 Provigent Ltd.
- *
- * ----------------------------------------------------------------------------
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- * ----------------------------------------------------------------------------
- *
  */
 #include <linux/delay.h>
 #include <linux/err.h>
@@ -45,90 +32,79 @@ static void i2c_dw_configure_fifo_master(struct dw_i2c_dev *dev)
        dw_writel(dev, dev->master_cfg, DW_IC_CON);
 }
 
-/**
- * i2c_dw_init() - Initialize the designware I2C master hardware
- * @dev: device private data
- *
- * This functions configures and enables the I2C master.
- * This function is called during I2C init function, and in case of timeout at
- * run time.
- */
-static int i2c_dw_init_master(struct dw_i2c_dev *dev)
+static int i2c_dw_set_timings_master(struct dw_i2c_dev *dev)
 {
-       u32 hcnt, lcnt;
-       u32 reg, comp_param1;
+       u32 ic_clk = i2c_dw_clk_rate(dev);
+       const char *mode_str, *fp_str = "";
+       u32 comp_param1;
        u32 sda_falling_time, scl_falling_time;
+       struct i2c_timings *t = &dev->timings;
        int ret;
 
        ret = i2c_dw_acquire_lock(dev);
        if (ret)
                return ret;
-
-       reg = dw_readl(dev, DW_IC_COMP_TYPE);
-       if (reg == ___constant_swab32(DW_IC_COMP_TYPE_VALUE)) {
-               /* Configure register endianess access */
-               dev->flags |= ACCESS_SWAP;
-       } else if (reg == (DW_IC_COMP_TYPE_VALUE & 0x0000ffff)) {
-               /* Configure register access mode 16bit */
-               dev->flags |= ACCESS_16BIT;
-       } else if (reg != DW_IC_COMP_TYPE_VALUE) {
-               dev_err(dev->dev,
-                       "Unknown Synopsys component type: 0x%08x\n", reg);
-               i2c_dw_release_lock(dev);
-               return -ENODEV;
-       }
-
        comp_param1 = dw_readl(dev, DW_IC_COMP_PARAM_1);
+       i2c_dw_release_lock(dev);
 
-       /* Disable the adapter */
-       __i2c_dw_disable(dev);
-
-       /* Set standard and fast speed deviders for high/low periods */
-
-       sda_falling_time = dev->sda_falling_time ?: 300; /* ns */
-       scl_falling_time = dev->scl_falling_time ?: 300; /* ns */
+       /* Set standard and fast speed dividers for high/low periods */
+       sda_falling_time = t->sda_fall_ns ?: 300; /* ns */
+       scl_falling_time = t->scl_fall_ns ?: 300; /* ns */
 
-       /* Set SCL timing parameters for standard-mode */
-       if (dev->ss_hcnt && dev->ss_lcnt) {
-               hcnt = dev->ss_hcnt;
-               lcnt = dev->ss_lcnt;
-       } else {
-               hcnt = i2c_dw_scl_hcnt(i2c_dw_clk_rate(dev),
+       /* Calculate SCL timing parameters for standard mode if not set */
+       if (!dev->ss_hcnt || !dev->ss_lcnt) {
+               dev->ss_hcnt =
+                       i2c_dw_scl_hcnt(ic_clk,
                                        4000,   /* tHD;STA = tHIGH = 4.0 us */
                                        sda_falling_time,
                                        0,      /* 0: DW default, 1: Ideal */
                                        0);     /* No offset */
-               lcnt = i2c_dw_scl_lcnt(i2c_dw_clk_rate(dev),
+               dev->ss_lcnt =
+                       i2c_dw_scl_lcnt(ic_clk,
                                        4700,   /* tLOW = 4.7 us */
                                        scl_falling_time,
                                        0);     /* No offset */
        }
-       dw_writel(dev, hcnt, DW_IC_SS_SCL_HCNT);
-       dw_writel(dev, lcnt, DW_IC_SS_SCL_LCNT);
-       dev_dbg(dev->dev, "Standard-mode HCNT:LCNT = %d:%d\n", hcnt, lcnt);
-
-       /* Set SCL timing parameters for fast-mode or fast-mode plus */
-       if ((dev->clk_freq == 1000000) && dev->fp_hcnt && dev->fp_lcnt) {
-               hcnt = dev->fp_hcnt;
-               lcnt = dev->fp_lcnt;
-       } else if (dev->fs_hcnt && dev->fs_lcnt) {
-               hcnt = dev->fs_hcnt;
-               lcnt = dev->fs_lcnt;
-       } else {
-               hcnt = i2c_dw_scl_hcnt(i2c_dw_clk_rate(dev),
+       dev_dbg(dev->dev, "Standard Mode HCNT:LCNT = %d:%d\n",
+               dev->ss_hcnt, dev->ss_lcnt);
+
+       /*
+        * Set SCL timing parameters for fast mode or fast mode plus. Only
+        * difference is the timing parameter values since the registers are
+        * the same.
+        */
+       if (t->bus_freq_hz == 1000000) {
+               /*
+                * Check are fast mode plus parameters available and use
+                * fast mode if not.
+                */
+               if (dev->fp_hcnt && dev->fp_lcnt) {
+                       dev->fs_hcnt = dev->fp_hcnt;
+                       dev->fs_lcnt = dev->fp_lcnt;
+                       fp_str = " Plus";
+               }
+       }
+       /*
+        * Calculate SCL timing parameters for fast mode if not set. They are
+        * needed also in high speed mode.
+        */
+       if (!dev->fs_hcnt || !dev->fs_lcnt) {
+               dev->fs_hcnt =
+                       i2c_dw_scl_hcnt(ic_clk,
                                        600,    /* tHD;STA = tHIGH = 0.6 us */
                                        sda_falling_time,
                                        0,      /* 0: DW default, 1: Ideal */
                                        0);     /* No offset */
-               lcnt = i2c_dw_scl_lcnt(i2c_dw_clk_rate(dev),
+               dev->fs_lcnt =
+                       i2c_dw_scl_lcnt(ic_clk,
                                        1300,   /* tLOW = 1.3 us */
                                        scl_falling_time,
                                        0);     /* No offset */
        }
-       dw_writel(dev, hcnt, DW_IC_FS_SCL_HCNT);
-       dw_writel(dev, lcnt, DW_IC_FS_SCL_LCNT);
-       dev_dbg(dev->dev, "Fast-mode HCNT:LCNT = %d:%d\n", hcnt, lcnt);
+       dev_dbg(dev->dev, "Fast Mode%s HCNT:LCNT = %d:%d\n",
+               fp_str, dev->fs_hcnt, dev->fs_lcnt);
 
+       /* Check is high speed possible and fall back to fast mode if not */
        if ((dev->master_cfg & DW_IC_CON_SPEED_MASK) ==
                DW_IC_CON_SPEED_HIGH) {
                if ((comp_param1 & DW_IC_COMP_PARAM_1_SPEED_MODE_MASK)
@@ -136,37 +112,70 @@ static int i2c_dw_init_master(struct dw_i2c_dev *dev)
                        dev_err(dev->dev, "High Speed not supported!\n");
                        dev->master_cfg &= ~DW_IC_CON_SPEED_MASK;
                        dev->master_cfg |= DW_IC_CON_SPEED_FAST;
+                       dev->hs_hcnt = 0;
+                       dev->hs_lcnt = 0;
                } else if (dev->hs_hcnt && dev->hs_lcnt) {
-                       hcnt = dev->hs_hcnt;
-                       lcnt = dev->hs_lcnt;
-                       dw_writel(dev, hcnt, DW_IC_HS_SCL_HCNT);
-                       dw_writel(dev, lcnt, DW_IC_HS_SCL_LCNT);
-                       dev_dbg(dev->dev, "HighSpeed-mode HCNT:LCNT = %d:%d\n",
-                               hcnt, lcnt);
+                       dev_dbg(dev->dev, "High Speed Mode HCNT:LCNT = %d:%d\n",
+                               dev->hs_hcnt, dev->hs_lcnt);
                }
        }
 
-       /* Configure SDA Hold Time if required */
-       reg = dw_readl(dev, DW_IC_COMP_VERSION);
-       if (reg >= DW_IC_SDA_HOLD_MIN_VERS) {
-               if (!dev->sda_hold_time) {
-                       /* Keep previous hold time setting if no one set it */
-                       dev->sda_hold_time = dw_readl(dev, DW_IC_SDA_HOLD);
-               }
-               /*
-                * Workaround for avoiding TX arbitration lost in case I2C
-                * slave pulls SDA down "too quickly" after falling egde of
-                * SCL by enabling non-zero SDA RX hold. Specification says it
-                * extends incoming SDA low to high transition while SCL is
-                * high but it apprears to help also above issue.
-                */
-               if (!(dev->sda_hold_time & DW_IC_SDA_HOLD_RX_MASK))
-                       dev->sda_hold_time |= 1 << DW_IC_SDA_HOLD_RX_SHIFT;
-               dw_writel(dev, dev->sda_hold_time, DW_IC_SDA_HOLD);
-       } else if (dev->sda_hold_time) {
-               dev_warn(dev->dev,
-                       "Hardware too old to adjust SDA hold time.\n");
+       ret = i2c_dw_set_sda_hold(dev);
+       if (ret)
+               goto out;
+
+       switch (dev->master_cfg & DW_IC_CON_SPEED_MASK) {
+       case DW_IC_CON_SPEED_STD:
+               mode_str = "Standard Mode";
+               break;
+       case DW_IC_CON_SPEED_HIGH:
+               mode_str = "High Speed Mode";
+               break;
+       default:
+               mode_str = "Fast Mode";
        }
+       dev_dbg(dev->dev, "Bus speed: %s%s\n", mode_str, fp_str);
+
+out:
+       return ret;
+}
+
+/**
+ * i2c_dw_init() - Initialize the designware I2C master hardware
+ * @dev: device private data
+ *
+ * This functions configures and enables the I2C master.
+ * This function is called during I2C init function, and in case of timeout at
+ * run time.
+ */
+static int i2c_dw_init_master(struct dw_i2c_dev *dev)
+{
+       int ret;
+
+       ret = i2c_dw_acquire_lock(dev);
+       if (ret)
+               return ret;
+
+       /* Disable the adapter */
+       __i2c_dw_disable(dev);
+
+       /* Write standard speed timing parameters */
+       dw_writel(dev, dev->ss_hcnt, DW_IC_SS_SCL_HCNT);
+       dw_writel(dev, dev->ss_lcnt, DW_IC_SS_SCL_LCNT);
+
+       /* Write fast mode/fast mode plus timing parameters */
+       dw_writel(dev, dev->fs_hcnt, DW_IC_FS_SCL_HCNT);
+       dw_writel(dev, dev->fs_lcnt, DW_IC_FS_SCL_LCNT);
+
+       /* Write high speed timing parameters if supported */
+       if (dev->hs_hcnt && dev->hs_lcnt) {
+               dw_writel(dev, dev->hs_hcnt, DW_IC_HS_SCL_HCNT);
+               dw_writel(dev, dev->hs_lcnt, DW_IC_HS_SCL_LCNT);
+       }
+
+       /* Write SDA hold time if supported */
+       if (dev->sda_hold_time)
+               dw_writel(dev, dev->sda_hold_time, DW_IC_SDA_HOLD);
 
        i2c_dw_configure_fifo_master(dev);
        i2c_dw_release_lock(dev);
@@ -253,13 +262,6 @@ i2c_dw_xfer_msg(struct dw_i2c_dev *dev)
                        break;
                }
 
-               if (msgs[dev->msg_write_idx].len == 0) {
-                       dev_err(dev->dev,
-                               "%s: invalid message length\n", __func__);
-                       dev->msg_err = -EINVAL;
-                       break;
-               }
-
                if (!(dev->status & STATUS_WRITE_IN_PROGRESS)) {
                        /* new i2c_msg */
                        buf = msgs[dev->msg_write_idx].buf;
@@ -502,6 +504,10 @@ static const struct i2c_algorithm i2c_dw_algo = {
        .functionality = i2c_dw_func,
 };
 
+static const struct i2c_adapter_quirks i2c_dw_quirks = {
+       .flags = I2C_AQ_NO_ZERO_LEN,
+};
+
 static u32 i2c_dw_read_clear_intrbits(struct dw_i2c_dev *dev)
 {
        u32 stat;
@@ -681,6 +687,14 @@ int i2c_dw_probe(struct dw_i2c_dev *dev)
        dev->disable = i2c_dw_disable;
        dev->disable_int = i2c_dw_disable_int;
 
+       ret = i2c_dw_set_reg_access(dev);
+       if (ret)
+               return ret;
+
+       ret = i2c_dw_set_timings_master(dev);
+       if (ret)
+               return ret;
+
        ret = dev->init(dev);
        if (ret)
                return ret;
@@ -689,6 +703,7 @@ int i2c_dw_probe(struct dw_i2c_dev *dev)
                 "Synopsys DesignWare I2C adapter");
        adap->retries = 3;
        adap->algo = &i2c_dw_algo;
+       adap->quirks = &i2c_dw_quirks;
        adap->dev.parent = dev->dev;
        i2c_set_adapdata(adap, dev);
 
index 86e1bd0..d50f804 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
 /*
  * Synopsys DesignWare I2C adapter driver (master only).
  *
@@ -7,22 +8,7 @@
  * Copyright (C) 2007 MontaVista Software Inc.
  * Copyright (C) 2009 Provigent Ltd.
  * Copyright (C) 2011, 2015, 2016 Intel 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/acpi.h>
 #include <linux/delay.h>
 #include <linux/err.h>
@@ -105,6 +91,7 @@ static int mfld_setup(struct pci_dev *pdev, struct dw_pci_controller *c)
        case 0x0817:
                c->bus_cfg &= ~DW_IC_CON_SPEED_MASK;
                c->bus_cfg |= DW_IC_CON_SPEED_STD;
+               /* fall through */
        case 0x0818:
        case 0x0819:
                c->bus_num = pdev->device - 0x817 + 3;
index 5660daf..1a8d2da 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
 /*
  * Synopsys DesignWare I2C adapter driver.
  *
@@ -6,20 +7,6 @@
  * Copyright (C) 2006 Texas Instruments.
  * Copyright (C) 2007 MontaVista Software Inc.
  * Copyright (C) 2009 Provigent Ltd.
- *
- * ----------------------------------------------------------------------------
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- * ----------------------------------------------------------------------------
- *
  */
 #include <linux/acpi.h>
 #include <linux/clk-provider.h>
@@ -96,6 +83,7 @@ static void dw_i2c_acpi_params(struct platform_device *pdev, char method[],
 static int dw_i2c_acpi_configure(struct platform_device *pdev)
 {
        struct dw_i2c_dev *dev = platform_get_drvdata(pdev);
+       struct i2c_timings *t = &dev->timings;
        u32 ss_ht = 0, fp_ht = 0, hs_ht = 0, fs_ht = 0;
        acpi_handle handle = ACPI_HANDLE(&pdev->dev);
        const struct acpi_device_id *id;
@@ -115,7 +103,7 @@ static int dw_i2c_acpi_configure(struct platform_device *pdev)
        dw_i2c_acpi_params(pdev, "HSCN", &dev->hs_hcnt, &dev->hs_lcnt, &hs_ht);
        dw_i2c_acpi_params(pdev, "FMCN", &dev->fs_hcnt, &dev->fs_lcnt, &fs_ht);
 
-       switch (dev->clk_freq) {
+       switch (t->bus_freq_hz) {
        case 100000:
                dev->sda_hold_time = ss_ht;
                break;
@@ -175,6 +163,8 @@ static inline int dw_i2c_acpi_configure(struct platform_device *pdev)
 
 static void i2c_dw_configure_master(struct dw_i2c_dev *dev)
 {
+       struct i2c_timings *t = &dev->timings;
+
        dev->functionality = I2C_FUNC_10BIT_ADDR | DW_IC_DEFAULT_FUNCTIONALITY;
 
        dev->master_cfg = DW_IC_CON_MASTER | DW_IC_CON_SLAVE_DISABLE |
@@ -182,7 +172,7 @@ static void i2c_dw_configure_master(struct dw_i2c_dev *dev)
 
        dev->mode = DW_IC_MASTER;
 
-       switch (dev->clk_freq) {
+       switch (t->bus_freq_hz) {
        case 100000:
                dev->master_cfg |= DW_IC_CON_SPEED_STD;
                break;
@@ -240,7 +230,8 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)
        struct dw_i2c_platform_data *pdata = dev_get_platdata(&pdev->dev);
        struct i2c_adapter *adap;
        struct dw_i2c_dev *dev;
-       u32 acpi_speed, ht = 0;
+       struct i2c_timings *t;
+       u32 acpi_speed;
        struct resource *mem;
        int i, irq, ret;
        static const int supported_speeds[] = {
@@ -272,18 +263,11 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)
                reset_control_deassert(dev->rst);
        }
 
-       if (pdata) {
-               dev->clk_freq = pdata->i2c_scl_freq;
-       } else {
-               device_property_read_u32(&pdev->dev, "i2c-sda-hold-time-ns",
-                                        &ht);
-               device_property_read_u32(&pdev->dev, "i2c-sda-falling-time-ns",
-                                        &dev->sda_falling_time);
-               device_property_read_u32(&pdev->dev, "i2c-scl-falling-time-ns",
-                                        &dev->scl_falling_time);
-               device_property_read_u32(&pdev->dev, "clock-frequency",
-                                        &dev->clk_freq);
-       }
+       t = &dev->timings;
+       if (pdata)
+               t->bus_freq_hz = pdata->i2c_scl_freq;
+       else
+               i2c_parse_fw_timings(&pdev->dev, t, false);
 
        acpi_speed = i2c_acpi_find_bus_speed(&pdev->dev);
        /*
@@ -300,12 +284,12 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)
         * Find bus speed from the "clock-frequency" device property, ACPI
         * or by using fast mode if neither is set.
         */
-       if (acpi_speed && dev->clk_freq)
-               dev->clk_freq = min(dev->clk_freq, acpi_speed);
-       else if (acpi_speed || dev->clk_freq)
-               dev->clk_freq = max(dev->clk_freq, acpi_speed);
+       if (acpi_speed && t->bus_freq_hz)
+               t->bus_freq_hz = min(t->bus_freq_hz, acpi_speed);
+       else if (acpi_speed || t->bus_freq_hz)
+               t->bus_freq_hz = max(t->bus_freq_hz, acpi_speed);
        else
-               dev->clk_freq = 400000;
+               t->bus_freq_hz = 400000;
 
        if (has_acpi_companion(&pdev->dev))
                dw_i2c_acpi_configure(pdev);
@@ -314,11 +298,11 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)
         * Only standard mode at 100kHz, fast mode at 400kHz,
         * fast mode plus at 1MHz and high speed mode at 3.4MHz are supported.
         */
-       if (dev->clk_freq != 100000 && dev->clk_freq != 400000
-           && dev->clk_freq != 1000000 && dev->clk_freq != 3400000) {
+       if (t->bus_freq_hz != 100000 && t->bus_freq_hz != 400000 &&
+           t->bus_freq_hz != 1000000 && t->bus_freq_hz != 3400000) {
                dev_err(&pdev->dev,
                        "%d Hz is unsupported, only 100kHz, 400kHz, 1MHz and 3.4MHz are supported\n",
-                       dev->clk_freq);
+                       t->bus_freq_hz);
                ret = -EINVAL;
                goto exit_reset;
        }
@@ -334,12 +318,14 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)
 
        dev->clk = devm_clk_get(&pdev->dev, NULL);
        if (!i2c_dw_prepare_clk(dev, true)) {
+               u64 clk_khz;
+
                dev->get_clk_rate_khz = i2c_dw_get_clk_rate_khz;
+               clk_khz = dev->get_clk_rate_khz(dev);
 
-               if (!dev->sda_hold_time && ht)
-                       dev->sda_hold_time = div_u64(
-                               (u64)dev->get_clk_rate_khz(dev) * ht + 500000,
-                               1000000);
+               if (!dev->sda_hold_time && t->sda_hold_ns)
+                       dev->sda_hold_time =
+                               div_u64(clk_khz * t->sda_hold_ns + 500000, 1000000);
        }
 
        dw_i2c_set_fifo_size(dev, pdev->id);
index 8ce2cd3..e7f9305 100644 (file)
@@ -1,23 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Synopsys DesignWare I2C adapter driver (slave only).
  *
  * Based on the Synopsys DesignWare I2C adapter driver (master).
  *
  * Copyright (C) 2016 Synopsys Inc.
- *
- * ----------------------------------------------------------------------------
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- * ----------------------------------------------------------------------------
- *
  */
 #include <linux/delay.h>
 #include <linux/err.h>
@@ -51,53 +38,18 @@ static void i2c_dw_configure_fifo_slave(struct dw_i2c_dev *dev)
  */
 static int i2c_dw_init_slave(struct dw_i2c_dev *dev)
 {
-       u32 reg, comp_param1;
        int ret;
 
        ret = i2c_dw_acquire_lock(dev);
        if (ret)
                return ret;
 
-       reg = dw_readl(dev, DW_IC_COMP_TYPE);
-       if (reg == ___constant_swab32(DW_IC_COMP_TYPE_VALUE)) {
-               /* Configure register endianness access. */
-               dev->flags |= ACCESS_SWAP;
-       } else if (reg == (DW_IC_COMP_TYPE_VALUE & 0x0000ffff)) {
-               /* Configure register access mode 16bit. */
-               dev->flags |= ACCESS_16BIT;
-       } else if (reg != DW_IC_COMP_TYPE_VALUE) {
-               dev_err(dev->dev,
-                       "Unknown Synopsys component type: 0x%08x\n", reg);
-               i2c_dw_release_lock(dev);
-               return -ENODEV;
-       }
-
-       comp_param1 = dw_readl(dev, DW_IC_COMP_PARAM_1);
-
        /* Disable the adapter. */
        __i2c_dw_disable(dev);
 
-       /* Configure SDA Hold Time if required. */
-       reg = dw_readl(dev, DW_IC_COMP_VERSION);
-       if (reg >= DW_IC_SDA_HOLD_MIN_VERS) {
-               if (!dev->sda_hold_time) {
-                       /* Keep previous hold time setting if no one set it. */
-                       dev->sda_hold_time = dw_readl(dev, DW_IC_SDA_HOLD);
-               }
-               /*
-                * Workaround for avoiding TX arbitration lost in case I2C
-                * slave pulls SDA down "too quickly" after falling egde of
-                * SCL by enabling non-zero SDA RX hold. Specification says it
-                * extends incoming SDA low to high transition while SCL is
-                * high but it apprears to help also above issue.
-                */
-               if (!(dev->sda_hold_time & DW_IC_SDA_HOLD_RX_MASK))
-                       dev->sda_hold_time |= 1 << DW_IC_SDA_HOLD_RX_SHIFT;
+       /* Write SDA hold time if supported */
+       if (dev->sda_hold_time)
                dw_writel(dev, dev->sda_hold_time, DW_IC_SDA_HOLD);
-       } else {
-               dev_warn(dev->dev,
-                        "Hardware too old to adjust SDA hold time.\n");
-       }
 
        i2c_dw_configure_fifo_slave(dev);
        i2c_dw_release_lock(dev);
@@ -299,6 +251,14 @@ int i2c_dw_probe_slave(struct dw_i2c_dev *dev)
        dev->disable = i2c_dw_disable;
        dev->disable_int = i2c_dw_disable_int;
 
+       ret = i2c_dw_set_reg_access(dev);
+       if (ret)
+               return ret;
+
+       ret = i2c_dw_set_sda_hold(dev);
+       if (ret)
+               return ret;
+
        ret = dev->init(dev);
        if (ret)
                return ret;
index ba9b6ea..35b302d 100644 (file)
@@ -1,13 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * I2C driver for the Renesas EMEV2 SoC
  *
  * Copyright (C) 2015 Wolfram Sang <wsa@sang-engineering.com>
  * Copyright 2013 Codethink Ltd.
  * Copyright 2010-2015 Renesas Electronics Corporation
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2
- * as published by the Free Software Foundation.
  */
 
 #include <linux/clk.h>
index de82ad8..c1ce229 100644 (file)
 
 #define EXYNOS5_I2C_TIMEOUT (msecs_to_jiffies(100))
 
-#define HSI2C_EXYNOS7  BIT(0)
+enum i2c_type_exynos {
+       I2C_TYPE_EXYNOS5,
+       I2C_TYPE_EXYNOS7,
+};
 
 struct exynos5_i2c {
        struct i2c_adapter      adap;
@@ -212,27 +215,30 @@ struct exynos5_i2c {
 /**
  * struct exynos_hsi2c_variant - platform specific HSI2C driver data
  * @fifo_depth: the fifo depth supported by the HSI2C module
+ * @hw: the hardware variant of Exynos I2C controller
  *
  * Specifies platform specific configuration of HSI2C module.
  * Note: A structure for driver specific platform data is used for future
  * expansion of its usage.
  */
 struct exynos_hsi2c_variant {
-       unsigned int    fifo_depth;
-       unsigned int    hw;
+       unsigned int            fifo_depth;
+       enum i2c_type_exynos    hw;
 };
 
 static const struct exynos_hsi2c_variant exynos5250_hsi2c_data = {
        .fifo_depth     = 64,
+       .hw             = I2C_TYPE_EXYNOS5,
 };
 
 static const struct exynos_hsi2c_variant exynos5260_hsi2c_data = {
        .fifo_depth     = 16,
+       .hw             = I2C_TYPE_EXYNOS5,
 };
 
 static const struct exynos_hsi2c_variant exynos7_hsi2c_data = {
        .fifo_depth     = 16,
-       .hw             = HSI2C_EXYNOS7,
+       .hw             = I2C_TYPE_EXYNOS7,
 };
 
 static const struct of_device_id exynos5_i2c_match[] = {
@@ -300,7 +306,7 @@ static int exynos5_i2c_set_timing(struct exynos5_i2c *i2c, bool hs_timings)
         */
        t_ftl_cycle = (readl(i2c->regs + HSI2C_CONF) >> 16) & 0x7;
        temp = clkin / op_clk - 8 - t_ftl_cycle;
-       if (i2c->variant->hw != HSI2C_EXYNOS7)
+       if (i2c->variant->hw != I2C_TYPE_EXYNOS7)
                temp -= t_ftl_cycle;
        div = temp / 512;
        clk_cycle = temp / (div + 1) - 2;
@@ -424,7 +430,7 @@ static irqreturn_t exynos5_i2c_irq(int irqno, void *dev_id)
        writel(int_status, i2c->regs + HSI2C_INT_STATUS);
 
        /* handle interrupt related to the transfer status */
-       if (i2c->variant->hw == HSI2C_EXYNOS7) {
+       if (i2c->variant->hw == I2C_TYPE_EXYNOS7) {
                if (int_status & HSI2C_INT_TRANS_DONE) {
                        i2c->trans_done = 1;
                        i2c->state = 0;
@@ -571,7 +577,7 @@ static void exynos5_i2c_bus_check(struct exynos5_i2c *i2c)
 {
        unsigned long timeout;
 
-       if (i2c->variant->hw != HSI2C_EXYNOS7)
+       if (i2c->variant->hw != I2C_TYPE_EXYNOS7)
                return;
 
        /*
@@ -612,7 +618,7 @@ static void exynos5_i2c_message_start(struct exynos5_i2c *i2c, int stop)
        unsigned long flags;
        unsigned short trig_lvl;
 
-       if (i2c->variant->hw == HSI2C_EXYNOS7)
+       if (i2c->variant->hw == I2C_TYPE_EXYNOS7)
                int_en |= HSI2C_INT_I2C_TRANS;
        else
                int_en |= HSI2C_INT_I2C;
diff --git a/drivers/i2c/busses/i2c-fsi.c b/drivers/i2c/busses/i2c-fsi.c
new file mode 100644 (file)
index 0000000..1e2be22
--- /dev/null
@@ -0,0 +1,752 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * FSI-attached I2C master algorithm
+ *
+ * Copyright 2018 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/bitfield.h>
+#include <linux/bitops.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/fsi.h>
+#include <linux/i2c.h>
+#include <linux/jiffies.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/slab.h>
+
+#define FSI_ENGID_I2C          0x7
+
+#define I2C_DEFAULT_CLK_DIV    6
+
+/* i2c registers */
+#define I2C_FSI_FIFO           0x00
+#define I2C_FSI_CMD            0x04
+#define I2C_FSI_MODE           0x08
+#define I2C_FSI_WATER_MARK     0x0C
+#define I2C_FSI_INT_MASK       0x10
+#define I2C_FSI_INT_COND       0x14
+#define I2C_FSI_OR_INT_MASK    0x14
+#define I2C_FSI_INTS           0x18
+#define I2C_FSI_AND_INT_MASK   0x18
+#define I2C_FSI_STAT           0x1C
+#define I2C_FSI_RESET_I2C      0x1C
+#define I2C_FSI_ESTAT          0x20
+#define I2C_FSI_RESET_ERR      0x20
+#define I2C_FSI_RESID_LEN      0x24
+#define I2C_FSI_SET_SCL                0x24
+#define I2C_FSI_PORT_BUSY      0x28
+#define I2C_FSI_RESET_SCL      0x2C
+#define I2C_FSI_SET_SDA                0x30
+#define I2C_FSI_RESET_SDA      0x34
+
+/* cmd register */
+#define I2C_CMD_WITH_START     BIT(31)
+#define I2C_CMD_WITH_ADDR      BIT(30)
+#define I2C_CMD_RD_CONT                BIT(29)
+#define I2C_CMD_WITH_STOP      BIT(28)
+#define I2C_CMD_FORCELAUNCH    BIT(27)
+#define I2C_CMD_ADDR           GENMASK(23, 17)
+#define I2C_CMD_READ           BIT(16)
+#define I2C_CMD_LEN            GENMASK(15, 0)
+
+/* mode register */
+#define I2C_MODE_CLKDIV                GENMASK(31, 16)
+#define I2C_MODE_PORT          GENMASK(15, 10)
+#define I2C_MODE_ENHANCED      BIT(3)
+#define I2C_MODE_DIAG          BIT(2)
+#define I2C_MODE_PACE_ALLOW    BIT(1)
+#define I2C_MODE_WRAP          BIT(0)
+
+/* watermark register */
+#define I2C_WATERMARK_HI       GENMASK(15, 12)
+#define I2C_WATERMARK_LO       GENMASK(7, 4)
+
+#define I2C_FIFO_HI_LVL                4
+#define I2C_FIFO_LO_LVL                4
+
+/* interrupt register */
+#define I2C_INT_INV_CMD                BIT(15)
+#define I2C_INT_PARITY         BIT(14)
+#define I2C_INT_BE_OVERRUN     BIT(13)
+#define I2C_INT_BE_ACCESS      BIT(12)
+#define I2C_INT_LOST_ARB       BIT(11)
+#define I2C_INT_NACK           BIT(10)
+#define I2C_INT_DAT_REQ                BIT(9)
+#define I2C_INT_CMD_COMP       BIT(8)
+#define I2C_INT_STOP_ERR       BIT(7)
+#define I2C_INT_BUSY           BIT(6)
+#define I2C_INT_IDLE           BIT(5)
+
+/* status register */
+#define I2C_STAT_INV_CMD       BIT(31)
+#define I2C_STAT_PARITY                BIT(30)
+#define I2C_STAT_BE_OVERRUN    BIT(29)
+#define I2C_STAT_BE_ACCESS     BIT(28)
+#define I2C_STAT_LOST_ARB      BIT(27)
+#define I2C_STAT_NACK          BIT(26)
+#define I2C_STAT_DAT_REQ       BIT(25)
+#define I2C_STAT_CMD_COMP      BIT(24)
+#define I2C_STAT_STOP_ERR      BIT(23)
+#define I2C_STAT_MAX_PORT      GENMASK(19, 16)
+#define I2C_STAT_ANY_INT       BIT(15)
+#define I2C_STAT_SCL_IN                BIT(11)
+#define I2C_STAT_SDA_IN                BIT(10)
+#define I2C_STAT_PORT_BUSY     BIT(9)
+#define I2C_STAT_SELF_BUSY     BIT(8)
+#define I2C_STAT_FIFO_COUNT    GENMASK(7, 0)
+
+#define I2C_STAT_ERR           (I2C_STAT_INV_CMD |                     \
+                                I2C_STAT_PARITY |                      \
+                                I2C_STAT_BE_OVERRUN |                  \
+                                I2C_STAT_BE_ACCESS |                   \
+                                I2C_STAT_LOST_ARB |                    \
+                                I2C_STAT_NACK |                        \
+                                I2C_STAT_STOP_ERR)
+#define I2C_STAT_ANY_RESP      (I2C_STAT_ERR |                         \
+                                I2C_STAT_DAT_REQ |                     \
+                                I2C_STAT_CMD_COMP)
+
+/* extended status register */
+#define I2C_ESTAT_FIFO_SZ      GENMASK(31, 24)
+#define I2C_ESTAT_SCL_IN_SY    BIT(15)
+#define I2C_ESTAT_SDA_IN_SY    BIT(14)
+#define I2C_ESTAT_S_SCL                BIT(13)
+#define I2C_ESTAT_S_SDA                BIT(12)
+#define I2C_ESTAT_M_SCL                BIT(11)
+#define I2C_ESTAT_M_SDA                BIT(10)
+#define I2C_ESTAT_HI_WATER     BIT(9)
+#define I2C_ESTAT_LO_WATER     BIT(8)
+#define I2C_ESTAT_PORT_BUSY    BIT(7)
+#define I2C_ESTAT_SELF_BUSY    BIT(6)
+#define I2C_ESTAT_VERSION      GENMASK(4, 0)
+
+/* port busy register */
+#define I2C_PORT_BUSY_RESET    BIT(31)
+
+/* wait for command complete or data request */
+#define I2C_CMD_SLEEP_MAX_US   500
+#define I2C_CMD_SLEEP_MIN_US   50
+
+/* wait after reset; choose time from legacy driver */
+#define I2C_RESET_SLEEP_MAX_US 2000
+#define I2C_RESET_SLEEP_MIN_US 1000
+
+/* choose timeout length from legacy driver; it's well tested */
+#define I2C_ABORT_TIMEOUT      msecs_to_jiffies(100)
+
+struct fsi_i2c_master {
+       struct fsi_device       *fsi;
+       u8                      fifo_size;
+       struct list_head        ports;
+       struct mutex            lock;
+};
+
+struct fsi_i2c_port {
+       struct list_head        list;
+       struct i2c_adapter      adapter;
+       struct fsi_i2c_master   *master;
+       u16                     port;
+       u16                     xfrd;
+};
+
+static int fsi_i2c_read_reg(struct fsi_device *fsi, unsigned int reg,
+                           u32 *data)
+{
+       int rc;
+       __be32 data_be;
+
+       rc = fsi_device_read(fsi, reg, &data_be, sizeof(data_be));
+       if (rc)
+               return rc;
+
+       *data = be32_to_cpu(data_be);
+
+       return 0;
+}
+
+static int fsi_i2c_write_reg(struct fsi_device *fsi, unsigned int reg,
+                            u32 *data)
+{
+       __be32 data_be = cpu_to_be32p(data);
+
+       return fsi_device_write(fsi, reg, &data_be, sizeof(data_be));
+}
+
+static int fsi_i2c_dev_init(struct fsi_i2c_master *i2c)
+{
+       int rc;
+       u32 mode = I2C_MODE_ENHANCED, extended_status, watermark;
+       u32 interrupt = 0;
+
+       /* since we use polling, disable interrupts */
+       rc = fsi_i2c_write_reg(i2c->fsi, I2C_FSI_INT_MASK, &interrupt);
+       if (rc)
+               return rc;
+
+       mode |= FIELD_PREP(I2C_MODE_CLKDIV, I2C_DEFAULT_CLK_DIV);
+       rc = fsi_i2c_write_reg(i2c->fsi, I2C_FSI_MODE, &mode);
+       if (rc)
+               return rc;
+
+       rc = fsi_i2c_read_reg(i2c->fsi, I2C_FSI_ESTAT, &extended_status);
+       if (rc)
+               return rc;
+
+       i2c->fifo_size = FIELD_GET(I2C_ESTAT_FIFO_SZ, extended_status);
+       watermark = FIELD_PREP(I2C_WATERMARK_HI,
+                              i2c->fifo_size - I2C_FIFO_HI_LVL);
+       watermark |= FIELD_PREP(I2C_WATERMARK_LO, I2C_FIFO_LO_LVL);
+
+       return fsi_i2c_write_reg(i2c->fsi, I2C_FSI_WATER_MARK, &watermark);
+}
+
+static int fsi_i2c_set_port(struct fsi_i2c_port *port)
+{
+       int rc;
+       struct fsi_device *fsi = port->master->fsi;
+       u32 mode, dummy = 0;
+
+       rc = fsi_i2c_read_reg(fsi, I2C_FSI_MODE, &mode);
+       if (rc)
+               return rc;
+
+       if (FIELD_GET(I2C_MODE_PORT, mode) == port->port)
+               return 0;
+
+       mode = (mode & ~I2C_MODE_PORT) | FIELD_PREP(I2C_MODE_PORT, port->port);
+       rc = fsi_i2c_write_reg(fsi, I2C_FSI_MODE, &mode);
+       if (rc)
+               return rc;
+
+       /* reset engine when port is changed */
+       return fsi_i2c_write_reg(fsi, I2C_FSI_RESET_ERR, &dummy);
+}
+
+static int fsi_i2c_start(struct fsi_i2c_port *port, struct i2c_msg *msg,
+                        bool stop)
+{
+       struct fsi_i2c_master *i2c = port->master;
+       u32 cmd = I2C_CMD_WITH_START | I2C_CMD_WITH_ADDR;
+
+       port->xfrd = 0;
+
+       if (msg->flags & I2C_M_RD)
+               cmd |= I2C_CMD_READ;
+
+       if (stop || msg->flags & I2C_M_STOP)
+               cmd |= I2C_CMD_WITH_STOP;
+
+       cmd |= FIELD_PREP(I2C_CMD_ADDR, msg->addr);
+       cmd |= FIELD_PREP(I2C_CMD_LEN, msg->len);
+
+       return fsi_i2c_write_reg(i2c->fsi, I2C_FSI_CMD, &cmd);
+}
+
+static int fsi_i2c_get_op_bytes(int op_bytes)
+{
+       /* fsi is limited to max 4 byte aligned ops */
+       if (op_bytes > 4)
+               return 4;
+       else if (op_bytes == 3)
+               return 2;
+       return op_bytes;
+}
+
+static int fsi_i2c_write_fifo(struct fsi_i2c_port *port, struct i2c_msg *msg,
+                             u8 fifo_count)
+{
+       int write;
+       int rc;
+       struct fsi_i2c_master *i2c = port->master;
+       int bytes_to_write = i2c->fifo_size - fifo_count;
+       int bytes_remaining = msg->len - port->xfrd;
+
+       bytes_to_write = min(bytes_to_write, bytes_remaining);
+
+       while (bytes_to_write) {
+               write = fsi_i2c_get_op_bytes(bytes_to_write);
+
+               rc = fsi_device_write(i2c->fsi, I2C_FSI_FIFO,
+                                     &msg->buf[port->xfrd], write);
+               if (rc)
+                       return rc;
+
+               port->xfrd += write;
+               bytes_to_write -= write;
+       }
+
+       return 0;
+}
+
+static int fsi_i2c_read_fifo(struct fsi_i2c_port *port, struct i2c_msg *msg,
+                            u8 fifo_count)
+{
+       int read;
+       int rc;
+       struct fsi_i2c_master *i2c = port->master;
+       int bytes_to_read;
+       int xfr_remaining = msg->len - port->xfrd;
+       u32 dummy;
+
+       bytes_to_read = min_t(int, fifo_count, xfr_remaining);
+
+       while (bytes_to_read) {
+               read = fsi_i2c_get_op_bytes(bytes_to_read);
+
+               if (xfr_remaining) {
+                       rc = fsi_device_read(i2c->fsi, I2C_FSI_FIFO,
+                                            &msg->buf[port->xfrd], read);
+                       if (rc)
+                               return rc;
+
+                       port->xfrd += read;
+                       xfr_remaining -= read;
+               } else {
+                       /* no more buffer but data in fifo, need to clear it */
+                       rc = fsi_device_read(i2c->fsi, I2C_FSI_FIFO, &dummy,
+                                            read);
+                       if (rc)
+                               return rc;
+               }
+
+               bytes_to_read -= read;
+       }
+
+       return 0;
+}
+
+static int fsi_i2c_get_scl(struct i2c_adapter *adap)
+{
+       u32 stat = 0;
+       struct fsi_i2c_port *port = adap->algo_data;
+       struct fsi_i2c_master *i2c = port->master;
+
+       fsi_i2c_read_reg(i2c->fsi, I2C_FSI_STAT, &stat);
+
+       return !!(stat & I2C_STAT_SCL_IN);
+}
+
+static void fsi_i2c_set_scl(struct i2c_adapter *adap, int val)
+{
+       u32 dummy = 0;
+       struct fsi_i2c_port *port = adap->algo_data;
+       struct fsi_i2c_master *i2c = port->master;
+
+       if (val)
+               fsi_i2c_write_reg(i2c->fsi, I2C_FSI_SET_SCL, &dummy);
+       else
+               fsi_i2c_write_reg(i2c->fsi, I2C_FSI_RESET_SCL, &dummy);
+}
+
+static int fsi_i2c_get_sda(struct i2c_adapter *adap)
+{
+       u32 stat = 0;
+       struct fsi_i2c_port *port = adap->algo_data;
+       struct fsi_i2c_master *i2c = port->master;
+
+       fsi_i2c_read_reg(i2c->fsi, I2C_FSI_STAT, &stat);
+
+       return !!(stat & I2C_STAT_SDA_IN);
+}
+
+static void fsi_i2c_set_sda(struct i2c_adapter *adap, int val)
+{
+       u32 dummy = 0;
+       struct fsi_i2c_port *port = adap->algo_data;
+       struct fsi_i2c_master *i2c = port->master;
+
+       if (val)
+               fsi_i2c_write_reg(i2c->fsi, I2C_FSI_SET_SDA, &dummy);
+       else
+               fsi_i2c_write_reg(i2c->fsi, I2C_FSI_RESET_SDA, &dummy);
+}
+
+static void fsi_i2c_prepare_recovery(struct i2c_adapter *adap)
+{
+       int rc;
+       u32 mode;
+       struct fsi_i2c_port *port = adap->algo_data;
+       struct fsi_i2c_master *i2c = port->master;
+
+       rc = fsi_i2c_read_reg(i2c->fsi, I2C_FSI_MODE, &mode);
+       if (rc)
+               return;
+
+       mode |= I2C_MODE_DIAG;
+       fsi_i2c_write_reg(i2c->fsi, I2C_FSI_MODE, &mode);
+}
+
+static void fsi_i2c_unprepare_recovery(struct i2c_adapter *adap)
+{
+       int rc;
+       u32 mode;
+       struct fsi_i2c_port *port = adap->algo_data;
+       struct fsi_i2c_master *i2c = port->master;
+
+       rc = fsi_i2c_read_reg(i2c->fsi, I2C_FSI_MODE, &mode);
+       if (rc)
+               return;
+
+       mode &= ~I2C_MODE_DIAG;
+       fsi_i2c_write_reg(i2c->fsi, I2C_FSI_MODE, &mode);
+}
+
+static int fsi_i2c_reset_bus(struct fsi_i2c_master *i2c,
+                            struct fsi_i2c_port *port)
+{
+       int rc;
+       u32 stat, dummy = 0;
+
+       /* force bus reset, ignore errors */
+       i2c_recover_bus(&port->adapter);
+
+       /* reset errors */
+       rc = fsi_i2c_write_reg(i2c->fsi, I2C_FSI_RESET_ERR, &dummy);
+       if (rc)
+               return rc;
+
+       /* wait for command complete */
+       usleep_range(I2C_RESET_SLEEP_MIN_US, I2C_RESET_SLEEP_MAX_US);
+
+       rc = fsi_i2c_read_reg(i2c->fsi, I2C_FSI_STAT, &stat);
+       if (rc)
+               return rc;
+
+       if (stat & I2C_STAT_CMD_COMP)
+               return 0;
+
+       /* failed to get command complete; reset engine again */
+       rc = fsi_i2c_write_reg(i2c->fsi, I2C_FSI_RESET_I2C, &dummy);
+       if (rc)
+               return rc;
+
+       /* re-init engine again */
+       return fsi_i2c_dev_init(i2c);
+}
+
+static int fsi_i2c_reset_engine(struct fsi_i2c_master *i2c, u16 port)
+{
+       int rc;
+       u32 mode, dummy = 0;
+
+       /* reset engine */
+       rc = fsi_i2c_write_reg(i2c->fsi, I2C_FSI_RESET_I2C, &dummy);
+       if (rc)
+               return rc;
+
+       /* re-init engine */
+       rc = fsi_i2c_dev_init(i2c);
+       if (rc)
+               return rc;
+
+       rc = fsi_i2c_read_reg(i2c->fsi, I2C_FSI_MODE, &mode);
+       if (rc)
+               return rc;
+
+       /* set port; default after reset is 0 */
+       if (port) {
+               mode &= ~I2C_MODE_PORT;
+               mode |= FIELD_PREP(I2C_MODE_PORT, port);
+               rc = fsi_i2c_write_reg(i2c->fsi, I2C_FSI_MODE, &mode);
+               if (rc)
+                       return rc;
+       }
+
+       /* reset busy register; hw workaround */
+       dummy = I2C_PORT_BUSY_RESET;
+       rc = fsi_i2c_write_reg(i2c->fsi, I2C_FSI_PORT_BUSY, &dummy);
+       if (rc)
+               return rc;
+
+       return 0;
+}
+
+static int fsi_i2c_abort(struct fsi_i2c_port *port, u32 status)
+{
+       int rc;
+       unsigned long start;
+       u32 cmd = I2C_CMD_WITH_STOP;
+       u32 stat;
+       struct fsi_i2c_master *i2c = port->master;
+       struct fsi_device *fsi = i2c->fsi;
+
+       rc = fsi_i2c_reset_engine(i2c, port->port);
+       if (rc)
+               return rc;
+
+       rc = fsi_i2c_read_reg(fsi, I2C_FSI_STAT, &stat);
+       if (rc)
+               return rc;
+
+       /* if sda is low, peform full bus reset */
+       if (!(stat & I2C_STAT_SDA_IN)) {
+               rc = fsi_i2c_reset_bus(i2c, port);
+               if (rc)
+                       return rc;
+       }
+
+       /* skip final stop command for these errors */
+       if (status & (I2C_STAT_PARITY | I2C_STAT_LOST_ARB | I2C_STAT_STOP_ERR))
+               return 0;
+
+       /* write stop command */
+       rc = fsi_i2c_write_reg(fsi, I2C_FSI_CMD, &cmd);
+       if (rc)
+               return rc;
+
+       /* wait until we see command complete in the master */
+       start = jiffies;
+
+       do {
+               rc = fsi_i2c_read_reg(fsi, I2C_FSI_STAT, &status);
+               if (rc)
+                       return rc;
+
+               if (status & I2C_STAT_CMD_COMP)
+                       return 0;
+
+               usleep_range(I2C_CMD_SLEEP_MIN_US, I2C_CMD_SLEEP_MAX_US);
+       } while (time_after(start + I2C_ABORT_TIMEOUT, jiffies));
+
+       return -ETIMEDOUT;
+}
+
+static int fsi_i2c_handle_status(struct fsi_i2c_port *port,
+                                struct i2c_msg *msg, u32 status)
+{
+       int rc;
+       u8 fifo_count;
+
+       if (status & I2C_STAT_ERR) {
+               rc = fsi_i2c_abort(port, status);
+               if (rc)
+                       return rc;
+
+               if (status & I2C_STAT_INV_CMD)
+                       return -EINVAL;
+
+               if (status & (I2C_STAT_PARITY | I2C_STAT_BE_OVERRUN |
+                   I2C_STAT_BE_ACCESS))
+                       return -EPROTO;
+
+               if (status & I2C_STAT_NACK)
+                       return -ENXIO;
+
+               if (status & I2C_STAT_LOST_ARB)
+                       return -EAGAIN;
+
+               if (status & I2C_STAT_STOP_ERR)
+                       return -EBADMSG;
+
+               return -EIO;
+       }
+
+       if (status & I2C_STAT_DAT_REQ) {
+               fifo_count = FIELD_GET(I2C_STAT_FIFO_COUNT, status);
+
+               if (msg->flags & I2C_M_RD)
+                       return fsi_i2c_read_fifo(port, msg, fifo_count);
+
+               return fsi_i2c_write_fifo(port, msg, fifo_count);
+       }
+
+       if (status & I2C_STAT_CMD_COMP) {
+               if (port->xfrd < msg->len)
+                       return -ENODATA;
+
+               return msg->len;
+       }
+
+       return 0;
+}
+
+static int fsi_i2c_wait(struct fsi_i2c_port *port, struct i2c_msg *msg,
+                       unsigned long timeout)
+{
+       u32 status = 0;
+       int rc;
+       unsigned long start = jiffies;
+
+       do {
+               rc = fsi_i2c_read_reg(port->master->fsi, I2C_FSI_STAT,
+                                     &status);
+               if (rc)
+                       return rc;
+
+               if (status & I2C_STAT_ANY_RESP) {
+                       rc = fsi_i2c_handle_status(port, msg, status);
+                       if (rc < 0)
+                               return rc;
+
+                       /* cmd complete and all data xfrd */
+                       if (rc == msg->len)
+                               return 0;
+
+                       /* need to xfr more data, but maybe don't need wait */
+                       continue;
+               }
+
+               usleep_range(I2C_CMD_SLEEP_MIN_US, I2C_CMD_SLEEP_MAX_US);
+       } while (time_after(start + timeout, jiffies));
+
+       return -ETIMEDOUT;
+}
+
+static int fsi_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
+                       int num)
+{
+       int i, rc;
+       unsigned long start_time;
+       struct fsi_i2c_port *port = adap->algo_data;
+       struct fsi_i2c_master *master = port->master;
+       struct i2c_msg *msg;
+
+       mutex_lock(&master->lock);
+
+       rc = fsi_i2c_set_port(port);
+       if (rc)
+               goto unlock;
+
+       for (i = 0; i < num; i++) {
+               msg = msgs + i;
+               start_time = jiffies;
+
+               rc = fsi_i2c_start(port, msg, i == num - 1);
+               if (rc)
+                       goto unlock;
+
+               rc = fsi_i2c_wait(port, msg,
+                                 adap->timeout - (jiffies - start_time));
+               if (rc)
+                       goto unlock;
+       }
+
+unlock:
+       mutex_unlock(&master->lock);
+       return rc ? : num;
+}
+
+static u32 fsi_i2c_functionality(struct i2c_adapter *adap)
+{
+       return I2C_FUNC_I2C | I2C_FUNC_PROTOCOL_MANGLING |
+               I2C_FUNC_SMBUS_EMUL | I2C_FUNC_SMBUS_BLOCK_DATA;
+}
+
+static struct i2c_bus_recovery_info fsi_i2c_bus_recovery_info = {
+       .recover_bus = i2c_generic_scl_recovery,
+       .get_scl = fsi_i2c_get_scl,
+       .set_scl = fsi_i2c_set_scl,
+       .get_sda = fsi_i2c_get_sda,
+       .set_sda = fsi_i2c_set_sda,
+       .prepare_recovery = fsi_i2c_prepare_recovery,
+       .unprepare_recovery = fsi_i2c_unprepare_recovery,
+};
+
+static const struct i2c_algorithm fsi_i2c_algorithm = {
+       .master_xfer = fsi_i2c_xfer,
+       .functionality = fsi_i2c_functionality,
+};
+
+static int fsi_i2c_probe(struct device *dev)
+{
+       struct fsi_i2c_master *i2c;
+       struct fsi_i2c_port *port;
+       struct device_node *np;
+       int rc;
+       u32 port_no;
+
+       i2c = devm_kzalloc(dev, sizeof(*i2c), GFP_KERNEL);
+       if (!i2c)
+               return -ENOMEM;
+
+       mutex_init(&i2c->lock);
+       i2c->fsi = to_fsi_dev(dev);
+       INIT_LIST_HEAD(&i2c->ports);
+
+       rc = fsi_i2c_dev_init(i2c);
+       if (rc)
+               return rc;
+
+       /* Add adapter for each i2c port of the master. */
+       for_each_available_child_of_node(dev->of_node, np) {
+               rc = of_property_read_u32(np, "reg", &port_no);
+               if (rc || port_no > USHRT_MAX)
+                       continue;
+
+               port = kzalloc(sizeof(*port), GFP_KERNEL);
+               if (!port)
+                       break;
+
+               port->master = i2c;
+               port->port = port_no;
+
+               port->adapter.owner = THIS_MODULE;
+               port->adapter.dev.of_node = np;
+               port->adapter.dev.parent = dev;
+               port->adapter.algo = &fsi_i2c_algorithm;
+               port->adapter.bus_recovery_info = &fsi_i2c_bus_recovery_info;
+               port->adapter.algo_data = port;
+
+               snprintf(port->adapter.name, sizeof(port->adapter.name),
+                        "i2c_bus-%u", port_no);
+
+               rc = i2c_add_adapter(&port->adapter);
+               if (rc < 0) {
+                       dev_err(dev, "Failed to register adapter: %d\n", rc);
+                       kfree(port);
+                       continue;
+               }
+
+               list_add(&port->list, &i2c->ports);
+       }
+
+       dev_set_drvdata(dev, i2c);
+
+       return 0;
+}
+
+static int fsi_i2c_remove(struct device *dev)
+{
+       struct fsi_i2c_master *i2c = dev_get_drvdata(dev);
+       struct fsi_i2c_port *port, *tmp;
+
+       list_for_each_entry_safe(port, tmp, &i2c->ports, list) {
+               list_del(&port->list);
+               i2c_del_adapter(&port->adapter);
+               kfree(port);
+       }
+
+       return 0;
+}
+
+static const struct fsi_device_id fsi_i2c_ids[] = {
+       { FSI_ENGID_I2C, FSI_VERSION_ANY },
+       { }
+};
+
+static struct fsi_driver fsi_i2c_driver = {
+       .id_table = fsi_i2c_ids,
+       .drv = {
+               .name = "i2c-fsi",
+               .bus = &fsi_bus_type,
+               .probe = fsi_i2c_probe,
+               .remove = fsi_i2c_remove,
+       },
+};
+
+module_fsi_driver(fsi_i2c_driver);
+
+MODULE_AUTHOR("Eddie James <eajames@us.ibm.com>");
+MODULE_DESCRIPTION("FSI attached I2C master");
+MODULE_LICENSE("GPL");
index 66f85bb..c008d20 100644 (file)
@@ -78,49 +78,43 @@ static struct dentry *i2c_gpio_debug_dir;
 #define getscl(bd)     ((bd)->getscl((bd)->data))
 
 #define WIRE_ATTRIBUTE(wire) \
-static int fops_##wire##_get(void *data, u64 *val)     \
-{                                                      \
-       struct i2c_gpio_private_data *priv = data;      \
-                                                       \
-       i2c_lock_adapter(&priv->adap);                  \
-       *val = get##wire(&priv->bit_data);              \
-       i2c_unlock_adapter(&priv->adap);                \
-       return 0;                                       \
-}                                                      \
-static int fops_##wire##_set(void *data, u64 val)      \
-{                                                      \
-       struct i2c_gpio_private_data *priv = data;      \
-                                                       \
-       i2c_lock_adapter(&priv->adap);                  \
-       set##wire(&priv->bit_data, val);                \
-       i2c_unlock_adapter(&priv->adap);                \
-       return 0;                                       \
-}                                                      \
+static int fops_##wire##_get(void *data, u64 *val)             \
+{                                                              \
+       struct i2c_gpio_private_data *priv = data;              \
+                                                               \
+       i2c_lock_bus(&priv->adap, I2C_LOCK_ROOT_ADAPTER);       \
+       *val = get##wire(&priv->bit_data);                      \
+       i2c_unlock_bus(&priv->adap, I2C_LOCK_ROOT_ADAPTER);     \
+       return 0;                                               \
+}                                                              \
+static int fops_##wire##_set(void *data, u64 val)              \
+{                                                              \
+       struct i2c_gpio_private_data *priv = data;              \
+                                                               \
+       i2c_lock_bus(&priv->adap, I2C_LOCK_ROOT_ADAPTER);       \
+       set##wire(&priv->bit_data, val);                        \
+       i2c_unlock_bus(&priv->adap, I2C_LOCK_ROOT_ADAPTER);     \
+       return 0;                                               \
+}                                                              \
 DEFINE_DEBUGFS_ATTRIBUTE(fops_##wire, fops_##wire##_get, fops_##wire##_set, "%llu\n")
 
 WIRE_ATTRIBUTE(scl);
 WIRE_ATTRIBUTE(sda);
 
-static int fops_incomplete_transfer_set(void *data, u64 addr)
+static void i2c_gpio_incomplete_transfer(struct i2c_gpio_private_data *priv,
+                                       u32 pattern, u8 pattern_size)
 {
-       struct i2c_gpio_private_data *priv = data;
        struct i2c_algo_bit_data *bit_data = &priv->bit_data;
-       int i, pattern;
+       int i;
 
-       if (addr > 0x7f)
-               return -EINVAL;
-
-       /* ADDR (7 bit) + RD (1 bit) + SDA hi (1 bit) */
-       pattern = (addr << 2) | 3;
-
-       i2c_lock_adapter(&priv->adap);
+       i2c_lock_bus(&priv->adap, I2C_LOCK_ROOT_ADAPTER);
 
        /* START condition */
        setsda(bit_data, 0);
        udelay(bit_data->udelay);
 
-       /* Send ADDR+RD, request ACK, don't send STOP */
-       for (i = 8; i >= 0; i--) {
+       /* Send pattern, request ACK, don't send STOP */
+       for (i = pattern_size - 1; i >= 0; i--) {
                setscl(bit_data, 0);
                udelay(bit_data->udelay / 2);
                setsda(bit_data, (pattern >> i) & 1);
@@ -129,11 +123,44 @@ static int fops_incomplete_transfer_set(void *data, u64 addr)
                udelay(bit_data->udelay);
        }
 
-       i2c_unlock_adapter(&priv->adap);
+       i2c_unlock_bus(&priv->adap, I2C_LOCK_ROOT_ADAPTER);
+}
+
+static int fops_incomplete_addr_phase_set(void *data, u64 addr)
+{
+       struct i2c_gpio_private_data *priv = data;
+       u32 pattern;
+
+       if (addr > 0x7f)
+               return -EINVAL;
+
+       /* ADDR (7 bit) + RD (1 bit) + Client ACK, keep SDA hi (1 bit) */
+       pattern = (addr << 2) | 3;
+
+       i2c_gpio_incomplete_transfer(priv, pattern, 9);
+
+       return 0;
+}
+DEFINE_DEBUGFS_ATTRIBUTE(fops_incomplete_addr_phase, NULL, fops_incomplete_addr_phase_set, "%llu\n");
+
+static int fops_incomplete_write_byte_set(void *data, u64 addr)
+{
+       struct i2c_gpio_private_data *priv = data;
+       u32 pattern;
+
+       if (addr > 0x7f)
+               return -EINVAL;
+
+       /* ADDR (7 bit) + WR (1 bit) + Client ACK (1 bit) */
+       pattern = (addr << 2) | 1;
+       /* 0x00 (8 bit) + Client ACK, keep SDA hi (1 bit) */
+       pattern = (pattern << 9) | 1;
+
+       i2c_gpio_incomplete_transfer(priv, pattern, 18);
 
        return 0;
 }
-DEFINE_DEBUGFS_ATTRIBUTE(fops_incomplete_transfer, NULL, fops_incomplete_transfer_set, "%llu\n");
+DEFINE_DEBUGFS_ATTRIBUTE(fops_incomplete_write_byte, NULL, fops_incomplete_write_byte_set, "%llu\n");
 
 static void i2c_gpio_fault_injector_init(struct platform_device *pdev)
 {
@@ -156,8 +183,10 @@ static void i2c_gpio_fault_injector_init(struct platform_device *pdev)
 
        debugfs_create_file_unsafe("scl", 0600, priv->debug_dir, priv, &fops_scl);
        debugfs_create_file_unsafe("sda", 0600, priv->debug_dir, priv, &fops_sda);
-       debugfs_create_file_unsafe("incomplete_transfer", 0200, priv->debug_dir,
-                                  priv, &fops_incomplete_transfer);
+       debugfs_create_file_unsafe("incomplete_address_phase", 0200, priv->debug_dir,
+                                  priv, &fops_incomplete_addr_phase);
+       debugfs_create_file_unsafe("incomplete_write_byte", 0200, priv->debug_dir,
+                                  priv, &fops_incomplete_write_byte);
 }
 
 static void i2c_gpio_fault_injector_exit(struct platform_device *pdev)
index 56dc69e..ff340d7 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Renesas Solutions Highlander FPGA I2C/SMBus support.
  *
@@ -6,10 +7,6 @@
  * Copyright (C) 2008  Paul Mundt
  * Copyright (C) 2008  Renesas Solutions Corp.
  * Copyright (C) 2008  Atom Create Engineering Co., Ltd.
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License version 2. See the file "COPYING" in the main directory
- * of this archive for more details.
  */
 #include <linux/module.h>
 #include <linux/interrupt.h>
index aa72660..941c223 100644 (file)
@@ -70,6 +70,7 @@
  * Cannon Lake-H (PCH)         0xa323  32      hard    yes     yes     yes
  * Cannon Lake-LP (PCH)                0x9da3  32      hard    yes     yes     yes
  * Cedar Fork (PCH)            0x18df  32      hard    yes     yes     yes
+ * Ice Lake-LP (PCH)           0x34a3  32      hard    yes     yes     yes
  *
  * Features supported by this driver:
  * Software PEC                                no
 #define PCI_DEVICE_ID_INTEL_DH89XXCC_SMBUS             0x2330
 #define PCI_DEVICE_ID_INTEL_COLETOCREEK_SMBUS          0x23b0
 #define PCI_DEVICE_ID_INTEL_GEMINILAKE_SMBUS           0x31d4
+#define PCI_DEVICE_ID_INTEL_ICELAKE_LP_SMBUS           0x34a3
 #define PCI_DEVICE_ID_INTEL_5_3400_SERIES_SMBUS                0x3b30
 #define PCI_DEVICE_ID_INTEL_BROXTON_SMBUS              0x5ad4
 #define PCI_DEVICE_ID_INTEL_LYNXPOINT_SMBUS            0x8c22
@@ -1034,6 +1036,7 @@ static const struct pci_device_id i801_ids[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_KABYLAKE_PCH_H_SMBUS) },
        { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CANNONLAKE_H_SMBUS) },
        { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CANNONLAKE_LP_SMBUS) },
+       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICELAKE_LP_SMBUS) },
        { 0, }
 };
 
@@ -1518,6 +1521,7 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
        case PCI_DEVICE_ID_INTEL_CDF_SMBUS:
        case PCI_DEVICE_ID_INTEL_DNV_SMBUS:
        case PCI_DEVICE_ID_INTEL_KABYLAKE_PCH_H_SMBUS:
+       case PCI_DEVICE_ID_INTEL_ICELAKE_LP_SMBUS:
                priv->features |= FEATURE_I2C_BLOCK_READ;
                priv->features |= FEATURE_IRQ;
                priv->features |= FEATURE_SMBUS_PEC;
index 498c5e8..c406700 100644 (file)
@@ -421,10 +421,14 @@ static int i2c_imx_bus_busy(struct imx_i2c_struct *i2c_imx, int for_busy)
                        return -EAGAIN;
                }
 
-               if (for_busy && (temp & I2SR_IBB))
+               if (for_busy && (temp & I2SR_IBB)) {
+                       i2c_imx->stopped = 0;
                        break;
-               if (!for_busy && !(temp & I2SR_IBB))
+               }
+               if (!for_busy && !(temp & I2SR_IBB)) {
+                       i2c_imx->stopped = 1;
                        break;
+               }
                if (time_after(jiffies, orig_jiffies + msecs_to_jiffies(500))) {
                        dev_dbg(&i2c_imx->adapter.dev,
                                "<%s> I2C bus is busy\n", __func__);
@@ -538,7 +542,6 @@ static int i2c_imx_start(struct imx_i2c_struct *i2c_imx)
        result = i2c_imx_bus_busy(i2c_imx, 1);
        if (result)
                return result;
-       i2c_imx->stopped = 0;
 
        temp |= I2CR_IIEN | I2CR_MTX | I2CR_TXAK;
        temp &= ~I2CR_DMAEN;
@@ -567,10 +570,8 @@ static void i2c_imx_stop(struct imx_i2c_struct *i2c_imx)
                udelay(i2c_imx->disable_delay);
        }
 
-       if (!i2c_imx->stopped) {
+       if (!i2c_imx->stopped)
                i2c_imx_bus_busy(i2c_imx, 0);
-               i2c_imx->stopped = 1;
-       }
 
        /* Disable I2C controller */
        temp = i2c_imx->hwdata->i2cr_ien_opcode ^ I2CR_IEN,
@@ -668,9 +669,6 @@ static int i2c_imx_dma_read(struct imx_i2c_struct *i2c_imx,
        struct imx_i2c_dma *dma = i2c_imx->dma;
        struct device *dev = &i2c_imx->adapter.dev;
 
-       temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
-       temp |= I2CR_DMAEN;
-       imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
 
        dma->chan_using = dma->chan_rx;
        dma->dma_transfer_dir = DMA_DEV_TO_MEM;
@@ -727,7 +725,6 @@ static int i2c_imx_dma_read(struct imx_i2c_struct *i2c_imx,
                temp &= ~(I2CR_MSTA | I2CR_MTX);
                imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
                i2c_imx_bus_busy(i2c_imx, 0);
-               i2c_imx->stopped = 1;
        } else {
                /*
                 * For i2c master receiver repeat restart operation like:
@@ -783,6 +780,7 @@ static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs, bo
        int i, result;
        unsigned int temp;
        int block_data = msgs->flags & I2C_M_RECV_LEN;
+       int use_dma = i2c_imx->dma && msgs->len >= DMA_THRESHOLD && !block_data;
 
        dev_dbg(&i2c_imx->adapter.dev,
                "<%s> write slave address: addr=0x%x\n",
@@ -809,12 +807,14 @@ static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs, bo
         */
        if ((msgs->len - 1) || block_data)
                temp &= ~I2CR_TXAK;
+       if (use_dma)
+               temp |= I2CR_DMAEN;
        imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
        imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR); /* dummy read */
 
        dev_dbg(&i2c_imx->adapter.dev, "<%s> read data\n", __func__);
 
-       if (i2c_imx->dma && msgs->len >= DMA_THRESHOLD && !block_data)
+       if (use_dma)
                return i2c_imx_dma_read(i2c_imx, msgs, is_lastmsg);
 
        /* read data */
@@ -850,7 +850,6 @@ static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs, bo
                                temp &= ~(I2CR_MSTA | I2CR_MTX);
                                imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
                                i2c_imx_bus_busy(i2c_imx, 0);
-                               i2c_imx->stopped = 1;
                        } else {
                                /*
                                 * For i2c master receiver repeat restart operation like:
index 642c589..7d79317 100644 (file)
@@ -567,9 +567,6 @@ static int mxs_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg,
        dev_dbg(i2c->dev, "addr: 0x%04x, len: %d, flags: 0x%x, stop: %d\n",
                msg->addr, msg->len, msg->flags, stop);
 
-       if (msg->len == 0)
-               return -EINVAL;
-
        /*
         * The MX28 I2C IP block can only do PIO READ for transfer of to up
         * 4 bytes of length. The write transfer is not limited as it can use
@@ -683,6 +680,10 @@ static const struct i2c_algorithm mxs_i2c_algo = {
        .functionality = mxs_i2c_func,
 };
 
+static const struct i2c_adapter_quirks mxs_i2c_quirks = {
+       .flags = I2C_AQ_NO_ZERO_LEN,
+};
+
 static void mxs_i2c_derive_timing(struct mxs_i2c_dev *i2c, uint32_t speed)
 {
        /* The I2C block clock runs at 24MHz */
@@ -854,6 +855,7 @@ static int mxs_i2c_probe(struct platform_device *pdev)
        strlcpy(adap->name, "MXS I2C adapter", sizeof(adap->name));
        adap->owner = THIS_MODULE;
        adap->algo = &mxs_i2c_algo;
+       adap->quirks = &mxs_i2c_quirks;
        adap->dev.parent = dev;
        adap->nr = pdev->id;
        adap->dev.of_node = pdev->dev.of_node;
index 88444ef..87f9caa 100644 (file)
@@ -2,7 +2,7 @@
  * i2c-ocores.c: I2C bus driver for OpenCores I2C controller
  * (https://opencores.org/project/i2c/overview)
  *
- * Peter Korsgaard <jacmet@sunsite.dk>
+ * Peter Korsgaard <peter@korsgaard.com>
  *
  * Support for the GRLIB port of the controller by
  * Andreas Larsson <andreas@gaisler.com>
@@ -576,7 +576,7 @@ static struct platform_driver ocores_i2c_driver = {
 
 module_platform_driver(ocores_i2c_driver);
 
-MODULE_AUTHOR("Peter Korsgaard <jacmet@sunsite.dk>");
+MODULE_AUTHOR("Peter Korsgaard <peter@korsgaard.com>");
 MODULE_DESCRIPTION("OpenCores I2C bus driver");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("platform:ocores-i2c");
diff --git a/drivers/i2c/busses/i2c-owl.c b/drivers/i2c/busses/i2c-owl.c
new file mode 100644 (file)
index 0000000..96b4572
--- /dev/null
@@ -0,0 +1,495 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Actions Semiconductor Owl SoC's I2C driver
+ *
+ * Copyright (c) 2014 Actions Semi Inc.
+ * Author: David Liu <liuwei@actions-semi.com>
+ *
+ * Copyright (c) 2018 Linaro Ltd.
+ * Author: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+
+/* I2C registers */
+#define OWL_I2C_REG_CTL                0x0000
+#define OWL_I2C_REG_CLKDIV     0x0004
+#define OWL_I2C_REG_STAT       0x0008
+#define OWL_I2C_REG_ADDR       0x000C
+#define OWL_I2C_REG_TXDAT      0x0010
+#define OWL_I2C_REG_RXDAT      0x0014
+#define OWL_I2C_REG_CMD                0x0018
+#define OWL_I2C_REG_FIFOCTL    0x001C
+#define OWL_I2C_REG_FIFOSTAT   0x0020
+#define OWL_I2C_REG_DATCNT     0x0024
+#define OWL_I2C_REG_RCNT       0x0028
+
+/* I2Cx_CTL Bit Mask */
+#define OWL_I2C_CTL_RB         BIT(1)
+#define OWL_I2C_CTL_GBCC(x)    (((x) & 0x3) << 2)
+#define        OWL_I2C_CTL_GBCC_NONE   OWL_I2C_CTL_GBCC(0)
+#define        OWL_I2C_CTL_GBCC_START  OWL_I2C_CTL_GBCC(1)
+#define        OWL_I2C_CTL_GBCC_STOP   OWL_I2C_CTL_GBCC(2)
+#define        OWL_I2C_CTL_GBCC_RSTART OWL_I2C_CTL_GBCC(3)
+#define OWL_I2C_CTL_IRQE       BIT(5)
+#define OWL_I2C_CTL_EN         BIT(7)
+#define OWL_I2C_CTL_AE         BIT(8)
+#define OWL_I2C_CTL_SHSM       BIT(10)
+
+#define OWL_I2C_DIV_FACTOR(x)  ((x) & 0xff)
+
+/* I2Cx_STAT Bit Mask */
+#define OWL_I2C_STAT_RACK      BIT(0)
+#define OWL_I2C_STAT_BEB       BIT(1)
+#define OWL_I2C_STAT_IRQP      BIT(2)
+#define OWL_I2C_STAT_LAB       BIT(3)
+#define OWL_I2C_STAT_STPD      BIT(4)
+#define OWL_I2C_STAT_STAD      BIT(5)
+#define OWL_I2C_STAT_BBB       BIT(6)
+#define OWL_I2C_STAT_TCB       BIT(7)
+#define OWL_I2C_STAT_LBST      BIT(8)
+#define OWL_I2C_STAT_SAMB      BIT(9)
+#define OWL_I2C_STAT_SRGC      BIT(10)
+
+/* I2Cx_CMD Bit Mask */
+#define OWL_I2C_CMD_SBE                BIT(0)
+#define OWL_I2C_CMD_RBE                BIT(4)
+#define OWL_I2C_CMD_DE         BIT(8)
+#define OWL_I2C_CMD_NS         BIT(9)
+#define OWL_I2C_CMD_SE         BIT(10)
+#define OWL_I2C_CMD_MSS                BIT(11)
+#define OWL_I2C_CMD_WRS                BIT(12)
+#define OWL_I2C_CMD_SECL       BIT(15)
+
+#define OWL_I2C_CMD_AS(x)      (((x) & 0x7) << 1)
+#define OWL_I2C_CMD_SAS(x)     (((x) & 0x7) << 5)
+
+/* I2Cx_FIFOCTL Bit Mask */
+#define OWL_I2C_FIFOCTL_NIB    BIT(0)
+#define OWL_I2C_FIFOCTL_RFR    BIT(1)
+#define OWL_I2C_FIFOCTL_TFR    BIT(2)
+
+/* I2Cc_FIFOSTAT Bit Mask */
+#define OWL_I2C_FIFOSTAT_RNB   BIT(1)
+#define OWL_I2C_FIFOSTAT_RFE   BIT(2)
+#define OWL_I2C_FIFOSTAT_TFF   BIT(5)
+#define OWL_I2C_FIFOSTAT_TFD   GENMASK(23, 16)
+#define OWL_I2C_FIFOSTAT_RFD   GENMASK(15, 8)
+
+/* I2C bus timeout */
+#define OWL_I2C_TIMEOUT                msecs_to_jiffies(4 * 1000)
+
+#define OWL_I2C_MAX_RETRIES    50
+
+#define OWL_I2C_DEF_SPEED_HZ   100000
+#define OWL_I2C_MAX_SPEED_HZ   400000
+
+struct owl_i2c_dev {
+       struct i2c_adapter      adap;
+       struct i2c_msg          *msg;
+       struct completion       msg_complete;
+       struct clk              *clk;
+       spinlock_t              lock;
+       void __iomem            *base;
+       unsigned long           clk_rate;
+       u32                     bus_freq;
+       u32                     msg_ptr;
+       int                     err;
+};
+
+static void owl_i2c_update_reg(void __iomem *reg, unsigned int val, bool state)
+{
+       unsigned int regval;
+
+       regval = readl(reg);
+
+       if (state)
+               regval |= val;
+       else
+               regval &= ~val;
+
+       writel(regval, reg);
+}
+
+static void owl_i2c_reset(struct owl_i2c_dev *i2c_dev)
+{
+       owl_i2c_update_reg(i2c_dev->base + OWL_I2C_REG_CTL,
+                          OWL_I2C_CTL_EN, false);
+       mdelay(1);
+       owl_i2c_update_reg(i2c_dev->base + OWL_I2C_REG_CTL,
+                          OWL_I2C_CTL_EN, true);
+
+       /* Clear status registers */
+       writel(0, i2c_dev->base + OWL_I2C_REG_STAT);
+}
+
+static int owl_i2c_reset_fifo(struct owl_i2c_dev *i2c_dev)
+{
+       unsigned int val, timeout = 0;
+
+       /* Reset FIFO */
+       owl_i2c_update_reg(i2c_dev->base + OWL_I2C_REG_FIFOCTL,
+                          OWL_I2C_FIFOCTL_RFR | OWL_I2C_FIFOCTL_TFR,
+                          true);
+
+       /* Wait 50ms for FIFO reset complete */
+       do {
+               val = readl(i2c_dev->base + OWL_I2C_REG_FIFOCTL);
+               if (!(val & (OWL_I2C_FIFOCTL_RFR | OWL_I2C_FIFOCTL_TFR)))
+                       break;
+               usleep_range(500, 1000);
+       } while (timeout++ < OWL_I2C_MAX_RETRIES);
+
+       if (timeout > OWL_I2C_MAX_RETRIES) {
+               dev_err(&i2c_dev->adap.dev, "FIFO reset timeout\n");
+               return -ETIMEDOUT;
+       }
+
+       return 0;
+}
+
+static void owl_i2c_set_freq(struct owl_i2c_dev *i2c_dev)
+{
+       unsigned int val;
+
+       val = DIV_ROUND_UP(i2c_dev->clk_rate, i2c_dev->bus_freq * 16);
+
+       /* Set clock divider factor */
+       writel(OWL_I2C_DIV_FACTOR(val), i2c_dev->base + OWL_I2C_REG_CLKDIV);
+}
+
+static irqreturn_t owl_i2c_interrupt(int irq, void *_dev)
+{
+       struct owl_i2c_dev *i2c_dev = _dev;
+       struct i2c_msg *msg = i2c_dev->msg;
+       unsigned long flags;
+       unsigned int stat, fifostat;
+
+       spin_lock_irqsave(&i2c_dev->lock, flags);
+
+       i2c_dev->err = 0;
+
+       /* Handle NACK from slave */
+       fifostat = readl(i2c_dev->base + OWL_I2C_REG_FIFOSTAT);
+       if (fifostat & OWL_I2C_FIFOSTAT_RNB) {
+               i2c_dev->err = -ENXIO;
+               goto stop;
+       }
+
+       /* Handle bus error */
+       stat = readl(i2c_dev->base + OWL_I2C_REG_STAT);
+       if (stat & OWL_I2C_STAT_BEB) {
+               i2c_dev->err = -EIO;
+               goto stop;
+       }
+
+       /* Handle FIFO read */
+       if (msg->flags & I2C_M_RD) {
+               while ((readl(i2c_dev->base + OWL_I2C_REG_FIFOSTAT) &
+                       OWL_I2C_FIFOSTAT_RFE) && i2c_dev->msg_ptr < msg->len) {
+                       msg->buf[i2c_dev->msg_ptr++] = readl(i2c_dev->base +
+                                                            OWL_I2C_REG_RXDAT);
+               }
+       } else {
+               /* Handle the remaining bytes which were not sent */
+               while (!(readl(i2c_dev->base + OWL_I2C_REG_FIFOSTAT) &
+                        OWL_I2C_FIFOSTAT_TFF) && i2c_dev->msg_ptr < msg->len) {
+                       writel(msg->buf[i2c_dev->msg_ptr++],
+                              i2c_dev->base + OWL_I2C_REG_TXDAT);
+               }
+       }
+
+stop:
+       /* Clear pending interrupts */
+       owl_i2c_update_reg(i2c_dev->base + OWL_I2C_REG_STAT,
+                          OWL_I2C_STAT_IRQP, true);
+
+       complete_all(&i2c_dev->msg_complete);
+       spin_unlock_irqrestore(&i2c_dev->lock, flags);
+
+       return IRQ_HANDLED;
+}
+
+static u32 owl_i2c_func(struct i2c_adapter *adap)
+{
+       return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+}
+
+static int owl_i2c_check_bus_busy(struct i2c_adapter *adap)
+{
+       struct owl_i2c_dev *i2c_dev = i2c_get_adapdata(adap);
+       unsigned long timeout;
+
+       /* Check for Bus busy */
+       timeout = jiffies + OWL_I2C_TIMEOUT;
+       while (readl(i2c_dev->base + OWL_I2C_REG_STAT) & OWL_I2C_STAT_BBB) {
+               if (time_after(jiffies, timeout)) {
+                       dev_err(&adap->dev, "Bus busy timeout\n");
+                       return -ETIMEDOUT;
+               }
+       }
+
+       return 0;
+}
+
+static int owl_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
+                              int num)
+{
+       struct owl_i2c_dev *i2c_dev = i2c_get_adapdata(adap);
+       struct i2c_msg *msg;
+       unsigned long time_left, flags;
+       unsigned int i2c_cmd, val;
+       unsigned int addr;
+       int ret, idx;
+
+       spin_lock_irqsave(&i2c_dev->lock, flags);
+
+       /* Reset I2C controller */
+       owl_i2c_reset(i2c_dev);
+
+       /* Set bus frequency */
+       owl_i2c_set_freq(i2c_dev);
+
+       /*
+        * Spinlock should be released before calling reset FIFO and
+        * bus busy check since those functions may sleep
+        */
+       spin_unlock_irqrestore(&i2c_dev->lock, flags);
+
+       /* Reset FIFO */
+       ret = owl_i2c_reset_fifo(i2c_dev);
+       if (ret)
+               goto unlocked_err_exit;
+
+       /* Check for bus busy */
+       ret = owl_i2c_check_bus_busy(adap);
+       if (ret)
+               goto unlocked_err_exit;
+
+       spin_lock_irqsave(&i2c_dev->lock, flags);
+
+       /* Check for Arbitration lost */
+       val = readl(i2c_dev->base + OWL_I2C_REG_STAT);
+       if (val & OWL_I2C_STAT_LAB) {
+               val &= ~OWL_I2C_STAT_LAB;
+               writel(val, i2c_dev->base + OWL_I2C_REG_STAT);
+               ret = -EAGAIN;
+               goto err_exit;
+       }
+
+       reinit_completion(&i2c_dev->msg_complete);
+
+       /* Enable I2C controller interrupt */
+       owl_i2c_update_reg(i2c_dev->base + OWL_I2C_REG_CTL,
+                          OWL_I2C_CTL_IRQE, true);
+
+       /*
+        * Select: FIFO enable, Master mode, Stop enable, Data count enable,
+        * Send start bit
+        */
+       i2c_cmd = OWL_I2C_CMD_SECL | OWL_I2C_CMD_MSS | OWL_I2C_CMD_SE |
+                 OWL_I2C_CMD_NS | OWL_I2C_CMD_DE | OWL_I2C_CMD_SBE;
+
+       /* Handle repeated start condition */
+       if (num > 1) {
+               /* Set internal address length and enable repeated start */
+               i2c_cmd |= OWL_I2C_CMD_AS(msgs[0].len + 1) |
+                          OWL_I2C_CMD_SAS(1) | OWL_I2C_CMD_RBE;
+
+               /* Write slave address */
+               addr = i2c_8bit_addr_from_msg(&msgs[0]);
+               writel(addr, i2c_dev->base + OWL_I2C_REG_TXDAT);
+
+               /* Write internal register address */
+               for (idx = 0; idx < msgs[0].len; idx++)
+                       writel(msgs[0].buf[idx],
+                              i2c_dev->base + OWL_I2C_REG_TXDAT);
+
+               msg = &msgs[1];
+       } else {
+               /* Set address length */
+               i2c_cmd |= OWL_I2C_CMD_AS(1);
+               msg = &msgs[0];
+       }
+
+       i2c_dev->msg = msg;
+       i2c_dev->msg_ptr = 0;
+
+       /* Set data count for the message */
+       writel(msg->len, i2c_dev->base + OWL_I2C_REG_DATCNT);
+
+       addr = i2c_8bit_addr_from_msg(msg);
+       writel(addr, i2c_dev->base + OWL_I2C_REG_TXDAT);
+
+       if (!(msg->flags & I2C_M_RD)) {
+               /* Write data to FIFO */
+               for (idx = 0; idx < msg->len; idx++) {
+                       /* Check for FIFO full */
+                       if (readl(i2c_dev->base + OWL_I2C_REG_FIFOSTAT) &
+                           OWL_I2C_FIFOSTAT_TFF)
+                               break;
+
+                       writel(msg->buf[idx],
+                              i2c_dev->base + OWL_I2C_REG_TXDAT);
+               }
+
+               i2c_dev->msg_ptr = idx;
+       }
+
+       /* Ignore the NACK if needed */
+       if (msg->flags & I2C_M_IGNORE_NAK)
+               owl_i2c_update_reg(i2c_dev->base + OWL_I2C_REG_FIFOCTL,
+                                  OWL_I2C_FIFOCTL_NIB, true);
+       else
+               owl_i2c_update_reg(i2c_dev->base + OWL_I2C_REG_FIFOCTL,
+                                  OWL_I2C_FIFOCTL_NIB, false);
+
+       /* Start the transfer */
+       writel(i2c_cmd, i2c_dev->base + OWL_I2C_REG_CMD);
+
+       spin_unlock_irqrestore(&i2c_dev->lock, flags);
+
+       time_left = wait_for_completion_timeout(&i2c_dev->msg_complete,
+                                               adap->timeout);
+
+       spin_lock_irqsave(&i2c_dev->lock, flags);
+       if (time_left == 0) {
+               dev_err(&adap->dev, "Transaction timed out\n");
+               /* Send stop condition and release the bus */
+               owl_i2c_update_reg(i2c_dev->base + OWL_I2C_REG_CTL,
+                                  OWL_I2C_CTL_GBCC_STOP | OWL_I2C_CTL_RB,
+                                  true);
+               ret = -ETIMEDOUT;
+               goto err_exit;
+       }
+
+       ret = i2c_dev->err < 0 ? i2c_dev->err : num;
+
+err_exit:
+       spin_unlock_irqrestore(&i2c_dev->lock, flags);
+
+unlocked_err_exit:
+       /* Disable I2C controller */
+       owl_i2c_update_reg(i2c_dev->base + OWL_I2C_REG_CTL,
+                          OWL_I2C_CTL_EN, false);
+
+       return ret;
+}
+
+static const struct i2c_algorithm owl_i2c_algorithm = {
+       .master_xfer    = owl_i2c_master_xfer,
+       .functionality  = owl_i2c_func,
+};
+
+static const struct i2c_adapter_quirks owl_i2c_quirks = {
+       .flags          = I2C_AQ_COMB | I2C_AQ_COMB_WRITE_FIRST,
+       .max_read_len   = 240,
+       .max_write_len  = 240,
+       .max_comb_1st_msg_len = 6,
+       .max_comb_2nd_msg_len = 240,
+};
+
+static int owl_i2c_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct owl_i2c_dev *i2c_dev;
+       struct resource *res;
+       int ret, irq;
+
+       i2c_dev = devm_kzalloc(dev, sizeof(*i2c_dev), GFP_KERNEL);
+       if (!i2c_dev)
+               return -ENOMEM;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       i2c_dev->base = devm_ioremap_resource(dev, res);
+       if (IS_ERR(i2c_dev->base))
+               return PTR_ERR(i2c_dev->base);
+
+       irq = platform_get_irq(pdev, 0);
+       if (irq < 0) {
+               dev_err(dev, "failed to get IRQ number\n");
+               return irq;
+       }
+
+       if (of_property_read_u32(dev->of_node, "clock-frequency",
+                                &i2c_dev->bus_freq))
+               i2c_dev->bus_freq = OWL_I2C_DEF_SPEED_HZ;
+
+       /* We support only frequencies of 100k and 400k for now */
+       if (i2c_dev->bus_freq != OWL_I2C_DEF_SPEED_HZ &&
+           i2c_dev->bus_freq != OWL_I2C_MAX_SPEED_HZ) {
+               dev_err(dev, "invalid clock-frequency %d\n", i2c_dev->bus_freq);
+               return -EINVAL;
+       }
+
+       i2c_dev->clk = devm_clk_get(dev, NULL);
+       if (IS_ERR(i2c_dev->clk)) {
+               dev_err(dev, "failed to get clock\n");
+               return PTR_ERR(i2c_dev->clk);
+       }
+
+       ret = clk_prepare_enable(i2c_dev->clk);
+       if (ret)
+               return ret;
+
+       i2c_dev->clk_rate = clk_get_rate(i2c_dev->clk);
+       if (!i2c_dev->clk_rate) {
+               dev_err(dev, "input clock rate should not be zero\n");
+               ret = -EINVAL;
+               goto disable_clk;
+       }
+
+       init_completion(&i2c_dev->msg_complete);
+       spin_lock_init(&i2c_dev->lock);
+       i2c_dev->adap.owner = THIS_MODULE;
+       i2c_dev->adap.algo = &owl_i2c_algorithm;
+       i2c_dev->adap.timeout = OWL_I2C_TIMEOUT;
+       i2c_dev->adap.quirks = &owl_i2c_quirks;
+       i2c_dev->adap.dev.parent = dev;
+       i2c_dev->adap.dev.of_node = dev->of_node;
+       snprintf(i2c_dev->adap.name, sizeof(i2c_dev->adap.name),
+                "%s", "OWL I2C adapter");
+       i2c_set_adapdata(&i2c_dev->adap, i2c_dev);
+
+       platform_set_drvdata(pdev, i2c_dev);
+
+       ret = devm_request_irq(dev, irq, owl_i2c_interrupt, 0, pdev->name,
+                              i2c_dev);
+       if (ret) {
+               dev_err(dev, "failed to request irq %d\n", irq);
+               goto disable_clk;
+       }
+
+       return i2c_add_adapter(&i2c_dev->adap);
+
+disable_clk:
+       clk_disable_unprepare(i2c_dev->clk);
+
+       return ret;
+}
+
+static const struct of_device_id owl_i2c_of_match[] = {
+       { .compatible = "actions,s900-i2c" },
+       { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, owl_i2c_of_match);
+
+static struct platform_driver owl_i2c_driver = {
+       .probe          = owl_i2c_probe,
+       .driver         = {
+               .name   = "owl-i2c",
+               .of_match_table = of_match_ptr(owl_i2c_of_match),
+       },
+};
+module_platform_driver(owl_i2c_driver);
+
+MODULE_AUTHOR("David Liu <liuwei@actions-semi.com>");
+MODULE_AUTHOR("Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>");
+MODULE_DESCRIPTION("Actions Semiconductor Owl SoC's I2C driver");
+MODULE_LICENSE("GPL");
index 55fd5c6..50803e5 100644 (file)
@@ -365,7 +365,6 @@ static int pasemi_smb_probe(struct pci_dev *dev,
        smbus->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
        smbus->adapter.algo = &smbus_algorithm;
        smbus->adapter.algo_data = smbus;
-       smbus->adapter.nr = PCI_FUNC(dev->devfn);
 
        /* set up the sysfs linkage to our parent device */
        smbus->adapter.dev.parent = &dev->dev;
@@ -373,7 +372,7 @@ static int pasemi_smb_probe(struct pci_dev *dev,
        reg_write(smbus, REG_CTL, (CTL_MTR | CTL_MRR |
                  (CLK_100K_DIV & CTL_CLK_M)));
 
-       error = i2c_add_numbered_adapter(&smbus->adapter);
+       error = i2c_add_adapter(&smbus->adapter);
        if (error)
                goto out_release_region;
 
index dae8ac6..0829cb6 100644 (file)
@@ -444,16 +444,6 @@ static enum pmcmsptwi_xfer_result pmcmsptwi_xfer_cmd(
 {
        enum pmcmsptwi_xfer_result retval;
 
-       if ((cmd->type == MSP_TWI_CMD_WRITE && cmd->write_len == 0) ||
-           (cmd->type == MSP_TWI_CMD_READ && cmd->read_len == 0) ||
-           (cmd->type == MSP_TWI_CMD_WRITE_READ &&
-           (cmd->read_len == 0 || cmd->write_len == 0))) {
-               dev_err(&pmcmsptwi_adapter.dev,
-                       "%s: Cannot transfer less than 1 byte\n",
-                       __func__);
-               return -EINVAL;
-       }
-
        mutex_lock(&data->lock);
        dev_dbg(&pmcmsptwi_adapter.dev,
                "Setting address to 0x%04x\n", cmd->addr);
@@ -532,11 +522,6 @@ static int pmcmsptwi_master_xfer(struct i2c_adapter *adap,
                cmd.write_data = msg->buf;
        }
 
-       if (msg->len == 0) {
-               dev_err(&adap->dev, "Zero-byte messages unsupported\n");
-               return -EINVAL;
-       }
-
        cmd.addr = msg->addr;
 
        if (msg->flags & I2C_M_TEN) {
@@ -578,7 +563,7 @@ static u32 pmcmsptwi_i2c_func(struct i2c_adapter *adapter)
 }
 
 static const struct i2c_adapter_quirks pmcmsptwi_i2c_quirks = {
-       .flags = I2C_AQ_COMB_WRITE_THEN_READ,
+       .flags = I2C_AQ_COMB_WRITE_THEN_READ | I2C_AQ_NO_ZERO_LEN,
        .max_write_len = MSP_MAX_BYTES_PER_RW,
        .max_read_len = MSP_MAX_BYTES_PER_RW,
        .max_comb_1st_msg_len = MSP_MAX_BYTES_PER_RW,
diff --git a/drivers/i2c/busses/i2c-qcom-geni.c b/drivers/i2c/busses/i2c-qcom-geni.c
new file mode 100644 (file)
index 0000000..36732eb
--- /dev/null
@@ -0,0 +1,673 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+
+#include <linux/clk.h>
+#include <linux/dma-mapping.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/qcom-geni-se.h>
+#include <linux/spinlock.h>
+
+#define SE_I2C_TX_TRANS_LEN            0x26c
+#define SE_I2C_RX_TRANS_LEN            0x270
+#define SE_I2C_SCL_COUNTERS            0x278
+
+#define SE_I2C_ERR  (M_CMD_OVERRUN_EN | M_ILLEGAL_CMD_EN | M_CMD_FAILURE_EN |\
+                       M_GP_IRQ_1_EN | M_GP_IRQ_3_EN | M_GP_IRQ_4_EN)
+#define SE_I2C_ABORT           BIT(1)
+
+/* M_CMD OP codes for I2C */
+#define I2C_WRITE              0x1
+#define I2C_READ               0x2
+#define I2C_WRITE_READ         0x3
+#define I2C_ADDR_ONLY          0x4
+#define I2C_BUS_CLEAR          0x6
+#define I2C_STOP_ON_BUS                0x7
+/* M_CMD params for I2C */
+#define PRE_CMD_DELAY          BIT(0)
+#define TIMESTAMP_BEFORE       BIT(1)
+#define STOP_STRETCH           BIT(2)
+#define TIMESTAMP_AFTER                BIT(3)
+#define POST_COMMAND_DELAY     BIT(4)
+#define IGNORE_ADD_NACK                BIT(6)
+#define READ_FINISHED_WITH_ACK BIT(7)
+#define BYPASS_ADDR_PHASE      BIT(8)
+#define SLV_ADDR_MSK           GENMASK(15, 9)
+#define SLV_ADDR_SHFT          9
+/* I2C SCL COUNTER fields */
+#define HIGH_COUNTER_MSK       GENMASK(29, 20)
+#define HIGH_COUNTER_SHFT      20
+#define LOW_COUNTER_MSK                GENMASK(19, 10)
+#define LOW_COUNTER_SHFT       10
+#define CYCLE_COUNTER_MSK      GENMASK(9, 0)
+
+enum geni_i2c_err_code {
+       GP_IRQ0,
+       NACK,
+       GP_IRQ2,
+       BUS_PROTO,
+       ARB_LOST,
+       GP_IRQ5,
+       GENI_OVERRUN,
+       GENI_ILLEGAL_CMD,
+       GENI_ABORT_DONE,
+       GENI_TIMEOUT,
+};
+
+#define DM_I2C_CB_ERR          ((BIT(NACK) | BIT(BUS_PROTO) | BIT(ARB_LOST)) \
+                                                                       << 5)
+
+#define I2C_AUTO_SUSPEND_DELAY 250
+#define KHZ(freq)              (1000 * freq)
+#define PACKING_BYTES_PW       4
+
+#define ABORT_TIMEOUT          HZ
+#define XFER_TIMEOUT           HZ
+#define RST_TIMEOUT            HZ
+
+struct geni_i2c_dev {
+       struct geni_se se;
+       u32 tx_wm;
+       int irq;
+       int err;
+       struct i2c_adapter adap;
+       struct completion done;
+       struct i2c_msg *cur;
+       int cur_wr;
+       int cur_rd;
+       spinlock_t lock;
+       u32 clk_freq_out;
+       const struct geni_i2c_clk_fld *clk_fld;
+       int suspended;
+};
+
+struct geni_i2c_err_log {
+       int err;
+       const char *msg;
+};
+
+static const struct geni_i2c_err_log gi2c_log[] = {
+       [GP_IRQ0] = {-EIO, "Unknown I2C err GP_IRQ0"},
+       [NACK] = {-ENXIO, "NACK: slv unresponsive, check its power/reset-ln"},
+       [GP_IRQ2] = {-EIO, "Unknown I2C err GP IRQ2"},
+       [BUS_PROTO] = {-EPROTO, "Bus proto err, noisy/unepxected start/stop"},
+       [ARB_LOST] = {-EAGAIN, "Bus arbitration lost, clock line undriveable"},
+       [GP_IRQ5] = {-EIO, "Unknown I2C err GP IRQ5"},
+       [GENI_OVERRUN] = {-EIO, "Cmd overrun, check GENI cmd-state machine"},
+       [GENI_ILLEGAL_CMD] = {-EIO, "Illegal cmd, check GENI cmd-state machine"},
+       [GENI_ABORT_DONE] = {-ETIMEDOUT, "Abort after timeout successful"},
+       [GENI_TIMEOUT] = {-ETIMEDOUT, "I2C TXN timed out"},
+};
+
+struct geni_i2c_clk_fld {
+       u32     clk_freq_out;
+       u8      clk_div;
+       u8      t_high_cnt;
+       u8      t_low_cnt;
+       u8      t_cycle_cnt;
+};
+
+/*
+ * Hardware uses the underlying formula to calculate time periods of
+ * SCL clock cycle. Firmware uses some additional cycles excluded from the
+ * below formula and it is confirmed that the time periods are within
+ * specification limits.
+ *
+ * time of high period of SCL: t_high = (t_high_cnt * clk_div) / source_clock
+ * time of low period of SCL: t_low = (t_low_cnt * clk_div) / source_clock
+ * time of full period of SCL: t_cycle = (t_cycle_cnt * clk_div) / source_clock
+ * clk_freq_out = t / t_cycle
+ * source_clock = 19.2 MHz
+ */
+static const struct geni_i2c_clk_fld geni_i2c_clk_map[] = {
+       {KHZ(100), 7, 10, 11, 26},
+       {KHZ(400), 2,  5, 12, 24},
+       {KHZ(1000), 1, 3,  9, 18},
+};
+
+static int geni_i2c_clk_map_idx(struct geni_i2c_dev *gi2c)
+{
+       int i;
+       const struct geni_i2c_clk_fld *itr = geni_i2c_clk_map;
+
+       for (i = 0; i < ARRAY_SIZE(geni_i2c_clk_map); i++, itr++) {
+               if (itr->clk_freq_out == gi2c->clk_freq_out) {
+                       gi2c->clk_fld = itr;
+                       return 0;
+               }
+       }
+       return -EINVAL;
+}
+
+static void qcom_geni_i2c_conf(struct geni_i2c_dev *gi2c)
+{
+       const struct geni_i2c_clk_fld *itr = gi2c->clk_fld;
+       u32 val;
+
+       writel_relaxed(0, gi2c->se.base + SE_GENI_CLK_SEL);
+
+       val = (itr->clk_div << CLK_DIV_SHFT) | SER_CLK_EN;
+       writel_relaxed(val, gi2c->se.base + GENI_SER_M_CLK_CFG);
+
+       val = itr->t_high_cnt << HIGH_COUNTER_SHFT;
+       val |= itr->t_low_cnt << LOW_COUNTER_SHFT;
+       val |= itr->t_cycle_cnt;
+       writel_relaxed(val, gi2c->se.base + SE_I2C_SCL_COUNTERS);
+}
+
+static void geni_i2c_err_misc(struct geni_i2c_dev *gi2c)
+{
+       u32 m_cmd = readl_relaxed(gi2c->se.base + SE_GENI_M_CMD0);
+       u32 m_stat = readl_relaxed(gi2c->se.base + SE_GENI_M_IRQ_STATUS);
+       u32 geni_s = readl_relaxed(gi2c->se.base + SE_GENI_STATUS);
+       u32 geni_ios = readl_relaxed(gi2c->se.base + SE_GENI_IOS);
+       u32 dma = readl_relaxed(gi2c->se.base + SE_GENI_DMA_MODE_EN);
+       u32 rx_st, tx_st;
+
+       if (dma) {
+               rx_st = readl_relaxed(gi2c->se.base + SE_DMA_RX_IRQ_STAT);
+               tx_st = readl_relaxed(gi2c->se.base + SE_DMA_TX_IRQ_STAT);
+       } else {
+               rx_st = readl_relaxed(gi2c->se.base + SE_GENI_RX_FIFO_STATUS);
+               tx_st = readl_relaxed(gi2c->se.base + SE_GENI_TX_FIFO_STATUS);
+       }
+       dev_dbg(gi2c->se.dev, "DMA:%d tx_stat:0x%x, rx_stat:0x%x, irq-stat:0x%x\n",
+               dma, tx_st, rx_st, m_stat);
+       dev_dbg(gi2c->se.dev, "m_cmd:0x%x, geni_status:0x%x, geni_ios:0x%x\n",
+               m_cmd, geni_s, geni_ios);
+}
+
+static void geni_i2c_err(struct geni_i2c_dev *gi2c, int err)
+{
+       if (!gi2c->err)
+               gi2c->err = gi2c_log[err].err;
+       if (gi2c->cur)
+               dev_dbg(gi2c->se.dev, "len:%d, slv-addr:0x%x, RD/WR:%d\n",
+                       gi2c->cur->len, gi2c->cur->addr, gi2c->cur->flags);
+
+       if (err != NACK && err != GENI_ABORT_DONE) {
+               dev_err(gi2c->se.dev, "%s\n", gi2c_log[err].msg);
+               geni_i2c_err_misc(gi2c);
+       }
+}
+
+static irqreturn_t geni_i2c_irq(int irq, void *dev)
+{
+       struct geni_i2c_dev *gi2c = dev;
+       int j;
+       u32 m_stat;
+       u32 rx_st;
+       u32 dm_tx_st;
+       u32 dm_rx_st;
+       u32 dma;
+       struct i2c_msg *cur;
+       unsigned long flags;
+
+       spin_lock_irqsave(&gi2c->lock, flags);
+       m_stat = readl_relaxed(gi2c->se.base + SE_GENI_M_IRQ_STATUS);
+       rx_st = readl_relaxed(gi2c->se.base + SE_GENI_RX_FIFO_STATUS);
+       dm_tx_st = readl_relaxed(gi2c->se.base + SE_DMA_TX_IRQ_STAT);
+       dm_rx_st = readl_relaxed(gi2c->se.base + SE_DMA_RX_IRQ_STAT);
+       dma = readl_relaxed(gi2c->se.base + SE_GENI_DMA_MODE_EN);
+       cur = gi2c->cur;
+
+       if (!cur ||
+           m_stat & (M_CMD_FAILURE_EN | M_CMD_ABORT_EN) ||
+           dm_rx_st & (DM_I2C_CB_ERR)) {
+               if (m_stat & M_GP_IRQ_1_EN)
+                       geni_i2c_err(gi2c, NACK);
+               if (m_stat & M_GP_IRQ_3_EN)
+                       geni_i2c_err(gi2c, BUS_PROTO);
+               if (m_stat & M_GP_IRQ_4_EN)
+                       geni_i2c_err(gi2c, ARB_LOST);
+               if (m_stat & M_CMD_OVERRUN_EN)
+                       geni_i2c_err(gi2c, GENI_OVERRUN);
+               if (m_stat & M_ILLEGAL_CMD_EN)
+                       geni_i2c_err(gi2c, GENI_ILLEGAL_CMD);
+               if (m_stat & M_CMD_ABORT_EN)
+                       geni_i2c_err(gi2c, GENI_ABORT_DONE);
+               if (m_stat & M_GP_IRQ_0_EN)
+                       geni_i2c_err(gi2c, GP_IRQ0);
+
+               /* Disable the TX Watermark interrupt to stop TX */
+               if (!dma)
+                       writel_relaxed(0, gi2c->se.base +
+                                          SE_GENI_TX_WATERMARK_REG);
+               goto irqret;
+       }
+
+       if (dma) {
+               dev_dbg(gi2c->se.dev, "i2c dma tx:0x%x, dma rx:0x%x\n",
+                       dm_tx_st, dm_rx_st);
+               goto irqret;
+       }
+
+       if (cur->flags & I2C_M_RD &&
+           m_stat & (M_RX_FIFO_WATERMARK_EN | M_RX_FIFO_LAST_EN)) {
+               u32 rxcnt = rx_st & RX_FIFO_WC_MSK;
+
+               for (j = 0; j < rxcnt; j++) {
+                       u32 val;
+                       int p = 0;
+
+                       val = readl_relaxed(gi2c->se.base + SE_GENI_RX_FIFOn);
+                       while (gi2c->cur_rd < cur->len && p < sizeof(val)) {
+                               cur->buf[gi2c->cur_rd++] = val & 0xff;
+                               val >>= 8;
+                               p++;
+                       }
+                       if (gi2c->cur_rd == cur->len)
+                               break;
+               }
+       } else if (!(cur->flags & I2C_M_RD) &&
+                  m_stat & M_TX_FIFO_WATERMARK_EN) {
+               for (j = 0; j < gi2c->tx_wm; j++) {
+                       u32 temp;
+                       u32 val = 0;
+                       int p = 0;
+
+                       while (gi2c->cur_wr < cur->len && p < sizeof(val)) {
+                               temp = cur->buf[gi2c->cur_wr++];
+                               val |= temp << (p * 8);
+                               p++;
+                       }
+                       writel_relaxed(val, gi2c->se.base + SE_GENI_TX_FIFOn);
+                       /* TX Complete, Disable the TX Watermark interrupt */
+                       if (gi2c->cur_wr == cur->len) {
+                               writel_relaxed(0, gi2c->se.base +
+                                               SE_GENI_TX_WATERMARK_REG);
+                               break;
+                       }
+               }
+       }
+irqret:
+       if (m_stat)
+               writel_relaxed(m_stat, gi2c->se.base + SE_GENI_M_IRQ_CLEAR);
+
+       if (dma) {
+               if (dm_tx_st)
+                       writel_relaxed(dm_tx_st, gi2c->se.base +
+                                               SE_DMA_TX_IRQ_CLR);
+               if (dm_rx_st)
+                       writel_relaxed(dm_rx_st, gi2c->se.base +
+                                               SE_DMA_RX_IRQ_CLR);
+       }
+       /* if this is err with done-bit not set, handle that through timeout. */
+       if (m_stat & M_CMD_DONE_EN || m_stat & M_CMD_ABORT_EN)
+               complete(&gi2c->done);
+       else if (dm_tx_st & TX_DMA_DONE || dm_tx_st & TX_RESET_DONE)
+               complete(&gi2c->done);
+       else if (dm_rx_st & RX_DMA_DONE || dm_rx_st & RX_RESET_DONE)
+               complete(&gi2c->done);
+
+       spin_unlock_irqrestore(&gi2c->lock, flags);
+       return IRQ_HANDLED;
+}
+
+static void geni_i2c_abort_xfer(struct geni_i2c_dev *gi2c)
+{
+       u32 val;
+       unsigned long time_left = ABORT_TIMEOUT;
+       unsigned long flags;
+
+       spin_lock_irqsave(&gi2c->lock, flags);
+       geni_i2c_err(gi2c, GENI_TIMEOUT);
+       gi2c->cur = NULL;
+       geni_se_abort_m_cmd(&gi2c->se);
+       spin_unlock_irqrestore(&gi2c->lock, flags);
+       do {
+               time_left = wait_for_completion_timeout(&gi2c->done, time_left);
+               val = readl_relaxed(gi2c->se.base + SE_GENI_M_IRQ_STATUS);
+       } while (!(val & M_CMD_ABORT_EN) && time_left);
+
+       if (!(val & M_CMD_ABORT_EN))
+               dev_err(gi2c->se.dev, "Timeout abort_m_cmd\n");
+}
+
+static void geni_i2c_rx_fsm_rst(struct geni_i2c_dev *gi2c)
+{
+       u32 val;
+       unsigned long time_left = RST_TIMEOUT;
+
+       writel_relaxed(1, gi2c->se.base + SE_DMA_RX_FSM_RST);
+       do {
+               time_left = wait_for_completion_timeout(&gi2c->done, time_left);
+               val = readl_relaxed(gi2c->se.base + SE_DMA_RX_IRQ_STAT);
+       } while (!(val & RX_RESET_DONE) && time_left);
+
+       if (!(val & RX_RESET_DONE))
+               dev_err(gi2c->se.dev, "Timeout resetting RX_FSM\n");
+}
+
+static void geni_i2c_tx_fsm_rst(struct geni_i2c_dev *gi2c)
+{
+       u32 val;
+       unsigned long time_left = RST_TIMEOUT;
+
+       writel_relaxed(1, gi2c->se.base + SE_DMA_TX_FSM_RST);
+       do {
+               time_left = wait_for_completion_timeout(&gi2c->done, time_left);
+               val = readl_relaxed(gi2c->se.base + SE_DMA_TX_IRQ_STAT);
+       } while (!(val & TX_RESET_DONE) && time_left);
+
+       if (!(val & TX_RESET_DONE))
+               dev_err(gi2c->se.dev, "Timeout resetting TX_FSM\n");
+}
+
+static int geni_i2c_rx_one_msg(struct geni_i2c_dev *gi2c, struct i2c_msg *msg,
+                               u32 m_param)
+{
+       dma_addr_t rx_dma;
+       enum geni_se_xfer_mode mode;
+       unsigned long time_left = XFER_TIMEOUT;
+
+       gi2c->cur = msg;
+       mode = msg->len > 32 ? GENI_SE_DMA : GENI_SE_FIFO;
+       geni_se_select_mode(&gi2c->se, mode);
+       writel_relaxed(msg->len, gi2c->se.base + SE_I2C_RX_TRANS_LEN);
+       geni_se_setup_m_cmd(&gi2c->se, I2C_READ, m_param);
+       if (mode == GENI_SE_DMA) {
+               int ret;
+
+               ret = geni_se_rx_dma_prep(&gi2c->se, msg->buf, msg->len,
+                                                               &rx_dma);
+               if (ret) {
+                       mode = GENI_SE_FIFO;
+                       geni_se_select_mode(&gi2c->se, mode);
+               }
+       }
+
+       time_left = wait_for_completion_timeout(&gi2c->done, XFER_TIMEOUT);
+       if (!time_left)
+               geni_i2c_abort_xfer(gi2c);
+
+       gi2c->cur_rd = 0;
+       if (mode == GENI_SE_DMA) {
+               if (gi2c->err)
+                       geni_i2c_rx_fsm_rst(gi2c);
+               geni_se_rx_dma_unprep(&gi2c->se, rx_dma, msg->len);
+       }
+       return gi2c->err;
+}
+
+static int geni_i2c_tx_one_msg(struct geni_i2c_dev *gi2c, struct i2c_msg *msg,
+                               u32 m_param)
+{
+       dma_addr_t tx_dma;
+       enum geni_se_xfer_mode mode;
+       unsigned long time_left;
+
+       gi2c->cur = msg;
+       mode = msg->len > 32 ? GENI_SE_DMA : GENI_SE_FIFO;
+       geni_se_select_mode(&gi2c->se, mode);
+       writel_relaxed(msg->len, gi2c->se.base + SE_I2C_TX_TRANS_LEN);
+       geni_se_setup_m_cmd(&gi2c->se, I2C_WRITE, m_param);
+       if (mode == GENI_SE_DMA) {
+               int ret;
+
+               ret = geni_se_tx_dma_prep(&gi2c->se, msg->buf, msg->len,
+                                                               &tx_dma);
+               if (ret) {
+                       mode = GENI_SE_FIFO;
+                       geni_se_select_mode(&gi2c->se, mode);
+               }
+       }
+
+       if (mode == GENI_SE_FIFO) /* Get FIFO IRQ */
+               writel_relaxed(1, gi2c->se.base + SE_GENI_TX_WATERMARK_REG);
+
+       time_left = wait_for_completion_timeout(&gi2c->done, XFER_TIMEOUT);
+       if (!time_left)
+               geni_i2c_abort_xfer(gi2c);
+
+       gi2c->cur_wr = 0;
+       if (mode == GENI_SE_DMA) {
+               if (gi2c->err)
+                       geni_i2c_tx_fsm_rst(gi2c);
+               geni_se_tx_dma_unprep(&gi2c->se, tx_dma, msg->len);
+       }
+       return gi2c->err;
+}
+
+static int geni_i2c_xfer(struct i2c_adapter *adap,
+                        struct i2c_msg msgs[],
+                        int num)
+{
+       struct geni_i2c_dev *gi2c = i2c_get_adapdata(adap);
+       int i, ret;
+
+       gi2c->err = 0;
+       reinit_completion(&gi2c->done);
+       ret = pm_runtime_get_sync(gi2c->se.dev);
+       if (ret < 0) {
+               dev_err(gi2c->se.dev, "error turning SE resources:%d\n", ret);
+               pm_runtime_put_noidle(gi2c->se.dev);
+               /* Set device in suspended since resume failed */
+               pm_runtime_set_suspended(gi2c->se.dev);
+               return ret;
+       }
+
+       qcom_geni_i2c_conf(gi2c);
+       for (i = 0; i < num; i++) {
+               u32 m_param = i < (num - 1) ? STOP_STRETCH : 0;
+
+               m_param |= ((msgs[i].addr << SLV_ADDR_SHFT) & SLV_ADDR_MSK);
+
+               if (msgs[i].flags & I2C_M_RD)
+                       ret = geni_i2c_rx_one_msg(gi2c, &msgs[i], m_param);
+               else
+                       ret = geni_i2c_tx_one_msg(gi2c, &msgs[i], m_param);
+
+               if (ret)
+                       break;
+       }
+       if (ret == 0)
+               ret = num;
+
+       pm_runtime_mark_last_busy(gi2c->se.dev);
+       pm_runtime_put_autosuspend(gi2c->se.dev);
+       gi2c->cur = NULL;
+       gi2c->err = 0;
+       return ret;
+}
+
+static u32 geni_i2c_func(struct i2c_adapter *adap)
+{
+       return I2C_FUNC_I2C | (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK);
+}
+
+static const struct i2c_algorithm geni_i2c_algo = {
+       .master_xfer    = geni_i2c_xfer,
+       .functionality  = geni_i2c_func,
+};
+
+static int geni_i2c_probe(struct platform_device *pdev)
+{
+       struct geni_i2c_dev *gi2c;
+       struct resource *res;
+       u32 proto, tx_depth;
+       int ret;
+
+       gi2c = devm_kzalloc(&pdev->dev, sizeof(*gi2c), GFP_KERNEL);
+       if (!gi2c)
+               return -ENOMEM;
+
+       gi2c->se.dev = &pdev->dev;
+       gi2c->se.wrapper = dev_get_drvdata(pdev->dev.parent);
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       gi2c->se.base = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(gi2c->se.base))
+               return PTR_ERR(gi2c->se.base);
+
+       gi2c->se.clk = devm_clk_get(&pdev->dev, "se");
+       if (IS_ERR(gi2c->se.clk)) {
+               ret = PTR_ERR(gi2c->se.clk);
+               dev_err(&pdev->dev, "Err getting SE Core clk %d\n", ret);
+               return ret;
+       }
+
+       ret = device_property_read_u32(&pdev->dev, "clock-frequency",
+                                                       &gi2c->clk_freq_out);
+       if (ret) {
+               dev_info(&pdev->dev,
+                       "Bus frequency not specified, default to 100kHz.\n");
+               gi2c->clk_freq_out = KHZ(100);
+       }
+
+       gi2c->irq = platform_get_irq(pdev, 0);
+       if (gi2c->irq < 0) {
+               dev_err(&pdev->dev, "IRQ error for i2c-geni\n");
+               return gi2c->irq;
+       }
+
+       ret = geni_i2c_clk_map_idx(gi2c);
+       if (ret) {
+               dev_err(&pdev->dev, "Invalid clk frequency %d Hz: %d\n",
+                       gi2c->clk_freq_out, ret);
+               return ret;
+       }
+
+       gi2c->adap.algo = &geni_i2c_algo;
+       init_completion(&gi2c->done);
+       spin_lock_init(&gi2c->lock);
+       platform_set_drvdata(pdev, gi2c);
+       ret = devm_request_irq(&pdev->dev, gi2c->irq, geni_i2c_irq,
+                              IRQF_TRIGGER_HIGH, "i2c_geni", gi2c);
+       if (ret) {
+               dev_err(&pdev->dev, "Request_irq failed:%d: err:%d\n",
+                       gi2c->irq, ret);
+               return ret;
+       }
+       /* Disable the interrupt so that the system can enter low-power mode */
+       disable_irq(gi2c->irq);
+       i2c_set_adapdata(&gi2c->adap, gi2c);
+       gi2c->adap.dev.parent = &pdev->dev;
+       gi2c->adap.dev.of_node = pdev->dev.of_node;
+       strlcpy(gi2c->adap.name, "Geni-I2C", sizeof(gi2c->adap.name));
+
+       ret = geni_se_resources_on(&gi2c->se);
+       if (ret) {
+               dev_err(&pdev->dev, "Error turning on resources %d\n", ret);
+               return ret;
+       }
+       proto = geni_se_read_proto(&gi2c->se);
+       tx_depth = geni_se_get_tx_fifo_depth(&gi2c->se);
+       if (proto != GENI_SE_I2C) {
+               dev_err(&pdev->dev, "Invalid proto %d\n", proto);
+               geni_se_resources_off(&gi2c->se);
+               return -ENXIO;
+       }
+       gi2c->tx_wm = tx_depth - 1;
+       geni_se_init(&gi2c->se, gi2c->tx_wm, tx_depth);
+       geni_se_config_packing(&gi2c->se, BITS_PER_BYTE, PACKING_BYTES_PW,
+                                                       true, true, true);
+       ret = geni_se_resources_off(&gi2c->se);
+       if (ret) {
+               dev_err(&pdev->dev, "Error turning off resources %d\n", ret);
+               return ret;
+       }
+
+       dev_dbg(&pdev->dev, "i2c fifo/se-dma mode. fifo depth:%d\n", tx_depth);
+
+       ret = i2c_add_adapter(&gi2c->adap);
+       if (ret) {
+               dev_err(&pdev->dev, "Error adding i2c adapter %d\n", ret);
+               return ret;
+       }
+
+       gi2c->suspended = 1;
+       pm_runtime_set_suspended(gi2c->se.dev);
+       pm_runtime_set_autosuspend_delay(gi2c->se.dev, I2C_AUTO_SUSPEND_DELAY);
+       pm_runtime_use_autosuspend(gi2c->se.dev);
+       pm_runtime_enable(gi2c->se.dev);
+
+       return 0;
+}
+
+static int geni_i2c_remove(struct platform_device *pdev)
+{
+       struct geni_i2c_dev *gi2c = platform_get_drvdata(pdev);
+
+       pm_runtime_disable(gi2c->se.dev);
+       i2c_del_adapter(&gi2c->adap);
+       return 0;
+}
+
+static int __maybe_unused geni_i2c_runtime_suspend(struct device *dev)
+{
+       int ret;
+       struct geni_i2c_dev *gi2c = dev_get_drvdata(dev);
+
+       disable_irq(gi2c->irq);
+       ret = geni_se_resources_off(&gi2c->se);
+       if (ret) {
+               enable_irq(gi2c->irq);
+               return ret;
+
+       } else {
+               gi2c->suspended = 1;
+       }
+
+       return 0;
+}
+
+static int __maybe_unused geni_i2c_runtime_resume(struct device *dev)
+{
+       int ret;
+       struct geni_i2c_dev *gi2c = dev_get_drvdata(dev);
+
+       ret = geni_se_resources_on(&gi2c->se);
+       if (ret)
+               return ret;
+
+       enable_irq(gi2c->irq);
+       gi2c->suspended = 0;
+       return 0;
+}
+
+static int __maybe_unused geni_i2c_suspend_noirq(struct device *dev)
+{
+       struct geni_i2c_dev *gi2c = dev_get_drvdata(dev);
+
+       if (!gi2c->suspended) {
+               geni_i2c_runtime_suspend(dev);
+               pm_runtime_disable(dev);
+               pm_runtime_set_suspended(dev);
+               pm_runtime_enable(dev);
+       }
+       return 0;
+}
+
+static const struct dev_pm_ops geni_i2c_pm_ops = {
+       SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(geni_i2c_suspend_noirq, NULL)
+       SET_RUNTIME_PM_OPS(geni_i2c_runtime_suspend, geni_i2c_runtime_resume,
+                                                                       NULL)
+};
+
+static const struct of_device_id geni_i2c_dt_match[] = {
+       { .compatible = "qcom,geni-i2c" },
+       {}
+};
+MODULE_DEVICE_TABLE(of, geni_i2c_dt_match);
+
+static struct platform_driver geni_i2c_driver = {
+       .probe  = geni_i2c_probe,
+       .remove = geni_i2c_remove,
+       .driver = {
+               .name = "geni_i2c",
+               .pm = &geni_i2c_pm_ops,
+               .of_match_table = geni_i2c_dt_match,
+       },
+};
+
+module_platform_driver(geni_i2c_driver);
+
+MODULE_DESCRIPTION("I2C Controller Driver for GENI based QUP cores");
+MODULE_LICENSE("GPL v2");
index 3c1c817..52cf42b 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Driver for the Renesas R-Car I2C unit
  *
@@ -9,16 +10,8 @@
  *
  * This file is based on the drivers/i2c/busses/i2c-sh7760.c
  * (c) 2005-2008 MSC Vertriebsges.m.b.H, Manuel Lauss <mlau@msc-ge.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * 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/bitops.h>
 #include <linux/clk.h>
 #include <linux/delay.h>
 #include <linux/dmaengine.h>
 #define ID_ARBLOST     (1 << 3)
 #define ID_NACK                (1 << 4)
 /* persistent flags */
-#define ID_P_NO_RXDMA  (1 << 30) /* HW forbids RXDMA sometimes */
-#define ID_P_PM_BLOCKED        (1 << 31)
-#define ID_P_MASK      (ID_P_PM_BLOCKED | ID_P_NO_RXDMA)
+#define ID_P_REP_AFTER_RD      BIT(29)
+#define ID_P_NO_RXDMA          BIT(30) /* HW forbids RXDMA sometimes */
+#define ID_P_PM_BLOCKED                BIT(31)
+#define ID_P_MASK              GENMASK(31, 29)
 
 enum rcar_i2c_type {
        I2C_RCAR_GEN1,
@@ -183,8 +177,6 @@ static void rcar_i2c_set_scl(struct i2c_adapter *adap, int val)
        rcar_i2c_write(priv, ICMCR, priv->recovery_icmcr);
 };
 
-/* No get_sda, because the HW only reports its bus free logic, not SDA itself */
-
 static void rcar_i2c_set_sda(struct i2c_adapter *adap, int val)
 {
        struct rcar_i2c_priv *priv = i2c_get_adapdata(adap);
@@ -197,10 +189,19 @@ static void rcar_i2c_set_sda(struct i2c_adapter *adap, int val)
        rcar_i2c_write(priv, ICMCR, priv->recovery_icmcr);
 };
 
+static int rcar_i2c_get_bus_free(struct i2c_adapter *adap)
+{
+       struct rcar_i2c_priv *priv = i2c_get_adapdata(adap);
+
+       return !(rcar_i2c_read(priv, ICMCR) & FSDA);
+
+};
+
 static struct i2c_bus_recovery_info rcar_i2c_bri = {
        .get_scl = rcar_i2c_get_scl,
        .set_scl = rcar_i2c_set_scl,
        .set_sda = rcar_i2c_set_sda,
+       .get_bus_free = rcar_i2c_get_bus_free,
        .recover_bus = i2c_generic_scl_recovery,
 };
 static void rcar_i2c_init(struct rcar_i2c_priv *priv)
@@ -215,7 +216,7 @@ static void rcar_i2c_init(struct rcar_i2c_priv *priv)
 
 static int rcar_i2c_bus_barrier(struct rcar_i2c_priv *priv)
 {
-       int i, ret;
+       int i;
 
        for (i = 0; i < LOOP_TIMEOUT; i++) {
                /* make sure that bus is not busy */
@@ -226,13 +227,7 @@ static int rcar_i2c_bus_barrier(struct rcar_i2c_priv *priv)
 
        /* Waiting did not help, try to recover */
        priv->recovery_icmcr = MDBS | OBPC | FSDA | FSCL;
-       ret = i2c_recover_bus(&priv->adap);
-
-       /* No failure when recovering, so check bus busy bit again */
-       if (ret == 0)
-               ret = (rcar_i2c_read(priv, ICMCR) & FSDA) ? -EBUSY : 0;
-
-       return ret;
+       return i2c_recover_bus(&priv->adap);
 }
 
 static int rcar_i2c_clock_calculate(struct rcar_i2c_priv *priv, struct i2c_timings *t)
@@ -343,7 +338,10 @@ static void rcar_i2c_prepare_msg(struct rcar_i2c_priv *priv)
                rcar_i2c_write(priv, ICMSR, 0);
                rcar_i2c_write(priv, ICMCR, RCAR_BUS_PHASE_START);
        } else {
-               rcar_i2c_write(priv, ICMCR, RCAR_BUS_PHASE_START);
+               if (priv->flags & ID_P_REP_AFTER_RD)
+                       priv->flags &= ~ID_P_REP_AFTER_RD;
+               else
+                       rcar_i2c_write(priv, ICMCR, RCAR_BUS_PHASE_START);
                rcar_i2c_write(priv, ICMSR, 0);
        }
        rcar_i2c_write(priv, ICMIER, read ? RCAR_IRQ_RECV : RCAR_IRQ_SEND);
@@ -548,15 +546,15 @@ static void rcar_i2c_irq_recv(struct rcar_i2c_priv *priv, u32 msr)
                priv->pos++;
        }
 
-       /*
-        * If next received data is the _LAST_, go to STOP phase. Might be
-        * overwritten by REP START when setting up a new msg. Not elegant
-        * but the only stable sequence for REP START I have found so far.
-        * If you want to change this code, make sure sending one transfer with
-        * four messages (WR-RD-WR-RD) works!
-        */
-       if (priv->pos + 1 >= msg->len)
-               rcar_i2c_write(priv, ICMCR, RCAR_BUS_PHASE_STOP);
+       /* If next received data is the _LAST_, go to new phase. */
+       if (priv->pos + 1 == msg->len) {
+               if (priv->flags & ID_LAST_MSG) {
+                       rcar_i2c_write(priv, ICMCR, RCAR_BUS_PHASE_STOP);
+               } else {
+                       rcar_i2c_write(priv, ICMCR, RCAR_BUS_PHASE_START);
+                       priv->flags |= ID_P_REP_AFTER_RD;
+               }
+       }
 
        if (priv->pos == msg->len && !(priv->flags & ID_LAST_MSG))
                rcar_i2c_next_msg(priv);
@@ -624,9 +622,11 @@ static irqreturn_t rcar_i2c_irq(int irq, void *ptr)
        struct rcar_i2c_priv *priv = ptr;
        u32 msr, val;
 
-       /* Clear START or STOP as soon as we can */
-       val = rcar_i2c_read(priv, ICMCR);
-       rcar_i2c_write(priv, ICMCR, val & RCAR_BUS_MASK_DATA);
+       /* Clear START or STOP immediately, except for REPSTART after read */
+       if (likely(!(priv->flags & ID_P_REP_AFTER_RD))) {
+               val = rcar_i2c_read(priv, ICMCR);
+               rcar_i2c_write(priv, ICMCR, val & RCAR_BUS_MASK_DATA);
+       }
 
        msr = rcar_i2c_read(priv, ICMSR);
 
@@ -795,14 +795,8 @@ static int rcar_i2c_master_xfer(struct i2c_adapter *adap,
        if (ret < 0)
                goto out;
 
-       for (i = 0; i < num; i++) {
-               /* This HW can't send STOP after address phase */
-               if (msgs[i].len == 0) {
-                       ret = -EOPNOTSUPP;
-                       goto out;
-               }
+       for (i = 0; i < num; i++)
                rcar_i2c_request_dma(priv, msgs + i);
-       }
 
        /* init first message */
        priv->msg = msgs;
@@ -889,6 +883,10 @@ static const struct i2c_algorithm rcar_i2c_algo = {
        .unreg_slave    = rcar_unreg_slave,
 };
 
+static const struct i2c_adapter_quirks rcar_i2c_quirks = {
+       .flags = I2C_AQ_NO_ZERO_LEN,
+};
+
 static const struct of_device_id rcar_i2c_dt_ids[] = {
        { .compatible = "renesas,i2c-r8a7778", .data = (void *)I2C_RCAR_GEN1 },
        { .compatible = "renesas,i2c-r8a7779", .data = (void *)I2C_RCAR_GEN1 },
@@ -942,6 +940,7 @@ static int rcar_i2c_probe(struct platform_device *pdev)
        adap->dev.parent = dev;
        adap->dev.of_node = dev->of_node;
        adap->bus_recovery_info = &rcar_i2c_bri;
+       adap->quirks = &rcar_i2c_quirks;
        i2c_set_adapdata(adap, priv);
        strlcpy(adap->name, pdev->name, sizeof(adap->name));
 
index 5f1fca7..b75ff14 100644 (file)
@@ -1,12 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Renesas RIIC driver
  *
  * Copyright (C) 2013 Wolfram Sang <wsa@sang-engineering.com>
  * Copyright (C) 2013 Renesas Solutions Corp.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
  */
 
 /*
index 9fe2b69..2f2e28d 100644 (file)
@@ -919,9 +919,9 @@ static int s3c24xx_i2c_cpufreq_transition(struct notifier_block *nb,
 
        if ((val == CPUFREQ_POSTCHANGE && delta_f < 0) ||
            (val == CPUFREQ_PRECHANGE && delta_f > 0)) {
-               i2c_lock_adapter(&i2c->adap);
+               i2c_lock_bus(&i2c->adap, I2C_LOCK_ROOT_ADAPTER);
                ret = s3c24xx_i2c_clockrate(i2c, &got);
-               i2c_unlock_adapter(&i2c->adap);
+               i2c_unlock_bus(&i2c->adap, I2C_LOCK_ROOT_ADAPTER);
 
                if (ret < 0)
                        dev_err(i2c->dev, "cannot find frequency (%d)\n", ret);
index 5fda418..439e877 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * SuperH Mobile I2C Controller
  *
@@ -7,15 +8,6 @@
  *
  * Portions of the code based on out-of-tree driver i2c-sh7343.c
  * Copyright (c) 2006 Carlos Munoz <carlos@kenati.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 #include <linux/clk.h>
@@ -613,11 +605,6 @@ static void sh_mobile_i2c_xfer_dma(struct sh_mobile_i2c_data *pd)
 static int start_ch(struct sh_mobile_i2c_data *pd, struct i2c_msg *usr_msg,
                    bool do_init)
 {
-       if (usr_msg->len == 0 && (usr_msg->flags & I2C_M_RD)) {
-               dev_err(pd->dev, "Unsupported zero length i2c read\n");
-               return -EOPNOTSUPP;
-       }
-
        if (do_init) {
                /* Initialize channel registers */
                iic_wr(pd, ICCR, ICCR_SCP);
@@ -758,6 +745,10 @@ static const struct i2c_algorithm sh_mobile_i2c_algorithm = {
        .master_xfer    = sh_mobile_i2c_xfer,
 };
 
+static const struct i2c_adapter_quirks sh_mobile_i2c_quirks = {
+       .flags = I2C_AQ_NO_ZERO_LEN_READ,
+};
+
 /*
  * r8a7740 chip has lasting errata on I2C I/O pad reset.
  * this is work-around for it.
@@ -925,6 +916,7 @@ static int sh_mobile_i2c_probe(struct platform_device *dev)
 
        adap->owner = THIS_MODULE;
        adap->algo = &sh_mobile_i2c_algorithm;
+       adap->quirks = &sh_mobile_i2c_quirks;
        adap->dev.parent = &dev->dev;
        adap->retries = 5;
        adap->nr = dev->id;
index 4053259..a94e724 100644 (file)
@@ -590,9 +590,9 @@ static int __maybe_unused sprd_i2c_suspend_noirq(struct device *pdev)
 {
        struct sprd_i2c *i2c_dev = dev_get_drvdata(pdev);
 
-       i2c_lock_adapter(&i2c_dev->adap);
+       i2c_lock_bus(&i2c_dev->adap, I2C_LOCK_ROOT_ADAPTER);
        i2c_dev->is_suspended = true;
-       i2c_unlock_adapter(&i2c_dev->adap);
+       i2c_unlock_bus(&i2c_dev->adap, I2C_LOCK_ROOT_ADAPTER);
 
        return pm_runtime_force_suspend(pdev);
 }
@@ -601,9 +601,9 @@ static int __maybe_unused sprd_i2c_resume_noirq(struct device *pdev)
 {
        struct sprd_i2c *i2c_dev = dev_get_drvdata(pdev);
 
-       i2c_lock_adapter(&i2c_dev->adap);
+       i2c_lock_bus(&i2c_dev->adap, I2C_LOCK_ROOT_ADAPTER);
        i2c_dev->is_suspended = false;
-       i2c_unlock_adapter(&i2c_dev->adap);
+       i2c_unlock_bus(&i2c_dev->adap, I2C_LOCK_ROOT_ADAPTER);
 
        return pm_runtime_force_resume(pdev);
 }
index fce52bd..5503fa1 100644 (file)
@@ -673,12 +673,6 @@ static int stu300_xfer_msg(struct i2c_adapter *adap,
                        msg->addr, msg->len, msg->flags, stop);
        }
 
-       /* Zero-length messages are not supported by this hardware */
-       if (msg->len == 0) {
-               ret = -EINVAL;
-               goto exit_disable;
-       }
-
        /*
         * For some reason, sending the address sometimes fails when running
         * on  the 13 MHz clock. No interrupt arrives. This is a work around,
@@ -863,6 +857,10 @@ static const struct i2c_algorithm stu300_algo = {
        .functionality  = stu300_func,
 };
 
+static const struct i2c_adapter_quirks stu300_quirks = {
+       .flags = I2C_AQ_NO_ZERO_LEN,
+};
+
 static int stu300_probe(struct platform_device *pdev)
 {
        struct stu300_dev *dev;
@@ -920,6 +918,8 @@ static int stu300_probe(struct platform_device *pdev)
        adap->algo = &stu300_algo;
        adap->dev.parent = &pdev->dev;
        adap->dev.of_node = pdev->dev.of_node;
+       adap->quirks = &stu300_quirks;
+
        i2c_set_adapdata(adap, dev);
 
        /* i2c device drivers may be active on return from add_adapter() */
index 797def5..60c8561 100644 (file)
 
 #define I2C_CONFIG_LOAD_TIMEOUT                        1000000
 
+#define I2C_MST_FIFO_CONTROL                   0x0b4
+#define I2C_MST_FIFO_CONTROL_RX_FLUSH          BIT(0)
+#define I2C_MST_FIFO_CONTROL_TX_FLUSH          BIT(1)
+#define I2C_MST_FIFO_CONTROL_RX_TRIG(x)                (((x) - 1) <<  4)
+#define I2C_MST_FIFO_CONTROL_TX_TRIG(x)                (((x) - 1) << 16)
+
+#define I2C_MST_FIFO_STATUS                    0x0b8
+#define I2C_MST_FIFO_STATUS_RX_MASK            0xff
+#define I2C_MST_FIFO_STATUS_RX_SHIFT           0
+#define I2C_MST_FIFO_STATUS_TX_MASK            0xff0000
+#define I2C_MST_FIFO_STATUS_TX_SHIFT           16
+
 /*
  * msg_end_type: The bus control which need to be send at end of transfer.
  * @MSG_END_STOP: Send stop pulse at end of transfer.
@@ -154,6 +166,7 @@ struct tegra_i2c_hw_feature {
        u16 clk_divisor_fast_plus_mode;
        bool has_multi_master_mode;
        bool has_slcg_override_reg;
+       bool has_mst_fifo;
 };
 
 /**
@@ -266,13 +279,24 @@ static void tegra_i2c_unmask_irq(struct tegra_i2c_dev *i2c_dev, u32 mask)
 static int tegra_i2c_flush_fifos(struct tegra_i2c_dev *i2c_dev)
 {
        unsigned long timeout = jiffies + HZ;
-       u32 val = i2c_readl(i2c_dev, I2C_FIFO_CONTROL);
+       unsigned int offset;
+       u32 mask, val;
+
+       if (i2c_dev->hw->has_mst_fifo) {
+               mask = I2C_MST_FIFO_CONTROL_TX_FLUSH |
+                      I2C_MST_FIFO_CONTROL_RX_FLUSH;
+               offset = I2C_MST_FIFO_CONTROL;
+       } else {
+               mask = I2C_FIFO_CONTROL_TX_FLUSH |
+                      I2C_FIFO_CONTROL_RX_FLUSH;
+               offset = I2C_FIFO_CONTROL;
+       }
 
-       val |= I2C_FIFO_CONTROL_TX_FLUSH | I2C_FIFO_CONTROL_RX_FLUSH;
-       i2c_writel(i2c_dev, val, I2C_FIFO_CONTROL);
+       val = i2c_readl(i2c_dev, offset);
+       val |= mask;
+       i2c_writel(i2c_dev, val, offset);
 
-       while (i2c_readl(i2c_dev, I2C_FIFO_CONTROL) &
-               (I2C_FIFO_CONTROL_TX_FLUSH | I2C_FIFO_CONTROL_RX_FLUSH)) {
+       while (i2c_readl(i2c_dev, offset) & mask) {
                if (time_after(jiffies, timeout)) {
                        dev_warn(i2c_dev->dev, "timeout waiting for fifo flush\n");
                        return -ETIMEDOUT;
@@ -290,9 +314,15 @@ static int tegra_i2c_empty_rx_fifo(struct tegra_i2c_dev *i2c_dev)
        size_t buf_remaining = i2c_dev->msg_buf_remaining;
        int words_to_transfer;
 
-       val = i2c_readl(i2c_dev, I2C_FIFO_STATUS);
-       rx_fifo_avail = (val & I2C_FIFO_STATUS_RX_MASK) >>
-               I2C_FIFO_STATUS_RX_SHIFT;
+       if (i2c_dev->hw->has_mst_fifo) {
+               val = i2c_readl(i2c_dev, I2C_MST_FIFO_STATUS);
+               rx_fifo_avail = (val & I2C_MST_FIFO_STATUS_RX_MASK) >>
+                       I2C_MST_FIFO_STATUS_RX_SHIFT;
+       } else {
+               val = i2c_readl(i2c_dev, I2C_FIFO_STATUS);
+               rx_fifo_avail = (val & I2C_FIFO_STATUS_RX_MASK) >>
+                       I2C_FIFO_STATUS_RX_SHIFT;
+       }
 
        /* Rounds down to not include partial word at the end of buf */
        words_to_transfer = buf_remaining / BYTES_PER_FIFO_WORD;
@@ -321,6 +351,7 @@ static int tegra_i2c_empty_rx_fifo(struct tegra_i2c_dev *i2c_dev)
        BUG_ON(rx_fifo_avail > 0 && buf_remaining > 0);
        i2c_dev->msg_buf_remaining = buf_remaining;
        i2c_dev->msg_buf = buf;
+
        return 0;
 }
 
@@ -332,9 +363,15 @@ static int tegra_i2c_fill_tx_fifo(struct tegra_i2c_dev *i2c_dev)
        size_t buf_remaining = i2c_dev->msg_buf_remaining;
        int words_to_transfer;
 
-       val = i2c_readl(i2c_dev, I2C_FIFO_STATUS);
-       tx_fifo_avail = (val & I2C_FIFO_STATUS_TX_MASK) >>
-               I2C_FIFO_STATUS_TX_SHIFT;
+       if (i2c_dev->hw->has_mst_fifo) {
+               val = i2c_readl(i2c_dev, I2C_MST_FIFO_STATUS);
+               tx_fifo_avail = (val & I2C_MST_FIFO_STATUS_TX_MASK) >>
+                       I2C_MST_FIFO_STATUS_TX_SHIFT;
+       } else {
+               val = i2c_readl(i2c_dev, I2C_FIFO_STATUS);
+               tx_fifo_avail = (val & I2C_FIFO_STATUS_TX_MASK) >>
+                       I2C_FIFO_STATUS_TX_SHIFT;
+       }
 
        /* Rounds down to not include partial word at the end of buf */
        words_to_transfer = buf_remaining / BYTES_PER_FIFO_WORD;
@@ -516,9 +553,15 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev)
                i2c_writel(i2c_dev, 0x00, I2C_SL_ADDR2);
        }
 
-       val = 7 << I2C_FIFO_CONTROL_TX_TRIG_SHIFT |
-               0 << I2C_FIFO_CONTROL_RX_TRIG_SHIFT;
-       i2c_writel(i2c_dev, val, I2C_FIFO_CONTROL);
+       if (i2c_dev->hw->has_mst_fifo) {
+               val = I2C_MST_FIFO_CONTROL_TX_TRIG(8) |
+                     I2C_MST_FIFO_CONTROL_RX_TRIG(1);
+               i2c_writel(i2c_dev, val, I2C_MST_FIFO_CONTROL);
+       } else {
+               val = 7 << I2C_FIFO_CONTROL_TX_TRIG_SHIFT |
+                       0 << I2C_FIFO_CONTROL_RX_TRIG_SHIFT;
+               i2c_writel(i2c_dev, val, I2C_FIFO_CONTROL);
+       }
 
        err = tegra_i2c_flush_fifos(i2c_dev);
        if (err)
@@ -802,6 +845,7 @@ static const struct tegra_i2c_hw_feature tegra20_i2c_hw = {
        .has_config_load_reg = false,
        .has_multi_master_mode = false,
        .has_slcg_override_reg = false,
+       .has_mst_fifo = false,
 };
 
 static const struct tegra_i2c_hw_feature tegra30_i2c_hw = {
@@ -814,6 +858,7 @@ static const struct tegra_i2c_hw_feature tegra30_i2c_hw = {
        .has_config_load_reg = false,
        .has_multi_master_mode = false,
        .has_slcg_override_reg = false,
+       .has_mst_fifo = false,
 };
 
 static const struct tegra_i2c_hw_feature tegra114_i2c_hw = {
@@ -826,6 +871,7 @@ static const struct tegra_i2c_hw_feature tegra114_i2c_hw = {
        .has_config_load_reg = false,
        .has_multi_master_mode = false,
        .has_slcg_override_reg = false,
+       .has_mst_fifo = false,
 };
 
 static const struct tegra_i2c_hw_feature tegra124_i2c_hw = {
@@ -838,6 +884,7 @@ static const struct tegra_i2c_hw_feature tegra124_i2c_hw = {
        .has_config_load_reg = true,
        .has_multi_master_mode = false,
        .has_slcg_override_reg = true,
+       .has_mst_fifo = false,
 };
 
 static const struct tegra_i2c_hw_feature tegra210_i2c_hw = {
@@ -850,10 +897,25 @@ static const struct tegra_i2c_hw_feature tegra210_i2c_hw = {
        .has_config_load_reg = true,
        .has_multi_master_mode = true,
        .has_slcg_override_reg = true,
+       .has_mst_fifo = false,
+};
+
+static const struct tegra_i2c_hw_feature tegra194_i2c_hw = {
+       .has_continue_xfer_support = true,
+       .has_per_pkt_xfer_complete_irq = true,
+       .has_single_clk_source = true,
+       .clk_divisor_hs_mode = 1,
+       .clk_divisor_std_fast_mode = 0x19,
+       .clk_divisor_fast_plus_mode = 0x10,
+       .has_config_load_reg = true,
+       .has_multi_master_mode = true,
+       .has_slcg_override_reg = true,
+       .has_mst_fifo = true,
 };
 
 /* Match table for of_platform binding */
 static const struct of_device_id tegra_i2c_of_match[] = {
+       { .compatible = "nvidia,tegra194-i2c", .data = &tegra194_i2c_hw, },
        { .compatible = "nvidia,tegra210-i2c", .data = &tegra210_i2c_hw, },
        { .compatible = "nvidia,tegra124-i2c", .data = &tegra124_i2c_hw, },
        { .compatible = "nvidia,tegra114-i2c", .data = &tegra114_i2c_hw, },
index 484bfa1..34cd4b3 100644 (file)
@@ -173,9 +173,6 @@ static int xlr_i2c_tx(struct xlr_i2c_private *priv,  u16 len,
        u8 offset;
        u32 xfer;
 
-       if (!len)
-               return -EOPNOTSUPP;
-
        offset = buf[0];
        xlr_i2c_wreg(priv->iobase, XLR_I2C_ADDR, offset);
        xlr_i2c_wreg(priv->iobase, XLR_I2C_DEVADDR, addr);
@@ -241,9 +238,6 @@ static int xlr_i2c_rx(struct xlr_i2c_private *priv, u16 len, u8 *buf, u16 addr)
        unsigned long timeout, stoptime, checktime;
        int nbytes, timedout;
 
-       if (!len)
-               return -EOPNOTSUPP;
-
        xlr_i2c_wreg(priv->iobase, XLR_I2C_CFG,
                        XLR_I2C_CFG_NOADDR | priv->cfg->cfg_extra);
        xlr_i2c_wreg(priv->iobase, XLR_I2C_BYTECNT, len - 1);
@@ -340,6 +334,10 @@ static const struct i2c_algorithm xlr_i2c_algo = {
        .functionality  = xlr_func,
 };
 
+static const struct i2c_adapter_quirks xlr_i2c_quirks = {
+       .flags = I2C_AQ_NO_ZERO_LEN,
+};
+
 static const struct xlr_i2c_config xlr_i2c_config_default = {
        .status_busy    = XLR_I2C_BUS_BUSY,
        .cfg_extra      = 0,
@@ -427,6 +425,7 @@ static int xlr_i2c_probe(struct platform_device *pdev)
        priv->adap.owner        = THIS_MODULE;
        priv->adap.algo_data    = priv;
        priv->adap.algo         = &xlr_i2c_algo;
+       priv->adap.quirks       = &xlr_i2c_quirks;
        priv->adap.nr           = pdev->id;
        priv->adap.class        = I2C_CLASS_HWMON;
        snprintf(priv->adap.name, sizeof(priv->adap.name), "xlr-i2c");
index 7c3b474..32affd3 100644 (file)
@@ -453,8 +453,12 @@ static int acpi_gsb_i2c_read_bytes(struct i2c_client *client,
                else
                        dev_err(&client->adapter->dev, "i2c read %d bytes from client@%#x starting at reg %#x failed, error: %d\n",
                                data_len, client->addr, cmd, ret);
-       } else {
+       /* 2 transfers must have completed successfully */
+       } else if (ret == 2) {
                memcpy(data, buffer, data_len);
+               ret = 0;
+       } else {
+               ret = -EIO;
        }
 
        kfree(buffer);
@@ -482,11 +486,16 @@ static int acpi_gsb_i2c_write_bytes(struct i2c_client *client,
        msgs[0].buf = buffer;
 
        ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
-       if (ret < 0)
-               dev_err(&client->adapter->dev, "i2c write failed\n");
 
        kfree(buffer);
-       return ret;
+
+       if (ret < 0) {
+               dev_err(&client->adapter->dev, "i2c write failed: %d\n", ret);
+               return ret;
+       }
+
+       /* 1 transfer must have completed successfully */
+       return (ret == 1) ? 0 : -EIO;
 }
 
 static acpi_status
@@ -590,8 +599,6 @@ i2c_acpi_space_handler(u32 function, acpi_physical_address command,
                if (action == ACPI_READ) {
                        status = acpi_gsb_i2c_read_bytes(client, command,
                                        gsb->data, info->access_length);
-                       if (status > 0)
-                               status = 0;
                } else {
                        status = acpi_gsb_i2c_write_bytes(client, command,
                                        gsb->data, info->access_length);
index 15c95aa..f157377 100644 (file)
@@ -62,7 +62,7 @@
 
 /*
  * core_lock protects i2c_adapter_idr, and guarantees that device detection,
- * deletion of detected devices, and attach_adapter calls are serialized
+ * deletion of detected devices are serialized
  */
 static DEFINE_MUTEX(core_lock);
 static DEFINE_IDR(i2c_adapter_idr);
@@ -158,6 +158,22 @@ static void set_sda_gpio_value(struct i2c_adapter *adap, int val)
        gpiod_set_value_cansleep(adap->bus_recovery_info->sda_gpiod, val);
 }
 
+static int i2c_generic_bus_free(struct i2c_adapter *adap)
+{
+       struct i2c_bus_recovery_info *bri = adap->bus_recovery_info;
+       int ret = -EOPNOTSUPP;
+
+       if (bri->get_bus_free)
+               ret = bri->get_bus_free(adap);
+       else if (bri->get_sda)
+               ret = bri->get_sda(adap);
+
+       if (ret < 0)
+               return ret;
+
+       return ret ? 0 : -EBUSY;
+}
+
 /*
  * We are generating clock pulses. ndelay() determines durating of clk pulses.
  * We will generate clock with rate 100 KHz and so duration of both clock levels
@@ -169,21 +185,28 @@ static void set_sda_gpio_value(struct i2c_adapter *adap, int val)
 int i2c_generic_scl_recovery(struct i2c_adapter *adap)
 {
        struct i2c_bus_recovery_info *bri = adap->bus_recovery_info;
-       int i = 0, val = 1, ret = 0;
+       int i = 0, scl = 1, ret;
 
        if (bri->prepare_recovery)
                bri->prepare_recovery(adap);
 
-       bri->set_scl(adap, val);
+       /*
+        * If we can set SDA, we will always create a STOP to ensure additional
+        * pulses will do no harm. This is achieved by letting SDA follow SCL
+        * half a cycle later. Check the 'incomplete_write_byte' fault injector
+        * for details.
+        */
+       bri->set_scl(adap, scl);
+       ndelay(RECOVERY_NDELAY / 2);
        if (bri->set_sda)
-               bri->set_sda(adap, 1);
-       ndelay(RECOVERY_NDELAY);
+               bri->set_sda(adap, scl);
+       ndelay(RECOVERY_NDELAY / 2);
 
        /*
         * By this time SCL is high, as we need to give 9 falling-rising edges
         */
        while (i++ < RECOVERY_CLK_CNT * 2) {
-               if (val) {
+               if (scl) {
                        /* SCL shouldn't be low here */
                        if (!bri->get_scl(adap)) {
                                dev_err(&adap->dev,
@@ -191,41 +214,27 @@ int i2c_generic_scl_recovery(struct i2c_adapter *adap)
                                ret = -EBUSY;
                                break;
                        }
-                       /* Break if SDA is high */
-                       if (bri->get_sda && bri->get_sda(adap))
-                               break;
                }
 
-               val = !val;
-               bri->set_scl(adap, val);
-
-               /*
-                * If we can set SDA, we will always create STOP here to ensure
-                * the additional pulses will do no harm. This is achieved by
-                * letting SDA follow SCL half a cycle later.
-                */
+               scl = !scl;
+               bri->set_scl(adap, scl);
+               /* Creating STOP again, see above */
                ndelay(RECOVERY_NDELAY / 2);
                if (bri->set_sda)
-                       bri->set_sda(adap, val);
+                       bri->set_sda(adap, scl);
                ndelay(RECOVERY_NDELAY / 2);
-       }
-
-       /* check if recovery actually succeeded */
-       if (bri->get_sda && !bri->get_sda(adap))
-               ret = -EBUSY;
 
-       /* If all went well, send STOP for a sane bus state. */
-       if (ret == 0 && bri->set_sda) {
-               bri->set_scl(adap, 0);
-               ndelay(RECOVERY_NDELAY / 2);
-               bri->set_sda(adap, 0);
-               ndelay(RECOVERY_NDELAY / 2);
-               bri->set_scl(adap, 1);
-               ndelay(RECOVERY_NDELAY / 2);
-               bri->set_sda(adap, 1);
-               ndelay(RECOVERY_NDELAY / 2);
+               if (scl) {
+                       ret = i2c_generic_bus_free(adap);
+                       if (ret == 0)
+                               break;
+               }
        }
 
+       /* If we can't check bus status, assume recovery worked */
+       if (ret == -EOPNOTSUPP)
+               ret = 0;
+
        if (bri->unprepare_recovery)
                bri->unprepare_recovery(adap);
 
@@ -274,6 +283,10 @@ static void i2c_init_recovery(struct i2c_adapter *adap)
                        err_str = "no {get|set}_scl() found";
                        goto err;
                }
+               if (!bri->set_sda && !bri->get_sda) {
+                       err_str = "either get_sda() or set_sda() needed";
+                       goto err;
+               }
        }
 
        return;
@@ -1111,15 +1124,6 @@ static int i2c_do_add_adapter(struct i2c_driver *driver,
        /* Detect supported devices on that bus, and instantiate them */
        i2c_detect(adap, driver);
 
-       /* Let legacy drivers scan this bus for matching devices */
-       if (driver->attach_adapter) {
-               dev_warn(&adap->dev, "%s: attach_adapter method is deprecated\n",
-                        driver->driver.name);
-               dev_warn(&adap->dev,
-                        "Please use another way to instantiate your i2c_client\n");
-               /* We ignore the return code; if it fails, too bad */
-               driver->attach_adapter(adap);
-       }
        return 0;
 }
 
@@ -1563,6 +1567,8 @@ void i2c_parse_fw_timings(struct device *dev, struct i2c_timings *t, bool use_de
        ret = device_property_read_u32(dev, "i2c-sda-falling-time-ns", &t->sda_fall_ns);
        if (ret && use_defaults)
                t->sda_fall_ns = t->scl_fall_ns;
+
+       device_property_read_u32(dev, "i2c-sda-hold-time-ns", &t->sda_hold_ns);
 }
 EXPORT_SYMBOL_GPL(i2c_parse_fw_timings);
 
@@ -1826,9 +1832,15 @@ static int i2c_check_for_quirks(struct i2c_adapter *adap, struct i2c_msg *msgs,
                if (msgs[i].flags & I2C_M_RD) {
                        if (do_len_check && i2c_quirk_exceeded(len, q->max_read_len))
                                return i2c_quirk_error(adap, &msgs[i], "msg too long");
+
+                       if (q->flags & I2C_AQ_NO_ZERO_LEN_READ && len == 0)
+                               return i2c_quirk_error(adap, &msgs[i], "no zero length");
                } else {
                        if (do_len_check && i2c_quirk_exceeded(len, q->max_write_len))
                                return i2c_quirk_error(adap, &msgs[i], "msg too long");
+
+                       if (q->flags & I2C_AQ_NO_ZERO_LEN_WRITE && len == 0)
+                               return i2c_quirk_error(adap, &msgs[i], "no zero length");
                }
        }
 
index 4a78c65..47a9f70 100644 (file)
@@ -47,9 +47,9 @@ int i2c_slave_register(struct i2c_client *client, i2c_slave_cb_t slave_cb)
 
        client->slave_cb = slave_cb;
 
-       i2c_lock_adapter(client->adapter);
+       i2c_lock_bus(client->adapter, I2C_LOCK_ROOT_ADAPTER);
        ret = client->adapter->algo->reg_slave(client);
-       i2c_unlock_adapter(client->adapter);
+       i2c_unlock_bus(client->adapter, I2C_LOCK_ROOT_ADAPTER);
 
        if (ret) {
                client->slave_cb = NULL;
@@ -69,9 +69,9 @@ int i2c_slave_unregister(struct i2c_client *client)
                return -EOPNOTSUPP;
        }
 
-       i2c_lock_adapter(client->adapter);
+       i2c_lock_bus(client->adapter, I2C_LOCK_ROOT_ADAPTER);
        ret = client->adapter->algo->unreg_slave(client);
-       i2c_unlock_adapter(client->adapter);
+       i2c_unlock_bus(client->adapter, I2C_LOCK_ROOT_ADAPTER);
 
        if (ret == 0)
                client->slave_cb = NULL;
index 29646aa..f330690 100644 (file)
@@ -87,8 +87,8 @@ static int __i2c_mux_smbus_xfer(struct i2c_adapter *adap,
 
        ret = muxc->select(muxc, priv->chan_id);
        if (ret >= 0)
-               ret = parent->algo->smbus_xfer(parent, addr, flags,
-                                       read_write, command, size, data);
+               ret = __i2c_smbus_xfer(parent, addr, flags,
+                                      read_write, command, size, data);
        if (muxc->deselect)
                muxc->deselect(muxc, priv->chan_id);
 
index 12ad8d6..f2bf3e5 100644 (file)
@@ -94,31 +94,11 @@ static int mlxcpld_mux_reg_write(struct i2c_adapter *adap,
                                 struct i2c_client *client, u8 val)
 {
        struct mlxcpld_mux_plat_data *pdata = dev_get_platdata(&client->dev);
-       int ret = -ENODEV;
-
-       if (adap->algo->master_xfer) {
-               struct i2c_msg msg;
-               u8 msgbuf[] = {pdata->sel_reg_addr, val};
-
-               msg.addr = client->addr;
-               msg.flags = 0;
-               msg.len = 2;
-               msg.buf = msgbuf;
-               ret = __i2c_transfer(adap, &msg, 1);
-
-               if (ret >= 0 && ret != 1)
-                       ret = -EREMOTEIO;
-       } else if (adap->algo->smbus_xfer) {
-               union i2c_smbus_data data;
-
-               data.byte = val;
-               ret = adap->algo->smbus_xfer(adap, client->addr,
-                                            client->flags, I2C_SMBUS_WRITE,
-                                            pdata->sel_reg_addr,
-                                            I2C_SMBUS_BYTE_DATA, &data);
-       }
+       union i2c_smbus_data data = { .byte = val };
 
-       return ret;
+       return __i2c_smbus_xfer(adap, client->addr, client->flags,
+                               I2C_SMBUS_WRITE, pdata->sel_reg_addr,
+                               I2C_SMBUS_BYTE_DATA, &data);
 }
 
 static int mlxcpld_mux_select_chan(struct i2c_mux_core *muxc, u32 chan)
index 6a39ada..9e75d6b 100644 (file)
@@ -99,31 +99,11 @@ MODULE_DEVICE_TABLE(of, pca9541_of_match);
 static int pca9541_reg_write(struct i2c_client *client, u8 command, u8 val)
 {
        struct i2c_adapter *adap = client->adapter;
-       int ret;
-
-       if (adap->algo->master_xfer) {
-               struct i2c_msg msg;
-               char buf[2];
-
-               msg.addr = client->addr;
-               msg.flags = 0;
-               msg.len = 2;
-               buf[0] = command;
-               buf[1] = val;
-               msg.buf = buf;
-               ret = __i2c_transfer(adap, &msg, 1);
-       } else {
-               union i2c_smbus_data data;
-
-               data.byte = val;
-               ret = adap->algo->smbus_xfer(adap, client->addr,
-                                            client->flags,
-                                            I2C_SMBUS_WRITE,
-                                            command,
-                                            I2C_SMBUS_BYTE_DATA, &data);
-       }
+       union i2c_smbus_data data = { .byte = val };
 
-       return ret;
+       return __i2c_smbus_xfer(adap, client->addr, client->flags,
+                               I2C_SMBUS_WRITE, command,
+                               I2C_SMBUS_BYTE_DATA, &data);
 }
 
 /*
@@ -133,41 +113,14 @@ static int pca9541_reg_write(struct i2c_client *client, u8 command, u8 val)
 static int pca9541_reg_read(struct i2c_client *client, u8 command)
 {
        struct i2c_adapter *adap = client->adapter;
+       union i2c_smbus_data data;
        int ret;
-       u8 val;
-
-       if (adap->algo->master_xfer) {
-               struct i2c_msg msg[2] = {
-                       {
-                               .addr = client->addr,
-                               .flags = 0,
-                               .len = 1,
-                               .buf = &command
-                       },
-                       {
-                               .addr = client->addr,
-                               .flags = I2C_M_RD,
-                               .len = 1,
-                               .buf = &val
-                       }
-               };
-               ret = __i2c_transfer(adap, msg, 2);
-               if (ret == 2)
-                       ret = val;
-               else if (ret >= 0)
-                       ret = -EIO;
-       } else {
-               union i2c_smbus_data data;
-
-               ret = adap->algo->smbus_xfer(adap, client->addr,
-                                            client->flags,
-                                            I2C_SMBUS_READ,
-                                            command,
-                                            I2C_SMBUS_BYTE_DATA, &data);
-               if (!ret)
-                       ret = data.byte;
-       }
-       return ret;
+
+       ret = __i2c_smbus_xfer(adap, client->addr, client->flags,
+                              I2C_SMBUS_READ, command,
+                              I2C_SMBUS_BYTE_DATA, &data);
+
+       return ret ?: data.byte;
 }
 
 /*
@@ -345,11 +298,11 @@ static int pca9541_probe(struct i2c_client *client,
 
        /*
         * I2C accesses are unprotected here.
-        * We have to lock the adapter before releasing the bus.
+        * We have to lock the I2C segment before releasing the bus.
         */
-       i2c_lock_adapter(adap);
+       i2c_lock_bus(adap, I2C_LOCK_SEGMENT);
        pca9541_release_bus(client);
-       i2c_unlock_adapter(adap);
+       i2c_unlock_bus(adap, I2C_LOCK_SEGMENT);
 
        /* Create mux adapter */
 
index fbc7480..24bd927 100644 (file)
@@ -220,30 +220,11 @@ MODULE_DEVICE_TABLE(of, pca954x_of_match);
 static int pca954x_reg_write(struct i2c_adapter *adap,
                             struct i2c_client *client, u8 val)
 {
-       int ret = -ENODEV;
-
-       if (adap->algo->master_xfer) {
-               struct i2c_msg msg;
-               char buf[1];
-
-               msg.addr = client->addr;
-               msg.flags = 0;
-               msg.len = 1;
-               buf[0] = val;
-               msg.buf = buf;
-               ret = __i2c_transfer(adap, &msg, 1);
-
-               if (ret >= 0 && ret != 1)
-                       ret = -EREMOTEIO;
-       } else {
-               union i2c_smbus_data data;
-               ret = adap->algo->smbus_xfer(adap, client->addr,
-                                            client->flags,
-                                            I2C_SMBUS_WRITE,
-                                            val, I2C_SMBUS_BYTE, &data);
-       }
+       union i2c_smbus_data dummy;
 
-       return ret;
+       return __i2c_smbus_xfer(adap, client->addr, client->flags,
+                               I2C_SMBUS_WRITE, val,
+                               I2C_SMBUS_BYTE, &dummy);
 }
 
 static int pca954x_select_chan(struct i2c_mux_core *muxc, u32 chan)
@@ -368,7 +349,8 @@ static int pca954x_probe(struct i2c_client *client,
 {
        struct i2c_adapter *adap = to_i2c_adapter(client->dev.parent);
        struct pca954x_platform_data *pdata = dev_get_platdata(&client->dev);
-       struct device_node *of_node = client->dev.of_node;
+       struct device *dev = &client->dev;
+       struct device_node *np = dev->of_node;
        bool idle_disconnect_dt;
        struct gpio_desc *gpio;
        int num, force, class;
@@ -379,8 +361,7 @@ static int pca954x_probe(struct i2c_client *client,
        if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE))
                return -ENODEV;
 
-       muxc = i2c_mux_alloc(adap, &client->dev,
-                            PCA954X_MAX_NCHANS, sizeof(*data), 0,
+       muxc = i2c_mux_alloc(adap, dev, PCA954X_MAX_NCHANS, sizeof(*data), 0,
                             pca954x_select_chan, pca954x_deselect_mux);
        if (!muxc)
                return -ENOMEM;
@@ -390,7 +371,7 @@ static int pca954x_probe(struct i2c_client *client,
        data->client = client;
 
        /* Reset the mux if a reset GPIO is specified. */
-       gpio = devm_gpiod_get_optional(&client->dev, "reset", GPIOD_OUT_HIGH);
+       gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
        if (IS_ERR(gpio))
                return PTR_ERR(gpio);
        if (gpio) {
@@ -400,7 +381,7 @@ static int pca954x_probe(struct i2c_client *client,
                udelay(1);
        }
 
-       data->chip = of_device_get_match_data(&client->dev);
+       data->chip = of_device_get_match_data(dev);
        if (!data->chip)
                data->chip = &chips[id->driver_data];
 
@@ -414,8 +395,7 @@ static int pca954x_probe(struct i2c_client *client,
                if (!ret &&
                    (id.manufacturer_id != data->chip->id.manufacturer_id ||
                     id.part_id != data->chip->id.part_id)) {
-                       dev_warn(&client->dev,
-                                "unexpected device id %03x-%03x-%x\n",
+                       dev_warn(dev, "unexpected device id %03x-%03x-%x\n",
                                 id.manufacturer_id, id.part_id,
                                 id.die_revision);
                        return -ENODEV;
@@ -427,14 +407,14 @@ static int pca954x_probe(struct i2c_client *client,
         * initializes the mux to disconnected state.
         */
        if (i2c_smbus_write_byte(client, 0) < 0) {
-               dev_warn(&client->dev, "probe failed\n");
+               dev_warn(dev, "probe failed\n");
                return -ENODEV;
        }
 
        data->last_chan = 0;               /* force the first selection */
 
-       idle_disconnect_dt = of_node &&
-               of_property_read_bool(of_node, "i2c-mux-idle-disconnect");
+       idle_disconnect_dt = np &&
+               of_property_read_bool(np, "i2c-mux-idle-disconnect");
 
        ret = pca954x_irq_setup(muxc);
        if (ret)
@@ -465,7 +445,7 @@ static int pca954x_probe(struct i2c_client *client,
        }
 
        if (data->irq) {
-               ret = devm_request_threaded_irq(&client->dev, data->client->irq,
+               ret = devm_request_threaded_irq(dev, data->client->irq,
                                                NULL, pca954x_irq_handler,
                                                IRQF_ONESHOT | IRQF_SHARED,
                                                "pca954x", data);
@@ -473,8 +453,7 @@ static int pca954x_probe(struct i2c_client *client,
                        goto fail_cleanup;
        }
 
-       dev_info(&client->dev,
-                "registered %d multiplexed busses for I2C %s %s\n",
+       dev_info(dev, "registered %d multiplexed busses for I2C %s %s\n",
                 num, data->chip->muxtype == pca954x_ismux
                                ? "mux" : "switch", client->name);
 
index e52c58c..4d565b0 100644 (file)
@@ -574,13 +574,14 @@ static u8 hpt3xx_udma_filter(ide_drive_t *drive)
                if (!HPT370_ALLOW_ATA100_5 ||
                    check_in_drive_list(drive, bad_ata100_5))
                        return ATA_UDMA4;
+               /* else: fall through */
        case HPT372 :
        case HPT372A:
        case HPT372N:
        case HPT374 :
                if (ata_id_is_sata(drive->id))
                        mask &= ~0x0e;
-               /* Fall thru */
+               /* fall through */
        default:
                return mask;
        }
@@ -600,7 +601,7 @@ static u8 hpt3xx_mdma_filter(ide_drive_t *drive)
        case HPT374 :
                if (ata_id_is_sata(drive->id))
                        return 0x00;
-               /* Fall thru */
+               /* else: fall through */
        default:
                return 0x07;
        }
index 5bd2aaf..a8df300 100644 (file)
@@ -427,6 +427,7 @@ static int ide_floppy_get_capacity(ide_drive_t *drive)
                                 * (maintains previous driver behaviour)
                                 */
                                break;
+                       /* else: fall through */
                case CAPACITY_CURRENT:
                        /* Normal Zip/LS-120 disks */
                        if (memcmp(cap_desc, &floppy->cap_desc, 8))
index a444bad..0d93e0c 100644 (file)
@@ -460,7 +460,6 @@ void do_ide_request(struct request_queue *q)
        struct ide_host *host = hwif->host;
        struct request  *rq = NULL;
        ide_startstop_t startstop;
-       unsigned long queue_run_ms = 3; /* old plug delay */
 
        spin_unlock_irq(q->queue_lock);
 
@@ -480,9 +479,6 @@ repeat:
                prev_port = hwif->host->cur_port;
                if (drive->dev_flags & IDE_DFLAG_SLEEPING &&
                    time_after(drive->sleep, jiffies)) {
-                       unsigned long left = jiffies - drive->sleep;
-
-                       queue_run_ms = jiffies_to_msecs(left + 1);
                        ide_unlock_port(hwif);
                        goto plug_device;
                }
index 416a2f3..3b75a7b 100644 (file)
@@ -142,6 +142,7 @@ static void ide_classify_atapi_dev(ide_drive_t *drive)
                }
                /* Early cdrom models used zero */
                type = ide_cdrom;
+               /* fall through */
        case ide_cdrom:
                drive->dev_flags |= IDE_DFLAG_REMOVABLE;
 #ifdef CONFIG_PPC
index aee7b46..34c1165 100644 (file)
@@ -1746,7 +1746,6 @@ static void idetape_setup(ide_drive_t *drive, idetape_tape_t *tape, int minor)
 {
        unsigned long t;
        int speed;
-       int buffer_size;
        u16 *ctl = (u16 *)&tape->caps[12];
 
        ide_debug_log(IDE_DBG_FUNC, "minor: %d", minor);
@@ -1781,7 +1780,6 @@ static void idetape_setup(ide_drive_t *drive, idetape_tape_t *tape, int minor)
                *ctl /= 2;
                tape->buffer_size = *ctl * tape->blk_size;
        }
-       buffer_size = tape->buffer_size;
 
        /* select the "best" DSC read/write polling freq */
        speed = max(*(u16 *)&tape->caps[14], *(u16 *)&tape->caps[8]);
index 89b2902..c21d5c5 100644 (file)
@@ -128,7 +128,7 @@ ide_startstop_t do_rw_taskfile(ide_drive_t *drive, struct ide_cmd *orig_cmd)
                        return pre_task_out_intr(drive, cmd);
                }
                handler = task_pio_intr;
-               /* fall-through */
+               /* fall through */
        case ATA_PROT_NODATA:
                if (handler == NULL)
                        handler = task_no_data_intr;
@@ -140,6 +140,7 @@ ide_startstop_t do_rw_taskfile(ide_drive_t *drive, struct ide_cmd *orig_cmd)
                hwif->expiry = dma_ops->dma_timer_expiry;
                ide_execute_command(drive, cmd, ide_dma_intr, 2 * WAIT_CMD);
                dma_ops->dma_start(drive);
+               /* fall through */
        default:
                return ide_started;
        }
index c3062b5..024bc7b 100644 (file)
@@ -494,6 +494,7 @@ static int init_chipset_sis5513(struct pci_dev *dev)
                pci_read_config_byte(dev, 0x09, &reg);
                if ((reg & 0x0f) != 0x00)
                        pci_write_config_byte(dev, 0x09, reg&0xf0);
+               /* fall through */
        case ATA_16:
                /* force per drive recovery and active timings
                   needed on ATA_33 and below chips */
index 28e9b76..15d498f 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * LTC2632 Digital to analog convertors spi driver
  *
- * Copyright 2017 Maxime Roussin-Bélanger
+ * Copyright 2017 Maxime Roussin-Bélanger
  * expanded by Silvan Murer <silvan.murer@gmail.com>
  *
  * Licensed under the GPL-2.
index d619e86..13a4cec 100644 (file)
@@ -433,11 +433,11 @@ static int mlx90614_wakeup(struct mlx90614_data *data)
 
        dev_dbg(&data->client->dev, "Requesting wake-up");
 
-       i2c_lock_adapter(data->client->adapter);
+       i2c_lock_bus(data->client->adapter, I2C_LOCK_ROOT_ADAPTER);
        gpiod_direction_output(data->wakeup_gpio, 0);
        msleep(MLX90614_TIMING_WAKEUP);
        gpiod_direction_input(data->wakeup_gpio);
-       i2c_unlock_adapter(data->client->adapter);
+       i2c_unlock_bus(data->client->adapter, I2C_LOCK_ROOT_ADAPTER);
 
        data->ready_timestamp = jiffies +
                        msecs_to_jiffies(MLX90614_TIMING_STARTUP);
index d160d2d..abb6660 100644 (file)
@@ -36,7 +36,7 @@ config INFINIBAND_USER_ACCESS
          rdma-core <https://github.com/linux-rdma/rdma-core>.
 
 config INFINIBAND_USER_ACCESS_UCM
-       bool "Userspace CM (UCM, DEPRECATED)"
+       tristate "Userspace CM (UCM, DEPRECATED)"
        depends on BROKEN || COMPILE_TEST
        depends on INFINIBAND_USER_ACCESS
        help
index 182436b..6ec748e 100644 (file)
@@ -186,6 +186,7 @@ static void ib_umem_notifier_release(struct mmu_notifier *mn,
        rbt_ib_umem_for_each_in_range(&context->umem_tree, 0,
                                      ULLONG_MAX,
                                      ib_umem_notifier_release_trampoline,
+                                     true,
                                      NULL);
        up_read(&context->umem_rwsem);
 }
@@ -207,22 +208,31 @@ static int invalidate_range_start_trampoline(struct ib_umem *item, u64 start,
        return 0;
 }
 
-static void ib_umem_notifier_invalidate_range_start(struct mmu_notifier *mn,
+static int ib_umem_notifier_invalidate_range_start(struct mmu_notifier *mn,
                                                    struct mm_struct *mm,
                                                    unsigned long start,
-                                                   unsigned long end)
+                                                   unsigned long end,
+                                                   bool blockable)
 {
        struct ib_ucontext *context = container_of(mn, struct ib_ucontext, mn);
+       int ret;
 
        if (!context->invalidate_range)
-               return;
+               return 0;
+
+       if (blockable)
+               down_read(&context->umem_rwsem);
+       else if (!down_read_trylock(&context->umem_rwsem))
+               return -EAGAIN;
 
        ib_ucontext_notifier_start_account(context);
-       down_read(&context->umem_rwsem);
-       rbt_ib_umem_for_each_in_range(&context->umem_tree, start,
+       ret = rbt_ib_umem_for_each_in_range(&context->umem_tree, start,
                                      end,
-                                     invalidate_range_start_trampoline, NULL);
+                                     invalidate_range_start_trampoline,
+                                     blockable, NULL);
        up_read(&context->umem_rwsem);
+
+       return ret;
 }
 
 static int invalidate_range_end_trampoline(struct ib_umem *item, u64 start,
@@ -242,10 +252,15 @@ static void ib_umem_notifier_invalidate_range_end(struct mmu_notifier *mn,
        if (!context->invalidate_range)
                return;
 
+       /*
+        * TODO: we currently bail out if there is any sleepable work to be done
+        * in ib_umem_notifier_invalidate_range_start so we shouldn't really block
+        * here. But this is ugly and fragile.
+        */
        down_read(&context->umem_rwsem);
        rbt_ib_umem_for_each_in_range(&context->umem_tree, start,
                                      end,
-                                     invalidate_range_end_trampoline, NULL);
+                                     invalidate_range_end_trampoline, true, NULL);
        up_read(&context->umem_rwsem);
        ib_ucontext_notifier_end_account(context);
 }
@@ -798,6 +813,7 @@ EXPORT_SYMBOL(ib_umem_odp_unmap_dma_pages);
 int rbt_ib_umem_for_each_in_range(struct rb_root_cached *root,
                                  u64 start, u64 last,
                                  umem_call_back cb,
+                                 bool blockable,
                                  void *cookie)
 {
        int ret_val = 0;
@@ -809,6 +825,9 @@ int rbt_ib_umem_for_each_in_range(struct rb_root_cached *root,
 
        for (node = rbt_ib_umem_iter_first(root, start, last - 1);
                        node; node = next) {
+               /* TODO move the blockable decision up to the callback */
+               if (!blockable)
+                       return -EAGAIN;
                next = rbt_ib_umem_iter_next(node, start, last - 1);
                umem = container_of(node, struct ib_umem_odp, interval_tree);
                ret_val = cb(umem->umem, start, last, cookie) || ret_val;
index fbe7198..bedd5fb 100644 (file)
@@ -198,7 +198,7 @@ int node_affinity_init(void)
                while ((dev = pci_get_device(ids->vendor, ids->device, dev))) {
                        node = pcibus_to_node(dev->bus);
                        if (node < 0)
-                               node = numa_node_id();
+                               goto out;
 
                        hfi1_per_node_cntr[node]++;
                }
@@ -206,6 +206,18 @@ int node_affinity_init(void)
        }
 
        return 0;
+
+out:
+       /*
+        * Invalid PCI NUMA node information found, note it, and populate
+        * our database 1:1.
+        */
+       pr_err("HFI: Invalid PCI NUMA node. Performance may be affected\n");
+       pr_err("HFI: System BIOS may need to be upgraded\n");
+       for (node = 0; node < node_affinity.num_possible_nodes; node++)
+               hfi1_per_node_cntr[node] = 1;
+
+       return 0;
 }
 
 static void node_affinity_destroy(struct hfi1_affinity_node *entry)
@@ -622,8 +634,14 @@ int hfi1_dev_affinity_init(struct hfi1_devdata *dd)
        int curr_cpu, possible, i, ret;
        bool new_entry = false;
 
-       if (node < 0)
-               node = numa_node_id();
+       /*
+        * If the BIOS does not have the NUMA node information set, select
+        * NUMA 0 so we get consistent performance.
+        */
+       if (node < 0) {
+               dd_dev_err(dd, "Invalid PCI NUMA node. Performance may be affected\n");
+               node = 0;
+       }
        dd->node = node;
 
        local_mask = cpumask_of_node(dd->node);
index 70aceef..e1c7996 100644 (file)
@@ -67,9 +67,9 @@ struct mmu_rb_handler {
 
 static unsigned long mmu_node_start(struct mmu_rb_node *);
 static unsigned long mmu_node_last(struct mmu_rb_node *);
-static void mmu_notifier_range_start(struct mmu_notifier *,
+static int mmu_notifier_range_start(struct mmu_notifier *,
                                     struct mm_struct *,
-                                    unsigned long, unsigned long);
+                                    unsigned long, unsigned long, bool);
 static struct mmu_rb_node *__mmu_rb_search(struct mmu_rb_handler *,
                                           unsigned long, unsigned long);
 static void do_remove(struct mmu_rb_handler *handler,
@@ -284,10 +284,11 @@ void hfi1_mmu_rb_remove(struct mmu_rb_handler *handler,
        handler->ops->remove(handler->ops_arg, node);
 }
 
-static void mmu_notifier_range_start(struct mmu_notifier *mn,
+static int mmu_notifier_range_start(struct mmu_notifier *mn,
                                     struct mm_struct *mm,
                                     unsigned long start,
-                                    unsigned long end)
+                                    unsigned long end,
+                                    bool blockable)
 {
        struct mmu_rb_handler *handler =
                container_of(mn, struct mmu_rb_handler, mn);
@@ -313,6 +314,8 @@ static void mmu_notifier_range_start(struct mmu_notifier *mn,
 
        if (added)
                queue_work(handler->wq, &handler->del_work);
+
+       return 0;
 }
 
 /*
index f1a87a6..d216e0d 100644 (file)
@@ -488,7 +488,7 @@ void mlx5_ib_free_implicit_mr(struct mlx5_ib_mr *imr)
 
        down_read(&ctx->umem_rwsem);
        rbt_ib_umem_for_each_in_range(&ctx->umem_tree, 0, ULLONG_MAX,
-                                     mr_leaf_free, imr);
+                                     mr_leaf_free, true, imr);
        up_read(&ctx->umem_rwsem);
 
        wait_event(imr->q_leaf_free, !atomic_read(&imr->num_leaf_free));
index 6bd97ff..4713957 100644 (file)
@@ -721,7 +721,7 @@ config KEYBOARD_CROS_EC
        help
          Say Y here to enable the matrix keyboard used by ChromeOS devices
          and implemented on the ChromeOS EC. You must enable one bus option
-         (MFD_CROS_EC_I2C or MFD_CROS_EC_SPI) to use this.
+         (CROS_EC_I2C or CROS_EC_SPI) to use this.
 
          To compile this driver as a module, choose M here: the
          module will be called cros_ec_keyb.
index 3df501c..f8663d7 100644 (file)
  * However, when used with the E3 mailboard that producecs non-standard
  * scancodes, a custom key table must be prepared and loaded from userspace.
  */
-#include <linux/gpio.h>
 #include <linux/irq.h>
+#include <linux/platform_data/ams-delta-fiq.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
 #include <linux/serio.h>
 #include <linux/slab.h>
 #include <linux/module.h>
 
-#include <asm/mach-types.h>
-#include <mach/board-ams-delta.h>
-
-#include <mach/ams-delta-fiq.h>
+#define DRIVER_NAME    "ams-delta-serio"
 
 MODULE_AUTHOR("Matt Callow");
 MODULE_DESCRIPTION("AMS Delta (E3) keyboard port driver");
 MODULE_LICENSE("GPL");
 
-static struct serio *ams_delta_serio;
+struct ams_delta_serio {
+       struct serio *serio;
+       struct regulator *vcc;
+       unsigned int *fiq_buffer;
+};
 
-static int check_data(int data)
+static int check_data(struct serio *serio, int data)
 {
        int i, parity = 0;
 
        /* check valid stop bit */
        if (!(data & 0x400)) {
-               dev_warn(&ams_delta_serio->dev,
-                               "invalid stop bit, data=0x%X\n",
-                               data);
+               dev_warn(&serio->dev, "invalid stop bit, data=0x%X\n", data);
                return SERIO_FRAME;
        }
        /* calculate the parity */
@@ -55,9 +56,9 @@ static int check_data(int data)
        }
        /* it should be odd */
        if (!(parity & 0x01)) {
-               dev_warn(&ams_delta_serio->dev,
-                               "parity check failed, data=0x%X parity=0x%X\n",
-                               data, parity);
+               dev_warn(&serio->dev,
+                        "parity check failed, data=0x%X parity=0x%X\n", data,
+                        parity);
                return SERIO_PARITY;
        }
        return 0;
@@ -65,127 +66,130 @@ static int check_data(int data)
 
 static irqreturn_t ams_delta_serio_interrupt(int irq, void *dev_id)
 {
-       int *circ_buff = &fiq_buffer[FIQ_CIRC_BUFF];
+       struct ams_delta_serio *priv = dev_id;
+       int *circ_buff = &priv->fiq_buffer[FIQ_CIRC_BUFF];
        int data, dfl;
        u8 scancode;
 
-       fiq_buffer[FIQ_IRQ_PEND] = 0;
+       priv->fiq_buffer[FIQ_IRQ_PEND] = 0;
 
        /*
         * Read data from the circular buffer, check it
         * and then pass it on the serio
         */
-       while (fiq_buffer[FIQ_KEYS_CNT] > 0) {
+       while (priv->fiq_buffer[FIQ_KEYS_CNT] > 0) {
 
-               data = circ_buff[fiq_buffer[FIQ_HEAD_OFFSET]++];
-               fiq_buffer[FIQ_KEYS_CNT]--;
-               if (fiq_buffer[FIQ_HEAD_OFFSET] == fiq_buffer[FIQ_BUF_LEN])
-                       fiq_buffer[FIQ_HEAD_OFFSET] = 0;
+               data = circ_buff[priv->fiq_buffer[FIQ_HEAD_OFFSET]++];
+               priv->fiq_buffer[FIQ_KEYS_CNT]--;
+               if (priv->fiq_buffer[FIQ_HEAD_OFFSET] ==
+                   priv->fiq_buffer[FIQ_BUF_LEN])
+                       priv->fiq_buffer[FIQ_HEAD_OFFSET] = 0;
 
-               dfl = check_data(data);
+               dfl = check_data(priv->serio, data);
                scancode = (u8) (data >> 1) & 0xFF;
-               serio_interrupt(ams_delta_serio, scancode, dfl);
+               serio_interrupt(priv->serio, scancode, dfl);
        }
        return IRQ_HANDLED;
 }
 
 static int ams_delta_serio_open(struct serio *serio)
 {
-       /* enable keyboard */
-       gpio_set_value(AMS_DELTA_GPIO_PIN_KEYBRD_PWR, 1);
+       struct ams_delta_serio *priv = serio->port_data;
 
-       return 0;
+       /* enable keyboard */
+       return regulator_enable(priv->vcc);
 }
 
 static void ams_delta_serio_close(struct serio *serio)
 {
+       struct ams_delta_serio *priv = serio->port_data;
+
        /* disable keyboard */
-       gpio_set_value(AMS_DELTA_GPIO_PIN_KEYBRD_PWR, 0);
+       regulator_disable(priv->vcc);
 }
 
-static const struct gpio ams_delta_gpios[] __initconst_or_module = {
-       {
-               .gpio   = AMS_DELTA_GPIO_PIN_KEYBRD_DATA,
-               .flags  = GPIOF_DIR_IN,
-               .label  = "serio-data",
-       },
-       {
-               .gpio   = AMS_DELTA_GPIO_PIN_KEYBRD_CLK,
-               .flags  = GPIOF_DIR_IN,
-               .label  = "serio-clock",
-       },
-       {
-               .gpio   = AMS_DELTA_GPIO_PIN_KEYBRD_PWR,
-               .flags  = GPIOF_OUT_INIT_LOW,
-               .label  = "serio-power",
-       },
-       {
-               .gpio   = AMS_DELTA_GPIO_PIN_KEYBRD_DATAOUT,
-               .flags  = GPIOF_OUT_INIT_LOW,
-               .label  = "serio-dataout",
-       },
-};
-
-static int __init ams_delta_serio_init(void)
+static int ams_delta_serio_init(struct platform_device *pdev)
 {
-       int err;
-
-       if (!machine_is_ams_delta())
-               return -ENODEV;
+       struct ams_delta_serio *priv;
+       struct serio *serio;
+       int irq, err;
 
-       ams_delta_serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
-       if (!ams_delta_serio)
+       priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+       if (!priv)
                return -ENOMEM;
 
-       ams_delta_serio->id.type = SERIO_8042;
-       ams_delta_serio->open = ams_delta_serio_open;
-       ams_delta_serio->close = ams_delta_serio_close;
-       strlcpy(ams_delta_serio->name, "AMS DELTA keyboard adapter",
-                       sizeof(ams_delta_serio->name));
-       strlcpy(ams_delta_serio->phys, "GPIO/serio0",
-                       sizeof(ams_delta_serio->phys));
-
-       err = gpio_request_array(ams_delta_gpios,
-                               ARRAY_SIZE(ams_delta_gpios));
-       if (err) {
-               pr_err("ams_delta_serio: Couldn't request gpio pins\n");
-               goto serio;
+       priv->fiq_buffer = pdev->dev.platform_data;
+       if (!priv->fiq_buffer)
+               return -EINVAL;
+
+       priv->vcc = devm_regulator_get(&pdev->dev, "vcc");
+       if (IS_ERR(priv->vcc)) {
+               err = PTR_ERR(priv->vcc);
+               dev_err(&pdev->dev, "regulator request failed (%d)\n", err);
+               /*
+                * When running on a non-dt platform and requested regulator
+                * is not available, devm_regulator_get() never returns
+                * -EPROBE_DEFER as it is not able to justify if the regulator
+                * may still appear later.  On the other hand, the board can
+                * still set full constriants flag at late_initcall in order
+                * to instruct devm_regulator_get() to returnn a dummy one
+                * if sufficient.  Hence, if we get -ENODEV here, let's convert
+                * it to -EPROBE_DEFER and wait for the board to decide or
+                * let Deferred Probe infrastructure handle this error.
+                */
+               if (err == -ENODEV)
+                       err = -EPROBE_DEFER;
+               return err;
        }
 
-       err = request_irq(gpio_to_irq(AMS_DELTA_GPIO_PIN_KEYBRD_CLK),
-                       ams_delta_serio_interrupt, IRQ_TYPE_EDGE_RISING,
-                       "ams-delta-serio", 0);
+       irq = platform_get_irq(pdev, 0);
+       if (irq < 0)
+               return -ENXIO;
+
+       err = devm_request_irq(&pdev->dev, irq, ams_delta_serio_interrupt,
+                              IRQ_TYPE_EDGE_RISING, DRIVER_NAME, priv);
        if (err < 0) {
-               pr_err("ams_delta_serio: couldn't request gpio interrupt %d\n",
-                               gpio_to_irq(AMS_DELTA_GPIO_PIN_KEYBRD_CLK));
-               goto gpio;
+               dev_err(&pdev->dev, "IRQ request failed (%d)\n", err);
+               return err;
        }
-       /*
-        * Since GPIO register handling for keyboard clock pin is performed
-        * at FIQ level, switch back from edge to simple interrupt handler
-        * to avoid bad interaction.
-        */
-       irq_set_handler(gpio_to_irq(AMS_DELTA_GPIO_PIN_KEYBRD_CLK),
-                       handle_simple_irq);
 
-       serio_register_port(ams_delta_serio);
-       dev_info(&ams_delta_serio->dev, "%s\n", ams_delta_serio->name);
+       serio = kzalloc(sizeof(*serio), GFP_KERNEL);
+       if (!serio)
+               return -ENOMEM;
+
+       priv->serio = serio;
+
+       serio->id.type = SERIO_8042;
+       serio->open = ams_delta_serio_open;
+       serio->close = ams_delta_serio_close;
+       strlcpy(serio->name, "AMS DELTA keyboard adapter", sizeof(serio->name));
+       strlcpy(serio->phys, dev_name(&pdev->dev), sizeof(serio->phys));
+       serio->dev.parent = &pdev->dev;
+       serio->port_data = priv;
+
+       serio_register_port(serio);
+
+       platform_set_drvdata(pdev, priv);
+
+       dev_info(&serio->dev, "%s\n", serio->name);
 
        return 0;
-gpio:
-       gpio_free_array(ams_delta_gpios,
-                       ARRAY_SIZE(ams_delta_gpios));
-serio:
-       kfree(ams_delta_serio);
-       return err;
 }
-module_init(ams_delta_serio_init);
 
-static void __exit ams_delta_serio_exit(void)
+static int ams_delta_serio_exit(struct platform_device *pdev)
 {
-       serio_unregister_port(ams_delta_serio);
-       free_irq(gpio_to_irq(AMS_DELTA_GPIO_PIN_KEYBRD_CLK), 0);
-       gpio_free_array(ams_delta_gpios,
-                       ARRAY_SIZE(ams_delta_gpios));
+       struct ams_delta_serio *priv = platform_get_drvdata(pdev);
+
+       serio_unregister_port(priv->serio);
+
+       return 0;
 }
-module_exit(ams_delta_serio_exit);
+
+static struct platform_driver ams_delta_serio_driver = {
+       .probe  = ams_delta_serio_init,
+       .remove = ams_delta_serio_exit,
+       .driver = {
+               .name   = DRIVER_NAME
+       },
+};
+module_platform_driver(ams_delta_serio_driver);
index bda0500..714affd 100644 (file)
@@ -304,7 +304,7 @@ static int rohm_i2c_burst_read(struct i2c_client *client, u8 start, void *buf,
        msg[1].len = len;
        msg[1].buf = buf;
 
-       i2c_lock_adapter(adap);
+       i2c_lock_bus(adap, I2C_LOCK_SEGMENT);
 
        for (i = 0; i < 2; i++) {
                if (__i2c_transfer(adap, &msg[i], 1) < 0) {
@@ -313,7 +313,7 @@ static int rohm_i2c_burst_read(struct i2c_client *client, u8 start, void *buf,
                }
        }
 
-       i2c_unlock_adapter(adap);
+       i2c_unlock_bus(adap, I2C_LOCK_SEGMENT);
 
        return ret;
 }
index 689ffe5..c60395b 100644 (file)
@@ -60,6 +60,27 @@ config IOMMU_IO_PGTABLE_ARMV7S_SELFTEST
 
 endmenu
 
+config IOMMU_DEBUGFS
+       bool "Export IOMMU internals in DebugFS"
+       depends on DEBUG_FS
+       help
+         Allows exposure of IOMMU device internals. This option enables
+         the use of debugfs by IOMMU drivers as required. Devices can,
+         at initialization time, cause the IOMMU code to create a top-level
+         debug/iommu directory, and then populate a subdirectory with
+         entries as required.
+
+config IOMMU_DEFAULT_PASSTHROUGH
+       bool "IOMMU passthrough by default"
+       depends on IOMMU_API
+        help
+         Enable passthrough by default, removing the need to pass in
+         iommu.passthrough=on or iommu=pt through command line. If this
+         is enabled, you can still disable with iommu.passthrough=off
+         or iommu=nopt depending on the architecture.
+
+         If unsure, say N here.
+
 config IOMMU_IOVA
        tristate
 
@@ -135,6 +156,18 @@ config AMD_IOMMU_V2
          hardware. Select this option if you want to use devices that support
          the PCI PRI and PASID interface.
 
+config AMD_IOMMU_DEBUGFS
+       bool "Enable AMD IOMMU internals in DebugFS"
+       depends on AMD_IOMMU && IOMMU_DEBUGFS
+       ---help---
+         !!!WARNING!!!  !!!WARNING!!!  !!!WARNING!!!  !!!WARNING!!!
+
+         DO NOT ENABLE THIS OPTION UNLESS YOU REALLY, -REALLY- KNOW WHAT YOU ARE DOING!!!
+         Exposes AMD IOMMU device internals in DebugFS.
+
+         This option is -NOT- intended for production environments, and should
+         not generally be enabled.
+
 # Intel IOMMU support
 config DMAR_TABLE
        bool
@@ -284,8 +317,8 @@ config IPMMU_VMSA
        select IOMMU_IO_PGTABLE_LPAE
        select ARM_DMA_USE_IOMMU
        help
-         Support for the Renesas VMSA-compatible IPMMU Renesas found in the
-         R-Mobile APE6 and R-Car H2/M2 SoCs.
+         Support for the Renesas VMSA-compatible IPMMU found in the R-Mobile
+         APE6, R-Car Gen2, and R-Car Gen3 SoCs.
 
          If unsure, say N.
 
index 1fb6958..ab5eba6 100644 (file)
@@ -2,6 +2,7 @@
 obj-$(CONFIG_IOMMU_API) += iommu.o
 obj-$(CONFIG_IOMMU_API) += iommu-traces.o
 obj-$(CONFIG_IOMMU_API) += iommu-sysfs.o
+obj-$(CONFIG_IOMMU_DEBUGFS) += iommu-debugfs.o
 obj-$(CONFIG_IOMMU_DMA) += dma-iommu.o
 obj-$(CONFIG_IOMMU_IO_PGTABLE) += io-pgtable.o
 obj-$(CONFIG_IOMMU_IO_PGTABLE_ARMV7S) += io-pgtable-arm-v7s.o
@@ -10,11 +11,12 @@ obj-$(CONFIG_IOMMU_IOVA) += iova.o
 obj-$(CONFIG_OF_IOMMU) += of_iommu.o
 obj-$(CONFIG_MSM_IOMMU) += msm_iommu.o
 obj-$(CONFIG_AMD_IOMMU) += amd_iommu.o amd_iommu_init.o
+obj-$(CONFIG_AMD_IOMMU_DEBUGFS) += amd_iommu_debugfs.o
 obj-$(CONFIG_AMD_IOMMU_V2) += amd_iommu_v2.o
 obj-$(CONFIG_ARM_SMMU) += arm-smmu.o
 obj-$(CONFIG_ARM_SMMU_V3) += arm-smmu-v3.o
 obj-$(CONFIG_DMAR_TABLE) += dmar.o
-obj-$(CONFIG_INTEL_IOMMU) += intel-iommu.o
+obj-$(CONFIG_INTEL_IOMMU) += intel-iommu.o intel-pasid.o
 obj-$(CONFIG_INTEL_IOMMU_SVM) += intel-svm.o
 obj-$(CONFIG_IPMMU_VMSA) += ipmmu-vmsa.o
 obj-$(CONFIG_IRQ_REMAP) += intel_irq_remapping.o irq_remapping.o
index 60b2eab..4e04fff 100644 (file)
@@ -1404,6 +1404,8 @@ static u64 *fetch_pte(struct protection_domain *domain,
        int level;
        u64 *pte;
 
+       *page_size = 0;
+
        if (address > PM_LEVEL_SIZE(domain->mode))
                return NULL;
 
@@ -1944,12 +1946,6 @@ static int __attach_device(struct iommu_dev_data *dev_data,
 {
        int ret;
 
-       /*
-        * Must be called with IRQs disabled. Warn here to detect early
-        * when its not.
-        */
-       WARN_ON(!irqs_disabled());
-
        /* lock domain */
        spin_lock(&domain->lock);
 
@@ -2115,12 +2111,6 @@ static void __detach_device(struct iommu_dev_data *dev_data)
 {
        struct protection_domain *domain;
 
-       /*
-        * Must be called with IRQs disabled. Warn here to detect early
-        * when its not.
-        */
-       WARN_ON(!irqs_disabled());
-
        domain = dev_data->domain;
 
        spin_lock(&domain->lock);
@@ -2405,9 +2395,9 @@ static void __unmap_single(struct dma_ops_domain *dma_dom,
        }
 
        if (amd_iommu_unmap_flush) {
-               dma_ops_free_iova(dma_dom, dma_addr, pages);
                domain_flush_tlb(&dma_dom->domain);
                domain_flush_complete(&dma_dom->domain);
+               dma_ops_free_iova(dma_dom, dma_addr, pages);
        } else {
                pages = __roundup_pow_of_two(pages);
                queue_iova(&dma_dom->iovad, dma_addr >> PAGE_SHIFT, pages, 0);
@@ -3192,7 +3182,6 @@ const struct iommu_ops amd_iommu_ops = {
        .detach_dev = amd_iommu_detach_device,
        .map = amd_iommu_map,
        .unmap = amd_iommu_unmap,
-       .map_sg = default_iommu_map_sg,
        .iova_to_phys = amd_iommu_iova_to_phys,
        .add_device = amd_iommu_add_device,
        .remove_device = amd_iommu_remove_device,
@@ -3874,7 +3863,8 @@ static void irte_ga_prepare(void *entry,
        irte->lo.fields_remap.int_type    = delivery_mode;
        irte->lo.fields_remap.dm          = dest_mode;
        irte->hi.fields.vector            = vector;
-       irte->lo.fields_remap.destination = dest_apicid;
+       irte->lo.fields_remap.destination = APICID_TO_IRTE_DEST_LO(dest_apicid);
+       irte->hi.fields.destination       = APICID_TO_IRTE_DEST_HI(dest_apicid);
        irte->lo.fields_remap.valid       = 1;
 }
 
@@ -3927,7 +3917,10 @@ static void irte_ga_set_affinity(void *entry, u16 devid, u16 index,
 
        if (!irte->lo.fields_remap.guest_mode) {
                irte->hi.fields.vector = vector;
-               irte->lo.fields_remap.destination = dest_apicid;
+               irte->lo.fields_remap.destination =
+                                       APICID_TO_IRTE_DEST_LO(dest_apicid);
+               irte->hi.fields.destination =
+                                       APICID_TO_IRTE_DEST_HI(dest_apicid);
                modify_irte_ga(devid, index, irte, NULL);
        }
 }
@@ -4344,7 +4337,10 @@ static int amd_ir_set_vcpu_affinity(struct irq_data *data, void *vcpu_info)
                irte->lo.val = 0;
                irte->hi.fields.vector = cfg->vector;
                irte->lo.fields_remap.guest_mode = 0;
-               irte->lo.fields_remap.destination = cfg->dest_apicid;
+               irte->lo.fields_remap.destination =
+                               APICID_TO_IRTE_DEST_LO(cfg->dest_apicid);
+               irte->hi.fields.destination =
+                               APICID_TO_IRTE_DEST_HI(cfg->dest_apicid);
                irte->lo.fields_remap.int_type = apic->irq_delivery_mode;
                irte->lo.fields_remap.dm = apic->irq_dest_mode;
 
@@ -4461,8 +4457,12 @@ int amd_iommu_update_ga(int cpu, bool is_run, void *data)
        raw_spin_lock_irqsave(&table->lock, flags);
 
        if (ref->lo.fields_vapic.guest_mode) {
-               if (cpu >= 0)
-                       ref->lo.fields_vapic.destination = cpu;
+               if (cpu >= 0) {
+                       ref->lo.fields_vapic.destination =
+                                               APICID_TO_IRTE_DEST_LO(cpu);
+                       ref->hi.fields.destination =
+                                               APICID_TO_IRTE_DEST_HI(cpu);
+               }
                ref->lo.fields_vapic.is_run = is_run;
                barrier();
        }
diff --git a/drivers/iommu/amd_iommu_debugfs.c b/drivers/iommu/amd_iommu_debugfs.c
new file mode 100644 (file)
index 0000000..c6a5c73
--- /dev/null
@@ -0,0 +1,33 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * AMD IOMMU driver
+ *
+ * Copyright (C) 2018 Advanced Micro Devices, Inc.
+ *
+ * Author: Gary R Hook <gary.hook@amd.com>
+ */
+
+#include <linux/debugfs.h>
+#include <linux/iommu.h>
+#include <linux/pci.h>
+#include "amd_iommu_proto.h"
+#include "amd_iommu_types.h"
+
+static struct dentry *amd_iommu_debugfs;
+static DEFINE_MUTEX(amd_iommu_debugfs_lock);
+
+#define        MAX_NAME_LEN    20
+
+void amd_iommu_debugfs_setup(struct amd_iommu *iommu)
+{
+       char name[MAX_NAME_LEN + 1];
+
+       mutex_lock(&amd_iommu_debugfs_lock);
+       if (!amd_iommu_debugfs)
+               amd_iommu_debugfs = debugfs_create_dir("amd",
+                                                      iommu_debugfs_dir);
+       mutex_unlock(&amd_iommu_debugfs_lock);
+
+       snprintf(name, MAX_NAME_LEN, "iommu%02d", iommu->index);
+       iommu->debugfs = debugfs_create_dir(name, amd_iommu_debugfs);
+}
index 904c575..84b3e44 100644 (file)
@@ -153,6 +153,7 @@ bool amd_iommu_dump;
 bool amd_iommu_irq_remap __read_mostly;
 
 int amd_iommu_guest_ir = AMD_IOMMU_GUEST_IR_VAPIC;
+static int amd_iommu_xt_mode = IRQ_REMAP_X2APIC_MODE;
 
 static bool amd_iommu_detected;
 static bool __initdata amd_iommu_disabled;
@@ -280,9 +281,9 @@ static void clear_translation_pre_enabled(struct amd_iommu *iommu)
 
 static void init_translation_status(struct amd_iommu *iommu)
 {
-       u32 ctrl;
+       u64 ctrl;
 
-       ctrl = readl(iommu->mmio_base + MMIO_CONTROL_OFFSET);
+       ctrl = readq(iommu->mmio_base + MMIO_CONTROL_OFFSET);
        if (ctrl & (1<<CONTROL_IOMMU_EN))
                iommu->flags |= AMD_IOMMU_FLAG_TRANS_PRE_ENABLED;
 }
@@ -386,30 +387,30 @@ static void iommu_set_device_table(struct amd_iommu *iommu)
 /* Generic functions to enable/disable certain features of the IOMMU. */
 static void iommu_feature_enable(struct amd_iommu *iommu, u8 bit)
 {
-       u32 ctrl;
+       u64 ctrl;
 
-       ctrl = readl(iommu->mmio_base + MMIO_CONTROL_OFFSET);
-       ctrl |= (1 << bit);
-       writel(ctrl, iommu->mmio_base + MMIO_CONTROL_OFFSET);
+       ctrl = readq(iommu->mmio_base +  MMIO_CONTROL_OFFSET);
+       ctrl |= (1ULL << bit);
+       writeq(ctrl, iommu->mmio_base +  MMIO_CONTROL_OFFSET);
 }
 
 static void iommu_feature_disable(struct amd_iommu *iommu, u8 bit)
 {
-       u32 ctrl;
+       u64 ctrl;
 
-       ctrl = readl(iommu->mmio_base + MMIO_CONTROL_OFFSET);
-       ctrl &= ~(1 << bit);
-       writel(ctrl, iommu->mmio_base + MMIO_CONTROL_OFFSET);
+       ctrl = readq(iommu->mmio_base + MMIO_CONTROL_OFFSET);
+       ctrl &= ~(1ULL << bit);
+       writeq(ctrl, iommu->mmio_base + MMIO_CONTROL_OFFSET);
 }
 
 static void iommu_set_inv_tlb_timeout(struct amd_iommu *iommu, int timeout)
 {
-       u32 ctrl;
+       u64 ctrl;
 
-       ctrl = readl(iommu->mmio_base + MMIO_CONTROL_OFFSET);
+       ctrl = readq(iommu->mmio_base + MMIO_CONTROL_OFFSET);
        ctrl &= ~CTRL_INV_TO_MASK;
        ctrl |= (timeout << CONTROL_INV_TIMEOUT) & CTRL_INV_TO_MASK;
-       writel(ctrl, iommu->mmio_base + MMIO_CONTROL_OFFSET);
+       writeq(ctrl, iommu->mmio_base + MMIO_CONTROL_OFFSET);
 }
 
 /* Function to enable the hardware */
@@ -827,6 +828,19 @@ static int iommu_init_ga(struct amd_iommu *iommu)
        return ret;
 }
 
+static void iommu_enable_xt(struct amd_iommu *iommu)
+{
+#ifdef CONFIG_IRQ_REMAP
+       /*
+        * XT mode (32-bit APIC destination ID) requires
+        * GA mode (128-bit IRTE support) as a prerequisite.
+        */
+       if (AMD_IOMMU_GUEST_IR_GA(amd_iommu_guest_ir) &&
+           amd_iommu_xt_mode == IRQ_REMAP_X2APIC_MODE)
+               iommu_feature_enable(iommu, CONTROL_XT_EN);
+#endif /* CONFIG_IRQ_REMAP */
+}
+
 static void iommu_enable_gt(struct amd_iommu *iommu)
 {
        if (!iommu_feature(iommu, FEATURE_GT))
@@ -1507,6 +1521,8 @@ static int __init init_iommu_one(struct amd_iommu *iommu, struct ivhd_header *h)
                        iommu->mmio_phys_end = MMIO_CNTR_CONF_OFFSET;
                if (((h->efr_attr & (0x1 << IOMMU_FEAT_GASUP_SHIFT)) == 0))
                        amd_iommu_guest_ir = AMD_IOMMU_GUEST_IR_LEGACY;
+               if (((h->efr_attr & (0x1 << IOMMU_FEAT_XTSUP_SHIFT)) == 0))
+                       amd_iommu_xt_mode = IRQ_REMAP_XAPIC_MODE;
                break;
        case 0x11:
        case 0x40:
@@ -1516,6 +1532,8 @@ static int __init init_iommu_one(struct amd_iommu *iommu, struct ivhd_header *h)
                        iommu->mmio_phys_end = MMIO_CNTR_CONF_OFFSET;
                if (((h->efr_reg & (0x1 << IOMMU_EFR_GASUP_SHIFT)) == 0))
                        amd_iommu_guest_ir = AMD_IOMMU_GUEST_IR_LEGACY;
+               if (((h->efr_reg & (0x1 << IOMMU_EFR_XTSUP_SHIFT)) == 0))
+                       amd_iommu_xt_mode = IRQ_REMAP_XAPIC_MODE;
                break;
        default:
                return -EINVAL;
@@ -1832,6 +1850,8 @@ static void print_iommu_info(void)
                pr_info("AMD-Vi: Interrupt remapping enabled\n");
                if (AMD_IOMMU_GUEST_IR_VAPIC(amd_iommu_guest_ir))
                        pr_info("AMD-Vi: virtual APIC enabled\n");
+               if (amd_iommu_xt_mode == IRQ_REMAP_X2APIC_MODE)
+                       pr_info("AMD-Vi: X2APIC enabled\n");
        }
 }
 
@@ -2168,6 +2188,7 @@ static void early_enable_iommu(struct amd_iommu *iommu)
        iommu_enable_event_buffer(iommu);
        iommu_set_exclusion_range(iommu);
        iommu_enable_ga(iommu);
+       iommu_enable_xt(iommu);
        iommu_enable(iommu);
        iommu_flush_all_caches(iommu);
 }
@@ -2212,6 +2233,7 @@ static void early_enable_iommus(void)
                        iommu_enable_command_buffer(iommu);
                        iommu_enable_event_buffer(iommu);
                        iommu_enable_ga(iommu);
+                       iommu_enable_xt(iommu);
                        iommu_set_device_table(iommu);
                        iommu_flush_all_caches(iommu);
                }
@@ -2691,8 +2713,7 @@ int __init amd_iommu_enable(void)
                return ret;
 
        irq_remapping_enabled = 1;
-
-       return 0;
+       return amd_iommu_xt_mode;
 }
 
 void amd_iommu_disable(void)
@@ -2721,6 +2742,7 @@ int __init amd_iommu_enable_faulting(void)
  */
 static int __init amd_iommu_init(void)
 {
+       struct amd_iommu *iommu;
        int ret;
 
        ret = iommu_go_to_state(IOMMU_INITIALIZED);
@@ -2730,14 +2752,15 @@ static int __init amd_iommu_init(void)
                        disable_iommus();
                        free_iommu_resources();
                } else {
-                       struct amd_iommu *iommu;
-
                        uninit_device_table_dma();
                        for_each_iommu(iommu)
                                iommu_flush_all_caches(iommu);
                }
        }
 
+       for_each_iommu(iommu)
+               amd_iommu_debugfs_setup(iommu);
+
        return ret;
 }
 
index 640c286..a8cd029 100644 (file)
@@ -33,6 +33,12 @@ extern void amd_iommu_uninit_devices(void);
 extern void amd_iommu_init_notifier(void);
 extern int amd_iommu_init_api(void);
 
+#ifdef CONFIG_AMD_IOMMU_DEBUGFS
+void amd_iommu_debugfs_setup(struct amd_iommu *iommu);
+#else
+static inline void amd_iommu_debugfs_setup(struct amd_iommu *iommu) {}
+#endif
+
 /* Needed for interrupt remapping */
 extern int amd_iommu_prepare(void);
 extern int amd_iommu_enable(void);
index 986cbe0..e2b342e 100644 (file)
 #define CONTROL_GAM_EN          0x19ULL
 #define CONTROL_GALOG_EN        0x1CULL
 #define CONTROL_GAINT_EN        0x1DULL
+#define CONTROL_XT_EN           0x32ULL
 
 #define CTRL_INV_TO_MASK       (7 << CONTROL_INV_TIMEOUT)
 #define CTRL_INV_TO_NONE       0
 #define IOMMU_CAP_EFR     27
 
 /* IOMMU Feature Reporting Field (for IVHD type 10h */
+#define IOMMU_FEAT_XTSUP_SHIFT 0
 #define IOMMU_FEAT_GASUP_SHIFT 6
 
 /* IOMMU Extended Feature Register (EFR) */
+#define IOMMU_EFR_XTSUP_SHIFT  2
 #define IOMMU_EFR_GASUP_SHIFT  7
 
 #define MAX_DOMAIN_ID 65536
@@ -437,7 +440,6 @@ extern struct kmem_cache *amd_iommu_irq_cache;
 #define APERTURE_RANGE_INDEX(a)        ((a) >> APERTURE_RANGE_SHIFT)
 #define APERTURE_PAGE_INDEX(a) (((a) >> 21) & 0x3fULL)
 
-
 /*
  * This struct is used to pass information about
  * incoming PPR faults around.
@@ -594,6 +596,11 @@ struct amd_iommu {
 
        u32 flags;
        volatile u64 __aligned(8) cmd_sem;
+
+#ifdef CONFIG_AMD_IOMMU_DEBUGFS
+       /* DebugFS Info */
+       struct dentry *debugfs;
+#endif
 };
 
 static inline struct amd_iommu *dev_to_amd_iommu(struct device *dev)
@@ -810,6 +817,9 @@ union irte {
        } fields;
 };
 
+#define APICID_TO_IRTE_DEST_LO(x)    (x & 0xffffff)
+#define APICID_TO_IRTE_DEST_HI(x)    ((x >> 24) & 0xff)
+
 union irte_ga_lo {
        u64 val;
 
@@ -823,8 +833,8 @@ union irte_ga_lo {
                    dm          : 1,
                    /* ------ */
                    guest_mode  : 1,
-                   destination : 8,
-                   rsvd        : 48;
+                   destination : 24,
+                   ga_tag      : 32;
        } fields_remap;
 
        /* For guest vAPIC */
@@ -837,8 +847,7 @@ union irte_ga_lo {
                    is_run      : 1,
                    /* ------ */
                    guest_mode  : 1,
-                   destination : 8,
-                   rsvd2       : 16,
+                   destination : 24,
                    ga_tag      : 32;
        } fields_vapic;
 };
@@ -849,7 +858,8 @@ union irte_ga_hi {
                u64 vector      : 8,
                    rsvd_1      : 4,
                    ga_root_ptr : 40,
-                   rsvd_2      : 12;
+                   rsvd_2      : 4,
+                   destination : 8;
        } fields;
 };
 
index 22bdabd..5059d09 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/acpi_iort.h>
 #include <linux/bitfield.h>
 #include <linux/bitops.h>
+#include <linux/crash_dump.h>
 #include <linux/delay.h>
 #include <linux/dma-iommu.h>
 #include <linux/err.h>
 #define MSI_IOVA_BASE                  0x8000000
 #define MSI_IOVA_LENGTH                        0x100000
 
-static bool disable_bypass;
+static bool disable_bypass = 1;
 module_param_named(disable_bypass, disable_bypass, bool, S_IRUGO);
 MODULE_PARM_DESC(disable_bypass,
        "Disable bypass streams such that incoming transactions from devices that are not attached to an iommu domain will report an abort back to the device and will not be allowed to pass through the SMMU.");
@@ -1301,6 +1302,7 @@ static irqreturn_t arm_smmu_priq_thread(int irq, void *dev)
 
        /* Sync our overflow flag, as we believe we're up to speed */
        q->cons = Q_OVF(q, q->prod) | Q_WRP(q, q->cons) | Q_IDX(q, q->cons);
+       writel(q->cons, q->cons_reg);
        return IRQ_HANDLED;
 }
 
@@ -1997,7 +1999,6 @@ static struct iommu_ops arm_smmu_ops = {
        .attach_dev             = arm_smmu_attach_dev,
        .map                    = arm_smmu_map,
        .unmap                  = arm_smmu_unmap,
-       .map_sg                 = default_iommu_map_sg,
        .flush_iotlb_all        = arm_smmu_iotlb_sync,
        .iotlb_sync             = arm_smmu_iotlb_sync,
        .iova_to_phys           = arm_smmu_iova_to_phys,
@@ -2211,8 +2212,12 @@ static int arm_smmu_update_gbpa(struct arm_smmu_device *smmu, u32 set, u32 clr)
        reg &= ~clr;
        reg |= set;
        writel_relaxed(reg | GBPA_UPDATE, gbpa);
-       return readl_relaxed_poll_timeout(gbpa, reg, !(reg & GBPA_UPDATE),
-                                         1, ARM_SMMU_POLL_TIMEOUT_US);
+       ret = readl_relaxed_poll_timeout(gbpa, reg, !(reg & GBPA_UPDATE),
+                                        1, ARM_SMMU_POLL_TIMEOUT_US);
+
+       if (ret)
+               dev_err(smmu->dev, "GBPA not responding to update\n");
+       return ret;
 }
 
 static void arm_smmu_free_msis(void *data)
@@ -2392,8 +2397,15 @@ static int arm_smmu_device_reset(struct arm_smmu_device *smmu, bool bypass)
 
        /* Clear CR0 and sync (disables SMMU and queue processing) */
        reg = readl_relaxed(smmu->base + ARM_SMMU_CR0);
-       if (reg & CR0_SMMUEN)
+       if (reg & CR0_SMMUEN) {
+               if (is_kdump_kernel()) {
+                       arm_smmu_update_gbpa(smmu, GBPA_ABORT, 0);
+                       arm_smmu_device_disable(smmu);
+                       return -EBUSY;
+               }
+
                dev_warn(smmu->dev, "SMMU currently enabled! Resetting...\n");
+       }
 
        ret = arm_smmu_device_disable(smmu);
        if (ret)
@@ -2491,10 +2503,8 @@ static int arm_smmu_device_reset(struct arm_smmu_device *smmu, bool bypass)
                enables |= CR0_SMMUEN;
        } else {
                ret = arm_smmu_update_gbpa(smmu, 0, GBPA_ABORT);
-               if (ret) {
-                       dev_err(smmu->dev, "GBPA not responding to update\n");
+               if (ret)
                        return ret;
-               }
        }
        ret = arm_smmu_write_reg_sync(smmu, enables, ARM_SMMU_CR0,
                                      ARM_SMMU_CR0ACK);
index c73cfce..fd1b80e 100644 (file)
@@ -1562,7 +1562,6 @@ static struct iommu_ops arm_smmu_ops = {
        .attach_dev             = arm_smmu_attach_dev,
        .map                    = arm_smmu_map,
        .unmap                  = arm_smmu_unmap,
-       .map_sg                 = default_iommu_map_sg,
        .flush_iotlb_all        = arm_smmu_iotlb_sync,
        .iotlb_sync             = arm_smmu_iotlb_sync,
        .iova_to_phys           = arm_smmu_iova_to_phys,
@@ -2103,12 +2102,16 @@ static int arm_smmu_device_probe(struct platform_device *pdev)
        if (err)
                return err;
 
-       if (smmu->version == ARM_SMMU_V2 &&
-           smmu->num_context_banks != smmu->num_context_irqs) {
-               dev_err(dev,
-                       "found only %d context interrupt(s) but %d required\n",
-                       smmu->num_context_irqs, smmu->num_context_banks);
-               return -ENODEV;
+       if (smmu->version == ARM_SMMU_V2) {
+               if (smmu->num_context_banks > smmu->num_context_irqs) {
+                       dev_err(dev,
+                             "found only %d context irq(s) but %d required\n",
+                             smmu->num_context_irqs, smmu->num_context_banks);
+                       return -ENODEV;
+               }
+
+               /* Ignore superfluous interrupts */
+               smmu->num_context_irqs = smmu->num_context_banks;
        }
 
        for (i = 0; i < smmu->num_global_irqs; ++i) {
index 75456b5..d9c748b 100644 (file)
@@ -1339,8 +1339,8 @@ void qi_flush_iotlb(struct intel_iommu *iommu, u16 did, u64 addr,
        qi_submit_sync(&desc, iommu);
 }
 
-void qi_flush_dev_iotlb(struct intel_iommu *iommu, u16 sid, u16 qdep,
-                       u64 addr, unsigned mask)
+void qi_flush_dev_iotlb(struct intel_iommu *iommu, u16 sid, u16 pfsid,
+                       u16 qdep, u64 addr, unsigned mask)
 {
        struct qi_desc desc;
 
@@ -1355,7 +1355,7 @@ void qi_flush_dev_iotlb(struct intel_iommu *iommu, u16 sid, u16 qdep,
                qdep = 0;
 
        desc.low = QI_DEV_IOTLB_SID(sid) | QI_DEV_IOTLB_QDEP(qdep) |
-                  QI_DIOTLB_TYPE;
+                  QI_DIOTLB_TYPE | QI_DEV_IOTLB_PFSID(pfsid);
 
        qi_submit_sync(&desc, iommu);
 }
index b128cb4..1bd0cd7 100644 (file)
@@ -1332,7 +1332,6 @@ static const struct iommu_ops exynos_iommu_ops = {
        .detach_dev = exynos_iommu_detach_device,
        .map = exynos_iommu_map,
        .unmap = exynos_iommu_unmap,
-       .map_sg = default_iommu_map_sg,
        .iova_to_phys = exynos_iommu_iova_to_phys,
        .device_group = generic_device_group,
        .add_device = exynos_iommu_add_device,
index 6a237d1..5f3f10c 100644 (file)
@@ -52,6 +52,7 @@
 #include <asm/iommu.h>
 
 #include "irq_remapping.h"
+#include "intel-pasid.h"
 
 #define ROOT_SIZE              VTD_PAGE_SIZE
 #define CONTEXT_SIZE           VTD_PAGE_SIZE
@@ -379,60 +380,6 @@ static int hw_pass_through = 1;
        for (idx = 0; idx < g_num_of_iommus; idx++)             \
                if (domain->iommu_refcnt[idx])
 
-struct dmar_domain {
-       int     nid;                    /* node id */
-
-       unsigned        iommu_refcnt[DMAR_UNITS_SUPPORTED];
-                                       /* Refcount of devices per iommu */
-
-
-       u16             iommu_did[DMAR_UNITS_SUPPORTED];
-                                       /* Domain ids per IOMMU. Use u16 since
-                                        * domain ids are 16 bit wide according
-                                        * to VT-d spec, section 9.3 */
-
-       bool has_iotlb_device;
-       struct list_head devices;       /* all devices' list */
-       struct iova_domain iovad;       /* iova's that belong to this domain */
-
-       struct dma_pte  *pgd;           /* virtual address */
-       int             gaw;            /* max guest address width */
-
-       /* adjusted guest address width, 0 is level 2 30-bit */
-       int             agaw;
-
-       int             flags;          /* flags to find out type of domain */
-
-       int             iommu_coherency;/* indicate coherency of iommu access */
-       int             iommu_snooping; /* indicate snooping control feature*/
-       int             iommu_count;    /* reference count of iommu */
-       int             iommu_superpage;/* Level of superpages supported:
-                                          0 == 4KiB (no superpages), 1 == 2MiB,
-                                          2 == 1GiB, 3 == 512GiB, 4 == 1TiB */
-       u64             max_addr;       /* maximum mapped address */
-
-       struct iommu_domain domain;     /* generic domain data structure for
-                                          iommu core */
-};
-
-/* PCI domain-device relationship */
-struct device_domain_info {
-       struct list_head link;  /* link to domain siblings */
-       struct list_head global; /* link to global list */
-       u8 bus;                 /* PCI bus number */
-       u8 devfn;               /* PCI devfn number */
-       u8 pasid_supported:3;
-       u8 pasid_enabled:1;
-       u8 pri_supported:1;
-       u8 pri_enabled:1;
-       u8 ats_supported:1;
-       u8 ats_enabled:1;
-       u8 ats_qdep;
-       struct device *dev; /* it's NULL for PCIe-to-PCI bridge */
-       struct intel_iommu *iommu; /* IOMMU used by this device */
-       struct dmar_domain *domain; /* pointer to domain */
-};
-
 struct dmar_rmrr_unit {
        struct list_head list;          /* list of rmrr units   */
        struct acpi_dmar_header *hdr;   /* ACPI header          */
@@ -523,6 +470,27 @@ EXPORT_SYMBOL_GPL(intel_iommu_gfx_mapped);
 static DEFINE_SPINLOCK(device_domain_lock);
 static LIST_HEAD(device_domain_list);
 
+/*
+ * Iterate over elements in device_domain_list and call the specified
+ * callback @fn against each element. This helper should only be used
+ * in the context where the device_domain_lock has already been holden.
+ */
+int for_each_device_domain(int (*fn)(struct device_domain_info *info,
+                                    void *data), void *data)
+{
+       int ret = 0;
+       struct device_domain_info *info;
+
+       assert_spin_locked(&device_domain_lock);
+       list_for_each_entry(info, &device_domain_list, global) {
+               ret = fn(info, data);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+
 const struct iommu_ops intel_iommu_ops;
 
 static bool translation_pre_enabled(struct intel_iommu *iommu)
@@ -629,7 +597,7 @@ static void set_iommu_domain(struct intel_iommu *iommu, u16 did,
                domains[did & 0xff] = domain;
 }
 
-static inline void *alloc_pgtable_page(int node)
+void *alloc_pgtable_page(int node)
 {
        struct page *page;
        void *vaddr = NULL;
@@ -640,7 +608,7 @@ static inline void *alloc_pgtable_page(int node)
        return vaddr;
 }
 
-static inline void free_pgtable_page(void *vaddr)
+void free_pgtable_page(void *vaddr)
 {
        free_page((unsigned long)vaddr);
 }
@@ -723,7 +691,7 @@ int iommu_calculate_agaw(struct intel_iommu *iommu)
 }
 
 /* This functionin only returns single iommu in a domain */
-static struct intel_iommu *domain_get_iommu(struct dmar_domain *domain)
+struct intel_iommu *domain_get_iommu(struct dmar_domain *domain)
 {
        int iommu_id;
 
@@ -1501,6 +1469,20 @@ static void iommu_enable_dev_iotlb(struct device_domain_info *info)
                return;
 
        pdev = to_pci_dev(info->dev);
+       /* For IOMMU that supports device IOTLB throttling (DIT), we assign
+        * PFSID to the invalidation desc of a VF such that IOMMU HW can gauge
+        * queue depth at PF level. If DIT is not set, PFSID will be treated as
+        * reserved, which should be set to 0.
+        */
+       if (!ecap_dit(info->iommu->ecap))
+               info->pfsid = 0;
+       else {
+               struct pci_dev *pf_pdev;
+
+               /* 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);
+       }
 
 #ifdef CONFIG_INTEL_IOMMU_SVM
        /* The PCIe spec, in its wisdom, declares that the behaviour of
@@ -1566,7 +1548,8 @@ static void iommu_flush_dev_iotlb(struct dmar_domain *domain,
 
                sid = info->bus << 8 | info->devfn;
                qdep = info->ats_qdep;
-               qi_flush_dev_iotlb(info->iommu, sid, qdep, addr, mask);
+               qi_flush_dev_iotlb(info->iommu, sid, info->pfsid,
+                               qdep, addr, mask);
        }
        spin_unlock_irqrestore(&device_domain_lock, flags);
 }
@@ -1800,7 +1783,7 @@ static void free_dmar_iommu(struct intel_iommu *iommu)
        if (pasid_enabled(iommu)) {
                if (ecap_prs(iommu->ecap))
                        intel_svm_finish_prq(iommu);
-               intel_svm_free_pasid_tables(iommu);
+               intel_svm_exit(iommu);
        }
 #endif
 }
@@ -2495,6 +2478,7 @@ static struct dmar_domain *dmar_insert_one_dev_info(struct intel_iommu *iommu,
        info->dev = dev;
        info->domain = domain;
        info->iommu = iommu;
+       info->pasid_table = NULL;
 
        if (dev && dev_is_pci(dev)) {
                struct pci_dev *pdev = to_pci_dev(info->dev);
@@ -2552,6 +2536,15 @@ static struct dmar_domain *dmar_insert_one_dev_info(struct intel_iommu *iommu,
        list_add(&info->global, &device_domain_list);
        if (dev)
                dev->archdata.iommu = info;
+
+       if (dev && dev_is_pci(dev) && info->pasid_supported) {
+               ret = intel_pasid_alloc_table(dev);
+               if (ret) {
+                       __dmar_remove_one_dev_info(info);
+                       spin_unlock_irqrestore(&device_domain_lock, flags);
+                       return NULL;
+               }
+       }
        spin_unlock_irqrestore(&device_domain_lock, flags);
 
        if (dev && domain_context_mapping(domain, dev)) {
@@ -3304,6 +3297,18 @@ static int __init init_dmars(void)
        }
 
        for_each_active_iommu(iommu, drhd) {
+               /*
+                * Find the max pasid size of all IOMMU's in the system.
+                * We need to ensure the system pasid table is no bigger
+                * than the smallest supported.
+                */
+               if (pasid_enabled(iommu)) {
+                       u32 temp = 2 << ecap_pss(iommu->ecap);
+
+                       intel_pasid_max_id = min_t(u32, temp,
+                                                  intel_pasid_max_id);
+               }
+
                g_iommus[iommu->seq_id] = iommu;
 
                intel_iommu_init_qi(iommu);
@@ -3359,7 +3364,7 @@ static int __init init_dmars(void)
                        hw_pass_through = 0;
 #ifdef CONFIG_INTEL_IOMMU_SVM
                if (pasid_enabled(iommu))
-                       intel_svm_alloc_pasid_tables(iommu);
+                       intel_svm_init(iommu);
 #endif
        }
 
@@ -3526,7 +3531,7 @@ static unsigned long intel_alloc_iova(struct device *dev,
        return iova_pfn;
 }
 
-static struct dmar_domain *get_valid_domain_for_dev(struct device *dev)
+struct dmar_domain *get_valid_domain_for_dev(struct device *dev)
 {
        struct dmar_domain *domain, *tmp;
        struct dmar_rmrr_unit *rmrr;
@@ -4354,7 +4359,7 @@ static int intel_iommu_add(struct dmar_drhd_unit *dmaru)
 
 #ifdef CONFIG_INTEL_IOMMU_SVM
        if (pasid_enabled(iommu))
-               intel_svm_alloc_pasid_tables(iommu);
+               intel_svm_init(iommu);
 #endif
 
        if (dmaru->ignored) {
@@ -4906,6 +4911,7 @@ static void __dmar_remove_one_dev_info(struct device_domain_info *info)
        if (info->dev) {
                iommu_disable_dev_iotlb(info);
                domain_context_clear(iommu, info->dev);
+               intel_pasid_free_table(info->dev);
        }
 
        unlink_domain_info(info);
@@ -5231,22 +5237,16 @@ static void intel_iommu_put_resv_regions(struct device *dev,
 
 #ifdef CONFIG_INTEL_IOMMU_SVM
 #define MAX_NR_PASID_BITS (20)
-static inline unsigned long intel_iommu_get_pts(struct intel_iommu *iommu)
+static inline unsigned long intel_iommu_get_pts(struct device *dev)
 {
-       /*
-        * Convert ecap_pss to extend context entry pts encoding, also
-        * respect the soft pasid_max value set by the iommu.
-        * - number of PASID bits = ecap_pss + 1
-        * - number of PASID table entries = 2^(pts + 5)
-        * Therefore, pts = ecap_pss - 4
-        * e.g. KBL ecap_pss = 0x13, PASID has 20 bits, pts = 15
-        */
-       if (ecap_pss(iommu->ecap) < 5)
+       int pts, max_pasid;
+
+       max_pasid = intel_pasid_get_dev_max_id(dev);
+       pts = find_first_bit((unsigned long *)&max_pasid, MAX_NR_PASID_BITS);
+       if (pts < 5)
                return 0;
 
-       /* pasid_max is encoded as actual number of entries not the bits */
-       return find_first_bit((unsigned long *)&iommu->pasid_max,
-                       MAX_NR_PASID_BITS) - 5;
+       return pts - 5;
 }
 
 int intel_iommu_enable_pasid(struct intel_iommu *iommu, struct intel_svm_dev *sdev)
@@ -5282,8 +5282,8 @@ int intel_iommu_enable_pasid(struct intel_iommu *iommu, struct intel_svm_dev *sd
        if (!(ctx_lo & CONTEXT_PASIDE)) {
                if (iommu->pasid_state_table)
                        context[1].hi = (u64)virt_to_phys(iommu->pasid_state_table);
-               context[1].lo = (u64)virt_to_phys(iommu->pasid_table) |
-                       intel_iommu_get_pts(iommu);
+               context[1].lo = (u64)virt_to_phys(info->pasid_table->table) |
+                       intel_iommu_get_pts(sdev->dev);
 
                wmb();
                /* CONTEXT_TT_MULTI_LEVEL and CONTEXT_TT_DEV_IOTLB are both
@@ -5350,11 +5350,6 @@ struct intel_iommu *intel_svm_device_to_iommu(struct device *dev)
                return NULL;
        }
 
-       if (!iommu->pasid_table) {
-               dev_err(dev, "PASID not enabled on IOMMU; cannot enable SVM\n");
-               return NULL;
-       }
-
        return iommu;
 }
 #endif /* CONFIG_INTEL_IOMMU_SVM */
@@ -5367,7 +5362,6 @@ const struct iommu_ops intel_iommu_ops = {
        .detach_dev             = intel_iommu_detach_device,
        .map                    = intel_iommu_map,
        .unmap                  = intel_iommu_unmap,
-       .map_sg                 = default_iommu_map_sg,
        .iova_to_phys           = intel_iommu_iova_to_phys,
        .add_device             = intel_iommu_add_device,
        .remove_device          = intel_iommu_remove_device,
diff --git a/drivers/iommu/intel-pasid.c b/drivers/iommu/intel-pasid.c
new file mode 100644 (file)
index 0000000..fe95c9b
--- /dev/null
@@ -0,0 +1,239 @@
+// SPDX-License-Identifier: GPL-2.0
+/**
+ * intel-pasid.c - PASID idr, table and entry manipulation
+ *
+ * Copyright (C) 2018 Intel Corporation
+ *
+ * Author: Lu Baolu <baolu.lu@linux.intel.com>
+ */
+
+#define pr_fmt(fmt)    "DMAR: " fmt
+
+#include <linux/dmar.h>
+#include <linux/intel-iommu.h>
+#include <linux/iommu.h>
+#include <linux/memory.h>
+#include <linux/pci.h>
+#include <linux/pci-ats.h>
+#include <linux/spinlock.h>
+
+#include "intel-pasid.h"
+
+/*
+ * Intel IOMMU system wide PASID name space:
+ */
+static DEFINE_SPINLOCK(pasid_lock);
+u32 intel_pasid_max_id = PASID_MAX;
+static DEFINE_IDR(pasid_idr);
+
+int intel_pasid_alloc_id(void *ptr, int start, int end, gfp_t gfp)
+{
+       int ret, min, max;
+
+       min = max_t(int, start, PASID_MIN);
+       max = min_t(int, end, intel_pasid_max_id);
+
+       WARN_ON(in_interrupt());
+       idr_preload(gfp);
+       spin_lock(&pasid_lock);
+       ret = idr_alloc(&pasid_idr, ptr, min, max, GFP_ATOMIC);
+       spin_unlock(&pasid_lock);
+       idr_preload_end();
+
+       return ret;
+}
+
+void intel_pasid_free_id(int pasid)
+{
+       spin_lock(&pasid_lock);
+       idr_remove(&pasid_idr, pasid);
+       spin_unlock(&pasid_lock);
+}
+
+void *intel_pasid_lookup_id(int pasid)
+{
+       void *p;
+
+       spin_lock(&pasid_lock);
+       p = idr_find(&pasid_idr, pasid);
+       spin_unlock(&pasid_lock);
+
+       return p;
+}
+
+/*
+ * Per device pasid table management:
+ */
+static inline void
+device_attach_pasid_table(struct device_domain_info *info,
+                         struct pasid_table *pasid_table)
+{
+       info->pasid_table = pasid_table;
+       list_add(&info->table, &pasid_table->dev);
+}
+
+static inline void
+device_detach_pasid_table(struct device_domain_info *info,
+                         struct pasid_table *pasid_table)
+{
+       info->pasid_table = NULL;
+       list_del(&info->table);
+}
+
+struct pasid_table_opaque {
+       struct pasid_table      **pasid_table;
+       int                     segment;
+       int                     bus;
+       int                     devfn;
+};
+
+static int search_pasid_table(struct device_domain_info *info, void *opaque)
+{
+       struct pasid_table_opaque *data = opaque;
+
+       if (info->iommu->segment == data->segment &&
+           info->bus == data->bus &&
+           info->devfn == data->devfn &&
+           info->pasid_table) {
+               *data->pasid_table = info->pasid_table;
+               return 1;
+       }
+
+       return 0;
+}
+
+static int get_alias_pasid_table(struct pci_dev *pdev, u16 alias, void *opaque)
+{
+       struct pasid_table_opaque *data = opaque;
+
+       data->segment = pci_domain_nr(pdev->bus);
+       data->bus = PCI_BUS_NUM(alias);
+       data->devfn = alias & 0xff;
+
+       return for_each_device_domain(&search_pasid_table, data);
+}
+
+/*
+ * Allocate a pasid table for @dev. It should be called in a
+ * single-thread context.
+ */
+int intel_pasid_alloc_table(struct device *dev)
+{
+       struct device_domain_info *info;
+       struct pasid_table *pasid_table;
+       struct pasid_table_opaque data;
+       struct page *pages;
+       size_t size, count;
+       int ret, order;
+
+       info = dev->archdata.iommu;
+       if (WARN_ON(!info || !dev_is_pci(dev) ||
+                   !info->pasid_supported || info->pasid_table))
+               return -EINVAL;
+
+       /* DMA alias device already has a pasid table, use it: */
+       data.pasid_table = &pasid_table;
+       ret = pci_for_each_dma_alias(to_pci_dev(dev),
+                                    &get_alias_pasid_table, &data);
+       if (ret)
+               goto attach_out;
+
+       pasid_table = kzalloc(sizeof(*pasid_table), GFP_ATOMIC);
+       if (!pasid_table)
+               return -ENOMEM;
+       INIT_LIST_HEAD(&pasid_table->dev);
+
+       size = sizeof(struct pasid_entry);
+       count = min_t(int, pci_max_pasids(to_pci_dev(dev)), intel_pasid_max_id);
+       order = get_order(size * count);
+       pages = alloc_pages_node(info->iommu->node,
+                                GFP_ATOMIC | __GFP_ZERO,
+                                order);
+       if (!pages)
+               return -ENOMEM;
+
+       pasid_table->table = page_address(pages);
+       pasid_table->order = order;
+       pasid_table->max_pasid = count;
+
+attach_out:
+       device_attach_pasid_table(info, pasid_table);
+
+       return 0;
+}
+
+void intel_pasid_free_table(struct device *dev)
+{
+       struct device_domain_info *info;
+       struct pasid_table *pasid_table;
+
+       info = dev->archdata.iommu;
+       if (!info || !dev_is_pci(dev) ||
+           !info->pasid_supported || !info->pasid_table)
+               return;
+
+       pasid_table = info->pasid_table;
+       device_detach_pasid_table(info, pasid_table);
+
+       if (!list_empty(&pasid_table->dev))
+               return;
+
+       free_pages((unsigned long)pasid_table->table, pasid_table->order);
+       kfree(pasid_table);
+}
+
+struct pasid_table *intel_pasid_get_table(struct device *dev)
+{
+       struct device_domain_info *info;
+
+       info = dev->archdata.iommu;
+       if (!info)
+               return NULL;
+
+       return info->pasid_table;
+}
+
+int intel_pasid_get_dev_max_id(struct device *dev)
+{
+       struct device_domain_info *info;
+
+       info = dev->archdata.iommu;
+       if (!info || !info->pasid_table)
+               return 0;
+
+       return info->pasid_table->max_pasid;
+}
+
+struct pasid_entry *intel_pasid_get_entry(struct device *dev, int pasid)
+{
+       struct pasid_table *pasid_table;
+       struct pasid_entry *entries;
+
+       pasid_table = intel_pasid_get_table(dev);
+       if (WARN_ON(!pasid_table || pasid < 0 ||
+                   pasid >= intel_pasid_get_dev_max_id(dev)))
+               return NULL;
+
+       entries = pasid_table->table;
+
+       return &entries[pasid];
+}
+
+/*
+ * Interfaces for PASID table entry manipulation:
+ */
+static inline void pasid_clear_entry(struct pasid_entry *pe)
+{
+       WRITE_ONCE(pe->val, 0);
+}
+
+void intel_pasid_clear_entry(struct device *dev, int pasid)
+{
+       struct pasid_entry *pe;
+
+       pe = intel_pasid_get_entry(dev, pasid);
+       if (WARN_ON(!pe))
+               return;
+
+       pasid_clear_entry(pe);
+}
diff --git a/drivers/iommu/intel-pasid.h b/drivers/iommu/intel-pasid.h
new file mode 100644 (file)
index 0000000..1c05ed6
--- /dev/null
@@ -0,0 +1,39 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * intel-pasid.h - PASID idr, table and entry header
+ *
+ * Copyright (C) 2018 Intel Corporation
+ *
+ * Author: Lu Baolu <baolu.lu@linux.intel.com>
+ */
+
+#ifndef __INTEL_PASID_H
+#define __INTEL_PASID_H
+
+#define PASID_MIN                      0x1
+#define PASID_MAX                      0x100000
+
+struct pasid_entry {
+       u64 val;
+};
+
+/* The representative of a PASID table */
+struct pasid_table {
+       void                    *table;         /* pasid table pointer */
+       int                     order;          /* page order of pasid table */
+       int                     max_pasid;      /* max pasid */
+       struct list_head        dev;            /* device list */
+};
+
+extern u32 intel_pasid_max_id;
+int intel_pasid_alloc_id(void *ptr, int start, int end, gfp_t gfp);
+void intel_pasid_free_id(int pasid);
+void *intel_pasid_lookup_id(int pasid);
+int intel_pasid_alloc_table(struct device *dev);
+void intel_pasid_free_table(struct device *dev);
+struct pasid_table *intel_pasid_get_table(struct device *dev);
+int intel_pasid_get_dev_max_id(struct device *dev);
+struct pasid_entry *intel_pasid_get_entry(struct device *dev, int pasid);
+void intel_pasid_clear_entry(struct device *dev, int pasid);
+
+#endif /* __INTEL_PASID_H */
index 7d65aab..4a03e50 100644 (file)
 #include <linux/mm_types.h>
 #include <asm/page.h>
 
+#include "intel-pasid.h"
+
 #define PASID_ENTRY_P          BIT_ULL(0)
 #define PASID_ENTRY_FLPM_5LP   BIT_ULL(9)
 #define PASID_ENTRY_SRE                BIT_ULL(11)
 
 static irqreturn_t prq_event_thread(int irq, void *d);
 
-struct pasid_entry {
-       u64 val;
-};
-
 struct pasid_state_entry {
        u64 val;
 };
 
-int intel_svm_alloc_pasid_tables(struct intel_iommu *iommu)
+int intel_svm_init(struct intel_iommu *iommu)
 {
        struct page *pages;
        int order;
@@ -66,15 +64,6 @@ int intel_svm_alloc_pasid_tables(struct intel_iommu *iommu)
                iommu->pasid_max = 0x20000;
 
        order = get_order(sizeof(struct pasid_entry) * iommu->pasid_max);
-       pages = alloc_pages(GFP_KERNEL | __GFP_ZERO, order);
-       if (!pages) {
-               pr_warn("IOMMU: %s: Failed to allocate PASID table\n",
-                       iommu->name);
-               return -ENOMEM;
-       }
-       iommu->pasid_table = page_address(pages);
-       pr_info("%s: Allocated order %d PASID table.\n", iommu->name, order);
-
        if (ecap_dis(iommu->ecap)) {
                /* Just making it explicit... */
                BUILD_BUG_ON(sizeof(struct pasid_entry) != sizeof(struct pasid_state_entry));
@@ -86,24 +75,18 @@ int intel_svm_alloc_pasid_tables(struct intel_iommu *iommu)
                                iommu->name);
        }
 
-       idr_init(&iommu->pasid_idr);
-
        return 0;
 }
 
-int intel_svm_free_pasid_tables(struct intel_iommu *iommu)
+int intel_svm_exit(struct intel_iommu *iommu)
 {
        int order = get_order(sizeof(struct pasid_entry) * iommu->pasid_max);
 
-       if (iommu->pasid_table) {
-               free_pages((unsigned long)iommu->pasid_table, order);
-               iommu->pasid_table = NULL;
-       }
        if (iommu->pasid_state_table) {
                free_pages((unsigned long)iommu->pasid_state_table, order);
                iommu->pasid_state_table = NULL;
        }
-       idr_destroy(&iommu->pasid_idr);
+
        return 0;
 }
 
@@ -279,11 +262,9 @@ static void intel_mm_release(struct mmu_notifier *mn, struct mm_struct *mm)
         * page) so that we end up taking a fault that the hardware really
         * *has* to handle gracefully without affecting other processes.
         */
-       svm->iommu->pasid_table[svm->pasid].val = 0;
-       wmb();
-
        rcu_read_lock();
        list_for_each_entry_rcu(sdev, &svm->devs, list) {
+               intel_pasid_clear_entry(sdev->dev, svm->pasid);
                intel_flush_pasid_dev(svm, sdev, svm->pasid);
                intel_flush_svm_range_dev(svm, sdev, 0, -1, 0, !svm->mm);
        }
@@ -299,10 +280,12 @@ static const struct mmu_notifier_ops intel_mmuops = {
 };
 
 static DEFINE_MUTEX(pasid_mutex);
+static LIST_HEAD(global_svm_list);
 
 int intel_svm_bind_mm(struct device *dev, int *pasid, int flags, struct svm_dev_ops *ops)
 {
        struct intel_iommu *iommu = intel_svm_device_to_iommu(dev);
+       struct pasid_entry *entry;
        struct intel_svm_dev *sdev;
        struct intel_svm *svm = NULL;
        struct mm_struct *mm = NULL;
@@ -310,7 +293,7 @@ int intel_svm_bind_mm(struct device *dev, int *pasid, int flags, struct svm_dev_
        int pasid_max;
        int ret;
 
-       if (WARN_ON(!iommu || !iommu->pasid_table))
+       if (!iommu)
                return -EINVAL;
 
        if (dev_is_pci(dev)) {
@@ -330,13 +313,13 @@ int intel_svm_bind_mm(struct device *dev, int *pasid, int flags, struct svm_dev_
 
        mutex_lock(&pasid_mutex);
        if (pasid && !(flags & SVM_FLAG_PRIVATE_PASID)) {
-               int i;
+               struct intel_svm *t;
 
-               idr_for_each_entry(&iommu->pasid_idr, svm, i) {
-                       if (svm->mm != mm ||
-                           (svm->flags & SVM_FLAG_PRIVATE_PASID))
+               list_for_each_entry(t, &global_svm_list, list) {
+                       if (t->mm != mm || (t->flags & SVM_FLAG_PRIVATE_PASID))
                                continue;
 
+                       svm = t;
                        if (svm->pasid >= pasid_max) {
                                dev_warn(dev,
                                         "Limited PASID width. Cannot use existing PASID %d\n",
@@ -388,13 +371,13 @@ int intel_svm_bind_mm(struct device *dev, int *pasid, int flags, struct svm_dev_
                }
                svm->iommu = iommu;
 
-               if (pasid_max > iommu->pasid_max)
-                       pasid_max = iommu->pasid_max;
+               if (pasid_max > intel_pasid_max_id)
+                       pasid_max = intel_pasid_max_id;
 
                /* Do not use PASID 0 in caching mode (virtualised IOMMU) */
-               ret = idr_alloc(&iommu->pasid_idr, svm,
-                               !!cap_caching_mode(iommu->cap),
-                               pasid_max - 1, GFP_KERNEL);
+               ret = intel_pasid_alloc_id(svm,
+                                          !!cap_caching_mode(iommu->cap),
+                                          pasid_max - 1, GFP_KERNEL);
                if (ret < 0) {
                        kfree(svm);
                        kfree(sdev);
@@ -405,11 +388,12 @@ int intel_svm_bind_mm(struct device *dev, int *pasid, int flags, struct svm_dev_
                svm->mm = mm;
                svm->flags = flags;
                INIT_LIST_HEAD_RCU(&svm->devs);
+               INIT_LIST_HEAD(&svm->list);
                ret = -ENOMEM;
                if (mm) {
                        ret = mmu_notifier_register(&svm->notifier, mm);
                        if (ret) {
-                               idr_remove(&svm->iommu->pasid_idr, svm->pasid);
+                               intel_pasid_free_id(svm->pasid);
                                kfree(svm);
                                kfree(sdev);
                                goto out;
@@ -421,7 +405,8 @@ int intel_svm_bind_mm(struct device *dev, int *pasid, int flags, struct svm_dev_
                if (cpu_feature_enabled(X86_FEATURE_LA57))
                        pasid_entry_val |= PASID_ENTRY_FLPM_5LP;
 
-               iommu->pasid_table[svm->pasid].val = pasid_entry_val;
+               entry = intel_pasid_get_entry(dev, svm->pasid);
+               entry->val = pasid_entry_val;
 
                wmb();
 
@@ -431,6 +416,8 @@ int intel_svm_bind_mm(struct device *dev, int *pasid, int flags, struct svm_dev_
                 */
                if (cap_caching_mode(iommu->cap))
                        intel_flush_pasid_dev(svm, sdev, svm->pasid);
+
+               list_add_tail(&svm->list, &global_svm_list);
        }
        list_add_rcu(&sdev->list, &svm->devs);
 
@@ -454,10 +441,10 @@ int intel_svm_unbind_mm(struct device *dev, int pasid)
 
        mutex_lock(&pasid_mutex);
        iommu = intel_svm_device_to_iommu(dev);
-       if (!iommu || !iommu->pasid_table)
+       if (!iommu)
                goto out;
 
-       svm = idr_find(&iommu->pasid_idr, pasid);
+       svm = intel_pasid_lookup_id(pasid);
        if (!svm)
                goto out;
 
@@ -477,15 +464,15 @@ int intel_svm_unbind_mm(struct device *dev, int pasid)
                                intel_flush_pasid_dev(svm, sdev, svm->pasid);
                                intel_flush_svm_range_dev(svm, sdev, 0, -1, 0, !svm->mm);
                                kfree_rcu(sdev, rcu);
+                               intel_pasid_clear_entry(dev, svm->pasid);
 
                                if (list_empty(&svm->devs)) {
-                                       svm->iommu->pasid_table[svm->pasid].val = 0;
-                                       wmb();
-
-                                       idr_remove(&svm->iommu->pasid_idr, svm->pasid);
+                                       intel_pasid_free_id(svm->pasid);
                                        if (svm->mm)
                                                mmu_notifier_unregister(&svm->notifier, svm->mm);
 
+                                       list_del(&svm->list);
+
                                        /* We mandate that no page faults may be outstanding
                                         * for the PASID when intel_svm_unbind_mm() is called.
                                         * If that is not obeyed, subtle errors will happen.
@@ -512,10 +499,10 @@ int intel_svm_is_pasid_valid(struct device *dev, int pasid)
 
        mutex_lock(&pasid_mutex);
        iommu = intel_svm_device_to_iommu(dev);
-       if (!iommu || !iommu->pasid_table)
+       if (!iommu)
                goto out;
 
-       svm = idr_find(&iommu->pasid_idr, pasid);
+       svm = intel_pasid_lookup_id(pasid);
        if (!svm)
                goto out;
 
@@ -614,7 +601,7 @@ static irqreturn_t prq_event_thread(int irq, void *d)
 
                if (!svm || svm->pasid != req->pasid) {
                        rcu_read_lock();
-                       svm = idr_find(&iommu->pasid_idr, req->pasid);
+                       svm = intel_pasid_lookup_id(req->pasid);
                        /* It *can't* go away, because the driver is not permitted
                         * to unbind the mm while any page faults are outstanding.
                         * So we only need RCU to protect the internal idr code. */
index 50e3a9f..b5948ba 100644 (file)
@@ -192,6 +192,7 @@ static void *__arm_v7s_alloc_table(int lvl, gfp_t gfp,
 {
        struct io_pgtable_cfg *cfg = &data->iop.cfg;
        struct device *dev = cfg->iommu_dev;
+       phys_addr_t phys;
        dma_addr_t dma;
        size_t size = ARM_V7S_TABLE_SIZE(lvl);
        void *table = NULL;
@@ -200,6 +201,10 @@ static void *__arm_v7s_alloc_table(int lvl, gfp_t gfp,
                table = (void *)__get_dma_pages(__GFP_ZERO, get_order(size));
        else if (lvl == 2)
                table = kmem_cache_zalloc(data->l2_tables, gfp | GFP_DMA);
+       phys = virt_to_phys(table);
+       if (phys != (arm_v7s_iopte)phys)
+               /* Doesn't fit in PTE */
+               goto out_free;
        if (table && !(cfg->quirks & IO_PGTABLE_QUIRK_NO_DMA)) {
                dma = dma_map_single(dev, table, size, DMA_TO_DEVICE);
                if (dma_mapping_error(dev, dma))
@@ -209,7 +214,7 @@ static void *__arm_v7s_alloc_table(int lvl, gfp_t gfp,
                 * address directly, so if the DMA layer suggests otherwise by
                 * translating or truncating them, that bodes very badly...
                 */
-               if (dma != virt_to_phys(table))
+               if (dma != phys)
                        goto out_unmap;
        }
        kmemleak_ignore(table);
index 010a254..88641b4 100644 (file)
@@ -237,7 +237,8 @@ static void *__arm_lpae_alloc_pages(size_t size, gfp_t gfp,
        void *pages;
 
        VM_BUG_ON((gfp & __GFP_HIGHMEM));
-       p = alloc_pages_node(dev_to_node(dev), gfp | __GFP_ZERO, order);
+       p = alloc_pages_node(dev ? dev_to_node(dev) : NUMA_NO_NODE,
+                            gfp | __GFP_ZERO, order);
        if (!p)
                return NULL;
 
diff --git a/drivers/iommu/iommu-debugfs.c b/drivers/iommu/iommu-debugfs.c
new file mode 100644 (file)
index 0000000..3b1bf88
--- /dev/null
@@ -0,0 +1,66 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * IOMMU debugfs core infrastructure
+ *
+ * Copyright (C) 2018 Advanced Micro Devices, Inc.
+ *
+ * Author: Gary R Hook <gary.hook@amd.com>
+ */
+
+#include <linux/pci.h>
+#include <linux/iommu.h>
+#include <linux/debugfs.h>
+
+struct dentry *iommu_debugfs_dir;
+
+/**
+ * iommu_debugfs_setup - create the top-level iommu directory in debugfs
+ *
+ * Provide base enablement for using debugfs to expose internal data of an
+ * IOMMU driver. When called, this function creates the
+ * /sys/kernel/debug/iommu directory.
+ *
+ * Emit a strong warning at boot time to indicate that this feature is
+ * enabled.
+ *
+ * This function is called from iommu_init; drivers may then call
+ * iommu_debugfs_new_driver_dir() to instantiate a vendor-specific
+ * directory to be used to expose internal data.
+ */
+void iommu_debugfs_setup(void)
+{
+       if (!iommu_debugfs_dir) {
+               iommu_debugfs_dir = debugfs_create_dir("iommu", NULL);
+               pr_warn("\n");
+               pr_warn("*************************************************************\n");
+               pr_warn("**     NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE    **\n");
+               pr_warn("**                                                         **\n");
+               pr_warn("**  IOMMU DebugFS SUPPORT HAS BEEN ENABLED IN THIS KERNEL  **\n");
+               pr_warn("**                                                         **\n");
+               pr_warn("** This means that this kernel is built to expose internal **\n");
+               pr_warn("** IOMMU data structures, which may compromise security on **\n");
+               pr_warn("** your system.                                            **\n");
+               pr_warn("**                                                         **\n");
+               pr_warn("** If you see this message and you are not debugging the   **\n");
+               pr_warn("** kernel, report this immediately to your vendor!         **\n");
+               pr_warn("**                                                         **\n");
+               pr_warn("**     NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE    **\n");
+               pr_warn("*************************************************************\n");
+       }
+}
+
+/**
+ * iommu_debugfs_new_driver_dir - create a vendor directory under debugfs/iommu
+ * @vendor: name of the vendor-specific subdirectory to create
+ *
+ * This function is called by an IOMMU driver to create the top-level debugfs
+ * directory for that driver.
+ *
+ * Return: upon success, a pointer to the dentry for the new directory.
+ *         NULL in case of failure.
+ */
+struct dentry *iommu_debugfs_new_driver_dir(const char *vendor)
+{
+       return debugfs_create_dir(vendor, iommu_debugfs_dir);
+}
+EXPORT_SYMBOL_GPL(iommu_debugfs_new_driver_dir);
index 63b3756..8c15c59 100644 (file)
 
 static struct kset *iommu_group_kset;
 static DEFINE_IDA(iommu_group_ida);
+#ifdef CONFIG_IOMMU_DEFAULT_PASSTHROUGH
+static unsigned int iommu_def_domain_type = IOMMU_DOMAIN_IDENTITY;
+#else
 static unsigned int iommu_def_domain_type = IOMMU_DOMAIN_DMA;
+#endif
 
 struct iommu_callback_data {
        const struct iommu_ops *ops;
@@ -294,11 +298,39 @@ static ssize_t iommu_group_show_resv_regions(struct iommu_group *group,
        return (str - buf);
 }
 
+static ssize_t iommu_group_show_type(struct iommu_group *group,
+                                    char *buf)
+{
+       char *type = "unknown\n";
+
+       if (group->default_domain) {
+               switch (group->default_domain->type) {
+               case IOMMU_DOMAIN_BLOCKED:
+                       type = "blocked\n";
+                       break;
+               case IOMMU_DOMAIN_IDENTITY:
+                       type = "identity\n";
+                       break;
+               case IOMMU_DOMAIN_UNMANAGED:
+                       type = "unmanaged\n";
+                       break;
+               case IOMMU_DOMAIN_DMA:
+                       type = "DMA";
+                       break;
+               }
+       }
+       strcpy(buf, type);
+
+       return strlen(type);
+}
+
 static IOMMU_GROUP_ATTR(name, S_IRUGO, iommu_group_show_name, NULL);
 
 static IOMMU_GROUP_ATTR(reserved_regions, 0444,
                        iommu_group_show_resv_regions, NULL);
 
+static IOMMU_GROUP_ATTR(type, 0444, iommu_group_show_type, NULL);
+
 static void iommu_group_release(struct kobject *kobj)
 {
        struct iommu_group *group = to_iommu_group(kobj);
@@ -380,6 +412,10 @@ struct iommu_group *iommu_group_alloc(void)
        if (ret)
                return ERR_PTR(ret);
 
+       ret = iommu_group_create_file(group, &iommu_group_attr_type);
+       if (ret)
+               return ERR_PTR(ret);
+
        pr_debug("Allocated group %d\n", group->id);
 
        return group;
@@ -1637,8 +1673,8 @@ size_t iommu_unmap_fast(struct iommu_domain *domain,
 }
 EXPORT_SYMBOL_GPL(iommu_unmap_fast);
 
-size_t default_iommu_map_sg(struct iommu_domain *domain, unsigned long iova,
-                        struct scatterlist *sg, unsigned int nents, int prot)
+size_t iommu_map_sg(struct iommu_domain *domain, unsigned long iova,
+                   struct scatterlist *sg, unsigned int nents, int prot)
 {
        struct scatterlist *s;
        size_t mapped = 0;
@@ -1678,7 +1714,7 @@ out_err:
        return 0;
 
 }
-EXPORT_SYMBOL_GPL(default_iommu_map_sg);
+EXPORT_SYMBOL_GPL(iommu_map_sg);
 
 int iommu_domain_window_enable(struct iommu_domain *domain, u32 wnd_nr,
                               phys_addr_t paddr, u64 size, int prot)
@@ -1748,6 +1784,8 @@ static int __init iommu_init(void)
                                               NULL, kernel_kobj);
        BUG_ON(!iommu_group_kset);
 
+       iommu_debugfs_setup();
+
        return 0;
 }
 core_initcall(iommu_init);
index f026aa1..22b94f8 100644 (file)
@@ -47,6 +47,7 @@ struct ipmmu_features {
        unsigned int number_of_contexts;
        bool setup_imbuscr;
        bool twobit_imttbcr_sl0;
+       bool reserved_context;
 };
 
 struct ipmmu_vmsa_device {
@@ -73,7 +74,7 @@ struct ipmmu_vmsa_domain {
        struct io_pgtable_ops *iop;
 
        unsigned int context_id;
-       spinlock_t lock;                        /* Protects mappings */
+       struct mutex mutex;                     /* Protects mappings */
 };
 
 static struct ipmmu_vmsa_domain *to_vmsa_domain(struct iommu_domain *dom)
@@ -194,7 +195,9 @@ static struct ipmmu_vmsa_device *to_ipmmu(struct device *dev)
 #define IMPMBA(n)                      (0x0280 + ((n) * 4))
 #define IMPMBD(n)                      (0x02c0 + ((n) * 4))
 
-#define IMUCTR(n)                      (0x0300 + ((n) * 16))
+#define IMUCTR(n)                      ((n) < 32 ? IMUCTR0(n) : IMUCTR32(n))
+#define IMUCTR0(n)                     (0x0300 + ((n) * 16))
+#define IMUCTR32(n)                    (0x0600 + (((n) - 32) * 16))
 #define IMUCTR_FIXADDEN                        (1 << 31)
 #define IMUCTR_FIXADD_MASK             (0xff << 16)
 #define IMUCTR_FIXADD_SHIFT            16
@@ -204,7 +207,9 @@ static struct ipmmu_vmsa_device *to_ipmmu(struct device *dev)
 #define IMUCTR_FLUSH                   (1 << 1)
 #define IMUCTR_MMUEN                   (1 << 0)
 
-#define IMUASID(n)                     (0x0308 + ((n) * 16))
+#define IMUASID(n)                     ((n) < 32 ? IMUASID0(n) : IMUASID32(n))
+#define IMUASID0(n)                    (0x0308 + ((n) * 16))
+#define IMUASID32(n)                   (0x0608 + (((n) - 32) * 16))
 #define IMUASID_ASID8_MASK             (0xff << 8)
 #define IMUASID_ASID8_SHIFT            8
 #define IMUASID_ASID0_MASK             (0xff << 0)
@@ -595,7 +600,7 @@ static struct iommu_domain *__ipmmu_domain_alloc(unsigned type)
        if (!domain)
                return NULL;
 
-       spin_lock_init(&domain->lock);
+       mutex_init(&domain->mutex);
 
        return &domain->io_domain;
 }
@@ -641,7 +646,6 @@ static int ipmmu_attach_device(struct iommu_domain *io_domain,
        struct iommu_fwspec *fwspec = dev->iommu_fwspec;
        struct ipmmu_vmsa_device *mmu = to_ipmmu(dev);
        struct ipmmu_vmsa_domain *domain = to_vmsa_domain(io_domain);
-       unsigned long flags;
        unsigned int i;
        int ret = 0;
 
@@ -650,7 +654,7 @@ static int ipmmu_attach_device(struct iommu_domain *io_domain,
                return -ENXIO;
        }
 
-       spin_lock_irqsave(&domain->lock, flags);
+       mutex_lock(&domain->mutex);
 
        if (!domain->mmu) {
                /* The domain hasn't been used yet, initialize it. */
@@ -674,7 +678,7 @@ static int ipmmu_attach_device(struct iommu_domain *io_domain,
        } else
                dev_info(dev, "Reusing IPMMU context %u\n", domain->context_id);
 
-       spin_unlock_irqrestore(&domain->lock, flags);
+       mutex_unlock(&domain->mutex);
 
        if (ret < 0)
                return ret;
@@ -756,8 +760,12 @@ static bool ipmmu_slave_whitelist(struct device *dev)
        return false;
 }
 
-static const struct soc_device_attribute soc_r8a7795[] = {
+static const struct soc_device_attribute soc_rcar_gen3[] = {
        { .soc_id = "r8a7795", },
+       { .soc_id = "r8a7796", },
+       { .soc_id = "r8a77965", },
+       { .soc_id = "r8a77970", },
+       { .soc_id = "r8a77995", },
        { /* sentinel */ }
 };
 
@@ -765,7 +773,7 @@ static int ipmmu_of_xlate(struct device *dev,
                          struct of_phandle_args *spec)
 {
        /* For R-Car Gen3 use a white list to opt-in slave devices */
-       if (soc_device_match(soc_r8a7795) && !ipmmu_slave_whitelist(dev))
+       if (soc_device_match(soc_rcar_gen3) && !ipmmu_slave_whitelist(dev))
                return -ENODEV;
 
        iommu_fwspec_add_ids(dev, spec->args, 1);
@@ -889,7 +897,6 @@ static const struct iommu_ops ipmmu_ops = {
        .unmap = ipmmu_unmap,
        .flush_iotlb_all = ipmmu_iotlb_sync,
        .iotlb_sync = ipmmu_iotlb_sync,
-       .map_sg = default_iommu_map_sg,
        .iova_to_phys = ipmmu_iova_to_phys,
        .add_device = ipmmu_add_device,
        .remove_device = ipmmu_remove_device,
@@ -917,14 +924,16 @@ static const struct ipmmu_features ipmmu_features_default = {
        .number_of_contexts = 1, /* software only tested with one context */
        .setup_imbuscr = true,
        .twobit_imttbcr_sl0 = false,
+       .reserved_context = false,
 };
 
-static const struct ipmmu_features ipmmu_features_r8a7795 = {
+static const struct ipmmu_features ipmmu_features_rcar_gen3 = {
        .use_ns_alias_offset = false,
        .has_cache_leaf_nodes = true,
        .number_of_contexts = 8,
        .setup_imbuscr = false,
        .twobit_imttbcr_sl0 = true,
+       .reserved_context = true,
 };
 
 static const struct of_device_id ipmmu_of_ids[] = {
@@ -933,7 +942,19 @@ static const struct of_device_id ipmmu_of_ids[] = {
                .data = &ipmmu_features_default,
        }, {
                .compatible = "renesas,ipmmu-r8a7795",
-               .data = &ipmmu_features_r8a7795,
+               .data = &ipmmu_features_rcar_gen3,
+       }, {
+               .compatible = "renesas,ipmmu-r8a7796",
+               .data = &ipmmu_features_rcar_gen3,
+       }, {
+               .compatible = "renesas,ipmmu-r8a77965",
+               .data = &ipmmu_features_rcar_gen3,
+       }, {
+               .compatible = "renesas,ipmmu-r8a77970",
+               .data = &ipmmu_features_rcar_gen3,
+       }, {
+               .compatible = "renesas,ipmmu-r8a77995",
+               .data = &ipmmu_features_rcar_gen3,
        }, {
                /* Terminator */
        },
@@ -955,7 +976,7 @@ static int ipmmu_probe(struct platform_device *pdev)
        }
 
        mmu->dev = &pdev->dev;
-       mmu->num_utlbs = 32;
+       mmu->num_utlbs = 48;
        spin_lock_init(&mmu->lock);
        bitmap_zero(mmu->ctx, IPMMU_CTX_MAX);
        mmu->features = of_device_get_match_data(&pdev->dev);
@@ -1018,6 +1039,11 @@ static int ipmmu_probe(struct platform_device *pdev)
                }
 
                ipmmu_device_reset(mmu);
+
+               if (mmu->features->reserved_context) {
+                       dev_info(&pdev->dev, "IPMMU context 0 is reserved\n");
+                       set_bit(0, mmu->ctx);
+               }
        }
 
        /*
@@ -1081,12 +1107,19 @@ static struct platform_driver ipmmu_driver = {
 
 static int __init ipmmu_init(void)
 {
+       struct device_node *np;
        static bool setup_done;
        int ret;
 
        if (setup_done)
                return 0;
 
+       np = of_find_matching_node(NULL, ipmmu_of_ids);
+       if (!np)
+               return 0;
+
+       of_node_put(np);
+
        ret = platform_driver_register(&ipmmu_driver);
        if (ret < 0)
                return ret;
index 2737774..fc5f0b5 100644 (file)
@@ -395,20 +395,15 @@ static int msm_iommu_add_device(struct device *dev)
        struct msm_iommu_dev *iommu;
        struct iommu_group *group;
        unsigned long flags;
-       int ret = 0;
 
        spin_lock_irqsave(&msm_iommu_lock, flags);
-
        iommu = find_iommu_for_dev(dev);
+       spin_unlock_irqrestore(&msm_iommu_lock, flags);
+
        if (iommu)
                iommu_device_link(&iommu->iommu, dev);
        else
-               ret = -ENODEV;
-
-       spin_unlock_irqrestore(&msm_iommu_lock, flags);
-
-       if (ret)
-               return ret;
+               return -ENODEV;
 
        group = iommu_group_get_for_dev(dev);
        if (IS_ERR(group))
@@ -425,13 +420,12 @@ static void msm_iommu_remove_device(struct device *dev)
        unsigned long flags;
 
        spin_lock_irqsave(&msm_iommu_lock, flags);
-
        iommu = find_iommu_for_dev(dev);
+       spin_unlock_irqrestore(&msm_iommu_lock, flags);
+
        if (iommu)
                iommu_device_unlink(&iommu->iommu, dev);
 
-       spin_unlock_irqrestore(&msm_iommu_lock, flags);
-
        iommu_group_remove_device(dev);
 }
 
@@ -708,7 +702,6 @@ static struct iommu_ops msm_iommu_ops = {
        .detach_dev = msm_iommu_detach_dev,
        .map = msm_iommu_map,
        .unmap = msm_iommu_unmap,
-       .map_sg = default_iommu_map_sg,
        .iova_to_phys = msm_iommu_iova_to_phys,
        .add_device = msm_iommu_add_device,
        .remove_device = msm_iommu_remove_device,
index f2832a1..f9f69f7 100644 (file)
@@ -495,7 +495,6 @@ static struct iommu_ops mtk_iommu_ops = {
        .detach_dev     = mtk_iommu_detach_device,
        .map            = mtk_iommu_map,
        .unmap          = mtk_iommu_unmap,
-       .map_sg         = default_iommu_map_sg,
        .flush_iotlb_all = mtk_iommu_iotlb_sync,
        .iotlb_sync     = mtk_iommu_iotlb_sync,
        .iova_to_phys   = mtk_iommu_iova_to_phys,
index a7c2a97..676c029 100644 (file)
@@ -531,7 +531,6 @@ static struct iommu_ops mtk_iommu_ops = {
        .detach_dev     = mtk_iommu_detach_device,
        .map            = mtk_iommu_map,
        .unmap          = mtk_iommu_unmap,
-       .map_sg         = default_iommu_map_sg,
        .iova_to_phys   = mtk_iommu_iova_to_phys,
        .add_device     = mtk_iommu_add_device,
        .remove_device  = mtk_iommu_remove_device,
index af4a8e7..d2fb347 100644 (file)
@@ -550,7 +550,7 @@ static u32 *iopte_alloc(struct omap_iommu *obj, u32 *iopgd,
 
 pte_ready:
        iopte = iopte_offset(iopgd, da);
-       *pt_dma = virt_to_phys(iopte);
+       *pt_dma = iopgd_page_paddr(iopgd);
        dev_vdbg(obj->dev,
                 "%s: da:%08x pgd:%p *pgd:%08x pte:%p *pte:%08x\n",
                 __func__, da, iopgd, *iopgd, iopte, *iopte);
@@ -738,7 +738,7 @@ static size_t iopgtable_clear_entry_core(struct omap_iommu *obj, u32 da)
                }
                bytes *= nent;
                memset(iopte, 0, nent * sizeof(*iopte));
-               pt_dma = virt_to_phys(iopte);
+               pt_dma = iopgd_page_paddr(iopgd);
                flush_iopte_range(obj->dev, pt_dma, pt_offset, nent);
 
                /*
@@ -1548,7 +1548,6 @@ static const struct iommu_ops omap_iommu_ops = {
        .detach_dev     = omap_iommu_detach_dev,
        .map            = omap_iommu_map,
        .unmap          = omap_iommu_unmap,
-       .map_sg         = default_iommu_map_sg,
        .iova_to_phys   = omap_iommu_iova_to_phys,
        .add_device     = omap_iommu_add_device,
        .remove_device  = omap_iommu_remove_device,
index b48aee8..ee70e99 100644 (file)
@@ -590,7 +590,6 @@ static const struct iommu_ops qcom_iommu_ops = {
        .detach_dev     = qcom_iommu_detach_dev,
        .map            = qcom_iommu_map,
        .unmap          = qcom_iommu_unmap,
-       .map_sg         = default_iommu_map_sg,
        .flush_iotlb_all = qcom_iommu_iotlb_sync,
        .iotlb_sync     = qcom_iommu_iotlb_sync,
        .iova_to_phys   = qcom_iommu_iova_to_phys,
index de8d3bf..258115b 100644 (file)
@@ -521,10 +521,11 @@ static irqreturn_t rk_iommu_irq(int irq, void *dev_id)
        u32 int_status;
        dma_addr_t iova;
        irqreturn_t ret = IRQ_NONE;
-       int i;
+       int i, err;
 
-       if (WARN_ON(!pm_runtime_get_if_in_use(iommu->dev)))
-               return 0;
+       err = pm_runtime_get_if_in_use(iommu->dev);
+       if (WARN_ON_ONCE(err <= 0))
+               return ret;
 
        if (WARN_ON(clk_bulk_enable(iommu->num_clocks, iommu->clocks)))
                goto out;
@@ -620,11 +621,15 @@ static void rk_iommu_zap_iova(struct rk_iommu_domain *rk_domain,
        spin_lock_irqsave(&rk_domain->iommus_lock, flags);
        list_for_each(pos, &rk_domain->iommus) {
                struct rk_iommu *iommu;
+               int ret;
 
                iommu = list_entry(pos, struct rk_iommu, node);
 
                /* Only zap TLBs of IOMMUs that are powered on. */
-               if (pm_runtime_get_if_in_use(iommu->dev)) {
+               ret = pm_runtime_get_if_in_use(iommu->dev);
+               if (WARN_ON_ONCE(ret < 0))
+                       continue;
+               if (ret) {
                        WARN_ON(clk_bulk_enable(iommu->num_clocks,
                                                iommu->clocks));
                        rk_iommu_zap_lines(iommu, iova, size);
@@ -891,6 +896,7 @@ static void rk_iommu_detach_device(struct iommu_domain *domain,
        struct rk_iommu *iommu;
        struct rk_iommu_domain *rk_domain = to_rk_domain(domain);
        unsigned long flags;
+       int ret;
 
        /* Allow 'virtual devices' (eg drm) to detach from domain */
        iommu = rk_iommu_from_dev(dev);
@@ -909,7 +915,9 @@ static void rk_iommu_detach_device(struct iommu_domain *domain,
        list_del_init(&iommu->node);
        spin_unlock_irqrestore(&rk_domain->iommus_lock, flags);
 
-       if (pm_runtime_get_if_in_use(iommu->dev)) {
+       ret = pm_runtime_get_if_in_use(iommu->dev);
+       WARN_ON_ONCE(ret < 0);
+       if (ret > 0) {
                rk_iommu_disable(iommu);
                pm_runtime_put(iommu->dev);
        }
@@ -946,7 +954,8 @@ static int rk_iommu_attach_device(struct iommu_domain *domain,
        list_add_tail(&iommu->node, &rk_domain->iommus);
        spin_unlock_irqrestore(&rk_domain->iommus_lock, flags);
 
-       if (!pm_runtime_get_if_in_use(iommu->dev))
+       ret = pm_runtime_get_if_in_use(iommu->dev);
+       if (!ret || WARN_ON_ONCE(ret < 0))
                return 0;
 
        ret = rk_iommu_enable(iommu);
@@ -1110,7 +1119,6 @@ static const struct iommu_ops rk_iommu_ops = {
        .detach_dev = rk_iommu_detach_device,
        .map = rk_iommu_map,
        .unmap = rk_iommu_unmap,
-       .map_sg = default_iommu_map_sg,
        .add_device = rk_iommu_add_device,
        .remove_device = rk_iommu_remove_device,
        .iova_to_phys = rk_iommu_iova_to_phys,
@@ -1152,17 +1160,6 @@ static int rk_iommu_probe(struct platform_device *pdev)
        if (iommu->num_mmu == 0)
                return PTR_ERR(iommu->bases[0]);
 
-       i = 0;
-       while ((irq = platform_get_irq(pdev, i++)) != -ENXIO) {
-               if (irq < 0)
-                       return irq;
-
-               err = devm_request_irq(iommu->dev, irq, rk_iommu_irq,
-                                      IRQF_SHARED, dev_name(dev), iommu);
-               if (err)
-                       return err;
-       }
-
        iommu->reset_disabled = device_property_read_bool(dev,
                                        "rockchip,disable-mmu-reset");
 
@@ -1219,6 +1216,19 @@ static int rk_iommu_probe(struct platform_device *pdev)
 
        pm_runtime_enable(dev);
 
+       i = 0;
+       while ((irq = platform_get_irq(pdev, i++)) != -ENXIO) {
+               if (irq < 0)
+                       return irq;
+
+               err = devm_request_irq(iommu->dev, irq, rk_iommu_irq,
+                                      IRQF_SHARED, dev_name(dev), iommu);
+               if (err) {
+                       pm_runtime_disable(dev);
+                       goto err_remove_sysfs;
+               }
+       }
+
        return 0;
 err_remove_sysfs:
        iommu_device_sysfs_remove(&iommu->iommu);
index a004f6d..7b1361d 100644 (file)
@@ -377,7 +377,6 @@ static const struct iommu_ops gart_iommu_ops = {
        .remove_device  = gart_iommu_remove_device,
        .device_group   = generic_device_group,
        .map            = gart_iommu_map,
-       .map_sg         = default_iommu_map_sg,
        .unmap          = gart_iommu_unmap,
        .iova_to_phys   = gart_iommu_iova_to_phys,
        .pgsize_bitmap  = GART_IOMMU_PGSIZES,
index 44d40bc..0d03341 100644 (file)
@@ -876,7 +876,6 @@ static const struct iommu_ops tegra_smmu_ops = {
        .device_group = tegra_smmu_device_group,
        .map = tegra_smmu_map,
        .unmap = tegra_smmu_unmap,
-       .map_sg = default_iommu_map_sg,
        .iova_to_phys = tegra_smmu_iova_to_phys,
        .of_xlate = tegra_smmu_of_xlate,
        .pgsize_bitmap = SZ_4K,
index faf734f..0f6e30e 100644 (file)
@@ -217,6 +217,7 @@ static int bcm7038_l1_set_affinity(struct irq_data *d,
        return 0;
 }
 
+#ifdef CONFIG_SMP
 static void bcm7038_l1_cpu_offline(struct irq_data *d)
 {
        struct cpumask *mask = irq_data_get_affinity_mask(d);
@@ -241,6 +242,7 @@ static void bcm7038_l1_cpu_offline(struct irq_data *d)
        }
        irq_set_affinity_locked(d, &new_affinity, false);
 }
+#endif
 
 static int __init bcm7038_l1_init_one(struct device_node *dn,
                                      unsigned int idx,
@@ -293,7 +295,9 @@ static struct irq_chip bcm7038_l1_irq_chip = {
        .irq_mask               = bcm7038_l1_mask,
        .irq_unmask             = bcm7038_l1_unmask,
        .irq_set_affinity       = bcm7038_l1_set_affinity,
+#ifdef CONFIG_SMP
        .irq_cpu_offline        = bcm7038_l1_cpu_offline,
+#endif
 };
 
 static int bcm7038_l1_map(struct irq_domain *d, unsigned int virq,
index e214181..d5912f1 100644 (file)
@@ -861,7 +861,9 @@ static struct irq_chip gic_chip = {
        .irq_set_affinity       = gic_set_affinity,
        .irq_get_irqchip_state  = gic_irq_get_irqchip_state,
        .irq_set_irqchip_state  = gic_irq_set_irqchip_state,
-       .flags                  = IRQCHIP_SET_TYPE_MASKED,
+       .flags                  = IRQCHIP_SET_TYPE_MASKED |
+                                 IRQCHIP_SKIP_SET_WAKE |
+                                 IRQCHIP_MASK_ON_SUSPEND,
 };
 
 static struct irq_chip gic_eoimode1_chip = {
@@ -874,7 +876,9 @@ static struct irq_chip gic_eoimode1_chip = {
        .irq_get_irqchip_state  = gic_irq_get_irqchip_state,
        .irq_set_irqchip_state  = gic_irq_set_irqchip_state,
        .irq_set_vcpu_affinity  = gic_irq_set_vcpu_affinity,
-       .flags                  = IRQCHIP_SET_TYPE_MASKED,
+       .flags                  = IRQCHIP_SET_TYPE_MASKED |
+                                 IRQCHIP_SKIP_SET_WAKE |
+                                 IRQCHIP_MASK_ON_SUSPEND,
 };
 
 #define GIC_ID_NR      (1U << GICD_TYPER_ID_BITS(gic_data.rdists.gicd_typer))
index aed31af..85234d4 100644 (file)
@@ -12,7 +12,7 @@
 #include <asm/io.h>
 
 static void *intc_baseaddr;
-#define IPRA ((unsigned long)intc_baseaddr)
+#define IPRA (intc_baseaddr)
 
 static const unsigned char ipr_table[] = {
        0x03, 0x02, 0x01, 0x00, 0x13, 0x12, 0x11, 0x10, /* 16 - 23 */
@@ -34,7 +34,7 @@ static const unsigned char ipr_table[] = {
 static void h8s_disable_irq(struct irq_data *data)
 {
        int pos;
-       unsigned int addr;
+       void __iomem *addr;
        unsigned short pri;
        int irq = data->irq;
 
@@ -48,7 +48,7 @@ static void h8s_disable_irq(struct irq_data *data)
 static void h8s_enable_irq(struct irq_data *data)
 {
        int pos;
-       unsigned int addr;
+       void __iomem *addr;
        unsigned short pri;
        int irq = data->irq;
 
index f6fd57e..c19766f 100644 (file)
@@ -250,7 +250,7 @@ static int s3c_irqext0_type(struct irq_data *data, unsigned int type)
        void __iomem *gpcon_reg;
        unsigned long gpcon_offset, extint_offset;
 
-       if ((data->hwirq >= 0) && (data->hwirq <= 3)) {
+       if (data->hwirq <= 3) {
                gpcon_reg = S3C2410_GPFCON;
                extint_reg = S3C24XX_EXTINT0;
                gpcon_offset = (data->hwirq) * 2;
index 3df527f..0a2088e 100644 (file)
@@ -603,17 +603,24 @@ stm32_exti_host_data *stm32_exti_host_init(const struct stm32_exti_drv_data *dd,
                                        sizeof(struct stm32_exti_chip_data),
                                        GFP_KERNEL);
        if (!host_data->chips_data)
-               return NULL;
+               goto free_host_data;
 
        host_data->base = of_iomap(node, 0);
        if (!host_data->base) {
                pr_err("%pOF: Unable to map registers\n", node);
-               return NULL;
+               goto free_chips_data;
        }
 
        stm32_host_data = host_data;
 
        return host_data;
+
+free_chips_data:
+       kfree(host_data->chips_data);
+free_host_data:
+       kfree(host_data);
+
+       return NULL;
 }
 
 static struct
@@ -665,10 +672,8 @@ static int __init stm32_exti_init(const struct stm32_exti_drv_data *drv_data,
        struct irq_domain *domain;
 
        host_data = stm32_exti_host_init(drv_data, node);
-       if (!host_data) {
-               ret = -ENOMEM;
-               goto out_free_mem;
-       }
+       if (!host_data)
+               return -ENOMEM;
 
        domain = irq_domain_add_linear(node, drv_data->bank_nr * IRQS_PER_BANK,
                                       &irq_exti_domain_ops, NULL);
@@ -725,7 +730,6 @@ out_free_domain:
        irq_domain_remove(domain);
 out_unmap:
        iounmap(host_data->base);
-out_free_mem:
        kfree(host_data->chips_data);
        kfree(host_data);
        return ret;
@@ -752,10 +756,8 @@ __init stm32_exti_hierarchy_init(const struct stm32_exti_drv_data *drv_data,
        }
 
        host_data = stm32_exti_host_init(drv_data, node);
-       if (!host_data) {
-               ret = -ENOMEM;
-               goto out_free_mem;
-       }
+       if (!host_data)
+               return -ENOMEM;
 
        for (i = 0; i < drv_data->bank_nr; i++)
                stm32_exti_chip_init(host_data, i, node);
@@ -777,7 +779,6 @@ __init stm32_exti_hierarchy_init(const struct stm32_exti_drv_data *drv_data,
 
 out_unmap:
        iounmap(host_data->base);
-out_free_mem:
        kfree(host_data->chips_data);
        kfree(host_data);
        return ret;
index 0c08530..580e2d7 100644 (file)
@@ -205,8 +205,7 @@ static int __init tangox_irq_init(void __iomem *base, struct resource *baseres,
 
        tangox_irq_domain_init(dom);
 
-       irq_set_chained_handler(irq, tangox_irq_handler);
-       irq_set_handler_data(irq, dom);
+       irq_set_chained_handler_and_data(irq, tangox_irq_handler, dom);
 
        return 0;
 }
index a15a951..e539500 100644 (file)
@@ -98,14 +98,12 @@ static void xtensa_mx_irq_unmask(struct irq_data *d)
 
 static void xtensa_mx_irq_enable(struct irq_data *d)
 {
-       variant_irq_enable(d->hwirq);
        xtensa_mx_irq_unmask(d);
 }
 
 static void xtensa_mx_irq_disable(struct irq_data *d)
 {
        xtensa_mx_irq_mask(d);
-       variant_irq_disable(d->hwirq);
 }
 
 static void xtensa_mx_irq_ack(struct irq_data *d)
index f728755..000cb54 100644 (file)
@@ -55,14 +55,12 @@ static void xtensa_irq_unmask(struct irq_data *d)
 
 static void xtensa_irq_enable(struct irq_data *d)
 {
-       variant_irq_enable(d->hwirq);
        xtensa_irq_unmask(d);
 }
 
 static void xtensa_irq_disable(struct irq_data *d)
 {
        xtensa_irq_mask(d);
-       variant_irq_disable(d->hwirq);
 }
 
 static void xtensa_irq_ack(struct irq_data *d)
index 68dcbcb..8c74457 100644 (file)
@@ -432,7 +432,6 @@ static struct i2c_driver g4fan_driver = {
        .driver = {
                .name   = "therm_windtunnel",
        },
-       .attach_adapter = do_attach,
        .probe          = do_probe,
        .remove         = do_remove,
        .id_table       = therm_windtunnel_id,
@@ -445,7 +444,29 @@ static struct i2c_driver g4fan_driver = {
 
 static int therm_of_probe(struct platform_device *dev)
 {
-       return i2c_add_driver( &g4fan_driver );
+       struct i2c_adapter *adap;
+       int ret, i = 0;
+
+       adap = i2c_get_adapter(0);
+       if (!adap)
+               return -EPROBE_DEFER;
+
+       ret = i2c_add_driver(&g4fan_driver);
+       if (ret) {
+               i2c_put_adapter(adap);
+               return ret;
+       }
+
+       /* We assume Macs have consecutive I2C bus numbers starting at 0 */
+       while (adap) {
+               do_attach(adap);
+               if (x.running)
+                       return 0;
+               i2c_put_adapter(adap);
+               adap = i2c_get_adapter(++i);
+       }
+
+       return -ENODEV;
 }
 
 static int
index 17bf109..f6e0a8b 100644 (file)
@@ -1,7 +1,8 @@
 
 config BCACHE
        tristate "Block device as cache"
-       ---help---
+       select CRC64
+       help
        Allows a block device to be used as cache for other devices; uses
        a btree for indexing and the layout is optimized for SSDs.
 
@@ -10,7 +11,7 @@ config BCACHE
 config BCACHE_DEBUG
        bool "Bcache debugging"
        depends on BCACHE
-       ---help---
+       help
        Don't select this option unless you're a developer
 
        Enables extra debugging tools, allows expensive runtime checks to be
@@ -20,7 +21,7 @@ config BCACHE_CLOSURES_DEBUG
        bool "Debug closures"
        depends on BCACHE
        select DEBUG_FS
-       ---help---
+       help
        Keeps all active closures in a linked list and provides a debugfs
        interface to list them, which makes it possible to see asynchronous
        operations that get stuck.
index 7fa2631..7a28232 100644 (file)
@@ -87,8 +87,8 @@ void bch_rescale_priorities(struct cache_set *c, int sectors)
 {
        struct cache *ca;
        struct bucket *b;
-       unsigned next = c->nbuckets * c->sb.bucket_size / 1024;
-       unsigned i;
+       unsigned int next = c->nbuckets * c->sb.bucket_size / 1024;
+       unsigned int i;
        int r;
 
        atomic_sub(sectors, &c->rescale);
@@ -169,7 +169,7 @@ static void bch_invalidate_one_bucket(struct cache *ca, struct bucket *b)
 
 #define bucket_prio(b)                                                 \
 ({                                                                     \
-       unsigned min_prio = (INITIAL_PRIO - ca->set->min_prio) / 8;     \
+       unsigned int min_prio = (INITIAL_PRIO - ca->set->min_prio) / 8; \
                                                                        \
        (b->prio - ca->set->min_prio + min_prio) * GC_SECTORS_USED(b);  \
 })
@@ -244,6 +244,7 @@ static void invalidate_buckets_random(struct cache *ca)
 
        while (!fifo_full(&ca->free_inc)) {
                size_t n;
+
                get_random_bytes(&n, sizeof(n));
 
                n %= (size_t) (ca->sb.nbuckets - ca->sb.first_bucket);
@@ -301,7 +302,7 @@ do {                                                                        \
 
 static int bch_allocator_push(struct cache *ca, long bucket)
 {
-       unsigned i;
+       unsigned int i;
 
        /* Prios/gens are actually the most important reserve */
        if (fifo_push(&ca->free[RESERVE_PRIO], bucket))
@@ -385,7 +386,7 @@ out:
 
 /* Allocation */
 
-long bch_bucket_alloc(struct cache *ca, unsigned reserve, bool wait)
+long bch_bucket_alloc(struct cache *ca, unsigned int reserve, bool wait)
 {
        DEFINE_WAIT(w);
        struct bucket *b;
@@ -421,7 +422,7 @@ out:
        if (expensive_debug_checks(ca->set)) {
                size_t iter;
                long i;
-               unsigned j;
+               unsigned int j;
 
                for (iter = 0; iter < prio_buckets(ca) * 2; iter++)
                        BUG_ON(ca->prio_buckets[iter] == (uint64_t) r);
@@ -470,14 +471,14 @@ void __bch_bucket_free(struct cache *ca, struct bucket *b)
 
 void bch_bucket_free(struct cache_set *c, struct bkey *k)
 {
-       unsigned i;
+       unsigned int i;
 
        for (i = 0; i < KEY_PTRS(k); i++)
                __bch_bucket_free(PTR_CACHE(c, k, i),
                                  PTR_BUCKET(c, k, i));
 }
 
-int __bch_bucket_alloc_set(struct cache_set *c, unsigned reserve,
+int __bch_bucket_alloc_set(struct cache_set *c, unsigned int reserve,
                           struct bkey *k, int n, bool wait)
 {
        int i;
@@ -510,10 +511,11 @@ err:
        return -1;
 }
 
-int bch_bucket_alloc_set(struct cache_set *c, unsigned reserve,
+int bch_bucket_alloc_set(struct cache_set *c, unsigned int reserve,
                         struct bkey *k, int n, bool wait)
 {
        int ret;
+
        mutex_lock(&c->bucket_lock);
        ret = __bch_bucket_alloc_set(c, reserve, k, n, wait);
        mutex_unlock(&c->bucket_lock);
@@ -524,8 +526,8 @@ int bch_bucket_alloc_set(struct cache_set *c, unsigned reserve,
 
 struct open_bucket {
        struct list_head        list;
-       unsigned                last_write_point;
-       unsigned                sectors_free;
+       unsigned int            last_write_point;
+       unsigned int            sectors_free;
        BKEY_PADDED(key);
 };
 
@@ -556,7 +558,7 @@ struct open_bucket {
  */
 static struct open_bucket *pick_data_bucket(struct cache_set *c,
                                            const struct bkey *search,
-                                           unsigned write_point,
+                                           unsigned int write_point,
                                            struct bkey *alloc)
 {
        struct open_bucket *ret, *ret_task = NULL;
@@ -595,12 +597,16 @@ found:
  *
  * If s->writeback is true, will not fail.
  */
-bool bch_alloc_sectors(struct cache_set *c, struct bkey *k, unsigned sectors,
-                      unsigned write_point, unsigned write_prio, bool wait)
+bool bch_alloc_sectors(struct cache_set *c,
+                      struct bkey *k,
+                      unsigned int sectors,
+                      unsigned int write_point,
+                      unsigned int write_prio,
+                      bool wait)
 {
        struct open_bucket *b;
        BKEY_PADDED(key) alloc;
-       unsigned i;
+       unsigned int i;
 
        /*
         * We might have to allocate a new bucket, which we can't do with a
@@ -613,7 +619,7 @@ bool bch_alloc_sectors(struct cache_set *c, struct bkey *k, unsigned sectors,
        spin_lock(&c->data_bucket_lock);
 
        while (!(b = pick_data_bucket(c, k, write_point, &alloc.key))) {
-               unsigned watermark = write_prio
+               unsigned int watermark = write_prio
                        ? RESERVE_MOVINGGC
                        : RESERVE_NONE;
 
@@ -702,6 +708,7 @@ int bch_open_buckets_alloc(struct cache_set *c)
 
        for (i = 0; i < MAX_OPEN_BUCKETS; i++) {
                struct open_bucket *b = kzalloc(sizeof(*b), GFP_KERNEL);
+
                if (!b)
                        return -ENOMEM;
 
index 05f82ff..83504dd 100644 (file)
@@ -252,7 +252,7 @@ struct bcache_device {
        struct kobject          kobj;
 
        struct cache_set        *c;
-       unsigned                id;
+       unsigned int            id;
 #define BCACHEDEVNAME_SIZE     12
        char                    name[BCACHEDEVNAME_SIZE];
 
@@ -264,18 +264,19 @@ struct bcache_device {
 #define BCACHE_DEV_UNLINK_DONE         2
 #define BCACHE_DEV_WB_RUNNING          3
 #define BCACHE_DEV_RATE_DW_RUNNING     4
-       unsigned                nr_stripes;
-       unsigned                stripe_size;
+       unsigned int            nr_stripes;
+       unsigned int            stripe_size;
        atomic_t                *stripe_sectors_dirty;
        unsigned long           *full_dirty_stripes;
 
        struct bio_set          bio_split;
 
-       unsigned                data_csum:1;
+       unsigned int            data_csum:1;
 
-       int (*cache_miss)(struct btree *, struct search *,
-                         struct bio *, unsigned);
-       int (*ioctl) (struct bcache_device *, fmode_t, unsigned, unsigned long);
+       int (*cache_miss)(struct btree *b, struct search *s,
+                         struct bio *bio, unsigned int sectors);
+       int (*ioctl)(struct bcache_device *d, fmode_t mode,
+                    unsigned int cmd, unsigned long arg);
 };
 
 struct io {
@@ -284,7 +285,7 @@ struct io {
        struct list_head        lru;
 
        unsigned long           jiffies;
-       unsigned                sequential;
+       unsigned int            sequential;
        sector_t                last;
 };
 
@@ -358,18 +359,18 @@ struct cached_dev {
        struct cache_accounting accounting;
 
        /* The rest of this all shows up in sysfs */
-       unsigned                sequential_cutoff;
-       unsigned                readahead;
+       unsigned int            sequential_cutoff;
+       unsigned int            readahead;
 
-       unsigned                io_disable:1;
-       unsigned                verify:1;
-       unsigned                bypass_torture_test:1;
+       unsigned int            io_disable:1;
+       unsigned int            verify:1;
+       unsigned int            bypass_torture_test:1;
 
-       unsigned                partial_stripes_expensive:1;
-       unsigned                writeback_metadata:1;
-       unsigned                writeback_running:1;
+       unsigned int            partial_stripes_expensive:1;
+       unsigned int            writeback_metadata:1;
+       unsigned int            writeback_running:1;
        unsigned char           writeback_percent;
-       unsigned                writeback_delay;
+       unsigned int            writeback_delay;
 
        uint64_t                writeback_rate_target;
        int64_t                 writeback_rate_proportional;
@@ -377,16 +378,16 @@ struct cached_dev {
        int64_t                 writeback_rate_integral_scaled;
        int32_t                 writeback_rate_change;
 
-       unsigned                writeback_rate_update_seconds;
-       unsigned                writeback_rate_i_term_inverse;
-       unsigned                writeback_rate_p_term_inverse;
-       unsigned                writeback_rate_minimum;
+       unsigned int            writeback_rate_update_seconds;
+       unsigned int            writeback_rate_i_term_inverse;
+       unsigned int            writeback_rate_p_term_inverse;
+       unsigned int            writeback_rate_minimum;
 
        enum stop_on_failure    stop_when_cache_set_failed;
 #define DEFAULT_CACHED_DEV_ERROR_LIMIT 64
        atomic_t                io_errors;
-       unsigned                error_limit;
-       unsigned                offline_seconds;
+       unsigned int            error_limit;
+       unsigned int            offline_seconds;
 
        char                    backing_dev_name[BDEVNAME_SIZE];
 };
@@ -447,7 +448,7 @@ struct cache {
         * until a gc finishes - otherwise we could pointlessly burn a ton of
         * cpu
         */
-       unsigned                invalidate_needs_gc;
+       unsigned int            invalidate_needs_gc;
 
        bool                    discard; /* Get rid of? */
 
@@ -472,7 +473,7 @@ struct gc_stat {
 
        size_t                  nkeys;
        uint64_t                data;   /* sectors */
-       unsigned                in_use; /* percent */
+       unsigned int            in_use; /* percent */
 };
 
 /*
@@ -518,7 +519,7 @@ struct cache_set {
        int                     caches_loaded;
 
        struct bcache_device    **devices;
-       unsigned                devices_max_used;
+       unsigned int            devices_max_used;
        atomic_t                attached_dev_nr;
        struct list_head        cached_devs;
        uint64_t                cached_dev_sectors;
@@ -548,7 +549,7 @@ struct cache_set {
         * Default number of pages for a new btree node - may be less than a
         * full bucket
         */
-       unsigned                btree_pages;
+       unsigned int            btree_pages;
 
        /*
         * Lists of struct btrees; lru is the list for structs that have memory
@@ -571,7 +572,7 @@ struct cache_set {
        struct list_head        btree_cache_freed;
 
        /* Number of elements in btree_cache + btree_cache_freeable lists */
-       unsigned                btree_cache_used;
+       unsigned int            btree_cache_used;
 
        /*
         * If we need to allocate memory for a new btree node and that
@@ -613,8 +614,8 @@ struct cache_set {
        uint16_t                min_prio;
 
        /*
-        * max(gen - last_gc) for all buckets. When it gets too big we have to gc
-        * to keep gens from wrapping around.
+        * max(gen - last_gc) for all buckets. When it gets too big we have to
+        * gc to keep gens from wrapping around.
         */
        uint8_t                 need_gc;
        struct gc_stat          gc_stats;
@@ -649,7 +650,7 @@ struct cache_set {
        struct mutex            verify_lock;
 #endif
 
-       unsigned                nr_uuids;
+       unsigned int            nr_uuids;
        struct uuid_entry       *uuids;
        BKEY_PADDED(uuid_bucket);
        struct closure          uuid_write;
@@ -670,12 +671,12 @@ struct cache_set {
        struct journal          journal;
 
 #define CONGESTED_MAX          1024
-       unsigned                congested_last_us;
+       unsigned int            congested_last_us;
        atomic_t                congested;
 
        /* The rest of this all shows up in sysfs */
-       unsigned                congested_read_threshold_us;
-       unsigned                congested_write_threshold_us;
+       unsigned int            congested_read_threshold_us;
+       unsigned int            congested_write_threshold_us;
 
        struct time_stats       btree_gc_time;
        struct time_stats       btree_split_time;
@@ -694,16 +695,16 @@ struct cache_set {
                ON_ERROR_PANIC,
        }                       on_error;
 #define DEFAULT_IO_ERROR_LIMIT 8
-       unsigned                error_limit;
-       unsigned                error_decay;
+       unsigned int            error_limit;
+       unsigned int            error_decay;
 
        unsigned short          journal_delay_ms;
        bool                    expensive_debug_checks;
-       unsigned                verify:1;
-       unsigned                key_merging_disabled:1;
-       unsigned                gc_always_rewrite:1;
-       unsigned                shrinker_disabled:1;
-       unsigned                copy_gc_enabled:1;
+       unsigned int            verify:1;
+       unsigned int            key_merging_disabled:1;
+       unsigned int            gc_always_rewrite:1;
+       unsigned int            shrinker_disabled:1;
+       unsigned int            copy_gc_enabled:1;
 
 #define BUCKET_HASH_BITS       12
        struct hlist_head       bucket_hash[1 << BUCKET_HASH_BITS];
@@ -712,7 +713,7 @@ struct cache_set {
 };
 
 struct bbio {
-       unsigned                submit_time_us;
+       unsigned int            submit_time_us;
        union {
                struct bkey     key;
                uint64_t        _pad[3];
@@ -729,10 +730,10 @@ struct bbio {
 
 #define btree_bytes(c)         ((c)->btree_pages * PAGE_SIZE)
 #define btree_blocks(b)                                                        \
-       ((unsigned) (KEY_SIZE(&b->key) >> (b)->c->block_bits))
+       ((unsigned int) (KEY_SIZE(&b->key) >> (b)->c->block_bits))
 
 #define btree_default_blocks(c)                                                \
-       ((unsigned) ((PAGE_SECTORS * (c)->btree_pages) >> (c)->block_bits))
+       ((unsigned int) ((PAGE_SECTORS * (c)->btree_pages) >> (c)->block_bits))
 
 #define bucket_pages(c)                ((c)->sb.bucket_size / PAGE_SECTORS)
 #define bucket_bytes(c)                ((c)->sb.bucket_size << 9)
@@ -761,21 +762,21 @@ static inline sector_t bucket_remainder(struct cache_set *c, sector_t s)
 
 static inline struct cache *PTR_CACHE(struct cache_set *c,
                                      const struct bkey *k,
-                                     unsigned ptr)
+                                     unsigned int ptr)
 {
        return c->cache[PTR_DEV(k, ptr)];
 }
 
 static inline size_t PTR_BUCKET_NR(struct cache_set *c,
                                   const struct bkey *k,
-                                  unsigned ptr)
+                                  unsigned int ptr)
 {
        return sector_to_bucket(c, PTR_OFFSET(k, ptr));
 }
 
 static inline struct bucket *PTR_BUCKET(struct cache_set *c,
                                        const struct bkey *k,
-                                       unsigned ptr)
+                                       unsigned int ptr)
 {
        return PTR_CACHE(c, k, ptr)->buckets + PTR_BUCKET_NR(c, k, ptr);
 }
@@ -783,17 +784,18 @@ static inline struct bucket *PTR_BUCKET(struct cache_set *c,
 static inline uint8_t gen_after(uint8_t a, uint8_t b)
 {
        uint8_t r = a - b;
+
        return r > 128U ? 0 : r;
 }
 
 static inline uint8_t ptr_stale(struct cache_set *c, const struct bkey *k,
-                               unsigned i)
+                               unsigned int i)
 {
        return gen_after(PTR_BUCKET(c, k, i)->gen, PTR_GEN(k, i));
 }
 
 static inline bool ptr_available(struct cache_set *c, const struct bkey *k,
-                                unsigned i)
+                                unsigned int i)
 {
        return (PTR_DEV(k, i) < MAX_CACHES_PER_SET) && PTR_CACHE(c, k, i);
 }
@@ -879,16 +881,16 @@ static inline uint8_t bucket_gc_gen(struct bucket *b)
 #define BUCKET_GC_GEN_MAX      96U
 
 #define kobj_attribute_write(n, fn)                                    \
-       static struct kobj_attribute ksysfs_##n = __ATTR(n, S_IWUSR, NULL, fn)
+       static struct kobj_attribute ksysfs_##n = __ATTR(n, 0200, NULL, fn)
 
 #define kobj_attribute_rw(n, show, store)                              \
        static struct kobj_attribute ksysfs_##n =                       \
-               __ATTR(n, S_IWUSR|S_IRUSR, show, store)
+               __ATTR(n, 0600, show, store)
 
 static inline void wake_up_allocators(struct cache_set *c)
 {
        struct cache *ca;
-       unsigned i;
+       unsigned int i;
 
        for_each_cache(ca, c, i)
                wake_up_process(ca->alloc_thread);
@@ -924,40 +926,43 @@ static inline void wait_for_kthread_stop(void)
 /* Forward declarations */
 
 void bch_count_backing_io_errors(struct cached_dev *dc, struct bio *bio);
-void bch_count_io_errors(struct cache *, blk_status_t, int, const char *);
-void bch_bbio_count_io_errors(struct cache_set *, struct bio *,
-                             blk_status_t, const char *);
-void bch_bbio_endio(struct cache_set *, struct bio *, blk_status_t,
-               const char *);
-void bch_bbio_free(struct bio *, struct cache_set *);
-struct bio *bch_bbio_alloc(struct cache_set *);
-
-void __bch_submit_bbio(struct bio *, struct cache_set *);
-void bch_submit_bbio(struct bio *, struct cache_set *, struct bkey *, unsigned);
-
-uint8_t bch_inc_gen(struct cache *, struct bucket *);
-void bch_rescale_priorities(struct cache_set *, int);
-
-bool bch_can_invalidate_bucket(struct cache *, struct bucket *);
-void __bch_invalidate_one_bucket(struct cache *, struct bucket *);
-
-void __bch_bucket_free(struct cache *, struct bucket *);
-void bch_bucket_free(struct cache_set *, struct bkey *);
-
-long bch_bucket_alloc(struct cache *, unsigned, bool);
-int __bch_bucket_alloc_set(struct cache_set *, unsigned,
-                          struct bkey *, int, bool);
-int bch_bucket_alloc_set(struct cache_set *, unsigned,
-                        struct bkey *, int, bool);
-bool bch_alloc_sectors(struct cache_set *, struct bkey *, unsigned,
-                      unsigned, unsigned, bool);
+void bch_count_io_errors(struct cache *ca, blk_status_t error,
+                        int is_read, const char *m);
+void bch_bbio_count_io_errors(struct cache_set *c, struct bio *bio,
+                             blk_status_t error, const char *m);
+void bch_bbio_endio(struct cache_set *c, struct bio *bio,
+                   blk_status_t error, const char *m);
+void bch_bbio_free(struct bio *bio, struct cache_set *c);
+struct bio *bch_bbio_alloc(struct cache_set *c);
+
+void __bch_submit_bbio(struct bio *bio, struct cache_set *c);
+void bch_submit_bbio(struct bio *bio, struct cache_set *c,
+                    struct bkey *k, unsigned int ptr);
+
+uint8_t bch_inc_gen(struct cache *ca, struct bucket *b);
+void bch_rescale_priorities(struct cache_set *c, int sectors);
+
+bool bch_can_invalidate_bucket(struct cache *ca, struct bucket *b);
+void __bch_invalidate_one_bucket(struct cache *ca, struct bucket *b);
+
+void __bch_bucket_free(struct cache *ca, struct bucket *b);
+void bch_bucket_free(struct cache_set *c, struct bkey *k);
+
+long bch_bucket_alloc(struct cache *ca, unsigned int reserve, bool wait);
+int __bch_bucket_alloc_set(struct cache_set *c, unsigned int reserve,
+                          struct bkey *k, int n, bool wait);
+int bch_bucket_alloc_set(struct cache_set *c, unsigned int reserve,
+                        struct bkey *k, int n, bool wait);
+bool bch_alloc_sectors(struct cache_set *c, struct bkey *k,
+                      unsigned int sectors, unsigned int write_point,
+                      unsigned int write_prio, bool wait);
 bool bch_cached_dev_error(struct cached_dev *dc);
 
 __printf(2, 3)
-bool bch_cache_set_error(struct cache_set *, const char *, ...);
+bool bch_cache_set_error(struct cache_set *c, const char *fmt, ...);
 
-void bch_prio_write(struct cache *);
-void bch_write_bdev_super(struct cached_dev *, struct closure *);
+void bch_prio_write(struct cache *ca);
+void bch_write_bdev_super(struct cached_dev *dc, struct closure *parent);
 
 extern struct workqueue_struct *bcache_wq;
 extern struct mutex bch_register_lock;
@@ -969,30 +974,31 @@ extern struct kobj_type bch_cache_set_ktype;
 extern struct kobj_type bch_cache_set_internal_ktype;
 extern struct kobj_type bch_cache_ktype;
 
-void bch_cached_dev_release(struct kobject *);
-void bch_flash_dev_release(struct kobject *);
-void bch_cache_set_release(struct kobject *);
-void bch_cache_release(struct kobject *);
+void bch_cached_dev_release(struct kobject *kobj);
+void bch_flash_dev_release(struct kobject *kobj);
+void bch_cache_set_release(struct kobject *kobj);
+void bch_cache_release(struct kobject *kobj);
 
-int bch_uuid_write(struct cache_set *);
-void bcache_write_super(struct cache_set *);
+int bch_uuid_write(struct cache_set *c);
+void bcache_write_super(struct cache_set *c);
 
 int bch_flash_dev_create(struct cache_set *c, uint64_t size);
 
-int bch_cached_dev_attach(struct cached_dev *, struct cache_set *, uint8_t *);
-void bch_cached_dev_detach(struct cached_dev *);
-void bch_cached_dev_run(struct cached_dev *);
-void bcache_device_stop(struct bcache_device *);
-
-void bch_cache_set_unregister(struct cache_set *);
-void bch_cache_set_stop(struct cache_set *);
-
-struct cache_set *bch_cache_set_alloc(struct cache_sb *);
-void bch_btree_cache_free(struct cache_set *);
-int bch_btree_cache_alloc(struct cache_set *);
-void bch_moving_init_cache_set(struct cache_set *);
-int bch_open_buckets_alloc(struct cache_set *);
-void bch_open_buckets_free(struct cache_set *);
+int bch_cached_dev_attach(struct cached_dev *dc, struct cache_set *c,
+                         uint8_t *set_uuid);
+void bch_cached_dev_detach(struct cached_dev *dc);
+void bch_cached_dev_run(struct cached_dev *dc);
+void bcache_device_stop(struct bcache_device *d);
+
+void bch_cache_set_unregister(struct cache_set *c);
+void bch_cache_set_stop(struct cache_set *c);
+
+struct cache_set *bch_cache_set_alloc(struct cache_sb *sb);
+void bch_btree_cache_free(struct cache_set *c);
+int bch_btree_cache_alloc(struct cache_set *c);
+void bch_moving_init_cache_set(struct cache_set *c);
+int bch_open_buckets_alloc(struct cache_set *c);
+void bch_open_buckets_free(struct cache_set *c);
 
 int bch_cache_allocator_start(struct cache *ca);
 
index 596c93b..8f07fa6 100644 (file)
 
 #ifdef CONFIG_BCACHE_DEBUG
 
-void bch_dump_bset(struct btree_keys *b, struct bset *i, unsigned set)
+void bch_dump_bset(struct btree_keys *b, struct bset *i, unsigned int set)
 {
        struct bkey *k, *next;
 
        for (k = i->start; k < bset_bkey_last(i); k = next) {
                next = bkey_next(k);
 
-               printk(KERN_ERR "block %u key %u/%u: ", set,
-                      (unsigned) ((u64 *) k - i->d), i->keys);
+               pr_err("block %u key %u/%u: ", set,
+                      (unsigned int) ((u64 *) k - i->d), i->keys);
 
                if (b->ops->key_dump)
                        b->ops->key_dump(b, k);
                else
-                       printk("%llu:%llu\n", KEY_INODE(k), KEY_OFFSET(k));
+                       pr_err("%llu:%llu\n", KEY_INODE(k), KEY_OFFSET(k));
 
                if (next < bset_bkey_last(i) &&
                    bkey_cmp(k, b->ops->is_extents ?
                             &START_KEY(next) : next) > 0)
-                       printk(KERN_ERR "Key skipped backwards\n");
+                       pr_err("Key skipped backwards\n");
        }
 }
 
 void bch_dump_bucket(struct btree_keys *b)
 {
-       unsigned i;
+       unsigned int i;
 
        console_lock();
        for (i = 0; i <= b->nsets; i++)
@@ -53,7 +53,7 @@ void bch_dump_bucket(struct btree_keys *b)
 
 int __bch_count_data(struct btree_keys *b)
 {
-       unsigned ret = 0;
+       unsigned int ret = 0;
        struct btree_iter iter;
        struct bkey *k;
 
@@ -128,7 +128,7 @@ static inline void bch_btree_iter_next_check(struct btree_iter *iter) {}
 
 /* Keylists */
 
-int __bch_keylist_realloc(struct keylist *l, unsigned u64s)
+int __bch_keylist_realloc(struct keylist *l, unsigned int u64s)
 {
        size_t oldsize = bch_keylist_nkeys(l);
        size_t newsize = oldsize + u64s;
@@ -180,7 +180,7 @@ void bch_keylist_pop_front(struct keylist *l)
 /* Key/pointer manipulation */
 
 void bch_bkey_copy_single_ptr(struct bkey *dest, const struct bkey *src,
-                             unsigned i)
+                             unsigned int i)
 {
        BUG_ON(i > KEY_PTRS(src));
 
@@ -194,7 +194,7 @@ void bch_bkey_copy_single_ptr(struct bkey *dest, const struct bkey *src,
 
 bool __bch_cut_front(const struct bkey *where, struct bkey *k)
 {
-       unsigned i, len = 0;
+       unsigned int i, len = 0;
 
        if (bkey_cmp(where, &START_KEY(k)) <= 0)
                return false;
@@ -214,7 +214,7 @@ bool __bch_cut_front(const struct bkey *where, struct bkey *k)
 
 bool __bch_cut_back(const struct bkey *where, struct bkey *k)
 {
-       unsigned len = 0;
+       unsigned int len = 0;
 
        if (bkey_cmp(where, k) >= 0)
                return false;
@@ -240,9 +240,9 @@ bool __bch_cut_back(const struct bkey *where, struct bkey *k)
 #define BKEY_MANTISSA_MASK     ((1 << BKEY_MANTISSA_BITS) - 1)
 
 struct bkey_float {
-       unsigned        exponent:BKEY_EXPONENT_BITS;
-       unsigned        m:BKEY_MID_BITS;
-       unsigned        mantissa:BKEY_MANTISSA_BITS;
+       unsigned int    exponent:BKEY_EXPONENT_BITS;
+       unsigned int    m:BKEY_MID_BITS;
+       unsigned int    mantissa:BKEY_MANTISSA_BITS;
 } __packed;
 
 /*
@@ -311,7 +311,9 @@ void bch_btree_keys_free(struct btree_keys *b)
 }
 EXPORT_SYMBOL(bch_btree_keys_free);
 
-int bch_btree_keys_alloc(struct btree_keys *b, unsigned page_order, gfp_t gfp)
+int bch_btree_keys_alloc(struct btree_keys *b,
+                        unsigned int page_order,
+                        gfp_t gfp)
 {
        struct bset_tree *t = b->set;
 
@@ -345,7 +347,7 @@ EXPORT_SYMBOL(bch_btree_keys_alloc);
 void bch_btree_keys_init(struct btree_keys *b, const struct btree_keys_ops *ops,
                         bool *expensive_debug_checks)
 {
-       unsigned i;
+       unsigned int i;
 
        b->ops = ops;
        b->expensive_debug_checks = expensive_debug_checks;
@@ -370,7 +372,7 @@ EXPORT_SYMBOL(bch_btree_keys_init);
  * return array index next to j when does in-order traverse
  * of a binary tree which is stored in a linear array
  */
-static unsigned inorder_next(unsigned j, unsigned size)
+static unsigned int inorder_next(unsigned int j, unsigned int size)
 {
        if (j * 2 + 1 < size) {
                j = j * 2 + 1;
@@ -387,7 +389,7 @@ static unsigned inorder_next(unsigned j, unsigned size)
  * return array index previous to j when does in-order traverse
  * of a binary tree which is stored in a linear array
  */
-static unsigned inorder_prev(unsigned j, unsigned size)
+static unsigned int inorder_prev(unsigned int j, unsigned int size)
 {
        if (j * 2 < size) {
                j = j * 2;
@@ -400,7 +402,8 @@ static unsigned inorder_prev(unsigned j, unsigned size)
        return j;
 }
 
-/* I have no idea why this code works... and I'm the one who wrote it
+/*
+ * I have no idea why this code works... and I'm the one who wrote it
  *
  * However, I do know what it does:
  * Given a binary tree constructed in an array (i.e. how you normally implement
@@ -413,10 +416,12 @@ static unsigned inorder_prev(unsigned j, unsigned size)
  * extra is a function of size:
  *   extra = (size - rounddown_pow_of_two(size - 1)) << 1;
  */
-static unsigned __to_inorder(unsigned j, unsigned size, unsigned extra)
+static unsigned int __to_inorder(unsigned int j,
+                                 unsigned int size,
+                                 unsigned int extra)
 {
-       unsigned b = fls(j);
-       unsigned shift = fls(size - 1) - b;
+       unsigned int b = fls(j);
+       unsigned int shift = fls(size - 1) - b;
 
        j  ^= 1U << (b - 1);
        j <<= 1;
@@ -433,14 +438,16 @@ static unsigned __to_inorder(unsigned j, unsigned size, unsigned extra)
  * Return the cacheline index in bset_tree->data, where j is index
  * from a linear array which stores the auxiliar binary tree
  */
-static unsigned to_inorder(unsigned j, struct bset_tree *t)
+static unsigned int to_inorder(unsigned int j, struct bset_tree *t)
 {
        return __to_inorder(j, t->size, t->extra);
 }
 
-static unsigned __inorder_to_tree(unsigned j, unsigned size, unsigned extra)
+static unsigned int __inorder_to_tree(unsigned int j,
+                                     unsigned int size,
+                                     unsigned int extra)
 {
-       unsigned shift;
+       unsigned int shift;
 
        if (j > extra)
                j += j - extra;
@@ -457,7 +464,7 @@ static unsigned __inorder_to_tree(unsigned j, unsigned size, unsigned extra)
  * Return an index from a linear array which stores the auxiliar binary
  * tree, j is the cacheline index of t->data.
  */
-static unsigned inorder_to_tree(unsigned j, struct bset_tree *t)
+static unsigned int inorder_to_tree(unsigned int j, struct bset_tree *t)
 {
        return __inorder_to_tree(j, t->size, t->extra);
 }
@@ -468,14 +475,15 @@ void inorder_test(void)
        unsigned long done = 0;
        ktime_t start = ktime_get();
 
-       for (unsigned size = 2;
+       for (unsigned int size = 2;
             size < 65536000;
             size++) {
-               unsigned extra = (size - rounddown_pow_of_two(size - 1)) << 1;
-               unsigned i = 1, j = rounddown_pow_of_two(size - 1);
+               unsigned int extra =
+                       (size - rounddown_pow_of_two(size - 1)) << 1;
+               unsigned int i = 1, j = rounddown_pow_of_two(size - 1);
 
                if (!(size % 4096))
-                       printk(KERN_NOTICE "loop %u, %llu per us\n", size,
+                       pr_notice("loop %u, %llu per us\n", size,
                               done / ktime_us_delta(ktime_get(), start));
 
                while (1) {
@@ -518,30 +526,31 @@ void inorder_test(void)
  * of the previous key so we can walk backwards to it from t->tree[j]'s key.
  */
 
-static struct bkey *cacheline_to_bkey(struct bset_tree *t, unsigned cacheline,
-                                     unsigned offset)
+static struct bkey *cacheline_to_bkey(struct bset_tree *t,
+                                     unsigned int cacheline,
+                                     unsigned int offset)
 {
        return ((void *) t->data) + cacheline * BSET_CACHELINE + offset * 8;
 }
 
-static unsigned bkey_to_cacheline(struct bset_tree *t, struct bkey *k)
+static unsigned int bkey_to_cacheline(struct bset_tree *t, struct bkey *k)
 {
        return ((void *) k - (void *) t->data) / BSET_CACHELINE;
 }
 
-static unsigned bkey_to_cacheline_offset(struct bset_tree *t,
-                                        unsigned cacheline,
+static unsigned int bkey_to_cacheline_offset(struct bset_tree *t,
+                                        unsigned int cacheline,
                                         struct bkey *k)
 {
        return (u64 *) k - (u64 *) cacheline_to_bkey(t, cacheline, 0);
 }
 
-static struct bkey *tree_to_bkey(struct bset_tree *t, unsigned j)
+static struct bkey *tree_to_bkey(struct bset_tree *t, unsigned int j)
 {
        return cacheline_to_bkey(t, to_inorder(j, t), t->tree[j].m);
 }
 
-static struct bkey *tree_to_prev_bkey(struct bset_tree *t, unsigned j)
+static struct bkey *tree_to_prev_bkey(struct bset_tree *t, unsigned int j)
 {
        return (void *) (((uint64_t *) tree_to_bkey(t, j)) - t->prev[j]);
 }
@@ -550,7 +559,7 @@ static struct bkey *tree_to_prev_bkey(struct bset_tree *t, unsigned j)
  * For the write set - the one we're currently inserting keys into - we don't
  * maintain a full search tree, we just keep a simple lookup table in t->prev.
  */
-static struct bkey *table_to_bkey(struct bset_tree *t, unsigned cacheline)
+static struct bkey *table_to_bkey(struct bset_tree *t, unsigned int cacheline)
 {
        return cacheline_to_bkey(t, cacheline, t->prev[cacheline]);
 }
@@ -576,14 +585,15 @@ static inline uint64_t shrd128(uint64_t high, uint64_t low, uint8_t shift)
  * See make_bfloat() to check when most significant bit of f->exponent
  * is set or not.
  */
-static inline unsigned bfloat_mantissa(const struct bkey *k,
+static inline unsigned int bfloat_mantissa(const struct bkey *k,
                                       struct bkey_float *f)
 {
        const uint64_t *p = &k->low - (f->exponent >> 6);
+
        return shrd128(p[-1], p[0], f->exponent & 63) & BKEY_MANTISSA_MASK;
 }
 
-static void make_bfloat(struct bset_tree *t, unsigned j)
+static void make_bfloat(struct bset_tree *t, unsigned int j)
 {
        struct bkey_float *f = &t->tree[j];
        struct bkey *m = tree_to_bkey(t, j);
@@ -631,7 +641,7 @@ static void make_bfloat(struct bset_tree *t, unsigned j)
 static void bset_alloc_tree(struct btree_keys *b, struct bset_tree *t)
 {
        if (t != b->set) {
-               unsigned j = roundup(t[-1].size,
+               unsigned int j = roundup(t[-1].size,
                                     64 / sizeof(struct bkey_float));
 
                t->tree = t[-1].tree + j;
@@ -686,13 +696,13 @@ void bch_bset_build_written_tree(struct btree_keys *b)
 {
        struct bset_tree *t = bset_tree_last(b);
        struct bkey *prev = NULL, *k = t->data->start;
-       unsigned j, cacheline = 1;
+       unsigned int j, cacheline = 1;
 
        b->last_set_unwritten = 0;
 
        bset_alloc_tree(b, t);
 
-       t->size = min_t(unsigned,
+       t->size = min_t(unsigned int,
                        bkey_to_cacheline(t, bset_bkey_last(t->data)),
                        b->set->tree + btree_keys_cachelines(b) - t->tree);
 
@@ -732,7 +742,7 @@ EXPORT_SYMBOL(bch_bset_build_written_tree);
 void bch_bset_fix_invalidated_key(struct btree_keys *b, struct bkey *k)
 {
        struct bset_tree *t;
-       unsigned inorder, j = 1;
+       unsigned int inorder, j = 1;
 
        for (t = b->set; t <= bset_tree_last(b); t++)
                if (k < bset_bkey_last(t->data))
@@ -779,14 +789,15 @@ static void bch_bset_fix_lookup_table(struct btree_keys *b,
                                      struct bset_tree *t,
                                      struct bkey *k)
 {
-       unsigned shift = bkey_u64s(k);
-       unsigned j = bkey_to_cacheline(t, k);
+       unsigned int shift = bkey_u64s(k);
+       unsigned int j = bkey_to_cacheline(t, k);
 
        /* We're getting called from btree_split() or btree_gc, just bail out */
        if (!t->size)
                return;
 
-       /* k is the key we just inserted; we need to find the entry in the
+       /*
+        * k is the key we just inserted; we need to find the entry in the
         * lookup table for the first key that is strictly greater than k:
         * it's either k's cacheline or the next one
         */
@@ -794,7 +805,8 @@ static void bch_bset_fix_lookup_table(struct btree_keys *b,
               table_to_bkey(t, j) <= k)
                j++;
 
-       /* Adjust all the lookup table entries, and find a new key for any that
+       /*
+        * Adjust all the lookup table entries, and find a new key for any that
         * have gotten too big
         */
        for (; j < t->size; j++) {
@@ -819,7 +831,8 @@ static void bch_bset_fix_lookup_table(struct btree_keys *b,
             k != bset_bkey_last(t->data);
             k = bkey_next(k))
                if (t->size == bkey_to_cacheline(t, k)) {
-                       t->prev[t->size] = bkey_to_cacheline_offset(t, t->size, k);
+                       t->prev[t->size] =
+                               bkey_to_cacheline_offset(t, t->size, k);
                        t->size++;
                }
 }
@@ -867,10 +880,10 @@ void bch_bset_insert(struct btree_keys *b, struct bkey *where,
 }
 EXPORT_SYMBOL(bch_bset_insert);
 
-unsigned bch_btree_insert_key(struct btree_keys *b, struct bkey *k,
+unsigned int bch_btree_insert_key(struct btree_keys *b, struct bkey *k,
                              struct bkey *replace_key)
 {
-       unsigned status = BTREE_INSERT_STATUS_NO_INSERT;
+       unsigned int status = BTREE_INSERT_STATUS_NO_INSERT;
        struct bset *i = bset_tree_last(b)->data;
        struct bkey *m, *prev = NULL;
        struct btree_iter iter;
@@ -922,10 +935,10 @@ struct bset_search_iter {
 static struct bset_search_iter bset_search_write_set(struct bset_tree *t,
                                                     const struct bkey *search)
 {
-       unsigned li = 0, ri = t->size;
+       unsigned int li = 0, ri = t->size;
 
        while (li + 1 != ri) {
-               unsigned m = (li + ri) >> 1;
+               unsigned int m = (li + ri) >> 1;
 
                if (bkey_cmp(table_to_bkey(t, m), search) > 0)
                        ri = m;
@@ -944,7 +957,7 @@ static struct bset_search_iter bset_search_tree(struct bset_tree *t,
 {
        struct bkey *l, *r;
        struct bkey_float *f;
-       unsigned inorder, j, n = 1;
+       unsigned int inorder, j, n = 1;
 
        do {
                /*
@@ -958,7 +971,8 @@ static struct bset_search_iter bset_search_tree(struct bset_tree *t,
                 *              p = 0;
                 * but a branch instruction is avoided.
                 */
-               unsigned p = n << 4;
+               unsigned int p = n << 4;
+
                p &= ((int) (p - t->size)) >> 31;
 
                prefetch(&t->tree[p]);
@@ -978,7 +992,7 @@ static struct bset_search_iter bset_search_tree(struct bset_tree *t,
                 * to work  - that's done in make_bfloat()
                 */
                if (likely(f->exponent != 127))
-                       n = j * 2 + (((unsigned)
+                       n = j * 2 + (((unsigned int)
                                      (f->mantissa -
                                       bfloat_mantissa(search, f))) >> 31);
                else
@@ -1109,6 +1123,7 @@ static struct bkey *__bch_btree_iter_init(struct btree_keys *b,
                                          struct bset_tree *start)
 {
        struct bkey *ret = NULL;
+
        iter->size = ARRAY_SIZE(iter->data);
        iter->used = 0;
 
@@ -1184,7 +1199,8 @@ void bch_bset_sort_state_free(struct bset_sort_state *state)
        mempool_exit(&state->pool);
 }
 
-int bch_bset_sort_state_init(struct bset_sort_state *state, unsigned page_order)
+int bch_bset_sort_state_init(struct bset_sort_state *state,
+                            unsigned int page_order)
 {
        spin_lock_init(&state->time.lock);
 
@@ -1237,7 +1253,7 @@ static void btree_mergesort(struct btree_keys *b, struct bset *out,
 }
 
 static void __btree_sort(struct btree_keys *b, struct btree_iter *iter,
-                        unsigned start, unsigned order, bool fixup,
+                        unsigned int start, unsigned int order, bool fixup,
                         struct bset_sort_state *state)
 {
        uint64_t start_time;
@@ -1288,7 +1304,7 @@ static void __btree_sort(struct btree_keys *b, struct btree_iter *iter,
                bch_time_stats_update(&state->time, start_time);
 }
 
-void bch_btree_sort_partial(struct btree_keys *b, unsigned start,
+void bch_btree_sort_partial(struct btree_keys *b, unsigned int start,
                            struct bset_sort_state *state)
 {
        size_t order = b->page_order, keys = 0;
@@ -1298,7 +1314,7 @@ void bch_btree_sort_partial(struct btree_keys *b, unsigned start,
        __bch_btree_iter_init(b, &iter, NULL, &b->set[start]);
 
        if (start) {
-               unsigned i;
+               unsigned int i;
 
                for (i = start; i <= b->nsets; i++)
                        keys += b->set[i].data->keys;
@@ -1323,8 +1339,8 @@ void bch_btree_sort_into(struct btree_keys *b, struct btree_keys *new,
                         struct bset_sort_state *state)
 {
        uint64_t start_time = local_clock();
-
        struct btree_iter iter;
+
        bch_btree_iter_init(b, &iter, NULL);
 
        btree_mergesort(b, new->set->data, &iter, false, true);
@@ -1338,7 +1354,7 @@ void bch_btree_sort_into(struct btree_keys *b, struct btree_keys *new,
 
 void bch_btree_sort_lazy(struct btree_keys *b, struct bset_sort_state *state)
 {
-       unsigned crit = SORT_CRIT;
+       unsigned int crit = SORT_CRIT;
        int i;
 
        /* Don't sort if nothing to do */
@@ -1367,7 +1383,7 @@ EXPORT_SYMBOL(bch_btree_sort_lazy);
 
 void bch_btree_keys_stats(struct btree_keys *b, struct bset_stats *stats)
 {
-       unsigned i;
+       unsigned int i;
 
        for (i = 0; i <= b->nsets; i++) {
                struct bset_tree *t = &b->set[i];
index b867f22..bac76aa 100644 (file)
@@ -163,10 +163,10 @@ struct bset_tree {
         */
 
        /* size of the binary tree and prev array */
-       unsigned                size;
+       unsigned int            size;
 
        /* function of size - precalculated for to_inorder() */
-       unsigned                extra;
+       unsigned int            extra;
 
        /* copy of the last key in the set */
        struct bkey             end;
@@ -187,18 +187,25 @@ struct bset_tree {
 };
 
 struct btree_keys_ops {
-       bool            (*sort_cmp)(struct btree_iter_set,
-                                   struct btree_iter_set);
-       struct bkey     *(*sort_fixup)(struct btree_iter *, struct bkey *);
-       bool            (*insert_fixup)(struct btree_keys *, struct bkey *,
-                                       struct btree_iter *, struct bkey *);
-       bool            (*key_invalid)(struct btree_keys *,
-                                      const struct bkey *);
-       bool            (*key_bad)(struct btree_keys *, const struct bkey *);
-       bool            (*key_merge)(struct btree_keys *,
-                                    struct bkey *, struct bkey *);
-       void            (*key_to_text)(char *, size_t, const struct bkey *);
-       void            (*key_dump)(struct btree_keys *, const struct bkey *);
+       bool            (*sort_cmp)(struct btree_iter_set l,
+                                   struct btree_iter_set r);
+       struct bkey     *(*sort_fixup)(struct btree_iter *iter,
+                                      struct bkey *tmp);
+       bool            (*insert_fixup)(struct btree_keys *b,
+                                       struct bkey *insert,
+                                       struct btree_iter *iter,
+                                       struct bkey *replace_key);
+       bool            (*key_invalid)(struct btree_keys *bk,
+                                      const struct bkey *k);
+       bool            (*key_bad)(struct btree_keys *bk,
+                                  const struct bkey *k);
+       bool            (*key_merge)(struct btree_keys *bk,
+                                    struct bkey *l, struct bkey *r);
+       void            (*key_to_text)(char *buf,
+                                      size_t size,
+                                      const struct bkey *k);
+       void            (*key_dump)(struct btree_keys *keys,
+                                   const struct bkey *k);
 
        /*
         * Only used for deciding whether to use START_KEY(k) or just the key
@@ -211,7 +218,7 @@ struct btree_keys {
        const struct btree_keys_ops     *ops;
        uint8_t                 page_order;
        uint8_t                 nsets;
-       unsigned                last_set_unwritten:1;
+       unsigned int            last_set_unwritten:1;
        bool                    *expensive_debug_checks;
 
        /*
@@ -239,12 +246,14 @@ static inline bool bkey_written(struct btree_keys *b, struct bkey *k)
        return !b->last_set_unwritten || k < b->set[b->nsets].data->start;
 }
 
-static inline unsigned bset_byte_offset(struct btree_keys *b, struct bset *i)
+static inline unsigned int bset_byte_offset(struct btree_keys *b,
+                                           struct bset *i)
 {
        return ((size_t) i) - ((size_t) b->set->data);
 }
 
-static inline unsigned bset_sector_offset(struct btree_keys *b, struct bset *i)
+static inline unsigned int bset_sector_offset(struct btree_keys *b,
+                                             struct bset *i)
 {
        return bset_byte_offset(b, i) >> 9;
 }
@@ -273,25 +282,27 @@ static inline size_t bch_btree_keys_u64s_remaining(struct btree_keys *b)
 }
 
 static inline struct bset *bset_next_set(struct btree_keys *b,
-                                        unsigned block_bytes)
+                                        unsigned int block_bytes)
 {
        struct bset *i = bset_tree_last(b)->data;
 
        return ((void *) i) + roundup(set_bytes(i), block_bytes);
 }
 
-void bch_btree_keys_free(struct btree_keys *);
-int bch_btree_keys_alloc(struct btree_keys *, unsigned, gfp_t);
-void bch_btree_keys_init(struct btree_keys *, const struct btree_keys_ops *,
-                        bool *);
-
-void bch_bset_init_next(struct btree_keys *, struct bset *, uint64_t);
-void bch_bset_build_written_tree(struct btree_keys *);
-void bch_bset_fix_invalidated_key(struct btree_keys *, struct bkey *);
-bool bch_bkey_try_merge(struct btree_keys *, struct bkey *, struct bkey *);
-void bch_bset_insert(struct btree_keys *, struct bkey *, struct bkey *);
-unsigned bch_btree_insert_key(struct btree_keys *, struct bkey *,
-                             struct bkey *);
+void bch_btree_keys_free(struct btree_keys *b);
+int bch_btree_keys_alloc(struct btree_keys *b, unsigned int page_order,
+                        gfp_t gfp);
+void bch_btree_keys_init(struct btree_keys *b, const struct btree_keys_ops *ops,
+                        bool *expensive_debug_checks);
+
+void bch_bset_init_next(struct btree_keys *b, struct bset *i, uint64_t magic);
+void bch_bset_build_written_tree(struct btree_keys *b);
+void bch_bset_fix_invalidated_key(struct btree_keys *b, struct bkey *k);
+bool bch_bkey_try_merge(struct btree_keys *b, struct bkey *l, struct bkey *r);
+void bch_bset_insert(struct btree_keys *b, struct bkey *where,
+                    struct bkey *insert);
+unsigned int bch_btree_insert_key(struct btree_keys *b, struct bkey *k,
+                             struct bkey *replace_key);
 
 enum {
        BTREE_INSERT_STATUS_NO_INSERT = 0,
@@ -313,18 +324,21 @@ struct btree_iter {
        } data[MAX_BSETS];
 };
 
-typedef bool (*ptr_filter_fn)(struct btree_keys *, const struct bkey *);
+typedef bool (*ptr_filter_fn)(struct btree_keys *b, const struct bkey *k);
 
-struct bkey *bch_btree_iter_next(struct btree_iter *);
-struct bkey *bch_btree_iter_next_filter(struct btree_iter *,
-                                       struct btree_keys *, ptr_filter_fn);
+struct bkey *bch_btree_iter_next(struct btree_iter *iter);
+struct bkey *bch_btree_iter_next_filter(struct btree_iter *iter,
+                                       struct btree_keys *b,
+                                       ptr_filter_fn fn);
 
-void bch_btree_iter_push(struct btree_iter *, struct bkey *, struct bkey *);
-struct bkey *bch_btree_iter_init(struct btree_keys *, struct btree_iter *,
-                                struct bkey *);
+void bch_btree_iter_push(struct btree_iter *iter, struct bkey *k,
+                        struct bkey *end);
+struct bkey *bch_btree_iter_init(struct btree_keys *b,
+                                struct btree_iter *iter,
+                                struct bkey *search);
 
-struct bkey *__bch_bset_search(struct btree_keys *, struct bset_tree *,
-                              const struct bkey *);
+struct bkey *__bch_bset_search(struct btree_keys *b, struct bset_tree *t,
+                              const struct bkey *search);
 
 /*
  * Returns the first key that is strictly greater than search
@@ -349,21 +363,23 @@ static inline struct bkey *bch_bset_search(struct btree_keys *b,
 struct bset_sort_state {
        mempool_t               pool;
 
-       unsigned                page_order;
-       unsigned                crit_factor;
+       unsigned int            page_order;
+       unsigned int            crit_factor;
 
        struct time_stats       time;
 };
 
-void bch_bset_sort_state_free(struct bset_sort_state *);
-int bch_bset_sort_state_init(struct bset_sort_state *, unsigned);
-void bch_btree_sort_lazy(struct btree_keys *, struct bset_sort_state *);
-void bch_btree_sort_into(struct btree_keys *, struct btree_keys *,
-                        struct bset_sort_state *);
-void bch_btree_sort_and_fix_extents(struct btree_keys *, struct btree_iter *,
-                                   struct bset_sort_state *);
-void bch_btree_sort_partial(struct btree_keys *, unsigned,
-                           struct bset_sort_state *);
+void bch_bset_sort_state_free(struct bset_sort_state *state);
+int bch_bset_sort_state_init(struct bset_sort_state *state,
+                            unsigned int page_order);
+void bch_btree_sort_lazy(struct btree_keys *b, struct bset_sort_state *state);
+void bch_btree_sort_into(struct btree_keys *b, struct btree_keys *new,
+                        struct bset_sort_state *state);
+void bch_btree_sort_and_fix_extents(struct btree_keys *b,
+                                   struct btree_iter *iter,
+                                   struct bset_sort_state *state);
+void bch_btree_sort_partial(struct btree_keys *b, unsigned int start,
+                           struct bset_sort_state *state);
 
 static inline void bch_btree_sort(struct btree_keys *b,
                                  struct bset_sort_state *state)
@@ -377,13 +393,13 @@ struct bset_stats {
        size_t floats, failed;
 };
 
-void bch_btree_keys_stats(struct btree_keys *, struct bset_stats *);
+void bch_btree_keys_stats(struct btree_keys *b, struct bset_stats *state);
 
 /* Bkey utility code */
 
 #define bset_bkey_last(i)      bkey_idx((struct bkey *) (i)->d, (i)->keys)
 
-static inline struct bkey *bset_bkey_idx(struct bset *i, unsigned idx)
+static inline struct bkey *bset_bkey_idx(struct bset *i, unsigned int idx)
 {
        return bkey_idx(i->start, idx);
 }
@@ -401,10 +417,10 @@ static __always_inline int64_t bkey_cmp(const struct bkey *l,
                : (int64_t) KEY_OFFSET(l) - (int64_t) KEY_OFFSET(r);
 }
 
-void bch_bkey_copy_single_ptr(struct bkey *, const struct bkey *,
-                             unsigned);
-bool __bch_cut_front(const struct bkey *, struct bkey *);
-bool __bch_cut_back(const struct bkey *, struct bkey *);
+void bch_bkey_copy_single_ptr(struct bkey *dest, const struct bkey *src,
+                             unsigned int i);
+bool __bch_cut_front(const struct bkey *where, struct bkey *k);
+bool __bch_cut_back(const struct bkey *where, struct bkey *k);
 
 static inline bool bch_cut_front(const struct bkey *where, struct bkey *k)
 {
@@ -522,18 +538,20 @@ static inline size_t bch_keylist_bytes(struct keylist *l)
        return bch_keylist_nkeys(l) * sizeof(uint64_t);
 }
 
-struct bkey *bch_keylist_pop(struct keylist *);
-void bch_keylist_pop_front(struct keylist *);
-int __bch_keylist_realloc(struct keylist *, unsigned);
+struct bkey *bch_keylist_pop(struct keylist *l);
+void bch_keylist_pop_front(struct keylist *l);
+int __bch_keylist_realloc(struct keylist *l, unsigned int u64s);
 
 /* Debug stuff */
 
 #ifdef CONFIG_BCACHE_DEBUG
 
-int __bch_count_data(struct btree_keys *);
-void __printf(2, 3) __bch_check_keys(struct btree_keys *, const char *, ...);
-void bch_dump_bset(struct btree_keys *, struct bset *, unsigned);
-void bch_dump_bucket(struct btree_keys *);
+int __bch_count_data(struct btree_keys *b);
+void __printf(2, 3) __bch_check_keys(struct btree_keys *b,
+                                    const char *fmt,
+                                    ...);
+void bch_dump_bset(struct btree_keys *b, struct bset *i, unsigned int set);
+void bch_dump_bucket(struct btree_keys *b);
 
 #else
 
@@ -541,7 +559,7 @@ static inline int __bch_count_data(struct btree_keys *b) { return -1; }
 static inline void __printf(2, 3)
        __bch_check_keys(struct btree_keys *b, const char *fmt, ...) {}
 static inline void bch_dump_bucket(struct btree_keys *b) {}
-void bch_dump_bset(struct btree_keys *, struct bset *, unsigned);
+void bch_dump_bset(struct btree_keys *b, struct bset *i, unsigned int set);
 
 #endif
 
index c19f771..e7d4817 100644 (file)
@@ -183,7 +183,7 @@ static void bch_btree_init_next(struct btree *b)
 
 void bkey_put(struct cache_set *c, struct bkey *k)
 {
-       unsigned i;
+       unsigned int i;
 
        for (i = 0; i < KEY_PTRS(k); i++)
                if (ptr_available(c, k, i))
@@ -287,6 +287,7 @@ err:
 static void btree_node_read_endio(struct bio *bio)
 {
        struct closure *cl = bio->bi_private;
+
        closure_put(cl);
 }
 
@@ -435,7 +436,10 @@ static void do_btree_node_write(struct btree *b)
 
                continue_at(cl, btree_node_write_done, NULL);
        } else {
-               /* No problem for multipage bvec since the bio is just allocated */
+               /*
+                * No problem for multipage bvec since the bio is
+                * just allocated
+                */
                b->bio->bi_vcnt = 0;
                bch_bio_map(b->bio, i);
 
@@ -479,7 +483,7 @@ void __bch_btree_node_write(struct btree *b, struct closure *parent)
 
 void bch_btree_node_write(struct btree *b, struct closure *parent)
 {
-       unsigned nsets = b->keys.nsets;
+       unsigned int nsets = b->keys.nsets;
 
        lockdep_assert_held(&b->lock);
 
@@ -581,7 +585,7 @@ static void mca_bucket_free(struct btree *b)
        list_move(&b->list, &b->c->btree_cache_freeable);
 }
 
-static unsigned btree_order(struct bkey *k)
+static unsigned int btree_order(struct bkey *k)
 {
        return ilog2(KEY_SIZE(k) / PAGE_SECTORS ?: 1);
 }
@@ -589,7 +593,7 @@ static unsigned btree_order(struct bkey *k)
 static void mca_data_alloc(struct btree *b, struct bkey *k, gfp_t gfp)
 {
        if (!bch_btree_keys_alloc(&b->keys,
-                                 max_t(unsigned,
+                                 max_t(unsigned int,
                                        ilog2(b->c->btree_pages),
                                        btree_order(k)),
                                  gfp)) {
@@ -604,6 +608,7 @@ static struct btree *mca_bucket_alloc(struct cache_set *c,
                                      struct bkey *k, gfp_t gfp)
 {
        struct btree *b = kzalloc(sizeof(struct btree), gfp);
+
        if (!b)
                return NULL;
 
@@ -620,7 +625,7 @@ static struct btree *mca_bucket_alloc(struct cache_set *c,
        return b;
 }
 
-static int mca_reap(struct btree *b, unsigned min_order, bool flush)
+static int mca_reap(struct btree *b, unsigned int min_order, bool flush)
 {
        struct closure cl;
 
@@ -746,6 +751,7 @@ void bch_btree_cache_free(struct cache_set *c)
 {
        struct btree *b;
        struct closure cl;
+
        closure_init_stack(&cl);
 
        if (c->shrink.list.next)
@@ -786,7 +792,7 @@ void bch_btree_cache_free(struct cache_set *c)
 
 int bch_btree_cache_alloc(struct cache_set *c)
 {
-       unsigned i;
+       unsigned int i;
 
        for (i = 0; i < mca_reserve(c); i++)
                if (!mca_bucket_alloc(c, &ZERO_KEY, GFP_KERNEL))
@@ -1124,6 +1130,7 @@ static struct btree *btree_node_alloc_replacement(struct btree *b,
                                                  struct btree_op *op)
 {
        struct btree *n = bch_btree_node_alloc(b->c, op, b->level, b->parent);
+
        if (!IS_ERR_OR_NULL(n)) {
                mutex_lock(&n->write_lock);
                bch_btree_sort_into(&b->keys, &n->keys, &b->c->sort);
@@ -1136,7 +1143,7 @@ static struct btree *btree_node_alloc_replacement(struct btree *b,
 
 static void make_btree_freeing_key(struct btree *b, struct bkey *k)
 {
-       unsigned i;
+       unsigned int i;
 
        mutex_lock(&b->c->bucket_lock);
 
@@ -1157,7 +1164,7 @@ static int btree_check_reserve(struct btree *b, struct btree_op *op)
 {
        struct cache_set *c = b->c;
        struct cache *ca;
-       unsigned i, reserve = (c->root->level - b->level) * 2 + 1;
+       unsigned int i, reserve = (c->root->level - b->level) * 2 + 1;
 
        mutex_lock(&c->bucket_lock);
 
@@ -1181,7 +1188,7 @@ static uint8_t __bch_btree_mark_key(struct cache_set *c, int level,
                                    struct bkey *k)
 {
        uint8_t stale = 0;
-       unsigned i;
+       unsigned int i;
        struct bucket *g;
 
        /*
@@ -1219,7 +1226,7 @@ static uint8_t __bch_btree_mark_key(struct cache_set *c, int level,
                        SET_GC_MARK(g, GC_MARK_RECLAIMABLE);
 
                /* guard against overflow */
-               SET_GC_SECTORS_USED(g, min_t(unsigned,
+               SET_GC_SECTORS_USED(g, min_t(unsigned int,
                                             GC_SECTORS_USED(g) + KEY_SIZE(k),
                                             MAX_GC_SECTORS_USED));
 
@@ -1233,7 +1240,7 @@ static uint8_t __bch_btree_mark_key(struct cache_set *c, int level,
 
 void bch_initial_mark_key(struct cache_set *c, int level, struct bkey *k)
 {
-       unsigned i;
+       unsigned int i;
 
        for (i = 0; i < KEY_PTRS(k); i++)
                if (ptr_available(c, k, i) &&
@@ -1259,7 +1266,7 @@ void bch_update_bucket_in_use(struct cache_set *c, struct gc_stat *stats)
 static bool btree_gc_mark_node(struct btree *b, struct gc_stat *gc)
 {
        uint8_t stale = 0;
-       unsigned keys = 0, good_keys = 0;
+       unsigned int keys = 0, good_keys = 0;
        struct bkey *k;
        struct btree_iter iter;
        struct bset_tree *t;
@@ -1302,16 +1309,18 @@ static bool btree_gc_mark_node(struct btree *b, struct gc_stat *gc)
 
 struct gc_merge_info {
        struct btree    *b;
-       unsigned        keys;
+       unsigned int    keys;
 };
 
-static int bch_btree_insert_node(struct btree *, struct btree_op *,
-                                struct keylist *, atomic_t *, struct bkey *);
+static int bch_btree_insert_node(struct btree *b, struct btree_op *op,
+                                struct keylist *insert_keys,
+                                atomic_t *journal_ref,
+                                struct bkey *replace_key);
 
 static int btree_gc_coalesce(struct btree *b, struct btree_op *op,
                             struct gc_stat *gc, struct gc_merge_info *r)
 {
-       unsigned i, nodes = 0, keys = 0, blocks;
+       unsigned int i, nodes = 0, keys = 0, blocks;
        struct btree *new_nodes[GC_MERGE_NODES];
        struct keylist keylist;
        struct closure cl;
@@ -1511,11 +1520,11 @@ static int btree_gc_rewrite_node(struct btree *b, struct btree_op *op,
        return -EINTR;
 }
 
-static unsigned btree_gc_count_keys(struct btree *b)
+static unsigned int btree_gc_count_keys(struct btree *b)
 {
        struct bkey *k;
        struct btree_iter iter;
-       unsigned ret = 0;
+       unsigned int ret = 0;
 
        for_each_key_filter(&b->keys, k, &iter, bch_ptr_bad)
                ret += bkey_u64s(k);
@@ -1678,7 +1687,7 @@ static void btree_gc_start(struct cache_set *c)
 {
        struct cache *ca;
        struct bucket *b;
-       unsigned i;
+       unsigned int i;
 
        if (!c->gc_mark_valid)
                return;
@@ -1704,7 +1713,7 @@ static void bch_btree_gc_finish(struct cache_set *c)
 {
        struct bucket *b;
        struct cache *ca;
-       unsigned i;
+       unsigned int i;
 
        mutex_lock(&c->bucket_lock);
 
@@ -1722,7 +1731,7 @@ static void bch_btree_gc_finish(struct cache_set *c)
                struct bcache_device *d = c->devices[i];
                struct cached_dev *dc;
                struct keybuf_key *w, *n;
-               unsigned j;
+               unsigned int j;
 
                if (!d || UUID_FLASH_ONLY(&c->uuids[i]))
                        continue;
@@ -1814,7 +1823,7 @@ static void bch_btree_gc(struct cache_set *c)
 static bool gc_should_run(struct cache_set *c)
 {
        struct cache *ca;
-       unsigned i;
+       unsigned int i;
 
        for_each_cache(ca, c, i)
                if (ca->invalidate_needs_gc)
@@ -1905,7 +1914,7 @@ void bch_initial_gc_finish(struct cache_set *c)
 {
        struct cache *ca;
        struct bucket *b;
-       unsigned i;
+       unsigned int i;
 
        bch_btree_gc_finish(c);
 
@@ -1945,7 +1954,7 @@ void bch_initial_gc_finish(struct cache_set *c)
 static bool btree_insert_key(struct btree *b, struct bkey *k,
                             struct bkey *replace_key)
 {
-       unsigned status;
+       unsigned int status;
 
        BUG_ON(bkey_cmp(k, &b->key) > 0);
 
@@ -2044,7 +2053,7 @@ static int btree_split(struct btree *b, struct btree_op *op,
                           block_bytes(n1->c)) > (btree_blocks(b) * 4) / 5;
 
        if (split) {
-               unsigned keys = 0;
+               unsigned int keys = 0;
 
                trace_bcache_btree_node_split(b, btree_bset_first(n1)->keys);
 
@@ -2222,10 +2231,10 @@ int bch_btree_insert_check_key(struct btree *b, struct btree_op *op,
                rw_lock(true, b, b->level);
 
                if (b->key.ptr[0] != btree_ptr ||
-                   b->seq != seq + 1) {
+                   b->seq != seq + 1) {
                        op->lock = b->level;
                        goto out;
-               }
+               }
        }
 
        SET_KEY_PTRS(check_key, 1);
@@ -2300,7 +2309,7 @@ int bch_btree_insert(struct cache_set *c, struct keylist *keys,
 
 void bch_btree_set_root(struct btree *b)
 {
-       unsigned i;
+       unsigned int i;
        struct closure cl;
 
        closure_init_stack(&cl);
@@ -2412,7 +2421,7 @@ static inline int keybuf_nonoverlapping_cmp(struct keybuf_key *l,
 
 struct refill {
        struct btree_op op;
-       unsigned        nr_found;
+       unsigned int    nr_found;
        struct keybuf   *buf;
        struct bkey     *end;
        keybuf_pred_fn  *pred;
@@ -2488,6 +2497,7 @@ void bch_refill_keybuf(struct cache_set *c, struct keybuf *buf,
 
        if (!RB_EMPTY_ROOT(&buf->keys)) {
                struct keybuf_key *w;
+
                w = RB_FIRST(&buf->keys, struct keybuf_key, node);
                buf->start      = START_KEY(&w->key);
 
@@ -2519,6 +2529,7 @@ bool bch_keybuf_check_overlapping(struct keybuf *buf, struct bkey *start,
 {
        bool ret = false;
        struct keybuf_key *p, *w, s;
+
        s.key = *start;
 
        if (bkey_cmp(end, &buf->start) <= 0 ||
@@ -2545,6 +2556,7 @@ bool bch_keybuf_check_overlapping(struct keybuf *buf, struct bkey *start,
 struct keybuf_key *bch_keybuf_next(struct keybuf *buf)
 {
        struct keybuf_key *w;
+
        spin_lock(&buf->lock);
 
        w = RB_FIRST(&buf->keys, struct keybuf_key, node);
index 68e9d92..a68d6c5 100644 (file)
@@ -184,7 +184,7 @@ static inline struct bset *btree_bset_last(struct btree *b)
        return bset_tree_last(&b->keys)->data;
 }
 
-static inline unsigned bset_block_offset(struct btree *b, struct bset *i)
+static inline unsigned int bset_block_offset(struct btree *b, struct bset *i)
 {
        return bset_sector_offset(&b->keys, i) >> b->c->block_bits;
 }
@@ -213,7 +213,7 @@ struct btree_op {
        /* Btree level at which we start taking write locks */
        short                   lock;
 
-       unsigned                insert_collision:1;
+       unsigned int            insert_collision:1;
 };
 
 static inline void bch_btree_op_init(struct btree_op *op, int write_lock_level)
@@ -238,26 +238,28 @@ static inline void rw_unlock(bool w, struct btree *b)
        (w ? up_write : up_read)(&b->lock);
 }
 
-void bch_btree_node_read_done(struct btree *);
-void __bch_btree_node_write(struct btree *, struct closure *);
-void bch_btree_node_write(struct btree *, struct closure *);
-
-void bch_btree_set_root(struct btree *);
-struct btree *__bch_btree_node_alloc(struct cache_set *, struct btree_op *,
-                                    int, bool, struct btree *);
-struct btree *bch_btree_node_get(struct cache_set *, struct btree_op *,
-                                struct bkey *, int, bool, struct btree *);
-
-int bch_btree_insert_check_key(struct btree *, struct btree_op *,
-                              struct bkey *);
-int bch_btree_insert(struct cache_set *, struct keylist *,
-                    atomic_t *, struct bkey *);
-
-int bch_gc_thread_start(struct cache_set *);
-void bch_initial_gc_finish(struct cache_set *);
-void bch_moving_gc(struct cache_set *);
-int bch_btree_check(struct cache_set *);
-void bch_initial_mark_key(struct cache_set *, int, struct bkey *);
+void bch_btree_node_read_done(struct btree *b);
+void __bch_btree_node_write(struct btree *b, struct closure *parent);
+void bch_btree_node_write(struct btree *b, struct closure *parent);
+
+void bch_btree_set_root(struct btree *b);
+struct btree *__bch_btree_node_alloc(struct cache_set *c, struct btree_op *op,
+                                    int level, bool wait,
+                                    struct btree *parent);
+struct btree *bch_btree_node_get(struct cache_set *c, struct btree_op *op,
+                                struct bkey *k, int level, bool write,
+                                struct btree *parent);
+
+int bch_btree_insert_check_key(struct btree *b, struct btree_op *op,
+                              struct bkey *check_key);
+int bch_btree_insert(struct cache_set *c, struct keylist *keys,
+                    atomic_t *journal_ref, struct bkey *replace_key);
+
+int bch_gc_thread_start(struct cache_set *c);
+void bch_initial_gc_finish(struct cache_set *c);
+void bch_moving_gc(struct cache_set *c);
+int bch_btree_check(struct cache_set *c);
+void bch_initial_mark_key(struct cache_set *c, int level, struct bkey *k);
 
 static inline void wake_up_gc(struct cache_set *c)
 {
@@ -272,9 +274,9 @@ static inline void wake_up_gc(struct cache_set *c)
 
 #define MAP_END_KEY    1
 
-typedef int (btree_map_nodes_fn)(struct btree_op *, struct btree *);
-int __bch_btree_map_nodes(struct btree_op *, struct cache_set *,
-                         struct bkey *, btree_map_nodes_fn *, int);
+typedef int (btree_map_nodes_fn)(struct btree_op *b_op, struct btree *b);
+int __bch_btree_map_nodes(struct btree_op *op, struct cache_set *c,
+                         struct bkey *from, btree_map_nodes_fn *fn, int flags);
 
 static inline int bch_btree_map_nodes(struct btree_op *op, struct cache_set *c,
                                      struct bkey *from, btree_map_nodes_fn *fn)
@@ -290,21 +292,23 @@ static inline int bch_btree_map_leaf_nodes(struct btree_op *op,
        return __bch_btree_map_nodes(op, c, from, fn, MAP_LEAF_NODES);
 }
 
-typedef int (btree_map_keys_fn)(struct btree_op *, struct btree *,
-                               struct bkey *);
-int bch_btree_map_keys(struct btree_op *, struct cache_set *,
-                      struct bkey *, btree_map_keys_fn *, int);
-
-typedef bool (keybuf_pred_fn)(struct keybuf *, struct bkey *);
-
-void bch_keybuf_init(struct keybuf *);
-void bch_refill_keybuf(struct cache_set *, struct keybuf *,
-                      struct bkey *, keybuf_pred_fn *);
-bool bch_keybuf_check_overlapping(struct keybuf *, struct bkey *,
-                                 struct bkey *);
-void bch_keybuf_del(struct keybuf *, struct keybuf_key *);
-struct keybuf_key *bch_keybuf_next(struct keybuf *);
-struct keybuf_key *bch_keybuf_next_rescan(struct cache_set *, struct keybuf *,
-                                         struct bkey *, keybuf_pred_fn *);
+typedef int (btree_map_keys_fn)(struct btree_op *op, struct btree *b,
+                               struct bkey *k);
+int bch_btree_map_keys(struct btree_op *op, struct cache_set *c,
+                      struct bkey *from, btree_map_keys_fn *fn, int flags);
+
+typedef bool (keybuf_pred_fn)(struct keybuf *buf, struct bkey *k);
+
+void bch_keybuf_init(struct keybuf *buf);
+void bch_refill_keybuf(struct cache_set *c, struct keybuf *buf,
+                      struct bkey *end, keybuf_pred_fn *pred);
+bool bch_keybuf_check_overlapping(struct keybuf *buf, struct bkey *start,
+                                 struct bkey *end);
+void bch_keybuf_del(struct keybuf *buf, struct keybuf_key *w);
+struct keybuf_key *bch_keybuf_next(struct keybuf *buf);
+struct keybuf_key *bch_keybuf_next_rescan(struct cache_set *c,
+                                         struct keybuf *buf,
+                                         struct bkey *end,
+                                         keybuf_pred_fn *pred);
 void bch_update_bucket_in_use(struct cache_set *c, struct gc_stat *stats);
 #endif
index 6182536..73f5319 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Asynchronous refcounty things
  *
@@ -162,12 +163,13 @@ static struct dentry *closure_debug;
 static int debug_seq_show(struct seq_file *f, void *data)
 {
        struct closure *cl;
+
        spin_lock_irq(&closure_list_lock);
 
        list_for_each_entry(cl, &closure_list, all) {
                int r = atomic_read(&cl->remaining);
 
-               seq_printf(f, "%p: %pF -> %pf p %p r %i ",
+               seq_printf(f, "%p: %pS -> %pS p %p r %i ",
                           cl, (void *) cl->ip, cl->fn, cl->parent,
                           r & CLOSURE_REMAINING_MASK);
 
@@ -177,7 +179,7 @@ static int debug_seq_show(struct seq_file *f, void *data)
                           r & CLOSURE_RUNNING  ? "R" : "");
 
                if (r & CLOSURE_WAITING)
-                       seq_printf(f, " W %pF\n",
+                       seq_printf(f, " W %pS\n",
                                   (void *) cl->waiting_on);
 
                seq_printf(f, "\n");
index 7c2c5bc..eca0d49 100644 (file)
@@ -159,7 +159,7 @@ struct closure {
 #define CLOSURE_MAGIC_DEAD     0xc054dead
 #define CLOSURE_MAGIC_ALIVE    0xc054a11e
 
-       unsigned                magic;
+       unsigned int            magic;
        struct list_head        all;
        unsigned long           ip;
        unsigned long           waiting_on;
@@ -289,10 +289,12 @@ static inline void closure_init_stack(struct closure *cl)
 }
 
 /**
- * closure_wake_up - wake up all closures on a wait list.
+ * closure_wake_up - wake up all closures on a wait list,
+ *                  with memory barrier
  */
 static inline void closure_wake_up(struct closure_waitlist *list)
 {
+       /* Memory barrier for the wait list */
        smp_mb();
        __closure_wake_up(list);
 }
index 12034c0..06da66b 100644 (file)
@@ -67,34 +67,35 @@ void bch_btree_verify(struct btree *b)
        if (inmemory->keys != sorted->keys ||
            memcmp(inmemory->start,
                   sorted->start,
-                  (void *) bset_bkey_last(inmemory) - (void *) inmemory->start)) {
+                  (void *) bset_bkey_last(inmemory) -
+                  (void *) inmemory->start)) {
                struct bset *i;
-               unsigned j;
+               unsigned int j;
 
                console_lock();
 
-               printk(KERN_ERR "*** in memory:\n");
+               pr_err("*** in memory:\n");
                bch_dump_bset(&b->keys, inmemory, 0);
 
-               printk(KERN_ERR "*** read back in:\n");
+               pr_err("*** read back in:\n");
                bch_dump_bset(&v->keys, sorted, 0);
 
                for_each_written_bset(b, ondisk, i) {
-                       unsigned block = ((void *) i - (void *) ondisk) /
+                       unsigned int block = ((void *) i - (void *) ondisk) /
                                block_bytes(b->c);
 
-                       printk(KERN_ERR "*** on disk block %u:\n", block);
+                       pr_err("*** on disk block %u:\n", block);
                        bch_dump_bset(&b->keys, i, block);
                }
 
-               printk(KERN_ERR "*** block %zu not written\n",
+               pr_err("*** block %zu not written\n",
                       ((void *) i - (void *) ondisk) / block_bytes(b->c));
 
                for (j = 0; j < inmemory->keys; j++)
                        if (inmemory->d[j] != sorted->d[j])
                                break;
 
-               printk(KERN_ERR "b->written %u\n", b->written);
+               pr_err("b->written %u\n", b->written);
 
                console_unlock();
                panic("verify failed at %u\n", j);
@@ -176,9 +177,9 @@ static ssize_t bch_dump_read(struct file *file, char __user *buf,
 
        while (size) {
                struct keybuf_key *w;
-               unsigned bytes = min(i->bytes, size);
-
+               unsigned int bytes = min(i->bytes, size);
                int err = copy_to_user(buf, i->buf, bytes);
+
                if (err)
                        return err;
 
@@ -237,8 +238,8 @@ void bch_debug_init_cache_set(struct cache_set *c)
 {
        if (!IS_ERR_OR_NULL(bcache_debug)) {
                char name[50];
-               snprintf(name, 50, "bcache-%pU", c->sb.set_uuid);
 
+               snprintf(name, 50, "bcache-%pU", c->sb.set_uuid);
                c->debug = debugfs_create_file(name, 0400, bcache_debug, c,
                                               &cache_set_debug_ops);
        }
index acc48d3..fb3d4df 100644 (file)
@@ -8,8 +8,8 @@ struct cache_set;
 
 #ifdef CONFIG_BCACHE_DEBUG
 
-void bch_btree_verify(struct btree *);
-void bch_data_verify(struct cached_dev *, struct bio *);
+void bch_btree_verify(struct btree *b);
+void bch_data_verify(struct cached_dev *dc, struct bio *bio);
 
 #define expensive_debug_checks(c)      ((c)->expensive_debug_checks)
 #define key_merging_disabled(c)                ((c)->key_merging_disabled)
@@ -27,7 +27,7 @@ static inline void bch_data_verify(struct cached_dev *dc, struct bio *bio) {}
 #endif
 
 #ifdef CONFIG_DEBUG_FS
-void bch_debug_init_cache_set(struct cache_set *);
+void bch_debug_init_cache_set(struct cache_set *c);
 #else
 static inline void bch_debug_init_cache_set(struct cache_set *c) {}
 #endif
index 1d09674..c809724 100644 (file)
@@ -46,7 +46,7 @@ static bool bch_key_sort_cmp(struct btree_iter_set l,
 
 static bool __ptr_invalid(struct cache_set *c, const struct bkey *k)
 {
-       unsigned i;
+       unsigned int i;
 
        for (i = 0; i < KEY_PTRS(k); i++)
                if (ptr_available(c, k, i)) {
@@ -67,7 +67,7 @@ static bool __ptr_invalid(struct cache_set *c, const struct bkey *k)
 
 static const char *bch_ptr_status(struct cache_set *c, const struct bkey *k)
 {
-       unsigned i;
+       unsigned int i;
 
        for (i = 0; i < KEY_PTRS(k); i++)
                if (ptr_available(c, k, i)) {
@@ -96,7 +96,7 @@ static const char *bch_ptr_status(struct cache_set *c, const struct bkey *k)
 
 void bch_extent_to_text(char *buf, size_t size, const struct bkey *k)
 {
-       unsigned i = 0;
+       unsigned int i = 0;
        char *out = buf, *end = buf + size;
 
 #define p(...) (out += scnprintf(out, end - out, __VA_ARGS__))
@@ -126,22 +126,22 @@ void bch_extent_to_text(char *buf, size_t size, const struct bkey *k)
 static void bch_bkey_dump(struct btree_keys *keys, const struct bkey *k)
 {
        struct btree *b = container_of(keys, struct btree, keys);
-       unsigned j;
+       unsigned int j;
        char buf[80];
 
        bch_extent_to_text(buf, sizeof(buf), k);
-       printk(" %s", buf);
+       pr_err(" %s", buf);
 
        for (j = 0; j < KEY_PTRS(k); j++) {
                size_t n = PTR_BUCKET_NR(b->c, k, j);
-               printk(" bucket %zu", n);
 
+               pr_err(" bucket %zu", n);
                if (n >= b->c->sb.first_bucket && n < b->c->sb.nbuckets)
-                       printk(" prio %i",
+                       pr_err(" prio %i",
                               PTR_BUCKET(b->c, k, j)->prio);
        }
 
-       printk(" %s\n", bch_ptr_status(b->c, k));
+       pr_err(" %s\n", bch_ptr_status(b->c, k));
 }
 
 /* Btree ptrs */
@@ -166,12 +166,13 @@ bad:
 static bool bch_btree_ptr_invalid(struct btree_keys *bk, const struct bkey *k)
 {
        struct btree *b = container_of(bk, struct btree, keys);
+
        return __bch_btree_ptr_invalid(b->c, k);
 }
 
 static bool btree_ptr_bad_expensive(struct btree *b, const struct bkey *k)
 {
-       unsigned i;
+       unsigned int i;
        char buf[80];
        struct bucket *g;
 
@@ -204,7 +205,7 @@ err:
 static bool bch_btree_ptr_bad(struct btree_keys *bk, const struct bkey *k)
 {
        struct btree *b = container_of(bk, struct btree, keys);
-       unsigned i;
+       unsigned int i;
 
        if (!bkey_cmp(k, &ZERO_KEY) ||
            !KEY_PTRS(k) ||
@@ -327,13 +328,14 @@ static bool bch_extent_insert_fixup(struct btree_keys *b,
        struct cache_set *c = container_of(b, struct btree, keys)->c;
 
        uint64_t old_offset;
-       unsigned old_size, sectors_found = 0;
+       unsigned int old_size, sectors_found = 0;
 
        BUG_ON(!KEY_OFFSET(insert));
        BUG_ON(!KEY_SIZE(insert));
 
        while (1) {
                struct bkey *k = bch_btree_iter_next(iter);
+
                if (!k)
                        break;
 
@@ -363,7 +365,7 @@ static bool bch_extent_insert_fixup(struct btree_keys *b,
                         * k might have been split since we inserted/found the
                         * key we're replacing
                         */
-                       unsigned i;
+                       unsigned int i;
                        uint64_t offset = KEY_START(k) -
                                KEY_START(replace_key);
 
@@ -498,11 +500,12 @@ bad:
 static bool bch_extent_invalid(struct btree_keys *bk, const struct bkey *k)
 {
        struct btree *b = container_of(bk, struct btree, keys);
+
        return __bch_extent_invalid(b->c, k);
 }
 
 static bool bch_extent_bad_expensive(struct btree *b, const struct bkey *k,
-                                    unsigned ptr)
+                                    unsigned int ptr)
 {
        struct bucket *g = PTR_BUCKET(b->c, k, ptr);
        char buf[80];
@@ -534,7 +537,7 @@ err:
 static bool bch_extent_bad(struct btree_keys *bk, const struct bkey *k)
 {
        struct btree *b = container_of(bk, struct btree, keys);
-       unsigned i, stale;
+       unsigned int i, stale;
 
        if (!KEY_PTRS(k) ||
            bch_extent_invalid(bk, k))
@@ -574,10 +577,12 @@ static uint64_t merge_chksums(struct bkey *l, struct bkey *r)
                ~((uint64_t)1 << 63);
 }
 
-static bool bch_extent_merge(struct btree_keys *bk, struct bkey *l, struct bkey *r)
+static bool bch_extent_merge(struct btree_keys *bk,
+                            struct bkey *l,
+                            struct bkey *r)
 {
        struct btree *b = container_of(bk, struct btree, keys);
-       unsigned i;
+       unsigned int i;
 
        if (key_merging_disabled(b->c))
                return false;
index 0cd3575..4d667e0 100644 (file)
@@ -8,8 +8,8 @@ extern const struct btree_keys_ops bch_extent_keys_ops;
 struct bkey;
 struct cache_set;
 
-void bch_extent_to_text(char *, size_t, const struct bkey *);
-bool __bch_btree_ptr_invalid(struct cache_set *, const struct bkey *);
-bool __bch_extent_invalid(struct cache_set *, const struct bkey *);
+void bch_extent_to_text(char *buf, size_t size, const struct bkey *k);
+bool __bch_btree_ptr_invalid(struct cache_set *c, const struct bkey *k);
+bool __bch_extent_invalid(struct cache_set *c, const struct bkey *k);
 
 #endif /* _BCACHE_EXTENTS_H */
index 9612873..c250979 100644 (file)
@@ -17,6 +17,7 @@
 void bch_bbio_free(struct bio *bio, struct cache_set *c)
 {
        struct bbio *b = container_of(bio, struct bbio, bio);
+
        mempool_free(b, &c->bio_meta);
 }
 
@@ -42,9 +43,10 @@ void __bch_submit_bbio(struct bio *bio, struct cache_set *c)
 }
 
 void bch_submit_bbio(struct bio *bio, struct cache_set *c,
-                    struct bkey *k, unsigned ptr)
+                    struct bkey *k, unsigned int ptr)
 {
        struct bbio *b = container_of(bio, struct bbio, bio);
+
        bch_bkey_copy_single_ptr(&b->key, k, ptr);
        __bch_submit_bbio(bio, c);
 }
@@ -52,7 +54,7 @@ void bch_submit_bbio(struct bio *bio, struct cache_set *c,
 /* IO errors */
 void bch_count_backing_io_errors(struct cached_dev *dc, struct bio *bio)
 {
-       unsigned errors;
+       unsigned int errors;
 
        WARN_ONCE(!dc, "NULL pointer of struct cached_dev");
 
@@ -75,16 +77,16 @@ void bch_count_io_errors(struct cache *ca,
         */
 
        if (ca->set->error_decay) {
-               unsigned count = atomic_inc_return(&ca->io_count);
+               unsigned int count = atomic_inc_return(&ca->io_count);
 
                while (count > ca->set->error_decay) {
-                       unsigned errors;
-                       unsigned old = count;
-                       unsigned new = count - ca->set->error_decay;
+                       unsigned int errors;
+                       unsigned int old = count;
+                       unsigned int new = count - ca->set->error_decay;
 
                        /*
                         * First we subtract refresh from count; each time we
-                        * succesfully do so, we rescale the errors once:
+                        * successfully do so, we rescale the errors once:
                         */
 
                        count = atomic_cmpxchg(&ca->io_count, old, new);
@@ -104,7 +106,7 @@ void bch_count_io_errors(struct cache *ca,
        }
 
        if (error) {
-               unsigned errors = atomic_add_return(1 << IO_ERROR_SHIFT,
+               unsigned int errors = atomic_add_return(1 << IO_ERROR_SHIFT,
                                                    &ca->io_errors);
                errors >>= IO_ERROR_SHIFT;
 
@@ -126,18 +128,18 @@ void bch_bbio_count_io_errors(struct cache_set *c, struct bio *bio,
        struct cache *ca = PTR_CACHE(c, &b->key, 0);
        int is_read = (bio_data_dir(bio) == READ ? 1 : 0);
 
-       unsigned threshold = op_is_write(bio_op(bio))
+       unsigned int threshold = op_is_write(bio_op(bio))
                ? c->congested_write_threshold_us
                : c->congested_read_threshold_us;
 
        if (threshold) {
-               unsigned t = local_clock_us();
-
+               unsigned int t = local_clock_us();
                int us = t - b->submit_time_us;
                int congested = atomic_read(&c->congested);
 
                if (us > (int) threshold) {
                        int ms = us / 1024;
+
                        c->congested_last_us = t;
 
                        ms = min(ms, CONGESTED_MAX + congested);
index 10748c6..6116bbf 100644 (file)
 static void journal_read_endio(struct bio *bio)
 {
        struct closure *cl = bio->bi_private;
+
        closure_put(cl);
 }
 
 static int journal_read_bucket(struct cache *ca, struct list_head *list,
-                              unsigned bucket_index)
+                              unsigned int bucket_index)
 {
        struct journal_device *ja = &ca->journal;
        struct bio *bio = &ja->bio;
@@ -40,7 +41,7 @@ static int journal_read_bucket(struct cache *ca, struct list_head *list,
        struct journal_replay *i;
        struct jset *j, *data = ca->set->journal.w[0].data;
        struct closure cl;
-       unsigned len, left, offset = 0;
+       unsigned int len, left, offset = 0;
        int ret = 0;
        sector_t bucket = bucket_to_sector(ca->set, ca->sb.d[bucket_index]);
 
@@ -50,7 +51,7 @@ static int journal_read_bucket(struct cache *ca, struct list_head *list,
 
        while (offset < ca->sb.bucket_size) {
 reread:                left = ca->sb.bucket_size - offset;
-               len = min_t(unsigned, left, PAGE_SECTORS << JSET_BITS);
+               len = min_t(unsigned int, left, PAGE_SECTORS << JSET_BITS);
 
                bio_reset(bio);
                bio->bi_iter.bi_sector  = bucket + offset;
@@ -154,12 +155,12 @@ int bch_journal_read(struct cache_set *c, struct list_head *list)
        })
 
        struct cache *ca;
-       unsigned iter;
+       unsigned int iter;
 
        for_each_cache(ca, c, iter) {
                struct journal_device *ja = &ca->journal;
                DECLARE_BITMAP(bitmap, SB_JOURNAL_BUCKETS);
-               unsigned i, l, r, m;
+               unsigned int i, l, r, m;
                uint64_t seq;
 
                bitmap_zero(bitmap, SB_JOURNAL_BUCKETS);
@@ -192,7 +193,8 @@ int bch_journal_read(struct cache_set *c, struct list_head *list)
 
                for (l = find_first_zero_bit(bitmap, ca->sb.njournal_buckets);
                     l < ca->sb.njournal_buckets;
-                    l = find_next_zero_bit(bitmap, ca->sb.njournal_buckets, l + 1))
+                    l = find_next_zero_bit(bitmap, ca->sb.njournal_buckets,
+                                           l + 1))
                        if (read_bucket(l))
                                goto bsearch;
 
@@ -304,7 +306,7 @@ void bch_journal_mark(struct cache_set *c, struct list_head *list)
                     k < bset_bkey_last(&i->j);
                     k = bkey_next(k))
                        if (!__bch_extent_invalid(c, k)) {
-                               unsigned j;
+                               unsigned int j;
 
                                for (j = 0; j < KEY_PTRS(k); j++)
                                        if (ptr_available(c, k, j))
@@ -492,7 +494,7 @@ static void journal_reclaim(struct cache_set *c)
        struct bkey *k = &c->journal.key;
        struct cache *ca;
        uint64_t last_seq;
-       unsigned iter, n = 0;
+       unsigned int iter, n = 0;
        atomic_t p __maybe_unused;
 
        atomic_long_inc(&c->reclaim);
@@ -526,7 +528,7 @@ static void journal_reclaim(struct cache_set *c)
 
        for_each_cache(ca, c, iter) {
                struct journal_device *ja = &ca->journal;
-               unsigned next = (ja->cur_idx + 1) % ca->sb.njournal_buckets;
+               unsigned int next = (ja->cur_idx + 1) % ca->sb.njournal_buckets;
 
                /* No space available on this device */
                if (next == ja->discard_idx)
@@ -580,7 +582,7 @@ static void journal_write_endio(struct bio *bio)
        closure_put(&w->c->journal.io);
 }
 
-static void journal_write(struct closure *);
+static void journal_write(struct closure *cl);
 
 static void journal_write_done(struct closure *cl)
 {
@@ -609,11 +611,12 @@ static void journal_write_unlocked(struct closure *cl)
        struct cache *ca;
        struct journal_write *w = c->journal.cur;
        struct bkey *k = &c->journal.key;
-       unsigned i, sectors = set_blocks(w->data, block_bytes(c)) *
+       unsigned int i, sectors = set_blocks(w->data, block_bytes(c)) *
                c->sb.block_size;
 
        struct bio *bio;
        struct bio_list list;
+
        bio_list_init(&list);
 
        if (!w->need_write) {
@@ -705,7 +708,7 @@ static void journal_try_write(struct cache_set *c)
 }
 
 static struct journal_write *journal_wait_for_write(struct cache_set *c,
-                                                   unsigned nkeys)
+                                                   unsigned int nkeys)
        __acquires(&c->journal.lock)
 {
        size_t sectors;
index b578819..66f0fac 100644 (file)
@@ -110,7 +110,7 @@ struct journal {
        struct delayed_work     work;
 
        /* Number of blocks free in the bucket(s) we're currently writing to */
-       unsigned                blocks_free;
+       unsigned int            blocks_free;
        uint64_t                seq;
        DECLARE_FIFO(atomic_t, pin);
 
@@ -131,13 +131,13 @@ struct journal_device {
        uint64_t                seq[SB_JOURNAL_BUCKETS];
 
        /* Journal bucket we're currently writing to */
-       unsigned                cur_idx;
+       unsigned int            cur_idx;
 
        /* Last journal bucket that still contains an open journal entry */
-       unsigned                last_idx;
+       unsigned int            last_idx;
 
        /* Next journal bucket to be discarded */
-       unsigned                discard_idx;
+       unsigned int            discard_idx;
 
 #define DISCARD_READY          0
 #define DISCARD_IN_FLIGHT      1
@@ -167,14 +167,16 @@ struct cache_set;
 struct btree_op;
 struct keylist;
 
-atomic_t *bch_journal(struct cache_set *, struct keylist *, struct closure *);
-void bch_journal_next(struct journal *);
-void bch_journal_mark(struct cache_set *, struct list_head *);
-void bch_journal_meta(struct cache_set *, struct closure *);
-int bch_journal_read(struct cache_set *, struct list_head *);
-int bch_journal_replay(struct cache_set *, struct list_head *);
-
-void bch_journal_free(struct cache_set *);
-int bch_journal_alloc(struct cache_set *);
+atomic_t *bch_journal(struct cache_set *c,
+                     struct keylist *keys,
+                     struct closure *parent);
+void bch_journal_next(struct journal *j);
+void bch_journal_mark(struct cache_set *c, struct list_head *list);
+void bch_journal_meta(struct cache_set *c, struct closure *cl);
+int bch_journal_read(struct cache_set *c, struct list_head *list);
+int bch_journal_replay(struct cache_set *c, struct list_head *list);
+
+void bch_journal_free(struct cache_set *c);
+int bch_journal_alloc(struct cache_set *c);
 
 #endif /* _BCACHE_JOURNAL_H */
index a24c3a9..7891fb5 100644 (file)
@@ -23,7 +23,7 @@ static bool moving_pred(struct keybuf *buf, struct bkey *k)
 {
        struct cache_set *c = container_of(buf, struct cache_set,
                                           moving_gc_keys);
-       unsigned i;
+       unsigned int i;
 
        for (i = 0; i < KEY_PTRS(k); i++)
                if (ptr_available(c, k, i) &&
@@ -38,6 +38,7 @@ static bool moving_pred(struct keybuf *buf, struct bkey *k)
 static void moving_io_destructor(struct closure *cl)
 {
        struct moving_io *io = container_of(cl, struct moving_io, cl);
+
        kfree(io);
 }
 
@@ -186,9 +187,10 @@ static bool bucket_cmp(struct bucket *l, struct bucket *r)
        return GC_SECTORS_USED(l) < GC_SECTORS_USED(r);
 }
 
-static unsigned bucket_heap_top(struct cache *ca)
+static unsigned int bucket_heap_top(struct cache *ca)
 {
        struct bucket *b;
+
        return (b = heap_peek(&ca->heap)) ? GC_SECTORS_USED(b) : 0;
 }
 
@@ -196,7 +198,7 @@ void bch_moving_gc(struct cache_set *c)
 {
        struct cache *ca;
        struct bucket *b;
-       unsigned i;
+       unsigned int i;
 
        if (!c->copy_gc_enabled)
                return;
@@ -204,9 +206,9 @@ void bch_moving_gc(struct cache_set *c)
        mutex_lock(&c->bucket_lock);
 
        for_each_cache(ca, c, i) {
-               unsigned sectors_to_move = 0;
-               unsigned reserve_sectors = ca->sb.bucket_size *
-                       fifo_used(&ca->free[RESERVE_MOVINGGC]);
+               unsigned int sectors_to_move = 0;
+               unsigned int reserve_sectors = ca->sb.bucket_size *
+                            fifo_used(&ca->free[RESERVE_MOVINGGC]);
 
                ca->heap.used = 0;
 
index 7dbe8b6..51be355 100644 (file)
@@ -25,9 +25,9 @@
 
 struct kmem_cache *bch_search_cache;
 
-static void bch_data_insert_start(struct closure *);
+static void bch_data_insert_start(struct closure *cl);
 
-static unsigned cache_mode(struct cached_dev *dc)
+static unsigned int cache_mode(struct cached_dev *dc)
 {
        return BDEV_CACHE_MODE(&dc->sb);
 }
@@ -45,6 +45,7 @@ static void bio_csum(struct bio *bio, struct bkey *k)
 
        bio_for_each_segment(bv, bio, iter) {
                void *d = kmap(bv.bv_page) + bv.bv_offset;
+
                csum = bch_crc64_update(csum, d, bv.bv_len);
                kunmap(bv.bv_page);
        }
@@ -98,7 +99,7 @@ static void bch_data_insert_keys(struct closure *cl)
        closure_return(cl);
 }
 
-static int bch_keylist_realloc(struct keylist *l, unsigned u64s,
+static int bch_keylist_realloc(struct keylist *l, unsigned int u64s,
                               struct cache_set *c)
 {
        size_t oldsize = bch_keylist_nkeys(l);
@@ -125,7 +126,7 @@ static void bch_data_invalidate(struct closure *cl)
                 bio_sectors(bio), (uint64_t) bio->bi_iter.bi_sector);
 
        while (bio_sectors(bio)) {
-               unsigned sectors = min(bio_sectors(bio),
+               unsigned int sectors = min(bio_sectors(bio),
                                       1U << (KEY_SIZE_BITS - 1));
 
                if (bch_keylist_realloc(&op->insert_keys, 2, op->c))
@@ -135,7 +136,9 @@ static void bch_data_invalidate(struct closure *cl)
                bio->bi_iter.bi_size    -= sectors << 9;
 
                bch_keylist_add(&op->insert_keys,
-                               &KEY(op->inode, bio->bi_iter.bi_sector, sectors));
+                               &KEY(op->inode,
+                                    bio->bi_iter.bi_sector,
+                                    sectors));
        }
 
        op->insert_data_done = true;
@@ -151,7 +154,7 @@ static void bch_data_insert_error(struct closure *cl)
 
        /*
         * Our data write just errored, which means we've got a bunch of keys to
-        * insert that point to data that wasn't succesfully written.
+        * insert that point to data that wasn't successfully written.
         *
         * We don't have to insert those keys but we still have to invalidate
         * that region of the cache - so, if we just strip off all the pointers
@@ -211,7 +214,7 @@ static void bch_data_insert_start(struct closure *cl)
        bio->bi_opf &= ~(REQ_PREFLUSH|REQ_FUA);
 
        do {
-               unsigned i;
+               unsigned int i;
                struct bkey *k;
                struct bio_set *split = &op->c->bio_split;
 
@@ -328,7 +331,7 @@ void bch_data_insert(struct closure *cl)
 
 /* Congested? */
 
-unsigned bch_get_congested(struct cache_set *c)
+unsigned int bch_get_congested(struct cache_set *c)
 {
        int i;
        long rand;
@@ -372,8 +375,8 @@ static struct hlist_head *iohash(struct cached_dev *dc, uint64_t k)
 static bool check_should_bypass(struct cached_dev *dc, struct bio *bio)
 {
        struct cache_set *c = dc->disk.c;
-       unsigned mode = cache_mode(dc);
-       unsigned sectors, congested = bch_get_congested(c);
+       unsigned int mode = cache_mode(dc);
+       unsigned int sectors, congested = bch_get_congested(c);
        struct task_struct *task = current;
        struct io *i;
 
@@ -469,11 +472,11 @@ struct search {
        struct bio              *cache_miss;
        struct bcache_device    *d;
 
-       unsigned                insert_bio_sectors;
-       unsigned                recoverable:1;
-       unsigned                write:1;
-       unsigned                read_dirty_data:1;
-       unsigned                cache_missed:1;
+       unsigned int            insert_bio_sectors;
+       unsigned int            recoverable:1;
+       unsigned int            write:1;
+       unsigned int            read_dirty_data:1;
+       unsigned int            cache_missed:1;
 
        unsigned long           start_time;
 
@@ -514,20 +517,20 @@ static int cache_lookup_fn(struct btree_op *op, struct btree *b, struct bkey *k)
        struct search *s = container_of(op, struct search, op);
        struct bio *n, *bio = &s->bio.bio;
        struct bkey *bio_key;
-       unsigned ptr;
+       unsigned int ptr;
 
        if (bkey_cmp(k, &KEY(s->iop.inode, bio->bi_iter.bi_sector, 0)) <= 0)
                return MAP_CONTINUE;
 
        if (KEY_INODE(k) != s->iop.inode ||
            KEY_START(k) > bio->bi_iter.bi_sector) {
-               unsigned bio_sectors = bio_sectors(bio);
-               unsigned sectors = KEY_INODE(k) == s->iop.inode
+               unsigned int bio_sectors = bio_sectors(bio);
+               unsigned int sectors = KEY_INODE(k) == s->iop.inode
                        ? min_t(uint64_t, INT_MAX,
                                KEY_START(k) - bio->bi_iter.bi_sector)
                        : INT_MAX;
-
                int ret = s->d->cache_miss(b, s, bio, sectors);
+
                if (ret != MAP_CONTINUE)
                        return ret;
 
@@ -623,6 +626,7 @@ static void request_endio(struct bio *bio)
 
        if (bio->bi_status) {
                struct search *s = container_of(cl, struct search, cl);
+
                s->iop.status = bio->bi_status;
                /* Only cache read errors are recoverable */
                s->recoverable = false;
@@ -813,7 +817,8 @@ static void cached_dev_read_done(struct closure *cl)
 
        if (s->iop.bio) {
                bio_reset(s->iop.bio);
-               s->iop.bio->bi_iter.bi_sector = s->cache_miss->bi_iter.bi_sector;
+               s->iop.bio->bi_iter.bi_sector =
+                       s->cache_miss->bi_iter.bi_sector;
                bio_copy_dev(s->iop.bio, s->cache_miss);
                s->iop.bio->bi_iter.bi_size = s->insert_bio_sectors << 9;
                bch_bio_map(s->iop.bio, NULL);
@@ -856,10 +861,10 @@ static void cached_dev_read_done_bh(struct closure *cl)
 }
 
 static int cached_dev_cache_miss(struct btree *b, struct search *s,
-                                struct bio *bio, unsigned sectors)
+                                struct bio *bio, unsigned int sectors)
 {
        int ret = MAP_CONTINUE;
-       unsigned reada = 0;
+       unsigned int reada = 0;
        struct cached_dev *dc = container_of(s->d, struct cached_dev, disk);
        struct bio *miss, *cache_bio;
 
@@ -1212,6 +1217,7 @@ static int cached_dev_ioctl(struct bcache_device *d, fmode_t mode,
                            unsigned int cmd, unsigned long arg)
 {
        struct cached_dev *dc = container_of(d, struct cached_dev, disk);
+
        return __blkdev_driver_ioctl(dc->bdev, mode, cmd, arg);
 }
 
@@ -1226,7 +1232,7 @@ static int cached_dev_congested(void *data, int bits)
                return 1;
 
        if (cached_dev_get(dc)) {
-               unsigned i;
+               unsigned int i;
                struct cache *ca;
 
                for_each_cache(ca, d->c, i) {
@@ -1253,9 +1259,9 @@ void bch_cached_dev_request_init(struct cached_dev *dc)
 /* Flash backed devices */
 
 static int flash_dev_cache_miss(struct btree *b, struct search *s,
-                               struct bio *bio, unsigned sectors)
+                               struct bio *bio, unsigned int sectors)
 {
-       unsigned bytes = min(sectors, bio_sectors(bio)) << 9;
+       unsigned int bytes = min(sectors, bio_sectors(bio)) << 9;
 
        swap(bio->bi_iter.bi_size, bytes);
        zero_fill_bio(bio);
@@ -1338,7 +1344,7 @@ static int flash_dev_congested(void *data, int bits)
        struct bcache_device *d = data;
        struct request_queue *q;
        struct cache *ca;
-       unsigned i;
+       unsigned int i;
        int ret = 0;
 
        for_each_cache(ca, d->c, i) {
@@ -1361,8 +1367,7 @@ void bch_flash_dev_request_init(struct bcache_device *d)
 
 void bch_request_exit(void)
 {
-       if (bch_search_cache)
-               kmem_cache_destroy(bch_search_cache);
+       kmem_cache_destroy(bch_search_cache);
 }
 
 int __init bch_request_init(void)
index dea0886..aa055cf 100644 (file)
@@ -8,7 +8,7 @@ struct data_insert_op {
        struct bio              *bio;
        struct workqueue_struct *wq;
 
-       unsigned                inode;
+       unsigned int            inode;
        uint16_t                write_point;
        uint16_t                write_prio;
        blk_status_t            status;
@@ -17,15 +17,15 @@ struct data_insert_op {
                uint16_t        flags;
 
        struct {
-               unsigned        bypass:1;
-               unsigned        writeback:1;
-               unsigned        flush_journal:1;
-               unsigned        csum:1;
+               unsigned int    bypass:1;
+               unsigned int    writeback:1;
+               unsigned int    flush_journal:1;
+               unsigned int    csum:1;
 
-               unsigned        replace:1;
-               unsigned        replace_collision:1;
+               unsigned int    replace:1;
+               unsigned int    replace_collision:1;
 
-               unsigned        insert_data_done:1;
+               unsigned int    insert_data_done:1;
        };
        };
 
@@ -33,7 +33,7 @@ struct data_insert_op {
        BKEY_PADDED(replace_key);
 };
 
-unsigned bch_get_congested(struct cache_set *);
+unsigned int bch_get_congested(struct cache_set *c);
 void bch_data_insert(struct closure *cl);
 
 void bch_cached_dev_request_init(struct cached_dev *dc);
index be11932..894410f 100644 (file)
  * stored left shifted by 16, and scaled back in the sysfs show() function.
  */
 
-static const unsigned DAY_RESCALE              = 288;
-static const unsigned HOUR_RESCALE             = 12;
-static const unsigned FIVE_MINUTE_RESCALE      = 1;
-static const unsigned accounting_delay         = (HZ * 300) / 22;
-static const unsigned accounting_weight                = 32;
+static const unsigned int DAY_RESCALE          = 288;
+static const unsigned int HOUR_RESCALE         = 12;
+static const unsigned int FIVE_MINUTE_RESCALE  = 1;
+static const unsigned int accounting_delay     = (HZ * 300) / 22;
+static const unsigned int accounting_weight    = 32;
 
 /* sysfs reading/writing */
 
@@ -152,7 +152,7 @@ static void scale_accounting(struct timer_list *t)
        struct cache_accounting *acc = from_timer(acc, t, timer);
 
 #define move_stat(name) do {                                           \
-       unsigned t = atomic_xchg(&acc->collector.name, 0);              \
+       unsigned int t = atomic_xchg(&acc->collector.name, 0);          \
        t <<= 16;                                                       \
        acc->five_minute.name += t;                                     \
        acc->hour.name += t;                                            \
@@ -200,6 +200,7 @@ void bch_mark_cache_accounting(struct cache_set *c, struct bcache_device *d,
                               bool hit, bool bypass)
 {
        struct cached_dev *dc = container_of(d, struct cached_dev, disk);
+
        mark_cache_stats(&dc->accounting.collector, hit, bypass);
        mark_cache_stats(&c->accounting.collector, hit, bypass);
 }
@@ -207,6 +208,7 @@ void bch_mark_cache_accounting(struct cache_set *c, struct bcache_device *d,
 void bch_mark_cache_readahead(struct cache_set *c, struct bcache_device *d)
 {
        struct cached_dev *dc = container_of(d, struct cached_dev, disk);
+
        atomic_inc(&dc->accounting.collector.cache_readaheads);
        atomic_inc(&c->accounting.collector.cache_readaheads);
 }
@@ -214,6 +216,7 @@ void bch_mark_cache_readahead(struct cache_set *c, struct bcache_device *d)
 void bch_mark_cache_miss_collision(struct cache_set *c, struct bcache_device *d)
 {
        struct cached_dev *dc = container_of(d, struct cached_dev, disk);
+
        atomic_inc(&dc->accounting.collector.cache_miss_collisions);
        atomic_inc(&c->accounting.collector.cache_miss_collisions);
 }
index 0b70f9d..abfaabf 100644 (file)
@@ -23,7 +23,7 @@ struct cache_stats {
        unsigned long cache_miss_collisions;
        unsigned long sectors_bypassed;
 
-       unsigned                rescale;
+       unsigned int            rescale;
 };
 
 struct cache_accounting {
@@ -53,10 +53,13 @@ void bch_cache_accounting_clear(struct cache_accounting *acc);
 
 void bch_cache_accounting_destroy(struct cache_accounting *acc);
 
-void bch_mark_cache_accounting(struct cache_set *, struct bcache_device *,
-                              bool, bool);
-void bch_mark_cache_readahead(struct cache_set *, struct bcache_device *);
-void bch_mark_cache_miss_collision(struct cache_set *, struct bcache_device *);
-void bch_mark_sectors_bypassed(struct cache_set *, struct cached_dev *, int);
+void bch_mark_cache_accounting(struct cache_set *c, struct bcache_device *d,
+                              bool hit, bool bypass);
+void bch_mark_cache_readahead(struct cache_set *c, struct bcache_device *d);
+void bch_mark_cache_miss_collision(struct cache_set *c,
+                                  struct bcache_device *d);
+void bch_mark_sectors_bypassed(struct cache_set *c,
+                              struct cached_dev *dc,
+                              int sectors);
 
 #endif /* _BCACHE_STATS_H_ */
index 55a3764..94c756c 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * bcache setup/teardown code, and some metadata io - read a superblock and
  * figure out what to do with it.
@@ -61,7 +62,7 @@ static const char *read_super(struct cache_sb *sb, struct block_device *bdev,
        const char *err;
        struct cache_sb *s;
        struct buffer_head *bh = __bread(bdev, 1, SB_SIZE);
-       unsigned i;
+       unsigned int i;
 
        if (!bh)
                return "IO error";
@@ -149,7 +150,8 @@ static const char *read_super(struct cache_sb *sb, struct block_device *bdev,
                        goto err;
 
                err = "Invalid superblock: device too small";
-               if (get_capacity(bdev->bd_disk) < sb->bucket_size * sb->nbuckets)
+               if (get_capacity(bdev->bd_disk) <
+                   sb->bucket_size * sb->nbuckets)
                        goto err;
 
                err = "Bad UUID";
@@ -202,7 +204,7 @@ static void write_bdev_super_endio(struct bio *bio)
 static void __write_super(struct cache_sb *sb, struct bio *bio)
 {
        struct cache_sb *out = page_address(bio_first_page_all(bio));
-       unsigned i;
+       unsigned int i;
 
        bio->bi_iter.bi_sector  = SB_SECTOR;
        bio->bi_iter.bi_size    = SB_SIZE;
@@ -282,7 +284,7 @@ void bcache_write_super(struct cache_set *c)
 {
        struct closure *cl = &c->sb_write;
        struct cache *ca;
-       unsigned i;
+       unsigned int i;
 
        down(&c->sb_write_mutex);
        closure_init(cl, &c->cl);
@@ -334,7 +336,7 @@ static void uuid_io(struct cache_set *c, int op, unsigned long op_flags,
 {
        struct closure *cl = &c->uuid_write;
        struct uuid_entry *u;
-       unsigned i;
+       unsigned int i;
        char buf[80];
 
        BUG_ON(!parent);
@@ -415,8 +417,8 @@ static int __uuid_write(struct cache_set *c)
 {
        BKEY_PADDED(key) k;
        struct closure cl;
-       closure_init_stack(&cl);
 
+       closure_init_stack(&cl);
        lockdep_assert_held(&bch_register_lock);
 
        if (bch_bucket_alloc_set(c, RESERVE_BTREE, &k.key, 1, true))
@@ -456,6 +458,7 @@ static struct uuid_entry *uuid_find(struct cache_set *c, const char *uuid)
 static struct uuid_entry *uuid_find_empty(struct cache_set *c)
 {
        static const char zero_uuid[16] = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
+
        return uuid_find(c, zero_uuid);
 }
 
@@ -463,8 +466,8 @@ static struct uuid_entry *uuid_find_empty(struct cache_set *c)
  * Bucket priorities/gens:
  *
  * For each bucket, we store on disk its
  * 8 bit gen
  * 16 bit priority
*   8 bit gen
 16 bit priority
  *
  * See alloc.c for an explanation of the gen. The priority is used to implement
  * lru (and in the future other) cache replacement policies; for most purposes
@@ -587,7 +590,7 @@ static void prio_read(struct cache *ca, uint64_t bucket)
        struct prio_set *p = ca->disk_buckets;
        struct bucket_disk *d = p->data + prios_per_bucket(ca), *end = d;
        struct bucket *b;
-       unsigned bucket_nr = 0;
+       unsigned int bucket_nr = 0;
 
        for (b = ca->buckets;
             b < ca->buckets + ca->sb.nbuckets;
@@ -599,7 +602,8 @@ static void prio_read(struct cache *ca, uint64_t bucket)
 
                        prio_io(ca, bucket, REQ_OP_READ, 0);
 
-                       if (p->csum != bch_crc64(&p->magic, bucket_bytes(ca) - 8))
+                       if (p->csum !=
+                           bch_crc64(&p->magic, bucket_bytes(ca) - 8))
                                pr_warn("bad csum reading priorities");
 
                        if (p->magic != pset_magic(&ca->sb))
@@ -619,6 +623,7 @@ static void prio_read(struct cache *ca, uint64_t bucket)
 static int open_dev(struct block_device *b, fmode_t mode)
 {
        struct bcache_device *d = b->bd_disk->private_data;
+
        if (test_bit(BCACHE_DEV_CLOSING, &d->flags))
                return -ENXIO;
 
@@ -629,6 +634,7 @@ static int open_dev(struct block_device *b, fmode_t mode)
 static void release_dev(struct gendisk *b, fmode_t mode)
 {
        struct bcache_device *d = b->private_data;
+
        closure_put(&d->cl);
 }
 
@@ -662,7 +668,7 @@ static void bcache_device_unlink(struct bcache_device *d)
        lockdep_assert_held(&bch_register_lock);
 
        if (d->c && !test_and_set_bit(BCACHE_DEV_UNLINK_DONE, &d->flags)) {
-               unsigned i;
+               unsigned int i;
                struct cache *ca;
 
                sysfs_remove_link(&d->c->kobj, d->name);
@@ -676,7 +682,7 @@ static void bcache_device_unlink(struct bcache_device *d)
 static void bcache_device_link(struct bcache_device *d, struct cache_set *c,
                               const char *name)
 {
-       unsigned i;
+       unsigned int i;
        struct cache *ca;
 
        for_each_cache(ca, d->c, i)
@@ -715,7 +721,7 @@ static void bcache_device_detach(struct bcache_device *d)
 }
 
 static void bcache_device_attach(struct bcache_device *d, struct cache_set *c,
-                                unsigned id)
+                                unsigned int id)
 {
        d->id = id;
        d->c = c;
@@ -762,7 +768,7 @@ static void bcache_device_free(struct bcache_device *d)
        closure_debug_destroy(&d->cl);
 }
 
-static int bcache_device_init(struct bcache_device *d, unsigned block_size,
+static int bcache_device_init(struct bcache_device *d, unsigned int block_size,
                              sector_t sectors)
 {
        struct request_queue *q;
@@ -778,7 +784,7 @@ static int bcache_device_init(struct bcache_device *d, unsigned block_size,
 
        if (!d->nr_stripes || d->nr_stripes > max_stripes) {
                pr_err("nr_stripes too large or invalid: %u (start sector beyond end of disk?)",
-                       (unsigned)d->nr_stripes);
+                       (unsigned int)d->nr_stripes);
                return -ENOMEM;
        }
 
@@ -919,6 +925,7 @@ void bch_cached_dev_run(struct cached_dev *dc)
        if (!d->c &&
            BDEV_STATE(&dc->sb) != BDEV_STATE_NONE) {
                struct closure cl;
+
                closure_init_stack(&cl);
 
                SET_BDEV_STATE(&dc->sb, BDEV_STATE_STALE);
@@ -928,8 +935,10 @@ void bch_cached_dev_run(struct cached_dev *dc)
 
        add_disk(d->disk);
        bd_link_disk_holder(dc->bdev, dc->disk.disk);
-       /* won't show up in the uevent file, use udevadm monitor -e instead
-        * only class / kset properties are persistent */
+       /*
+        * won't show up in the uevent file, use udevadm monitor -e instead
+        * only class / kset properties are persistent
+        */
        kobject_uevent_env(&disk_to_dev(d->disk)->kobj, KOBJ_CHANGE, env);
        kfree(env[1]);
        kfree(env[2]);
@@ -976,6 +985,7 @@ static void cached_dev_detach_finish(struct work_struct *w)
 {
        struct cached_dev *dc = container_of(w, struct cached_dev, detach);
        struct closure cl;
+
        closure_init_stack(&cl);
 
        BUG_ON(!test_bit(BCACHE_DEV_DETACHING, &dc->disk.flags));
@@ -1097,12 +1107,14 @@ int bch_cached_dev_attach(struct cached_dev *dc, struct cache_set *c,
                }
        }
 
-       /* Deadlocks since we're called via sysfs...
-       sysfs_remove_file(&dc->kobj, &sysfs_attach);
+       /*
+        * Deadlocks since we're called via sysfs...
+        * sysfs_remove_file(&dc->kobj, &sysfs_attach);
         */
 
        if (bch_is_zero(u->uuid, 16)) {
                struct closure cl;
+
                closure_init_stack(&cl);
 
                memcpy(u->uuid, dc->sb.uuid, 16);
@@ -1124,11 +1136,11 @@ int bch_cached_dev_attach(struct cached_dev *dc, struct cache_set *c,
        list_move(&dc->list, &c->cached_devs);
        calc_cached_dev_sectors(c);
 
-       smp_wmb();
        /*
         * dc->c must be set before dc->count != 0 - paired with the mb in
         * cached_dev_get()
         */
+       smp_wmb();
        refcount_set(&dc->count, 1);
 
        /* Block writeback thread, but spawn it */
@@ -1212,7 +1224,7 @@ static void cached_dev_flush(struct closure *cl)
        continue_at(cl, cached_dev_free, system_wq);
 }
 
-static int cached_dev_init(struct cached_dev *dc, unsigned block_size)
+static int cached_dev_init(struct cached_dev *dc, unsigned int block_size)
 {
        int ret;
        struct io *io;
@@ -1320,6 +1332,7 @@ void bch_flash_dev_release(struct kobject *kobj)
 static void flash_dev_free(struct closure *cl)
 {
        struct bcache_device *d = container_of(cl, struct bcache_device, cl);
+
        mutex_lock(&bch_register_lock);
        atomic_long_sub(bcache_dev_sectors_dirty(d),
                        &d->c->flash_dev_dirty_sectors);
@@ -1459,17 +1472,18 @@ bool bch_cache_set_error(struct cache_set *c, const char *fmt, ...)
        if (test_and_set_bit(CACHE_SET_IO_DISABLE, &c->flags))
                pr_info("CACHE_SET_IO_DISABLE already set");
 
-       /* XXX: we can be called from atomic context
-       acquire_console_sem();
-       */
+       /*
+        * XXX: we can be called from atomic context
+        * acquire_console_sem();
+        */
 
-       printk(KERN_ERR "bcache: error on %pU: ", c->sb.set_uuid);
+       pr_err("bcache: error on %pU: ", c->sb.set_uuid);
 
        va_start(args, fmt);
        vprintk(fmt, args);
        va_end(args);
 
-       printk(", disabling caching\n");
+       pr_err(", disabling caching\n");
 
        if (c->on_error == ON_ERROR_PANIC)
                panic("panic forced after error\n");
@@ -1481,6 +1495,7 @@ bool bch_cache_set_error(struct cache_set *c, const char *fmt, ...)
 void bch_cache_set_release(struct kobject *kobj)
 {
        struct cache_set *c = container_of(kobj, struct cache_set, kobj);
+
        kfree(c);
        module_put(THIS_MODULE);
 }
@@ -1489,7 +1504,7 @@ static void cache_set_free(struct closure *cl)
 {
        struct cache_set *c = container_of(cl, struct cache_set, cl);
        struct cache *ca;
-       unsigned i;
+       unsigned int i;
 
        if (!IS_ERR_OR_NULL(c->debug))
                debugfs_remove(c->debug);
@@ -1532,7 +1547,7 @@ static void cache_set_flush(struct closure *cl)
        struct cache_set *c = container_of(cl, struct cache_set, caching);
        struct cache *ca;
        struct btree *b;
-       unsigned i;
+       unsigned int i;
 
        bch_cache_accounting_destroy(&c->accounting);
 
@@ -1671,6 +1686,7 @@ struct cache_set *bch_cache_set_alloc(struct cache_sb *sb)
 {
        int iter_size;
        struct cache_set *c = kzalloc(sizeof(struct cache_set), GFP_KERNEL);
+
        if (!c)
                return NULL;
 
@@ -1731,8 +1747,8 @@ struct cache_set *bch_cache_set_alloc(struct cache_sb *sb)
        if (!(c->devices = kcalloc(c->nr_uuids, sizeof(void *), GFP_KERNEL)) ||
            mempool_init_slab_pool(&c->search, 32, bch_search_cache) ||
            mempool_init_kmalloc_pool(&c->bio_meta, 2,
-                                     sizeof(struct bbio) + sizeof(struct bio_vec) *
-                                     bucket_pages(c)) ||
+                               sizeof(struct bbio) + sizeof(struct bio_vec) *
+                               bucket_pages(c)) ||
            mempool_init_kmalloc_pool(&c->fill_iter, 1, iter_size) ||
            bioset_init(&c->bio_split, 4, offsetof(struct bbio, bio),
                        BIOSET_NEED_BVECS|BIOSET_NEED_RESCUER) ||
@@ -1762,7 +1778,7 @@ static void run_cache_set(struct cache_set *c)
        struct cached_dev *dc, *t;
        struct cache *ca;
        struct closure cl;
-       unsigned i;
+       unsigned int i;
 
        closure_init_stack(&cl);
 
@@ -1804,7 +1820,9 @@ static void run_cache_set(struct cache_set *c)
                        goto err;
 
                err = "error reading btree root";
-               c->root = bch_btree_node_get(c, NULL, k, j->btree_level, true, NULL);
+               c->root = bch_btree_node_get(c, NULL, k,
+                                            j->btree_level,
+                                            true, NULL);
                if (IS_ERR_OR_NULL(c->root))
                        goto err;
 
@@ -1853,7 +1871,7 @@ static void run_cache_set(struct cache_set *c)
                pr_notice("invalidating existing data");
 
                for_each_cache(ca, c, i) {
-                       unsigned j;
+                       unsigned int j;
 
                        ca->sb.keys = clamp_t(int, ca->sb.nbuckets >> 7,
                                              2, SB_JOURNAL_BUCKETS);
@@ -1998,7 +2016,7 @@ err:
 void bch_cache_release(struct kobject *kobj)
 {
        struct cache *ca = container_of(kobj, struct cache, kobj);
-       unsigned i;
+       unsigned int i;
 
        if (ca->set) {
                BUG_ON(ca->set->cache[ca->sb.nr_this_dev] != ca);
@@ -2098,7 +2116,9 @@ static int register_cache(struct cache_sb *sb, struct page *sb_page,
                goto err;
        }
 
-       if (kobject_add(&ca->kobj, &part_to_dev(bdev->bd_part)->kobj, "bcache")) {
+       if (kobject_add(&ca->kobj,
+                       &part_to_dev(bdev->bd_part)->kobj,
+                       "bcache")) {
                err = "error calling kobject_add";
                ret = -ENOMEM;
                goto out;
@@ -2127,13 +2147,14 @@ err:
 
 /* Global interfaces/init */
 
-static ssize_t register_bcache(struct kobject *, struct kobj_attribute *,
-                              const char *, size_t);
+static ssize_t register_bcache(struct kobject *k, struct kobj_attribute *attr,
+                              const char *buffer, size_t size);
 
 kobj_attribute_write(register,         register_bcache);
 kobj_attribute_write(register_quiet,   register_bcache);
 
-static bool bch_is_open_backing(struct block_device *bdev) {
+static bool bch_is_open_backing(struct block_device *bdev)
+{
        struct cache_set *c, *tc;
        struct cached_dev *dc, *t;
 
@@ -2147,10 +2168,11 @@ static bool bch_is_open_backing(struct block_device *bdev) {
        return false;
 }
 
-static bool bch_is_open_cache(struct block_device *bdev) {
+static bool bch_is_open_cache(struct block_device *bdev)
+{
        struct cache_set *c, *tc;
        struct cache *ca;
-       unsigned i;
+       unsigned int i;
 
        list_for_each_entry_safe(c, tc, &bch_cache_sets, list)
                for_each_cache(ca, c, i)
@@ -2159,7 +2181,8 @@ static bool bch_is_open_cache(struct block_device *bdev) {
        return false;
 }
 
-static bool bch_is_open(struct block_device *bdev) {
+static bool bch_is_open(struct block_device *bdev)
+{
        return bch_is_open_cache(bdev) || bch_is_open_backing(bdev);
 }
 
@@ -2216,6 +2239,7 @@ static ssize_t register_bcache(struct kobject *k, struct kobj_attribute *attr,
        err = "failed to register device";
        if (SB_IS_BDEV(sb)) {
                struct cached_dev *dc = kzalloc(sizeof(*dc), GFP_KERNEL);
+
                if (!dc)
                        goto err_close;
 
@@ -2224,6 +2248,7 @@ static ssize_t register_bcache(struct kobject *k, struct kobj_attribute *attr,
                mutex_unlock(&bch_register_lock);
        } else {
                struct cache *ca = kzalloc(sizeof(*ca), GFP_KERNEL);
+
                if (!ca)
                        goto err_close;
 
index 81d3520..150cf4f 100644 (file)
@@ -130,8 +130,10 @@ rw_attribute(btree_shrinker_disabled);
 rw_attribute(copy_gc_enabled);
 rw_attribute(size);
 
-static ssize_t bch_snprint_string_list(char *buf, size_t size, const char * const list[],
-                           size_t selected)
+static ssize_t bch_snprint_string_list(char *buf,
+                                      size_t size,
+                                      const char * const list[],
+                                      size_t selected)
 {
        char *out = buf;
        size_t i;
@@ -148,7 +150,7 @@ SHOW(__bch_cached_dev)
 {
        struct cached_dev *dc = container_of(kobj, struct cached_dev,
                                             disk.kobj);
-       const char *states[] = { "no cache", "clean", "dirty", "inconsistent" };
+       char const *states[] = { "no cache", "clean", "dirty", "inconsistent" };
        int wb = dc->writeback_running;
 
 #define var(stat)              (dc->stat)
@@ -307,7 +309,7 @@ STORE(__cached_dev)
                if (v < 0)
                        return v;
 
-               if ((unsigned) v != BDEV_CACHE_MODE(&dc->sb)) {
+               if ((unsigned int) v != BDEV_CACHE_MODE(&dc->sb)) {
                        SET_BDEV_CACHE_MODE(&dc->sb, v);
                        bch_write_bdev_super(dc, NULL);
                }
@@ -341,8 +343,9 @@ STORE(__cached_dev)
                add_uevent_var(env, "DRIVER=bcache");
                add_uevent_var(env, "CACHED_UUID=%pU", dc->sb.uuid),
                add_uevent_var(env, "CACHED_LABEL=%s", buf);
-               kobject_uevent_env(
-                       &disk_to_dev(dc->disk.disk)->kobj, KOBJ_CHANGE, env->envp);
+               kobject_uevent_env(&disk_to_dev(dc->disk.disk)->kobj,
+                                  KOBJ_CHANGE,
+                                  env->envp);
                kfree(env);
        }
 
@@ -459,6 +462,7 @@ STORE(__bch_flash_dev)
 
        if (attr == &sysfs_size) {
                uint64_t v;
+
                strtoi_h_or_return(buf, v);
 
                u->sectors = v >> 9;
@@ -533,9 +537,9 @@ static int bch_bset_print_stats(struct cache_set *c, char *buf)
                        op.stats.floats, op.stats.failed);
 }
 
-static unsigned bch_root_usage(struct cache_set *c)
+static unsigned int bch_root_usage(struct cache_set *c)
 {
-       unsigned bytes = 0;
+       unsigned int bytes = 0;
        struct bkey *k;
        struct btree *b;
        struct btree_iter iter;
@@ -570,9 +574,9 @@ static size_t bch_cache_size(struct cache_set *c)
        return ret;
 }
 
-static unsigned bch_cache_max_chain(struct cache_set *c)
+static unsigned int bch_cache_max_chain(struct cache_set *c)
 {
-       unsigned ret = 0;
+       unsigned int ret = 0;
        struct hlist_head *h;
 
        mutex_lock(&c->bucket_lock);
@@ -580,7 +584,7 @@ static unsigned bch_cache_max_chain(struct cache_set *c)
        for (h = c->bucket_hash;
             h < c->bucket_hash + (1 << BUCKET_HASH_BITS);
             h++) {
-               unsigned i = 0;
+               unsigned int i = 0;
                struct hlist_node *p;
 
                hlist_for_each(p, h)
@@ -593,13 +597,13 @@ static unsigned bch_cache_max_chain(struct cache_set *c)
        return ret;
 }
 
-static unsigned bch_btree_used(struct cache_set *c)
+static unsigned int bch_btree_used(struct cache_set *c)
 {
        return div64_u64(c->gc_stats.key_bytes * 100,
                         (c->gc_stats.nodes ?: 1) * btree_bytes(c));
 }
 
-static unsigned bch_average_key_size(struct cache_set *c)
+static unsigned int bch_average_key_size(struct cache_set *c)
 {
        return c->gc_stats.nkeys
                ? div64_u64(c->gc_stats.data, c->gc_stats.nkeys)
@@ -703,6 +707,7 @@ STORE(__bch_cache_set)
        if (attr == &sysfs_flash_vol_create) {
                int r;
                uint64_t v;
+
                strtoi_h_or_return(buf, v);
 
                r = bch_flash_dev_create(c, v);
@@ -736,6 +741,7 @@ STORE(__bch_cache_set)
 
        if (attr == &sysfs_prune_cache) {
                struct shrink_control sc;
+
                sc.gfp_mask = GFP_KERNEL;
                sc.nr_to_scan = strtoul_or_return(buf);
                c->shrink.scan_objects(&c->shrink, &sc);
@@ -789,12 +795,14 @@ STORE_LOCKED(bch_cache_set)
 SHOW(bch_cache_set_internal)
 {
        struct cache_set *c = container_of(kobj, struct cache_set, internal);
+
        return bch_cache_set_show(&c->kobj, attr, buf);
 }
 
 STORE(bch_cache_set_internal)
 {
        struct cache_set *c = container_of(kobj, struct cache_set, internal);
+
        return bch_cache_set_store(&c->kobj, attr, buf, size);
 }
 
@@ -996,7 +1004,7 @@ STORE(__bch_cache)
                if (v < 0)
                        return v;
 
-               if ((unsigned) v != CACHE_REPLACEMENT(&ca->sb)) {
+               if ((unsigned int) v != CACHE_REPLACEMENT(&ca->sb)) {
                        mutex_lock(&ca->set->bucket_lock);
                        SET_CACHE_REPLACEMENT(&ca->sb, v);
                        mutex_unlock(&ca->set->bucket_lock);
index b54fe96..3fe8242 100644 (file)
@@ -44,9 +44,9 @@ STORE(fn)                                                             \
        static struct attribute sysfs_##_name =                         \
                { .name = #_name, .mode = _mode }
 
-#define write_attribute(n)     __sysfs_attribute(n, S_IWUSR)
-#define read_attribute(n)      __sysfs_attribute(n, S_IRUGO)
-#define rw_attribute(n)                __sysfs_attribute(n, S_IRUGO|S_IWUSR)
+#define write_attribute(n)     __sysfs_attribute(n, 0200)
+#define read_attribute(n)      __sysfs_attribute(n, 0444)
+#define rw_attribute(n)                __sysfs_attribute(n, 0644)
 
 #define sysfs_printf(file, fmt, ...)                                   \
 do {                                                                   \
index b15256b..20eddea 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * random utiility code, for bcache but in theory not specific to bcache
  *
@@ -133,6 +134,7 @@ bool bch_is_zero(const char *p, size_t n)
 int bch_parse_uuid(const char *s, char *uuid)
 {
        size_t i, j, x;
+
        memset(uuid, 0, 16);
 
        for (i = 0, j = 0;
@@ -279,134 +281,3 @@ int bch_bio_alloc_pages(struct bio *bio, gfp_t gfp_mask)
 
        return 0;
 }
-
-/*
- * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group (Any
- * use permitted, subject to terms of PostgreSQL license; see.)
-
- * If we have a 64-bit integer type, then a 64-bit CRC looks just like the
- * usual sort of implementation. (See Ross Williams' excellent introduction
- * A PAINLESS GUIDE TO CRC ERROR DETECTION ALGORITHMS, available from
- * ftp://ftp.rocksoft.com/papers/crc_v3.txt or several other net sites.)
- * If we have no working 64-bit type, then fake it with two 32-bit registers.
- *
- * The present implementation is a normal (not "reflected", in Williams'
- * terms) 64-bit CRC, using initial all-ones register contents and a final
- * bit inversion. The chosen polynomial is borrowed from the DLT1 spec
- * (ECMA-182, available from http://www.ecma.ch/ecma1/STAND/ECMA-182.HTM):
- *
- * x^64 + x^62 + x^57 + x^55 + x^54 + x^53 + x^52 + x^47 + x^46 + x^45 +
- * x^40 + x^39 + x^38 + x^37 + x^35 + x^33 + x^32 + x^31 + x^29 + x^27 +
- * x^24 + x^23 + x^22 + x^21 + x^19 + x^17 + x^13 + x^12 + x^10 + x^9 +
- * x^7 + x^4 + x + 1
-*/
-
-static const uint64_t crc_table[256] = {
-       0x0000000000000000ULL, 0x42F0E1EBA9EA3693ULL, 0x85E1C3D753D46D26ULL,
-       0xC711223CFA3E5BB5ULL, 0x493366450E42ECDFULL, 0x0BC387AEA7A8DA4CULL,
-       0xCCD2A5925D9681F9ULL, 0x8E224479F47CB76AULL, 0x9266CC8A1C85D9BEULL,
-       0xD0962D61B56FEF2DULL, 0x17870F5D4F51B498ULL, 0x5577EEB6E6BB820BULL,
-       0xDB55AACF12C73561ULL, 0x99A54B24BB2D03F2ULL, 0x5EB4691841135847ULL,
-       0x1C4488F3E8F96ED4ULL, 0x663D78FF90E185EFULL, 0x24CD9914390BB37CULL,
-       0xE3DCBB28C335E8C9ULL, 0xA12C5AC36ADFDE5AULL, 0x2F0E1EBA9EA36930ULL,
-       0x6DFEFF5137495FA3ULL, 0xAAEFDD6DCD770416ULL, 0xE81F3C86649D3285ULL,
-       0xF45BB4758C645C51ULL, 0xB6AB559E258E6AC2ULL, 0x71BA77A2DFB03177ULL,
-       0x334A9649765A07E4ULL, 0xBD68D2308226B08EULL, 0xFF9833DB2BCC861DULL,
-       0x388911E7D1F2DDA8ULL, 0x7A79F00C7818EB3BULL, 0xCC7AF1FF21C30BDEULL,
-       0x8E8A101488293D4DULL, 0x499B3228721766F8ULL, 0x0B6BD3C3DBFD506BULL,
-       0x854997BA2F81E701ULL, 0xC7B97651866BD192ULL, 0x00A8546D7C558A27ULL,
-       0x4258B586D5BFBCB4ULL, 0x5E1C3D753D46D260ULL, 0x1CECDC9E94ACE4F3ULL,
-       0xDBFDFEA26E92BF46ULL, 0x990D1F49C77889D5ULL, 0x172F5B3033043EBFULL,
-       0x55DFBADB9AEE082CULL, 0x92CE98E760D05399ULL, 0xD03E790CC93A650AULL,
-       0xAA478900B1228E31ULL, 0xE8B768EB18C8B8A2ULL, 0x2FA64AD7E2F6E317ULL,
-       0x6D56AB3C4B1CD584ULL, 0xE374EF45BF6062EEULL, 0xA1840EAE168A547DULL,
-       0x66952C92ECB40FC8ULL, 0x2465CD79455E395BULL, 0x3821458AADA7578FULL,
-       0x7AD1A461044D611CULL, 0xBDC0865DFE733AA9ULL, 0xFF3067B657990C3AULL,
-       0x711223CFA3E5BB50ULL, 0x33E2C2240A0F8DC3ULL, 0xF4F3E018F031D676ULL,
-       0xB60301F359DBE0E5ULL, 0xDA050215EA6C212FULL, 0x98F5E3FE438617BCULL,
-       0x5FE4C1C2B9B84C09ULL, 0x1D14202910527A9AULL, 0x93366450E42ECDF0ULL,
-       0xD1C685BB4DC4FB63ULL, 0x16D7A787B7FAA0D6ULL, 0x5427466C1E109645ULL,
-       0x4863CE9FF6E9F891ULL, 0x0A932F745F03CE02ULL, 0xCD820D48A53D95B7ULL,
-       0x8F72ECA30CD7A324ULL, 0x0150A8DAF8AB144EULL, 0x43A04931514122DDULL,
-       0x84B16B0DAB7F7968ULL, 0xC6418AE602954FFBULL, 0xBC387AEA7A8DA4C0ULL,
-       0xFEC89B01D3679253ULL, 0x39D9B93D2959C9E6ULL, 0x7B2958D680B3FF75ULL,
-       0xF50B1CAF74CF481FULL, 0xB7FBFD44DD257E8CULL, 0x70EADF78271B2539ULL,
-       0x321A3E938EF113AAULL, 0x2E5EB66066087D7EULL, 0x6CAE578BCFE24BEDULL,
-       0xABBF75B735DC1058ULL, 0xE94F945C9C3626CBULL, 0x676DD025684A91A1ULL,
-       0x259D31CEC1A0A732ULL, 0xE28C13F23B9EFC87ULL, 0xA07CF2199274CA14ULL,
-       0x167FF3EACBAF2AF1ULL, 0x548F120162451C62ULL, 0x939E303D987B47D7ULL,
-       0xD16ED1D631917144ULL, 0x5F4C95AFC5EDC62EULL, 0x1DBC74446C07F0BDULL,
-       0xDAAD56789639AB08ULL, 0x985DB7933FD39D9BULL, 0x84193F60D72AF34FULL,
-       0xC6E9DE8B7EC0C5DCULL, 0x01F8FCB784FE9E69ULL, 0x43081D5C2D14A8FAULL,
-       0xCD2A5925D9681F90ULL, 0x8FDAB8CE70822903ULL, 0x48CB9AF28ABC72B6ULL,
-       0x0A3B7B1923564425ULL, 0x70428B155B4EAF1EULL, 0x32B26AFEF2A4998DULL,
-       0xF5A348C2089AC238ULL, 0xB753A929A170F4ABULL, 0x3971ED50550C43C1ULL,
-       0x7B810CBBFCE67552ULL, 0xBC902E8706D82EE7ULL, 0xFE60CF6CAF321874ULL,
-       0xE224479F47CB76A0ULL, 0xA0D4A674EE214033ULL, 0x67C58448141F1B86ULL,
-       0x253565A3BDF52D15ULL, 0xAB1721DA49899A7FULL, 0xE9E7C031E063ACECULL,
-       0x2EF6E20D1A5DF759ULL, 0x6C0603E6B3B7C1CAULL, 0xF6FAE5C07D3274CDULL,
-       0xB40A042BD4D8425EULL, 0x731B26172EE619EBULL, 0x31EBC7FC870C2F78ULL,
-       0xBFC9838573709812ULL, 0xFD39626EDA9AAE81ULL, 0x3A28405220A4F534ULL,
-       0x78D8A1B9894EC3A7ULL, 0x649C294A61B7AD73ULL, 0x266CC8A1C85D9BE0ULL,
-       0xE17DEA9D3263C055ULL, 0xA38D0B769B89F6C6ULL, 0x2DAF4F0F6FF541ACULL,
-       0x6F5FAEE4C61F773FULL, 0xA84E8CD83C212C8AULL, 0xEABE6D3395CB1A19ULL,
-       0x90C79D3FEDD3F122ULL, 0xD2377CD44439C7B1ULL, 0x15265EE8BE079C04ULL,
-       0x57D6BF0317EDAA97ULL, 0xD9F4FB7AE3911DFDULL, 0x9B041A914A7B2B6EULL,
-       0x5C1538ADB04570DBULL, 0x1EE5D94619AF4648ULL, 0x02A151B5F156289CULL,
-       0x4051B05E58BC1E0FULL, 0x87409262A28245BAULL, 0xC5B073890B687329ULL,
-       0x4B9237F0FF14C443ULL, 0x0962D61B56FEF2D0ULL, 0xCE73F427ACC0A965ULL,
-       0x8C8315CC052A9FF6ULL, 0x3A80143F5CF17F13ULL, 0x7870F5D4F51B4980ULL,
-       0xBF61D7E80F251235ULL, 0xFD913603A6CF24A6ULL, 0x73B3727A52B393CCULL,
-       0x31439391FB59A55FULL, 0xF652B1AD0167FEEAULL, 0xB4A25046A88DC879ULL,
-       0xA8E6D8B54074A6ADULL, 0xEA16395EE99E903EULL, 0x2D071B6213A0CB8BULL,
-       0x6FF7FA89BA4AFD18ULL, 0xE1D5BEF04E364A72ULL, 0xA3255F1BE7DC7CE1ULL,
-       0x64347D271DE22754ULL, 0x26C49CCCB40811C7ULL, 0x5CBD6CC0CC10FAFCULL,
-       0x1E4D8D2B65FACC6FULL, 0xD95CAF179FC497DAULL, 0x9BAC4EFC362EA149ULL,
-       0x158E0A85C2521623ULL, 0x577EEB6E6BB820B0ULL, 0x906FC95291867B05ULL,
-       0xD29F28B9386C4D96ULL, 0xCEDBA04AD0952342ULL, 0x8C2B41A1797F15D1ULL,
-       0x4B3A639D83414E64ULL, 0x09CA82762AAB78F7ULL, 0x87E8C60FDED7CF9DULL,
-       0xC51827E4773DF90EULL, 0x020905D88D03A2BBULL, 0x40F9E43324E99428ULL,
-       0x2CFFE7D5975E55E2ULL, 0x6E0F063E3EB46371ULL, 0xA91E2402C48A38C4ULL,
-       0xEBEEC5E96D600E57ULL, 0x65CC8190991CB93DULL, 0x273C607B30F68FAEULL,
-       0xE02D4247CAC8D41BULL, 0xA2DDA3AC6322E288ULL, 0xBE992B5F8BDB8C5CULL,
-       0xFC69CAB42231BACFULL, 0x3B78E888D80FE17AULL, 0x7988096371E5D7E9ULL,
-       0xF7AA4D1A85996083ULL, 0xB55AACF12C735610ULL, 0x724B8ECDD64D0DA5ULL,
-       0x30BB6F267FA73B36ULL, 0x4AC29F2A07BFD00DULL, 0x08327EC1AE55E69EULL,
-       0xCF235CFD546BBD2BULL, 0x8DD3BD16FD818BB8ULL, 0x03F1F96F09FD3CD2ULL,
-       0x41011884A0170A41ULL, 0x86103AB85A2951F4ULL, 0xC4E0DB53F3C36767ULL,
-       0xD8A453A01B3A09B3ULL, 0x9A54B24BB2D03F20ULL, 0x5D45907748EE6495ULL,
-       0x1FB5719CE1045206ULL, 0x919735E51578E56CULL, 0xD367D40EBC92D3FFULL,
-       0x1476F63246AC884AULL, 0x568617D9EF46BED9ULL, 0xE085162AB69D5E3CULL,
-       0xA275F7C11F7768AFULL, 0x6564D5FDE549331AULL, 0x279434164CA30589ULL,
-       0xA9B6706FB8DFB2E3ULL, 0xEB46918411358470ULL, 0x2C57B3B8EB0BDFC5ULL,
-       0x6EA7525342E1E956ULL, 0x72E3DAA0AA188782ULL, 0x30133B4B03F2B111ULL,
-       0xF7021977F9CCEAA4ULL, 0xB5F2F89C5026DC37ULL, 0x3BD0BCE5A45A6B5DULL,
-       0x79205D0E0DB05DCEULL, 0xBE317F32F78E067BULL, 0xFCC19ED95E6430E8ULL,
-       0x86B86ED5267CDBD3ULL, 0xC4488F3E8F96ED40ULL, 0x0359AD0275A8B6F5ULL,
-       0x41A94CE9DC428066ULL, 0xCF8B0890283E370CULL, 0x8D7BE97B81D4019FULL,
-       0x4A6ACB477BEA5A2AULL, 0x089A2AACD2006CB9ULL, 0x14DEA25F3AF9026DULL,
-       0x562E43B4931334FEULL, 0x913F6188692D6F4BULL, 0xD3CF8063C0C759D8ULL,
-       0x5DEDC41A34BBEEB2ULL, 0x1F1D25F19D51D821ULL, 0xD80C07CD676F8394ULL,
-       0x9AFCE626CE85B507ULL,
-};
-
-uint64_t bch_crc64_update(uint64_t crc, const void *_data, size_t len)
-{
-       const unsigned char *data = _data;
-
-       while (len--) {
-               int i = ((int) (crc >> 56) ^ *data++) & 0xFF;
-               crc = crc_table[i] ^ (crc << 8);
-       }
-
-       return crc;
-}
-
-uint64_t bch_crc64(const void *data, size_t len)
-{
-       uint64_t crc = 0xffffffffffffffffULL;
-
-       crc = bch_crc64_update(crc, data, len);
-
-       return crc ^ 0xffffffffffffffffULL;
-}
index f7b0133..00aab6a 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/ratelimit.h>
 #include <linux/vmalloc.h>
 #include <linux/workqueue.h>
+#include <linux/crc64.h>
 
 #include "closure.h"
 
@@ -288,10 +289,10 @@ do {                                                                      \
 #define ANYSINT_MAX(t)                                                 \
        ((((t) 1 << (sizeof(t) * 8 - 2)) - (t) 1) * (t) 2 + (t) 1)
 
-int bch_strtoint_h(const char *, int *);
-int bch_strtouint_h(const char *, unsigned int *);
-int bch_strtoll_h(const char *, long long *);
-int bch_strtoull_h(const char *, unsigned long long *);
+int bch_strtoint_h(const char *cp, int *res);
+int bch_strtouint_h(const char *cp, unsigned int *res);
+int bch_strtoll_h(const char *cp, long long *res);
+int bch_strtoull_h(const char *cp, unsigned long long *res);
 
 static inline int bch_strtol_h(const char *cp, long *res)
 {
@@ -347,7 +348,7 @@ static inline int bch_strtoul_h(const char *cp, long *res)
        snprintf(buf, size,                                             \
                __builtin_types_compatible_p(typeof(var), int)          \
                     ? "%i\n" :                                         \
-               __builtin_types_compatible_p(typeof(var), unsigned)     \
+               __builtin_types_compatible_p(typeof(var), unsigned int) \
                     ? "%u\n" :                                         \
                __builtin_types_compatible_p(typeof(var), long)         \
                     ? "%li\n" :                                        \
@@ -379,7 +380,7 @@ struct time_stats {
 
 void bch_time_stats_update(struct time_stats *stats, uint64_t time);
 
-static inline unsigned local_clock_us(void)
+static inline unsigned int local_clock_us(void)
 {
        return local_clock() >> 10;
 }
@@ -402,7 +403,8 @@ do {                                                                        \
        __print_time_stat(stats, name,                                  \
                          average_duration,     duration_units);        \
        sysfs_print(name ## _ ##max_duration ## _ ## duration_units,    \
-                       div_u64((stats)->max_duration, NSEC_PER_ ## duration_units));\
+                       div_u64((stats)->max_duration,                  \
+                               NSEC_PER_ ## duration_units));          \
                                                                        \
        sysfs_print(name ## _last_ ## frequency_units, (stats)->last    \
                    ? div_s64(local_clock() - (stats)->last,            \
@@ -542,10 +544,27 @@ dup:                                                                      \
 #define RB_PREV(ptr, member)                                           \
        container_of_or_null(rb_prev(&(ptr)->member), typeof(*ptr), member)
 
+static inline uint64_t bch_crc64(const void *p, size_t len)
+{
+       uint64_t crc = 0xffffffffffffffffULL;
+
+       crc = crc64_be(crc, p, len);
+       return crc ^ 0xffffffffffffffffULL;
+}
+
+static inline uint64_t bch_crc64_update(uint64_t crc,
+                                       const void *p,
+                                       size_t len)
+{
+       crc = crc64_be(crc, p, len);
+       return crc;
+}
+
 /* Does linear interpolation between powers of two */
-static inline unsigned fract_exp_two(unsigned x, unsigned fract_bits)
+static inline unsigned int fract_exp_two(unsigned int x,
+                                        unsigned int fract_bits)
 {
-       unsigned fract = x & ~(~0 << fract_bits);
+       unsigned int fract = x & ~(~0 << fract_bits);
 
        x >>= fract_bits;
        x   = 1 << x;
@@ -561,8 +580,4 @@ static inline sector_t bdev_sectors(struct block_device *bdev)
 {
        return bdev->bd_inode->i_size >> 9;
 }
-
-uint64_t bch_crc64_update(uint64_t, const void *, size_t);
-uint64_t bch_crc64(const void *, size_t);
-
 #endif /* _BCACHE_UTIL_H */
index 481d4cf..08c3a9f 100644 (file)
@@ -215,7 +215,8 @@ static void update_writeback_rate(struct work_struct *work)
        smp_mb();
 }
 
-static unsigned writeback_delay(struct cached_dev *dc, unsigned sectors)
+static unsigned int writeback_delay(struct cached_dev *dc,
+                                   unsigned int sectors)
 {
        if (test_bit(BCACHE_DEV_DETACHING, &dc->disk.flags) ||
            !dc->writeback_percent)
@@ -249,6 +250,7 @@ static void dirty_init(struct keybuf_key *w)
 static void dirty_io_destructor(struct closure *cl)
 {
        struct dirty_io *io = container_of(cl, struct dirty_io, cl);
+
        kfree(io);
 }
 
@@ -263,7 +265,7 @@ static void write_dirty_finish(struct closure *cl)
        /* This is kind of a dumb way of signalling errors. */
        if (KEY_DIRTY(&w->key)) {
                int ret;
-               unsigned i;
+               unsigned int i;
                struct keylist keys;
 
                bch_keylist_init(&keys);
@@ -377,7 +379,7 @@ static void read_dirty_submit(struct closure *cl)
 
 static void read_dirty(struct cached_dev *dc)
 {
-       unsigned delay = 0;
+       unsigned int delay = 0;
        struct keybuf_key *next, *keys[MAX_WRITEBACKS_IN_PASS], *w;
        size_t size;
        int nk, i;
@@ -442,7 +444,8 @@ static void read_dirty(struct cached_dev *dc)
 
                        io = kzalloc(sizeof(struct dirty_io) +
                                     sizeof(struct bio_vec) *
-                                    DIV_ROUND_UP(KEY_SIZE(&w->key), PAGE_SECTORS),
+                                    DIV_ROUND_UP(KEY_SIZE(&w->key),
+                                                 PAGE_SECTORS),
                                     GFP_KERNEL);
                        if (!io)
                                goto err;
@@ -465,7 +468,8 @@ static void read_dirty(struct cached_dev *dc)
 
                        down(&dc->in_flight);
 
-                       /* We've acquired a semaphore for the maximum
+                       /*
+                        * We've acquired a semaphore for the maximum
                         * simultaneous number of writebacks; from here
                         * everything happens asynchronously.
                         */
@@ -498,11 +502,11 @@ err:
 
 /* Scan for dirty data */
 
-void bcache_dev_sectors_dirty_add(struct cache_set *c, unsigned inode,
+void bcache_dev_sectors_dirty_add(struct cache_set *c, unsigned int inode,
                                  uint64_t offset, int nr_sectors)
 {
        struct bcache_device *d = c->devices[inode];
-       unsigned stripe_offset, stripe, sectors_dirty;
+       unsigned int stripe_offset, stripe, sectors_dirty;
 
        if (!d)
                return;
@@ -514,7 +518,7 @@ void bcache_dev_sectors_dirty_add(struct cache_set *c, unsigned inode,
        stripe_offset = offset & (d->stripe_size - 1);
 
        while (nr_sectors) {
-               int s = min_t(unsigned, abs(nr_sectors),
+               int s = min_t(unsigned int, abs(nr_sectors),
                              d->stripe_size - stripe_offset);
 
                if (nr_sectors < 0)
@@ -538,7 +542,9 @@ void bcache_dev_sectors_dirty_add(struct cache_set *c, unsigned inode,
 
 static bool dirty_pred(struct keybuf *buf, struct bkey *k)
 {
-       struct cached_dev *dc = container_of(buf, struct cached_dev, writeback_keys);
+       struct cached_dev *dc = container_of(buf,
+                                            struct cached_dev,
+                                            writeback_keys);
 
        BUG_ON(KEY_INODE(k) != dc->disk.id);
 
@@ -548,7 +554,7 @@ static bool dirty_pred(struct keybuf *buf, struct bkey *k)
 static void refill_full_stripes(struct cached_dev *dc)
 {
        struct keybuf *buf = &dc->writeback_keys;
-       unsigned start_stripe, stripe, next_stripe;
+       unsigned int start_stripe, stripe, next_stripe;
        bool wrapped = false;
 
        stripe = offset_to_stripe(&dc->disk, KEY_OFFSET(&buf->last_scanned));
@@ -679,8 +685,10 @@ static int bch_writeback_thread(void *arg)
                         * data on cache. BCACHE_DEV_DETACHING flag is set in
                         * bch_cached_dev_detach().
                         */
-                       if (test_bit(BCACHE_DEV_DETACHING, &dc->disk.flags))
+                       if (test_bit(BCACHE_DEV_DETACHING, &dc->disk.flags)) {
+                               up_write(&dc->writeback_lock);
                                break;
+                       }
                }
 
                up_write(&dc->writeback_lock);
@@ -688,7 +696,7 @@ static int bch_writeback_thread(void *arg)
                read_dirty(dc);
 
                if (searched_full_index) {
-                       unsigned delay = dc->writeback_delay * HZ;
+                       unsigned int delay = dc->writeback_delay * HZ;
 
                        while (delay &&
                               !kthread_should_stop() &&
@@ -712,7 +720,7 @@ static int bch_writeback_thread(void *arg)
 
 struct sectors_dirty_init {
        struct btree_op op;
-       unsigned        inode;
+       unsigned int    inode;
        size_t          count;
        struct bkey     start;
 };
index 3745d70..d2b9fdb 100644 (file)
@@ -28,7 +28,7 @@ static inline uint64_t bcache_dev_sectors_dirty(struct bcache_device *d)
        return ret;
 }
 
-static inline unsigned offset_to_stripe(struct bcache_device *d,
+static inline unsigned int offset_to_stripe(struct bcache_device *d,
                                        uint64_t offset)
 {
        do_div(offset, d->stripe_size);
@@ -37,9 +37,9 @@ static inline unsigned offset_to_stripe(struct bcache_device *d,
 
 static inline bool bcache_dev_stripe_dirty(struct cached_dev *dc,
                                           uint64_t offset,
-                                          unsigned nr_sectors)
+                                          unsigned int nr_sectors)
 {
-       unsigned stripe = offset_to_stripe(&dc->disk, offset);
+       unsigned int stripe = offset_to_stripe(&dc->disk, offset);
 
        while (1) {
                if (atomic_read(dc->disk.stripe_sectors_dirty + stripe))
@@ -54,9 +54,9 @@ static inline bool bcache_dev_stripe_dirty(struct cached_dev *dc,
 }
 
 static inline bool should_writeback(struct cached_dev *dc, struct bio *bio,
-                                   unsigned cache_mode, bool would_skip)
+                                   unsigned int cache_mode, bool would_skip)
 {
-       unsigned in_use = dc->disk.c->gc_stats.in_use;
+       unsigned int in_use = dc->disk.c->gc_stats.in_use;
 
        if (cache_mode != CACHE_MODE_WRITEBACK ||
            test_bit(BCACHE_DEV_DETACHING, &dc->disk.flags) ||
@@ -96,10 +96,11 @@ static inline void bch_writeback_add(struct cached_dev *dc)
        }
 }
 
-void bcache_dev_sectors_dirty_add(struct cache_set *, unsigned, uint64_t, int);
+void bcache_dev_sectors_dirty_add(struct cache_set *c, unsigned int inode,
+                                 uint64_t offset, int nr_sectors);
 
-void bch_sectors_dirty_init(struct bcache_device *);
-void bch_cached_dev_writeback_init(struct cached_dev *);
-int bch_cached_dev_writeback_start(struct cached_dev *);
+void bch_sectors_dirty_init(struct bcache_device *d);
+void bch_cached_dev_writeback_init(struct cached_dev *dc);
+int bch_cached_dev_writeback_start(struct cached_dev *dc);
 
 #endif
index 3a28a68..5f1f80d 100644 (file)
@@ -268,9 +268,8 @@ static int persistent_memory_claim(struct dm_writecache *wc)
                i = 0;
                do {
                        long daa;
-                       void *dummy_addr;
                        daa = dax_direct_access(wc->ssd_dev->dax_dev, i, p - i,
-                                               &dummy_addr, &pfn);
+                                               NULL, &pfn);
                        if (daa <= 0) {
                                r = daa ? daa : -EINVAL;
                                goto err3;
index 16dffa0..dd2078b 100644 (file)
@@ -21,6 +21,7 @@ struct cec_notifier {
        struct list_head head;
        struct kref kref;
        struct device *dev;
+       const char *conn;
        struct cec_adapter *cec_adap;
        void (*callback)(struct cec_adapter *adap, u16 pa);
 
@@ -30,13 +31,14 @@ struct cec_notifier {
 static LIST_HEAD(cec_notifiers);
 static DEFINE_MUTEX(cec_notifiers_lock);
 
-struct cec_notifier *cec_notifier_get(struct device *dev)
+struct cec_notifier *cec_notifier_get_conn(struct device *dev, const char *conn)
 {
        struct cec_notifier *n;
 
        mutex_lock(&cec_notifiers_lock);
        list_for_each_entry(n, &cec_notifiers, head) {
-               if (n->dev == dev) {
+               if (n->dev == dev &&
+                   (!conn || !strcmp(n->conn, conn))) {
                        kref_get(&n->kref);
                        mutex_unlock(&cec_notifiers_lock);
                        return n;
@@ -46,6 +48,8 @@ struct cec_notifier *cec_notifier_get(struct device *dev)
        if (!n)
                goto unlock;
        n->dev = dev;
+       if (conn)
+               n->conn = kstrdup(conn, GFP_KERNEL);
        n->phys_addr = CEC_PHYS_ADDR_INVALID;
        mutex_init(&n->lock);
        kref_init(&n->kref);
@@ -54,7 +58,7 @@ unlock:
        mutex_unlock(&cec_notifiers_lock);
        return n;
 }
-EXPORT_SYMBOL_GPL(cec_notifier_get);
+EXPORT_SYMBOL_GPL(cec_notifier_get_conn);
 
 static void cec_notifier_release(struct kref *kref)
 {
@@ -62,6 +66,7 @@ static void cec_notifier_release(struct kref *kref)
                container_of(kref, struct cec_notifier, kref);
 
        list_del(&n->head);
+       kfree(n->conn);
        kfree(n);
 }
 
index f3acbb5..35a93b2 100644 (file)
@@ -1311,10 +1311,10 @@ static int af9013_wregs(struct i2c_client *client, u8 cmd, u16 reg,
        memcpy(&buf[3], val, len);
 
        if (lock)
-               i2c_lock_adapter(client->adapter);
+               i2c_lock_bus(client->adapter, I2C_LOCK_SEGMENT);
        ret = __i2c_transfer(client->adapter, msg, 1);
        if (lock)
-               i2c_unlock_adapter(client->adapter);
+               i2c_unlock_bus(client->adapter, I2C_LOCK_SEGMENT);
        if (ret < 0) {
                goto err;
        } else if (ret != 1) {
@@ -1352,10 +1352,10 @@ static int af9013_rregs(struct i2c_client *client, u8 cmd, u16 reg,
        buf[2] = cmd;
 
        if (lock)
-               i2c_lock_adapter(client->adapter);
+               i2c_lock_bus(client->adapter, I2C_LOCK_SEGMENT);
        ret = __i2c_transfer(client->adapter, msg, 2);
        if (lock)
-               i2c_unlock_adapter(client->adapter);
+               i2c_unlock_bus(client->adapter, I2C_LOCK_SEGMENT);
        if (ret < 0) {
                goto err;
        } else if (ret != 2) {
index f188694..84ac3f7 100644 (file)
@@ -213,7 +213,7 @@ static inline u32 log10times100(u32 value)
 
 static int drxk_i2c_lock(struct drxk_state *state)
 {
-       i2c_lock_adapter(state->i2c);
+       i2c_lock_bus(state->i2c, I2C_LOCK_SEGMENT);
        state->drxk_i2c_exclusive_lock = true;
 
        return 0;
@@ -224,7 +224,7 @@ static void drxk_i2c_unlock(struct drxk_state *state)
        if (!state->drxk_i2c_exclusive_lock)
                return;
 
-       i2c_unlock_adapter(state->i2c);
+       i2c_unlock_bus(state->i2c, I2C_LOCK_SEGMENT);
        state->drxk_i2c_exclusive_lock = false;
 }
 
index adc9046..c065956 100644 (file)
@@ -24,9 +24,9 @@ static int rtl2830_bulk_write(struct i2c_client *client, unsigned int reg,
        struct rtl2830_dev *dev = i2c_get_clientdata(client);
        int ret;
 
-       i2c_lock_adapter(client->adapter);
+       i2c_lock_bus(client->adapter, I2C_LOCK_SEGMENT);
        ret = regmap_bulk_write(dev->regmap, reg, val, val_count);
-       i2c_unlock_adapter(client->adapter);
+       i2c_unlock_bus(client->adapter, I2C_LOCK_SEGMENT);
        return ret;
 }
 
@@ -36,9 +36,9 @@ static int rtl2830_update_bits(struct i2c_client *client, unsigned int reg,
        struct rtl2830_dev *dev = i2c_get_clientdata(client);
        int ret;
 
-       i2c_lock_adapter(client->adapter);
+       i2c_lock_bus(client->adapter, I2C_LOCK_SEGMENT);
        ret = regmap_update_bits(dev->regmap, reg, mask, val);
-       i2c_unlock_adapter(client->adapter);
+       i2c_unlock_bus(client->adapter, I2C_LOCK_SEGMENT);
        return ret;
 }
 
@@ -48,9 +48,9 @@ static int rtl2830_bulk_read(struct i2c_client *client, unsigned int reg,
        struct rtl2830_dev *dev = i2c_get_clientdata(client);
        int ret;
 
-       i2c_lock_adapter(client->adapter);
+       i2c_lock_bus(client->adapter, I2C_LOCK_SEGMENT);
        ret = regmap_bulk_read(dev->regmap, reg, val, val_count);
-       i2c_unlock_adapter(client->adapter);
+       i2c_unlock_bus(client->adapter, I2C_LOCK_SEGMENT);
        return ret;
 }
 
index d402e4b..e506f66 100644 (file)
@@ -329,7 +329,7 @@ static int tda1004x_do_upload(struct tda1004x_state *state,
        tda1004x_write_byteI(state, dspCodeCounterReg, 0);
        fw_msg.addr = state->config->demod_address;
 
-       i2c_lock_adapter(state->i2c);
+       i2c_lock_bus(state->i2c, I2C_LOCK_SEGMENT);
        buf[0] = dspCodeInReg;
        while (pos != len) {
                // work out how much to send this time
@@ -342,14 +342,14 @@ static int tda1004x_do_upload(struct tda1004x_state *state,
                fw_msg.len = tx_size + 1;
                if (__i2c_transfer(state->i2c, &fw_msg, 1) != 1) {
                        printk(KERN_ERR "tda1004x: Error during firmware upload\n");
-                       i2c_unlock_adapter(state->i2c);
+                       i2c_unlock_bus(state->i2c, I2C_LOCK_SEGMENT);
                        return -EIO;
                }
                pos += tx_size;
 
                dprintk("%s: fw_pos=0x%x\n", __func__, pos);
        }
-       i2c_unlock_adapter(state->i2c);
+       i2c_unlock_bus(state->i2c, I2C_LOCK_SEGMENT);
 
        /* give the DSP a chance to settle 03/10/05 Hac */
        msleep(100);
index fcdf3d5..3bae24b 100644 (file)
@@ -585,18 +585,12 @@ int __must_check media_device_register_entity(struct media_device *mdev,
        entity->num_links = 0;
        entity->num_backlinks = 0;
 
-       if (!ida_pre_get(&mdev->entity_internal_idx, GFP_KERNEL))
-               return -ENOMEM;
-
-       mutex_lock(&mdev->graph_mutex);
-
-       ret = ida_get_new_above(&mdev->entity_internal_idx, 1,
-                               &entity->internal_idx);
-       if (ret < 0) {
-               mutex_unlock(&mdev->graph_mutex);
+       ret = ida_alloc_min(&mdev->entity_internal_idx, 1, GFP_KERNEL);
+       if (ret < 0)
                return ret;
-       }
+       entity->internal_idx = ret;
 
+       mutex_lock(&mdev->graph_mutex);
        mdev->entity_internal_idx_max =
                max(mdev->entity_internal_idx_max, entity->internal_idx);
 
@@ -642,7 +636,7 @@ static void __media_device_unregister_entity(struct media_entity *entity)
        struct media_interface *intf;
        unsigned int i;
 
-       ida_simple_remove(&mdev->entity_internal_idx, entity->internal_idx);
+       ida_free(&mdev->entity_internal_idx, entity->internal_idx);
 
        /* Remove all interface links pointing to this entity */
        list_for_each_entry(intf, &mdev->interfaces, graph_obj.list) {
index b25c8d3..94c1fe0 100644 (file)
@@ -536,6 +536,17 @@ menuconfig CEC_PLATFORM_DRIVERS
 
 if CEC_PLATFORM_DRIVERS
 
+config VIDEO_CROS_EC_CEC
+       tristate "ChromeOS EC CEC driver"
+       depends on MFD_CROS_EC
+       select CEC_CORE
+       select CEC_NOTIFIER
+       ---help---
+         If you say yes here you will get support for the
+         ChromeOS Embedded Controller's CEC.
+         The CEC bus is present in the HDMI connector and enables communication
+         between compatible devices.
+
 config VIDEO_MESON_AO_CEC
        tristate "Amlogic Meson AO CEC driver"
        depends on ARCH_MESON || COMPILE_TEST
index 08640ba..41322ab 100644 (file)
@@ -94,3 +94,5 @@ obj-$(CONFIG_VIDEO_QCOM_CAMSS)                += qcom/camss/
 obj-$(CONFIG_VIDEO_QCOM_VENUS)         += qcom/venus/
 
 obj-y                                  += meson/
+
+obj-y                                  += cros-ec-cec/
diff --git a/drivers/media/platform/cros-ec-cec/Makefile b/drivers/media/platform/cros-ec-cec/Makefile
new file mode 100644 (file)
index 0000000..9ce97f9
--- /dev/null
@@ -0,0 +1 @@
+obj-$(CONFIG_VIDEO_CROS_EC_CEC) += cros-ec-cec.o
diff --git a/drivers/media/platform/cros-ec-cec/cros-ec-cec.c b/drivers/media/platform/cros-ec-cec/cros-ec-cec.c
new file mode 100644 (file)
index 0000000..7bc4d8a
--- /dev/null
@@ -0,0 +1,347 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * CEC driver for ChromeOS Embedded Controller
+ *
+ * Copyright (c) 2018 BayLibre, SAS
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/dmi.h>
+#include <linux/pci.h>
+#include <linux/cec.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <media/cec.h>
+#include <media/cec-notifier.h>
+#include <linux/mfd/cros_ec.h>
+#include <linux/mfd/cros_ec_commands.h>
+
+#define DRV_NAME       "cros-ec-cec"
+
+/**
+ * struct cros_ec_cec - Driver data for EC CEC
+ *
+ * @cros_ec: Pointer to EC device
+ * @notifier: Notifier info for responding to EC events
+ * @adap: CEC adapter
+ * @notify: CEC notifier pointer
+ * @rx_msg: storage for a received message
+ */
+struct cros_ec_cec {
+       struct cros_ec_device *cros_ec;
+       struct notifier_block notifier;
+       struct cec_adapter *adap;
+       struct cec_notifier *notify;
+       struct cec_msg rx_msg;
+};
+
+static void handle_cec_message(struct cros_ec_cec *cros_ec_cec)
+{
+       struct cros_ec_device *cros_ec = cros_ec_cec->cros_ec;
+       uint8_t *cec_message = cros_ec->event_data.data.cec_message;
+       unsigned int len = cros_ec->event_size;
+
+       cros_ec_cec->rx_msg.len = len;
+       memcpy(cros_ec_cec->rx_msg.msg, cec_message, len);
+
+       cec_received_msg(cros_ec_cec->adap, &cros_ec_cec->rx_msg);
+}
+
+static void handle_cec_event(struct cros_ec_cec *cros_ec_cec)
+{
+       struct cros_ec_device *cros_ec = cros_ec_cec->cros_ec;
+       uint32_t events = cros_ec->event_data.data.cec_events;
+
+       if (events & EC_MKBP_CEC_SEND_OK)
+               cec_transmit_attempt_done(cros_ec_cec->adap,
+                                         CEC_TX_STATUS_OK);
+
+       /* FW takes care of all retries, tell core to avoid more retries */
+       if (events & EC_MKBP_CEC_SEND_FAILED)
+               cec_transmit_attempt_done(cros_ec_cec->adap,
+                                         CEC_TX_STATUS_MAX_RETRIES |
+                                         CEC_TX_STATUS_NACK);
+}
+
+static int cros_ec_cec_event(struct notifier_block *nb,
+                            unsigned long queued_during_suspend,
+                            void *_notify)
+{
+       struct cros_ec_cec *cros_ec_cec;
+       struct cros_ec_device *cros_ec;
+
+       cros_ec_cec = container_of(nb, struct cros_ec_cec, notifier);
+       cros_ec = cros_ec_cec->cros_ec;
+
+       if (cros_ec->event_data.event_type == EC_MKBP_EVENT_CEC_EVENT) {
+               handle_cec_event(cros_ec_cec);
+               return NOTIFY_OK;
+       }
+
+       if (cros_ec->event_data.event_type == EC_MKBP_EVENT_CEC_MESSAGE) {
+               handle_cec_message(cros_ec_cec);
+               return NOTIFY_OK;
+       }
+
+       return NOTIFY_DONE;
+}
+
+static int cros_ec_cec_set_log_addr(struct cec_adapter *adap, u8 logical_addr)
+{
+       struct cros_ec_cec *cros_ec_cec = adap->priv;
+       struct cros_ec_device *cros_ec = cros_ec_cec->cros_ec;
+       struct {
+               struct cros_ec_command msg;
+               struct ec_params_cec_set data;
+       } __packed msg = {};
+       int ret;
+
+       msg.msg.command = EC_CMD_CEC_SET;
+       msg.msg.outsize = sizeof(msg.data);
+       msg.data.cmd = CEC_CMD_LOGICAL_ADDRESS;
+       msg.data.val = logical_addr;
+
+       ret = cros_ec_cmd_xfer_status(cros_ec, &msg.msg);
+       if (ret < 0) {
+               dev_err(cros_ec->dev,
+                       "error setting CEC logical address on EC: %d\n", ret);
+               return ret;
+       }
+
+       return 0;
+}
+
+static int cros_ec_cec_transmit(struct cec_adapter *adap, u8 attempts,
+                               u32 signal_free_time, struct cec_msg *cec_msg)
+{
+       struct cros_ec_cec *cros_ec_cec = adap->priv;
+       struct cros_ec_device *cros_ec = cros_ec_cec->cros_ec;
+       struct {
+               struct cros_ec_command msg;
+               struct ec_params_cec_write data;
+       } __packed msg = {};
+       int ret;
+
+       msg.msg.command = EC_CMD_CEC_WRITE_MSG;
+       msg.msg.outsize = cec_msg->len;
+       memcpy(msg.data.msg, cec_msg->msg, cec_msg->len);
+
+       ret = cros_ec_cmd_xfer_status(cros_ec, &msg.msg);
+       if (ret < 0) {
+               dev_err(cros_ec->dev,
+                       "error writing CEC msg on EC: %d\n", ret);
+               return ret;
+       }
+
+       return 0;
+}
+
+static int cros_ec_cec_adap_enable(struct cec_adapter *adap, bool enable)
+{
+       struct cros_ec_cec *cros_ec_cec = adap->priv;
+       struct cros_ec_device *cros_ec = cros_ec_cec->cros_ec;
+       struct {
+               struct cros_ec_command msg;
+               struct ec_params_cec_set data;
+       } __packed msg = {};
+       int ret;
+
+       msg.msg.command = EC_CMD_CEC_SET;
+       msg.msg.outsize = sizeof(msg.data);
+       msg.data.cmd = CEC_CMD_ENABLE;
+       msg.data.val = enable;
+
+       ret = cros_ec_cmd_xfer_status(cros_ec, &msg.msg);
+       if (ret < 0) {
+               dev_err(cros_ec->dev,
+                       "error %sabling CEC on EC: %d\n",
+                       (enable ? "en" : "dis"), ret);
+               return ret;
+       }
+
+       return 0;
+}
+
+static const struct cec_adap_ops cros_ec_cec_ops = {
+       .adap_enable = cros_ec_cec_adap_enable,
+       .adap_log_addr = cros_ec_cec_set_log_addr,
+       .adap_transmit = cros_ec_cec_transmit,
+};
+
+#ifdef CONFIG_PM_SLEEP
+static int cros_ec_cec_suspend(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct cros_ec_cec *cros_ec_cec = dev_get_drvdata(&pdev->dev);
+
+       if (device_may_wakeup(dev))
+               enable_irq_wake(cros_ec_cec->cros_ec->irq);
+
+       return 0;
+}
+
+static int cros_ec_cec_resume(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct cros_ec_cec *cros_ec_cec = dev_get_drvdata(&pdev->dev);
+
+       if (device_may_wakeup(dev))
+               disable_irq_wake(cros_ec_cec->cros_ec->irq);
+
+       return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(cros_ec_cec_pm_ops,
+       cros_ec_cec_suspend, cros_ec_cec_resume);
+
+#if IS_ENABLED(CONFIG_PCI) && IS_ENABLED(CONFIG_DMI)
+
+/*
+ * The Firmware only handles a single CEC interface tied to a single HDMI
+ * connector we specify along with the DRM device name handling the HDMI output
+ */
+
+struct cec_dmi_match {
+       char *sys_vendor;
+       char *product_name;
+       char *devname;
+       char *conn;
+};
+
+static const struct cec_dmi_match cec_dmi_match_table[] = {
+       /* Google Fizz */
+       { "Google", "Fizz", "0000:00:02.0", "Port B" },
+};
+
+static int cros_ec_cec_get_notifier(struct device *dev,
+                                   struct cec_notifier **notify)
+{
+       int i;
+
+       for (i = 0 ; i < ARRAY_SIZE(cec_dmi_match_table) ; ++i) {
+               const struct cec_dmi_match *m = &cec_dmi_match_table[i];
+
+               if (dmi_match(DMI_SYS_VENDOR, m->sys_vendor) &&
+                   dmi_match(DMI_PRODUCT_NAME, m->product_name)) {
+                       struct device *d;
+
+                       /* Find the device, bail out if not yet registered */
+                       d = bus_find_device_by_name(&pci_bus_type, NULL,
+                                                   m->devname);
+                       if (!d)
+                               return -EPROBE_DEFER;
+
+                       *notify = cec_notifier_get_conn(d, m->conn);
+                       return 0;
+               }
+       }
+
+       /* Hardware support must be added in the cec_dmi_match_table */
+       dev_warn(dev, "CEC notifier not configured for this hardware\n");
+
+       return -ENODEV;
+}
+
+#else
+
+static int cros_ec_cec_get_notifier(struct device *dev,
+                                   struct cec_notifier **notify)
+{
+       return -ENODEV;
+}
+
+#endif
+
+static int cros_ec_cec_probe(struct platform_device *pdev)
+{
+       struct cros_ec_dev *ec_dev = dev_get_drvdata(pdev->dev.parent);
+       struct cros_ec_device *cros_ec = ec_dev->ec_dev;
+       struct cros_ec_cec *cros_ec_cec;
+       int ret;
+
+       cros_ec_cec = devm_kzalloc(&pdev->dev, sizeof(*cros_ec_cec),
+                                  GFP_KERNEL);
+       if (!cros_ec_cec)
+               return -ENOMEM;
+
+       platform_set_drvdata(pdev, cros_ec_cec);
+       cros_ec_cec->cros_ec = cros_ec;
+
+       ret = cros_ec_cec_get_notifier(&pdev->dev, &cros_ec_cec->notify);
+       if (ret)
+               return ret;
+
+       ret = device_init_wakeup(&pdev->dev, 1);
+       if (ret) {
+               dev_err(&pdev->dev, "failed to initialize wakeup\n");
+               return ret;
+       }
+
+       cros_ec_cec->adap = cec_allocate_adapter(&cros_ec_cec_ops, cros_ec_cec,
+                                                DRV_NAME, CEC_CAP_DEFAULTS, 1);
+       if (IS_ERR(cros_ec_cec->adap))
+               return PTR_ERR(cros_ec_cec->adap);
+
+       /* Get CEC events from the EC. */
+       cros_ec_cec->notifier.notifier_call = cros_ec_cec_event;
+       ret = blocking_notifier_chain_register(&cros_ec->event_notifier,
+                                              &cros_ec_cec->notifier);
+       if (ret) {
+               dev_err(&pdev->dev, "failed to register notifier\n");
+               cec_delete_adapter(cros_ec_cec->adap);
+               return ret;
+       }
+
+       ret = cec_register_adapter(cros_ec_cec->adap, &pdev->dev);
+       if (ret < 0) {
+               cec_delete_adapter(cros_ec_cec->adap);
+               return ret;
+       }
+
+       cec_register_cec_notifier(cros_ec_cec->adap, cros_ec_cec->notify);
+
+       return 0;
+}
+
+static int cros_ec_cec_remove(struct platform_device *pdev)
+{
+       struct cros_ec_cec *cros_ec_cec = platform_get_drvdata(pdev);
+       struct device *dev = &pdev->dev;
+       int ret;
+
+       ret = blocking_notifier_chain_unregister(
+                       &cros_ec_cec->cros_ec->event_notifier,
+                       &cros_ec_cec->notifier);
+
+       if (ret) {
+               dev_err(dev, "failed to unregister notifier\n");
+               return ret;
+       }
+
+       cec_unregister_adapter(cros_ec_cec->adap);
+
+       if (cros_ec_cec->notify)
+               cec_notifier_put(cros_ec_cec->notify);
+
+       return 0;
+}
+
+static struct platform_driver cros_ec_cec_driver = {
+       .probe = cros_ec_cec_probe,
+       .remove  = cros_ec_cec_remove,
+       .driver = {
+               .name = DRV_NAME,
+               .pm = &cros_ec_cec_pm_ops,
+       },
+};
+
+module_platform_driver(cros_ec_cec_driver);
+
+MODULE_DESCRIPTION("CEC driver for ChromeOS ECs");
+MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRV_NAME);
index 7e81cd8..054b3b7 100644 (file)
@@ -225,7 +225,7 @@ static int __tda18271_write_regs(struct dvb_frontend *fe, int idx, int len,
         */
        if (lock_i2c) {
                tda18271_i2c_gate_ctrl(fe, 1);
-               i2c_lock_adapter(priv->i2c_props.adap);
+               i2c_lock_bus(priv->i2c_props.adap, I2C_LOCK_SEGMENT);
        }
        while (len) {
                if (max > len)
@@ -246,7 +246,7 @@ static int __tda18271_write_regs(struct dvb_frontend *fe, int idx, int len,
                len -= max;
        }
        if (lock_i2c) {
-               i2c_unlock_adapter(priv->i2c_props.adap);
+               i2c_unlock_bus(priv->i2c_props.adap, I2C_LOCK_SEGMENT);
                tda18271_i2c_gate_ctrl(fe, 0);
        }
 
@@ -300,7 +300,7 @@ int tda18271_init_regs(struct dvb_frontend *fe)
         * as those could cause bad things
         */
        tda18271_i2c_gate_ctrl(fe, 1);
-       i2c_lock_adapter(priv->i2c_props.adap);
+       i2c_lock_bus(priv->i2c_props.adap, I2C_LOCK_SEGMENT);
 
        /* initialize registers */
        switch (priv->id) {
@@ -516,7 +516,7 @@ int tda18271_init_regs(struct dvb_frontend *fe)
        /* synchronize */
        __tda18271_write_regs(fe, R_EP1, 1, false);
 
-       i2c_unlock_adapter(priv->i2c_props.adap);
+       i2c_unlock_bus(priv->i2c_props.adap, I2C_LOCK_SEGMENT);
        tda18271_i2c_gate_ctrl(fe, 0);
 
        return 0;
index bb93cc5..bd25faf 100644 (file)
@@ -672,13 +672,6 @@ static int tegra_mc_probe(struct platform_device *pdev)
                return err;
        }
 
-       err = tegra_mc_reset_setup(mc);
-       if (err < 0) {
-               dev_err(&pdev->dev, "failed to register reset controller: %d\n",
-                       err);
-               return err;
-       }
-
        mc->irq = platform_get_irq(pdev, 0);
        if (mc->irq < 0) {
                dev_err(&pdev->dev, "interrupt not specified\n");
@@ -697,13 +690,16 @@ static int tegra_mc_probe(struct platform_device *pdev)
                return err;
        }
 
+       err = tegra_mc_reset_setup(mc);
+       if (err < 0)
+               dev_err(&pdev->dev, "failed to register reset controller: %d\n",
+                       err);
+
        if (IS_ENABLED(CONFIG_TEGRA_IOMMU_SMMU)) {
                mc->smmu = tegra_smmu_probe(&pdev->dev, mc->soc->smmu, mc);
-               if (IS_ERR(mc->smmu)) {
+               if (IS_ERR(mc->smmu))
                        dev_err(&pdev->dev, "failed to probe SMMU: %ld\n",
                                PTR_ERR(mc->smmu));
-                       return PTR_ERR(mc->smmu);
-               }
        }
 
        return 0;
index 632651f..2250d03 100644 (file)
@@ -249,6 +249,34 @@ static const struct of_device_id ti_emif_of_match[] = {
 };
 MODULE_DEVICE_TABLE(of, ti_emif_of_match);
 
+#ifdef CONFIG_PM_SLEEP
+static int ti_emif_resume(struct device *dev)
+{
+       unsigned long tmp =
+                       __raw_readl((void *)emif_instance->ti_emif_sram_virt);
+
+       /*
+        * Check to see if what we are copying is already present in the
+        * first byte at the destination, only copy if it is not which
+        * indicates we have lost context and sram no longer contains
+        * the PM code
+        */
+       if (tmp != ti_emif_sram)
+               ti_emif_push_sram(dev, emif_instance);
+
+       return 0;
+}
+
+static int ti_emif_suspend(struct device *dev)
+{
+       /*
+        * The contents will be present in DDR hence no need to
+        * explicitly save
+        */
+       return 0;
+}
+#endif /* CONFIG_PM_SLEEP */
+
 static int ti_emif_probe(struct platform_device *pdev)
 {
        int ret;
@@ -308,12 +336,17 @@ static int ti_emif_remove(struct platform_device *pdev)
        return 0;
 }
 
+static const struct dev_pm_ops ti_emif_pm_ops = {
+       SET_SYSTEM_SLEEP_PM_OPS(ti_emif_suspend, ti_emif_resume)
+};
+
 static struct platform_driver ti_emif_driver = {
        .probe = ti_emif_probe,
        .remove = ti_emif_remove,
        .driver = {
                .name = KBUILD_MODNAME,
                .of_match_table = of_match_ptr(ti_emif_of_match),
+               .pm = &ti_emif_pm_ops,
        },
 };
 module_platform_driver(ti_emif_driver);
index 84e3131..7b9052e 100644 (file)
@@ -146,14 +146,14 @@ int pm860x_page_reg_write(struct i2c_client *i2c, int reg,
        unsigned char zero;
        int ret;
 
-       i2c_lock_adapter(i2c->adapter);
+       i2c_lock_bus(i2c->adapter, I2C_LOCK_SEGMENT);
        read_device(i2c, 0xFA, 0, &zero);
        read_device(i2c, 0xFB, 0, &zero);
        read_device(i2c, 0xFF, 0, &zero);
        ret = write_device(i2c, reg, 1, &data);
        read_device(i2c, 0xFE, 0, &zero);
        read_device(i2c, 0xFC, 0, &zero);
-       i2c_unlock_adapter(i2c->adapter);
+       i2c_unlock_bus(i2c->adapter, I2C_LOCK_SEGMENT);
        return ret;
 }
 EXPORT_SYMBOL(pm860x_page_reg_write);
@@ -164,14 +164,14 @@ int pm860x_page_bulk_read(struct i2c_client *i2c, int reg,
        unsigned char zero = 0;
        int ret;
 
-       i2c_lock_adapter(i2c->adapter);
+       i2c_lock_bus(i2c->adapter, I2C_LOCK_SEGMENT);
        read_device(i2c, 0xfa, 0, &zero);
        read_device(i2c, 0xfb, 0, &zero);
        read_device(i2c, 0xff, 0, &zero);
        ret = read_device(i2c, reg, count, buf);
        read_device(i2c, 0xFE, 0, &zero);
        read_device(i2c, 0xFC, 0, &zero);
-       i2c_unlock_adapter(i2c->adapter);
+       i2c_unlock_bus(i2c->adapter, I2C_LOCK_SEGMENT);
        return ret;
 }
 EXPORT_SYMBOL(pm860x_page_bulk_read);
index b860eb5..11841f4 100644 (file)
@@ -202,26 +202,6 @@ config MFD_CROS_EC
          You also need to enable the driver for the bus you are using. The
          protocol for talking to the EC is defined by the bus driver.
 
-config MFD_CROS_EC_I2C
-       tristate "ChromeOS Embedded Controller (I2C)"
-       depends on MFD_CROS_EC && I2C
-
-       help
-         If you say Y here, you get support for talking to the ChromeOS
-         EC through an I2C bus. This uses a simple byte-level protocol with
-         a checksum. Failing accesses will be retried three times to
-         improve reliability.
-
-config MFD_CROS_EC_SPI
-       tristate "ChromeOS Embedded Controller (SPI)"
-       depends on MFD_CROS_EC && SPI
-
-       ---help---
-         If you say Y here, you get support for talking to the ChromeOS EC
-         through a SPI bus, using a byte-level protocol. Since the EC's
-         response time cannot be guaranteed, we support ignoring
-         'pre-amble' bytes before the response actually starts.
-
 config MFD_CROS_EC_CHARDEV
         tristate "Chrome OS Embedded Controller userspace device interface"
         depends on MFD_CROS_EC
@@ -232,6 +212,56 @@ config MFD_CROS_EC_CHARDEV
           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"
+       select MFD_CORE
+       select REGMAP
+       select REGMAP_IRQ
+       select MADERA_IRQ
+       select PINCTRL
+       select PINCTRL_MADERA
+       help
+         Support for the Cirrus Logic Madera platform audio codecs
+
+config MFD_MADERA_I2C
+       tristate "Cirrus Logic Madera codecs with I2C"
+       depends on MFD_MADERA
+       depends on I2C
+       select REGMAP_I2C
+       help
+         Support for the Cirrus Logic Madera platform audio SoC
+         core functionality controlled via I2C.
+
+config MFD_MADERA_SPI
+       tristate "Cirrus Logic Madera codecs with SPI"
+       depends on MFD_MADERA
+       depends on SPI_MASTER
+       select REGMAP_SPI
+       help
+         Support for the Cirrus Logic Madera platform audio SoC
+         core functionality controlled via SPI.
+
+config MFD_CS47L35
+       bool "Cirrus Logic CS47L35"
+       select PINCTRL_CS47L35
+       depends on MFD_MADERA
+       help
+         Support for Cirrus Logic CS47L35 Smart Codec
+
+config MFD_CS47L85
+       bool "Cirrus Logic CS47L85"
+       select PINCTRL_CS47L85
+       depends on MFD_MADERA
+       help
+         Support for Cirrus Logic CS47L85 Smart Codec
+
+config MFD_CS47L90
+       bool "Cirrus Logic CS47L90/91"
+       select PINCTRL_CS47L90
+       depends on MFD_MADERA
+       help
+         Support for Cirrus Logic CS47L90 and CS47L91 Smart Codecs
+
 config MFD_ASIC3
        bool "Compaq ASIC3"
        depends on GPIOLIB && ARM
@@ -1787,6 +1817,19 @@ config MFD_STW481X
          in various ST Microelectronics and ST-Ericsson embedded
          Nomadik series.
 
+config MFD_ROHM_BD718XX
+       tristate "ROHM BD71837 Power Management IC"
+       depends on I2C=y
+       depends on OF
+       select REGMAP_I2C
+       select REGMAP_IRQ
+       select MFD_CORE
+       help
+         Select this option to get support for the ROHM BD71837
+         Power Management ICs. BD71837 is designed to power processors like
+         NXP i.MX8. It contains 8 BUCK outputs and 7 LDOs, voltage monitoring
+         and emergency shut down as well as 32,768KHz clock output.
+
 config MFD_STM32_LPTIMER
        tristate "Support for STM32 Low-Power Timer"
        depends on (ARCH_STM32 && OF) || COMPILE_TEST
index e9fd20d..5856a94 100644 (file)
@@ -14,8 +14,6 @@ obj-$(CONFIG_MFD_BCM590XX)    += bcm590xx.o
 obj-$(CONFIG_MFD_BD9571MWV)    += bd9571mwv.o
 cros_ec_core-objs              := cros_ec.o
 obj-$(CONFIG_MFD_CROS_EC)      += cros_ec_core.o
-obj-$(CONFIG_MFD_CROS_EC_I2C)  += cros_ec_i2c.o
-obj-$(CONFIG_MFD_CROS_EC_SPI)  += cros_ec_spi.o
 obj-$(CONFIG_MFD_CROS_EC_CHARDEV) += cros_ec_dev.o
 obj-$(CONFIG_MFD_EXYNOS_LPASS) += exynos-lpass.o
 
@@ -72,6 +70,20 @@ wm8994-objs                  := wm8994-core.o wm8994-irq.o wm8994-regmap.o
 obj-$(CONFIG_MFD_WM8994)       += wm8994.o
 obj-$(CONFIG_MFD_WM97xx)       += wm97xx-core.o
 
+madera-objs                    := madera-core.o
+ifeq ($(CONFIG_MFD_CS47L35),y)
+madera-objs                    += cs47l35-tables.o
+endif
+ifeq ($(CONFIG_MFD_CS47L85),y)
+madera-objs                    += cs47l85-tables.o
+endif
+ifeq ($(CONFIG_MFD_CS47L90),y)
+madera-objs                    += cs47l90-tables.o
+endif
+obj-$(CONFIG_MFD_MADERA)       += madera.o
+obj-$(CONFIG_MFD_MADERA_I2C)   += madera-i2c.o
+obj-$(CONFIG_MFD_MADERA_SPI)   += madera-spi.o
+
 obj-$(CONFIG_TPS6105X)         += tps6105x.o
 obj-$(CONFIG_TPS65010)         += tps65010.o
 obj-$(CONFIG_TPS6507X)         += tps6507x.o
@@ -227,4 +239,5 @@ obj-$(CONFIG_MFD_STM32_TIMERS)      += stm32-timers.o
 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
 
index 83f1c5a..5f1e37d 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/regulator/consumer.h>
 #include <linux/regulator/machine.h>
 #include <linux/slab.h>
+#include <linux/ktime.h>
 #include <linux/platform_device.h>
 
 #include <linux/mfd/arizona/core.h>
@@ -236,22 +237,39 @@ static irqreturn_t arizona_overclocked(int irq, void *data)
 
 #define ARIZONA_REG_POLL_DELAY_US 7500
 
+static inline bool arizona_poll_reg_delay(ktime_t timeout)
+{
+       if (ktime_compare(ktime_get(), timeout) > 0)
+               return false;
+
+       usleep_range(ARIZONA_REG_POLL_DELAY_US / 2, ARIZONA_REG_POLL_DELAY_US);
+
+       return true;
+}
+
 static int arizona_poll_reg(struct arizona *arizona,
                            int timeout_ms, unsigned int reg,
                            unsigned int mask, unsigned int target)
 {
+       ktime_t timeout = ktime_add_us(ktime_get(), timeout_ms * USEC_PER_MSEC);
        unsigned int val = 0;
        int ret;
 
-       ret = regmap_read_poll_timeout(arizona->regmap,
-                                      reg, val, ((val & mask) == target),
-                                      ARIZONA_REG_POLL_DELAY_US,
-                                      timeout_ms * 1000);
-       if (ret)
-               dev_err(arizona->dev, "Polling reg 0x%x timed out: %x\n",
-                       reg, val);
+       do {
+               ret = regmap_read(arizona->regmap, reg, &val);
 
-       return ret;
+               if ((val & mask) == target)
+                       return 0;
+       } while (arizona_poll_reg_delay(timeout));
+
+       if (ret) {
+               dev_err(arizona->dev, "Failed polling reg 0x%x: %d\n",
+                       reg, ret);
+               return ret;
+       }
+
+       dev_err(arizona->dev, "Polling reg 0x%x timed out: %x\n", reg, val);
+       return -ETIMEDOUT;
 }
 
 static int arizona_wait_for_boot(struct arizona *arizona)
index f87342c..4d069ed 100644 (file)
@@ -349,6 +349,8 @@ static int as3722_i2c_of_probe(struct i2c_client *i2c,
                                        "ams,enable-internal-int-pullup");
        as3722->en_intern_i2c_pullup = of_property_read_bool(np,
                                        "ams,enable-internal-i2c-pullup");
+       as3722->en_ac_ok_pwr_on = of_property_read_bool(np,
+                                       "ams,enable-ac-ok-power-on");
        as3722->irq_flags = irqd_get_trigger_type(irq_data);
        dev_dbg(&i2c->dev, "IRQ flags are 0x%08lx\n", as3722->irq_flags);
        return 0;
@@ -360,6 +362,7 @@ static int as3722_i2c_probe(struct i2c_client *i2c,
        struct as3722 *as3722;
        unsigned long irq_flags;
        int ret;
+       u8 val = 0;
 
        as3722 = devm_kzalloc(&i2c->dev, sizeof(struct as3722), GFP_KERNEL);
        if (!as3722)
@@ -398,6 +401,15 @@ static int as3722_i2c_probe(struct i2c_client *i2c,
        if (ret < 0)
                return ret;
 
+       if (as3722->en_ac_ok_pwr_on)
+               val = AS3722_CTRL_SEQU1_AC_OK_PWR_ON;
+       ret = as3722_update_bits(as3722, AS3722_CTRL_SEQU1_REG,
+                       AS3722_CTRL_SEQU1_AC_OK_PWR_ON, val);
+       if (ret < 0) {
+               dev_err(as3722->dev, "CTRLsequ1 update failed: %d\n", ret);
+               return ret;
+       }
+
        ret = devm_mfd_add_devices(&i2c->dev, -1, as3722_devs,
                                   ARRAY_SIZE(as3722_devs), NULL, 0,
                                   regmap_irq_get_domain(as3722->irq_data));
index d35a5fe..a7b7c54 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,axp806", .data = (void *)AXP806_ID },
        { },
 };
 MODULE_DEVICE_TABLE(of, axp20x_i2c_of_match);
@@ -74,6 +75,7 @@ static const struct i2c_device_id axp20x_i2c_id[] = {
        { "axp202", 0 },
        { "axp209", 0 },
        { "axp221", 0 },
+       { "axp806", 0 },
        { },
 };
 MODULE_DEVICE_TABLE(i2c, axp20x_i2c_id);
index 9a2ef3d..0be511d 100644 (file)
@@ -221,6 +221,11 @@ static const struct resource axp803_pek_resources[] = {
        DEFINE_RES_IRQ_NAMED(AXP803_IRQ_PEK_FAL_EDGE, "PEK_DBF"),
 };
 
+static const struct resource axp806_pek_resources[] = {
+       DEFINE_RES_IRQ_NAMED(AXP806_IRQ_POK_RISE, "PEK_DBR"),
+       DEFINE_RES_IRQ_NAMED(AXP806_IRQ_POK_FALL, "PEK_DBF"),
+};
+
 static const struct resource axp809_pek_resources[] = {
        DEFINE_RES_IRQ_NAMED(AXP809_IRQ_PEK_RIS_EDGE, "PEK_DBR"),
        DEFINE_RES_IRQ_NAMED(AXP809_IRQ_PEK_FAL_EDGE, "PEK_DBF"),
@@ -730,6 +735,15 @@ static const struct mfd_cell axp803_cells[] = {
        {       .name                   = "axp20x-regulator" },
 };
 
+static const struct mfd_cell axp806_self_working_cells[] = {
+       {
+               .name                   = "axp221-pek",
+               .num_resources          = ARRAY_SIZE(axp806_pek_resources),
+               .resources              = axp806_pek_resources,
+       },
+       {       .name                   = "axp20x-regulator" },
+};
+
 static const struct mfd_cell axp806_cells[] = {
        {
                .id                     = 2,
@@ -842,8 +856,14 @@ int axp20x_match_device(struct axp20x_dev *axp20x)
                axp20x->regmap_irq_chip = &axp803_regmap_irq_chip;
                break;
        case AXP806_ID:
-               axp20x->nr_cells = ARRAY_SIZE(axp806_cells);
-               axp20x->cells = axp806_cells;
+               if (of_property_read_bool(axp20x->dev->of_node,
+                                         "x-powers,self-working-mode")) {
+                       axp20x->nr_cells = ARRAY_SIZE(axp806_self_working_cells);
+                       axp20x->cells = axp806_self_working_cells;
+               } else {
+                       axp20x->nr_cells = ARRAY_SIZE(axp806_cells);
+                       axp20x->cells = axp806_cells;
+               }
                axp20x->regmap_cfg = &axp806_regmap_config;
                axp20x->regmap_irq_chip = &axp806_regmap_irq_chip;
                break;
@@ -901,7 +921,9 @@ int axp20x_device_probe(struct axp20x_dev *axp20x)
         */
        if (axp20x->variant == AXP806_ID) {
                if (of_property_read_bool(axp20x->dev->of_node,
-                                         "x-powers,master-mode"))
+                                         "x-powers,master-mode") ||
+                   of_property_read_bool(axp20x->dev->of_node,
+                                         "x-powers,self-working-mode"))
                        regmap_write(axp20x->regmap, AXP806_REG_ADDR_EXT,
                                     AXP806_REG_ADDR_EXT_ADDR_MASTER_MODE);
                else
index 27af62e..999dac7 100644 (file)
@@ -378,10 +378,18 @@ error:
        kfree(msg);
 }
 
+static const struct mfd_cell cros_ec_cec_cells[] = {
+       { .name = "cros-ec-cec" }
+};
+
 static const struct mfd_cell cros_ec_rtc_cells[] = {
        { .name = "cros-ec-rtc" }
 };
 
+static const struct mfd_cell cros_usbpd_charger_cells[] = {
+       { .name = "cros-usbpd-charger" }
+};
+
 static int ec_device_probe(struct platform_device *pdev)
 {
        int retval = -ENOMEM;
@@ -420,6 +428,18 @@ static int ec_device_probe(struct platform_device *pdev)
        if (cros_ec_check_features(ec, EC_FEATURE_MOTION_SENSE))
                cros_ec_sensors_register(ec);
 
+       /* Check whether this EC instance has CEC host command support */
+       if (cros_ec_check_features(ec, EC_FEATURE_CEC)) {
+               retval = mfd_add_devices(ec->dev, PLATFORM_DEVID_AUTO,
+                                        cros_ec_cec_cells,
+                                        ARRAY_SIZE(cros_ec_cec_cells),
+                                        NULL, 0, NULL);
+               if (retval)
+                       dev_err(ec->dev,
+                               "failed to add cros-ec-cec device: %d\n",
+                               retval);
+       }
+
        /* Check whether this EC instance has RTC host command support */
        if (cros_ec_check_features(ec, EC_FEATURE_RTC)) {
                retval = mfd_add_devices(ec->dev, PLATFORM_DEVID_AUTO,
@@ -432,6 +452,18 @@ static int ec_device_probe(struct platform_device *pdev)
                                retval);
        }
 
+       /* Check whether this EC instance has the PD charge manager */
+       if (cros_ec_check_features(ec, EC_FEATURE_USB_PD)) {
+               retval = mfd_add_devices(ec->dev, PLATFORM_DEVID_AUTO,
+                                        cros_usbpd_charger_cells,
+                                        ARRAY_SIZE(cros_usbpd_charger_cells),
+                                        NULL, 0, NULL);
+               if (retval)
+                       dev_err(ec->dev,
+                               "failed to add cros-usbpd-charger device: %d\n",
+                               retval);
+       }
+
        /* Take control of the lightbar from the EC. */
        lb_manual_suspend_ctrl(ec, 1);
 
diff --git a/drivers/mfd/cs47l35-tables.c b/drivers/mfd/cs47l35-tables.c
new file mode 100644 (file)
index 0000000..604c9dd
--- /dev/null
@@ -0,0 +1,1609 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Regmap tables for CS47L35 codec
+ *
+ * Copyright (C) 2015-2017 Cirrus Logic
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2.
+ */
+
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+
+#include <linux/mfd/madera/core.h>
+#include <linux/mfd/madera/registers.h>
+
+#include "madera.h"
+
+static const struct reg_sequence cs47l35_reva_16_patch[] = {
+       { 0x460, 0x0c40 },
+       { 0x461, 0xcd1a },
+       { 0x462, 0x0c40 },
+       { 0x463, 0xb53b },
+       { 0x464, 0x0c40 },
+       { 0x465, 0x7503 },
+       { 0x466, 0x0c40 },
+       { 0x467, 0x4a41 },
+       { 0x468, 0x0041 },
+       { 0x469, 0x3491 },
+       { 0x46a, 0x0841 },
+       { 0x46b, 0x1f50 },
+       { 0x46c, 0x0446 },
+       { 0x46d, 0x14ed },
+       { 0x46e, 0x0446 },
+       { 0x46f, 0x1455 },
+       { 0x470, 0x04c6 },
+       { 0x471, 0x1220 },
+       { 0x472, 0x04c6 },
+       { 0x473, 0x040f },
+       { 0x474, 0x04ce },
+       { 0x475, 0x0339 },
+       { 0x476, 0x05df },
+       { 0x477, 0x028f },
+       { 0x478, 0x05df },
+       { 0x479, 0x0209 },
+       { 0x47a, 0x05df },
+       { 0x47b, 0x00cf },
+       { 0x47c, 0x05df },
+       { 0x47d, 0x0001 },
+       { 0x47e, 0x07ff },
+};
+
+int cs47l35_patch(struct madera *madera)
+{
+       int ret;
+
+       ret = regmap_register_patch(madera->regmap, cs47l35_reva_16_patch,
+                                   ARRAY_SIZE(cs47l35_reva_16_patch));
+       if (ret < 0)
+               dev_err(madera->dev, "Error applying patch: %d\n", ret);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(cs47l35_patch);
+
+static const struct reg_default cs47l35_reg_default[] = {
+       { 0x00000020, 0x0000 }, /* R32 (0x20) - Tone Generator 1 */
+       { 0x00000021, 0x1000 }, /* R33 (0x21) - Tone Generator 2 */
+       { 0x00000022, 0x0000 }, /* R34 (0x22) - Tone Generator 3 */
+       { 0x00000023, 0x1000 }, /* R35 (0x23) - Tone Generator 4 */
+       { 0x00000024, 0x0000 }, /* R36 (0x24) - Tone Generator 5 */
+       { 0x00000030, 0x0000 }, /* R48 (0x30) - PWM Drive 1 */
+       { 0x00000031, 0x0100 }, /* R49 (0x31) - PWM Drive 2 */
+       { 0x00000032, 0x0100 }, /* R50 (0x32) - PWM Drive 3 */
+       { 0x00000061, 0x01ff }, /* R97 (0x61) - Sample Rate Sequence Select 1 */
+       { 0x00000062, 0x01ff }, /* R98 (0x62) - Sample Rate Sequence Select 2 */
+       { 0x00000063, 0x01ff }, /* R99 (0x63) - Sample Rate Sequence Select 3 */
+       { 0x00000064, 0x01ff }, /* R100 (0x64) - Sample Rate Sequence Select 4*/
+       { 0x00000066, 0x01ff }, /* R102 (0x66) - Always On Triggers Sequence Select 1*/
+       { 0x00000067, 0x01ff }, /* R103 (0x67) - Always On Triggers Sequence Select 2*/
+       { 0x00000090, 0x0000 }, /* R144 (0x90) - Haptics Control 1 */
+       { 0x00000091, 0x7fff }, /* R145 (0x91) - Haptics Control 2 */
+       { 0x00000092, 0x0000 }, /* R146 (0x92) - Haptics phase 1 intensity */
+       { 0x00000093, 0x0000 }, /* R147 (0x93) - Haptics phase 1 duration */
+       { 0x00000094, 0x0000 }, /* R148 (0x94) - Haptics phase 2 intensity */
+       { 0x00000095, 0x0000 }, /* R149 (0x95) - Haptics phase 2 duration */
+       { 0x00000096, 0x0000 }, /* R150 (0x96) - Haptics phase 3 intensity */
+       { 0x00000097, 0x0000 }, /* R151 (0x97) - Haptics phase 3 duration */
+       { 0x000000A0, 0x0000 }, /* R160 (0xa0) - Comfort Noise Generator */
+       { 0x00000100, 0x0002 }, /* R256 (0x100) - Clock 32k 1 */
+       { 0x00000101, 0x0404 }, /* R257 (0x101) - System Clock 1 */
+       { 0x00000102, 0x0011 }, /* R258 (0x102) - Sample rate 1 */
+       { 0x00000103, 0x0011 }, /* R259 (0x103) - Sample rate 2 */
+       { 0x00000104, 0x0011 }, /* R260 (0x104) - Sample rate 3 */
+       { 0x00000120, 0x0305 }, /* R288 (0x120) - DSP Clock 1 */
+       { 0x00000122, 0x0000 }, /* R290 (0x122) - DSP Clock 2 */
+       { 0x00000149, 0x0000 }, /* R329 (0x149) - Output system clock */
+       { 0x0000014a, 0x0000 }, /* R330 (0x14a) - Output async clock */
+       { 0x00000152, 0x0000 }, /* R338 (0x152) - Rate Estimator 1 */
+       { 0x00000153, 0x0000 }, /* R339 (0x153) - Rate Estimator 2 */
+       { 0x00000154, 0x0000 }, /* R340 (0x154) - Rate Estimator 3 */
+       { 0x00000155, 0x0000 }, /* R341 (0x155) - Rate Estimator 4 */
+       { 0x00000156, 0x0000 }, /* R342 (0x156) - Rate Estimator 5 */
+       { 0x00000171, 0x0002 }, /* R369 (0x171) - FLL1 Control 1 */
+       { 0x00000172, 0x0008 }, /* R370 (0x172) - FLL1 Control 2 */
+       { 0x00000173, 0x0018 }, /* R371 (0x173) - FLL1 Control 3 */
+       { 0x00000174, 0x007d }, /* R372 (0x174) - FLL1 Control 4 */
+       { 0x00000175, 0x0000 }, /* R373 (0x175) - FLL1 Control 5 */
+       { 0x00000176, 0x0000 }, /* R374 (0x176) - FLL1 Control 6 */
+       { 0x00000177, 0x0281 }, /* R375 (0x177) - FLL1 Loop Filter Test 1 */
+       { 0x00000179, 0x0000 }, /* R377 (0x179) - FLL1 Control 7 */
+       { 0x0000017a, 0x0b06 }, /* R378 (0x17a) - FLL1 EFS2 */
+       { 0x0000017f, 0x0000 }, /* R383 (0x17f) - FLL1 Synchroniser 1 */
+       { 0x00000180, 0x0000 }, /* R384 (0x180) - FLL1 Synchroniser 2 */
+       { 0x00000181, 0x0000 }, /* R385 (0x181) - FLL1 Synchroniser 3 */
+       { 0x00000182, 0x0000 }, /* R386 (0x182) - FLL1 Synchroniser 4 */
+       { 0x00000183, 0x0000 }, /* R387 (0x183) - FLL1 Synchroniser 5 */
+       { 0x00000184, 0x0000 }, /* R388 (0x184) - FLL1 Synchroniser 6 */
+       { 0x00000185, 0x0001 }, /* R389 (0x185) - FLL1 Synchroniser 7 */
+       { 0x00000187, 0x0000 }, /* R391 (0x187) - FLL1 Spread Spectrum */
+       { 0x00000188, 0x000c }, /* R392 (0x188) - FLL1 GPIO Clock */
+       { 0x00000200, 0x0006 }, /* R512 (0x200) - Mic Charge Pump 1 */
+       { 0x0000020b, 0x0400 }, /* R523 (0x20b) - HP Charge Pump 8 */
+       { 0x00000213, 0x03e4 }, /* R531 (0x213) - LDO2 Control 1 */
+       { 0x00000218, 0x00e6 }, /* R536 (0x218) - Mic Bias Ctrl 1 */
+       { 0x00000219, 0x00e6 }, /* R537 (0x219) - Mic Bias Ctrl 2 */
+       { 0x0000021c, 0x0022 }, /* R540 (0x21c) - Mic Bias Ctrl 5 */
+       { 0x0000021e, 0x0022 }, /* R542 (0x21e) - Mic Bias Ctrl 6 */
+       { 0x0000027e, 0x0000 }, /* R638 (0x27e) - EDRE HP stereo control */
+       { 0x00000293, 0x0080 }, /* R659 (0x293) - Accessory Detect Mode 1 */
+       { 0x0000029b, 0x0000 }, /* R667 (0x29b) - Headphone Detect 1 */
+       { 0x000002a3, 0x1102 }, /* R675 (0x2a3) - Mic Detect Control 1 */
+       { 0x000002a4, 0x009f }, /* R676 (0x2a4) - Mic Detect Control 2 */
+       { 0x000002a6, 0x3d3d }, /* R678 (0x2a6) - Mic Detect Level 1 */
+       { 0x000002a7, 0x3d3d }, /* R679 (0x2a7) - Mic Detect Level 2 */
+       { 0x000002a8, 0x333d }, /* R680 (0x2a8) - Mic Detect Level 3 */
+       { 0x000002a9, 0x202d }, /* R681 (0x2a9) - Mic Detect Level 4 */
+       { 0x000002c6, 0x0010 }, /* R710 (0x2c5) - Mic Clamp control */
+       { 0x000002c8, 0x0000 }, /* R712 (0x2c8) - GP switch 1 */
+       { 0x000002d3, 0x0000 }, /* R723 (0x2d3) - Jack detect analogue */
+       { 0x00000300, 0x0000 }, /* R768 (0x300) - Input Enables */
+       { 0x00000308, 0x0000 }, /* R776 (0x308) - Input Rate */
+       { 0x00000309, 0x0022 }, /* R777 (0x309) - Input Volume Ramp */
+       { 0x0000030c, 0x0002 }, /* R780 (0x30c) - HPF Control */
+       { 0x00000310, 0x0080 }, /* R784 (0x310) - IN1L Control */
+       { 0x00000311, 0x0180 }, /* R785 (0x311) - ADC Digital Volume 1L */
+       { 0x00000312, 0x0500 }, /* R786 (0x312) - DMIC1L Control */
+       { 0x00000314, 0x0080 }, /* R788 (0x314) - IN1R Control */
+       { 0x00000315, 0x0180 }, /* R789 (0x315) - ADC Digital Volume 1R */
+       { 0x00000316, 0x0000 }, /* R790 (0x316) - DMIC1R Control */
+       { 0x00000318, 0x0080 }, /* R792 (0x318) - IN2L Control */
+       { 0x00000319, 0x0180 }, /* R793 (0x319) - ADC Digital Volume 2L */
+       { 0x0000031a, 0x0500 }, /* R794 (0x31a) - DMIC2L Control */
+       { 0x0000031c, 0x0080 }, /* R796 (0x31c) - IN2R Control */
+       { 0x0000031d, 0x0180 }, /* R797 (0x31d) - ADC Digital Volume 2R */
+       { 0x0000031e, 0x0000 }, /* R798 (0x31e) - DMIC2R Control */
+       { 0x00000400, 0x0000 }, /* R1024 (0x400) - Output Enables 1 */
+       { 0x00000408, 0x0000 }, /* R1032 (0x408) - Output Rate 1 */
+       { 0x00000409, 0x0022 }, /* R1033 (0x409) - Output Volume Ramp */
+       { 0x00000410, 0x0080 }, /* R1040 (0x410) - Output Path Config 1L */
+       { 0x00000411, 0x0180 }, /* R1041 (0x411) - DAC Digital Volume 1L */
+       { 0x00000413, 0x0001 }, /* R1043 (0x413) - Noise Gate Select 1L */
+       { 0x00000414, 0x0080 }, /* R1044 (0x414) - Output Path Config 1R */
+       { 0x00000415, 0x0180 }, /* R1045 (0x415) - DAC Digital Volume 1R */
+       { 0x00000417, 0x0002 }, /* R1047 (0x417) - Noise Gate Select 1R */
+       { 0x00000428, 0x0000 }, /* R1064 (0x428) - Output Path Config 4L */
+       { 0x00000429, 0x0180 }, /* R1065 (0x429) - DAC Digital Volume 4L */
+       { 0x0000042b, 0x0040 }, /* R1067 (0x42b) - Noise Gate Select 4L */
+       { 0x00000430, 0x0000 }, /* R1072 (0x430) - Output Path Config 5L */
+       { 0x00000431, 0x0180 }, /* R1073 (0x431) - DAC Digital Volume 5L */
+       { 0x00000433, 0x0100 }, /* R1075 (0x433) - Noise Gate Select 5L */
+       { 0x00000434, 0x0000 }, /* R1076 (0x434) - Output Path Config 5R */
+       { 0x00000435, 0x0180 }, /* R1077 (0x435) - DAC Digital Volume 5R */
+       { 0x00000437, 0x0200 }, /* R1079 (0x437) - Noise Gate Select 5R */
+       { 0x00000440, 0x0003 }, /* R1088 (0x440) - DRE Enable */
+       { 0x00000448, 0x0a83 }, /* R1096 (0x448) - eDRE Enable */
+       { 0x0000044a, 0x0000 }, /* R1098 (0x44a) - eDRE Manual */
+       { 0x00000450, 0x0000 }, /* R1104 (0x450) - DAC AEC Control 1 */
+       { 0x00000458, 0x0000 }, /* R1112 (0x458) - Noise Gate Control */
+       { 0x00000490, 0x0069 }, /* R1168 (0x490) - PDM SPK1 CTRL 1 */
+       { 0x00000491, 0x0000 }, /* R1169 (0x491) - PDM SPK1 CTRL 2 */
+       { 0x000004a0, 0x3080 }, /* R1184 (0x4a0) - HP1 Short Circuit Ctrl */
+       { 0x000004a8, 0x7120 }, /* R1192 (0x4a8) - HP Test Ctrl 5 */
+       { 0x000004a9, 0x7120 }, /* R1193 (0x4a9) - HP Test Ctrl 6 */
+       { 0x00000500, 0x000c }, /* R1280 (0x500) - AIF1 BCLK Ctrl */
+       { 0x00000501, 0x0000 }, /* R1281 (0x501) - AIF1 Tx Pin Ctrl */
+       { 0x00000502, 0x0000 }, /* R1282 (0x502) - AIF1 Rx Pin Ctrl */
+       { 0x00000503, 0x0000 }, /* R1283 (0x503) - AIF1 Rate Ctrl */
+       { 0x00000504, 0x0000 }, /* R1284 (0x504) - AIF1 Format */
+       { 0x00000506, 0x0040 }, /* R1286 (0x506) - AIF1 Rx BCLK Rate */
+       { 0x00000507, 0x1818 }, /* R1287 (0x507) - AIF1 Frame Ctrl 1 */
+       { 0x00000508, 0x1818 }, /* R1288 (0x508) - AIF1 Frame Ctrl 2 */
+       { 0x00000509, 0x0000 }, /* R1289 (0x509) - AIF1 Frame Ctrl 3 */
+       { 0x0000050a, 0x0001 }, /* R1290 (0x50a) - AIF1 Frame Ctrl 4 */
+       { 0x0000050b, 0x0002 }, /* R1291 (0x50b) - AIF1 Frame Ctrl 5 */
+       { 0x0000050c, 0x0003 }, /* R1292 (0x50c) - AIF1 Frame Ctrl 6 */
+       { 0x0000050d, 0x0004 }, /* R1293 (0x50d) - AIF1 Frame Ctrl 7 */
+       { 0x0000050e, 0x0005 }, /* R1294 (0x50e) - AIF1 Frame Ctrl 8 */
+       { 0x00000511, 0x0000 }, /* R1297 (0x511) - AIF1 Frame Ctrl 11 */
+       { 0x00000512, 0x0001 }, /* R1298 (0x512) - AIF1 Frame Ctrl 12 */
+       { 0x00000513, 0x0002 }, /* R1299 (0x513) - AIF1 Frame Ctrl 13 */
+       { 0x00000514, 0x0003 }, /* R1300 (0x514) - AIF1 Frame Ctrl 14 */
+       { 0x00000515, 0x0004 }, /* R1301 (0x515) - AIF1 Frame Ctrl 15 */
+       { 0x00000516, 0x0005 }, /* R1302 (0x516) - AIF1 Frame Ctrl 16 */
+       { 0x00000519, 0x0000 }, /* R1305 (0x519) - AIF1 Tx Enables */
+       { 0x0000051a, 0x0000 }, /* R1306 (0x51a) - AIF1 Rx Enables */
+       { 0x00000540, 0x000c }, /* R1344 (0x540) - AIF2 BCLK Ctrl */
+       { 0x00000541, 0x0000 }, /* R1345 (0x541) - AIF2 Tx Pin Ctrl */
+       { 0x00000542, 0x0000 }, /* R1346 (0x542) - AIF2 Rx Pin Ctrl */
+       { 0x00000543, 0x0000 }, /* R1347 (0x543) - AIF2 Rate Ctrl */
+       { 0x00000544, 0x0000 }, /* R1348 (0x544) - AIF2 Format */
+       { 0x00000546, 0x0040 }, /* R1350 (0x546) - AIF2 Rx BCLK Rate */
+       { 0x00000547, 0x1818 }, /* R1351 (0x547) - AIF2 Frame Ctrl 1 */
+       { 0x00000548, 0x1818 }, /* R1352 (0x548) - AIF2 Frame Ctrl 2 */
+       { 0x00000549, 0x0000 }, /* R1353 (0x549) - AIF2 Frame Ctrl 3 */
+       { 0x0000054a, 0x0001 }, /* R1354 (0x54a) - AIF2 Frame Ctrl 4 */
+       { 0x00000551, 0x0000 }, /* R1361 (0x551) - AIF2 Frame Ctrl 11 */
+       { 0x00000552, 0x0001 }, /* R1362 (0x552) - AIF2 Frame Ctrl 12 */
+       { 0x00000559, 0x0000 }, /* R1369 (0x559) - AIF2 Tx Enables */
+       { 0x0000055a, 0x0000 }, /* R1370 (0x55a) - AIF2 Rx Enables */
+       { 0x00000580, 0x000c }, /* R1408 (0x580) - AIF3 BCLK Ctrl */
+       { 0x00000581, 0x0000 }, /* R1409 (0x581) - AIF3 Tx Pin Ctrl */
+       { 0x00000582, 0x0000 }, /* R1410 (0x582) - AIF3 Rx Pin Ctrl */
+       { 0x00000583, 0x0000 }, /* R1411 (0x583) - AIF3 Rate Ctrl */
+       { 0x00000584, 0x0000 }, /* R1412 (0x584) - AIF3 Format */
+       { 0x00000586, 0x0040 }, /* R1414 (0x586) - AIF3 Rx BCLK Rate */
+       { 0x00000587, 0x1818 }, /* R1415 (0x587) - AIF3 Frame Ctrl 1 */
+       { 0x00000588, 0x1818 }, /* R1416 (0x588) - AIF3 Frame Ctrl 2 */
+       { 0x00000589, 0x0000 }, /* R1417 (0x589) - AIF3 Frame Ctrl 3 */
+       { 0x0000058a, 0x0001 }, /* R1418 (0x58a) - AIF3 Frame Ctrl 4 */
+       { 0x00000591, 0x0000 }, /* R1425 (0x591) - AIF3 Frame Ctrl 11 */
+       { 0x00000592, 0x0001 }, /* R1426 (0x592) - AIF3 Frame Ctrl 12 */
+       { 0x00000599, 0x0000 }, /* R1433 (0x599) - AIF3 Tx Enables */
+       { 0x0000059a, 0x0000 }, /* R1434 (0x59a) - AIF3 Rx Enables */
+       { 0x000005c2, 0x0000 }, /* R1474 (0x5c2) - SPD1 TX Control */
+       { 0x000005e3, 0x0000 }, /* R1507 (0x5e3) - SLIMbus Framer Ref Gear */
+       { 0x000005e5, 0x0000 }, /* R1509 (0x5e5) - SLIMbus Rates 1 */
+       { 0x000005e6, 0x0000 }, /* R1510 (0x5e6) - SLIMbus Rates 2 */
+       { 0x000005e7, 0x0000 }, /* R1511 (0x5e7) - SLIMbus Rates 3 */
+       { 0x000005e9, 0x0000 }, /* R1513 (0x5e9) - SLIMbus Rates 5 */
+       { 0x000005ea, 0x0000 }, /* R1514 (0x5ea) - SLIMbus Rates 6 */
+       { 0x000005eb, 0x0000 }, /* R1515 (0x5eb) - SLIMbus Rates 7 */
+       { 0x000005f5, 0x0000 }, /* R1525 (0x5f5) - SLIMbus RX Channel Enable */
+       { 0x000005f6, 0x0000 }, /* R1526 (0x5f6) - SLIMbus TX Channel Enable */
+       { 0x00000640, 0x0000 }, /* R1600 (0x640) - PWM1MIX Input 1 Source */
+       { 0x00000641, 0x0080 }, /* R1601 (0x641) - PWM1MIX Input 1 Volume */
+       { 0x00000642, 0x0000 }, /* R1602 (0x642) - PWM1MIX Input 2 Source */
+       { 0x00000643, 0x0080 }, /* R1603 (0x643) - PWM1MIX Input 2 Volume */
+       { 0x00000644, 0x0000 }, /* R1604 (0x644) - PWM1MIX Input 3 Source */
+       { 0x00000645, 0x0080 }, /* R1605 (0x645) - PWM1MIX Input 3 Volume */
+       { 0x00000646, 0x0000 }, /* R1606 (0x646) - PWM1MIX Input 4 Source */
+       { 0x00000647, 0x0080 }, /* R1607 (0x647) - PWM1MIX Input 4 Volume */
+       { 0x00000648, 0x0000 }, /* R1608 (0x648) - PWM2MIX Input 1 Source */
+       { 0x00000649, 0x0080 }, /* R1609 (0x649) - PWM2MIX Input 1 Volume */
+       { 0x0000064a, 0x0000 }, /* R1610 (0x64a) - PWM2MIX Input 2 Source */
+       { 0x0000064b, 0x0080 }, /* R1611 (0x64b) - PWM2MIX Input 2 Volume */
+       { 0x0000064c, 0x0000 }, /* R1612 (0x64c) - PWM2MIX Input 3 Source */
+       { 0x0000064d, 0x0080 }, /* R1613 (0x64d) - PWM2MIX Input 3 Volume */
+       { 0x0000064e, 0x0000 }, /* R1614 (0x64e) - PWM2MIX Input 4 Source */
+       { 0x0000064f, 0x0080 }, /* R1615 (0x64f) - PWM2MIX Input 4 Volume */
+       { 0x00000680, 0x0000 }, /* R1664 (0x680) - OUT1LMIX Input 1 Source */
+       { 0x00000681, 0x0080 }, /* R1665 (0x681) - OUT1LMIX Input 1 Volume */
+       { 0x00000682, 0x0000 }, /* R1666 (0x682) - OUT1LMIX Input 2 Source */
+       { 0x00000683, 0x0080 }, /* R1667 (0x683) - OUT1LMIX Input 2 Volume */
+       { 0x00000684, 0x0000 }, /* R1668 (0x684) - OUT1LMIX Input 3 Source */
+       { 0x00000685, 0x0080 }, /* R1669 (0x685) - OUT1LMIX Input 3 Volume */
+       { 0x00000686, 0x0000 }, /* R1670 (0x686) - OUT1LMIX Input 4 Source */
+       { 0x00000687, 0x0080 }, /* R1671 (0x687) - OUT1LMIX Input 4 Volume */
+       { 0x00000688, 0x0000 }, /* R1672 (0x688) - OUT1RMIX Input 1 Source */
+       { 0x00000689, 0x0080 }, /* R1673 (0x689) - OUT1RMIX Input 1 Volume */
+       { 0x0000068a, 0x0000 }, /* R1674 (0x68a) - OUT1RMIX Input 2 Source */
+       { 0x0000068b, 0x0080 }, /* R1675 (0x68b) - OUT1RMIX Input 2 Volume */
+       { 0x0000068c, 0x0000 }, /* R1672 (0x68c) - OUT1RMIX Input 3 Source */
+       { 0x0000068d, 0x0080 }, /* R1673 (0x68d) - OUT1RMIX Input 3 Volume */
+       { 0x0000068e, 0x0000 }, /* R1674 (0x68e) - OUT1RMIX Input 4 Source */
+       { 0x0000068f, 0x0080 }, /* R1675 (0x68f) - OUT1RMIX Input 4 Volume */
+       { 0x000006b0, 0x0000 }, /* R1712 (0x6b0) - OUT4LMIX Input 1 Source */
+       { 0x000006b1, 0x0080 }, /* R1713 (0x6b1) - OUT4LMIX Input 1 Volume */
+       { 0x000006b2, 0x0000 }, /* R1714 (0x6b2) - OUT4LMIX Input 2 Source */
+       { 0x000006b3, 0x0080 }, /* R1715 (0x6b3) - OUT4LMIX Input 2 Volume */
+       { 0x000006b4, 0x0000 }, /* R1716 (0x6b4) - OUT4LMIX Input 3 Source */
+       { 0x000006b5, 0x0080 }, /* R1717 (0x6b5) - OUT4LMIX Input 3 Volume */
+       { 0x000006b6, 0x0000 }, /* R1718 (0x6b6) - OUT4LMIX Input 4 Source */
+       { 0x000006b7, 0x0080 }, /* R1719 (0x6b7) - OUT4LMIX Input 4 Volume */
+       { 0x000006c0, 0x0000 }, /* R1728 (0x6c0) - OUT5LMIX Input 1 Source */
+       { 0x000006c1, 0x0080 }, /* R1729 (0x6c1) - OUT5LMIX Input 1 Volume */
+       { 0x000006c2, 0x0000 }, /* R1730 (0x6c2) - OUT5LMIX Input 2 Source */
+       { 0x000006c3, 0x0080 }, /* R1731 (0x6c3) - OUT5LMIX Input 2 Volume */
+       { 0x000006c4, 0x0000 }, /* R1732 (0x6c4) - OUT5LMIX Input 3 Source */
+       { 0x000006c5, 0x0080 }, /* R1733 (0x6c5) - OUT5LMIX Input 3 Volume */
+       { 0x000006c6, 0x0000 }, /* R1734 (0x6c6) - OUT5LMIX Input 4 Source */
+       { 0x000006c7, 0x0080 }, /* R1735 (0x6c7) - OUT5LMIX Input 4 Volume */
+       { 0x000006c8, 0x0000 }, /* R1736 (0x6c8) - OUT5RMIX Input 1 Source */
+       { 0x000006c9, 0x0080 }, /* R1737 (0x6c9) - OUT5RMIX Input 1 Volume */
+       { 0x000006ca, 0x0000 }, /* R1738 (0x6ca) - OUT5RMIX Input 2 Source */
+       { 0x000006cb, 0x0080 }, /* R1739 (0x6cb) - OUT5RMIX Input 2 Volume */
+       { 0x000006cc, 0x0000 }, /* R1740 (0x6cc) - OUT5RMIX Input 3 Source */
+       { 0x000006cd, 0x0080 }, /* R1741 (0x6cd) - OUT5RMIX Input 3 Volume */
+       { 0x000006ce, 0x0000 }, /* R1742 (0x6ce) - OUT5RMIX Input 4 Source */
+       { 0x000006cf, 0x0080 }, /* R1743 (0x6cf) - OUT5RMIX Input 4 Volume */
+       { 0x00000700, 0x0000 }, /* R1792 (0x700) - AIF1TX1MIX Input 1 Source */
+       { 0x00000701, 0x0080 }, /* R1793 (0x701) - AIF1TX1MIX Input 1 Volume */
+       { 0x00000702, 0x0000 }, /* R1794 (0x702) - AIF1TX1MIX Input 2 Source */
+       { 0x00000703, 0x0080 }, /* R1795 (0x703) - AIF1TX1MIX Input 2 Volume */
+       { 0x00000704, 0x0000 }, /* R1796 (0x704) - AIF1TX1MIX Input 3 Source */
+       { 0x00000705, 0x0080 }, /* R1797 (0x705) - AIF1TX1MIX Input 3 Volume */
+       { 0x00000706, 0x0000 }, /* R1798 (0x706) - AIF1TX1MIX Input 4 Source */
+       { 0x00000707, 0x0080 }, /* R1799 (0x707) - AIF1TX1MIX Input 4 Volume */
+       { 0x00000708, 0x0000 }, /* R1800 (0x708) - AIF1TX2MIX Input 1 Source */
+       { 0x00000709, 0x0080 }, /* R1801 (0x709) - AIF1TX2MIX Input 1 Volume */
+       { 0x0000070a, 0x0000 }, /* R1802 (0x70a) - AIF1TX2MIX Input 2 Source */
+       { 0x0000070b, 0x0080 }, /* R1803 (0x70b) - AIF1TX2MIX Input 2 Volume */
+       { 0x0000070c, 0x0000 }, /* R1804 (0x70c) - AIF1TX2MIX Input 3 Source */
+       { 0x0000070d, 0x0080 }, /* R1805 (0x70d) - AIF1TX2MIX Input 3 Volume */
+       { 0x0000070e, 0x0000 }, /* R1806 (0x70e) - AIF1TX2MIX Input 4 Source */
+       { 0x0000070f, 0x0080 }, /* R1807 (0x70f) - AIF1TX2MIX Input 4 Volume */
+       { 0x00000710, 0x0000 }, /* R1808 (0x710) - AIF1TX3MIX Input 1 Source */
+       { 0x00000711, 0x0080 }, /* R1809 (0x711) - AIF1TX3MIX Input 1 Volume */
+       { 0x00000712, 0x0000 }, /* R1810 (0x712) - AIF1TX3MIX Input 2 Source */
+       { 0x00000713, 0x0080 }, /* R1811 (0x713) - AIF1TX3MIX Input 2 Volume */
+       { 0x00000714, 0x0000 }, /* R1812 (0x714) - AIF1TX3MIX Input 3 Source */
+       { 0x00000715, 0x0080 }, /* R1813 (0x715) - AIF1TX3MIX Input 3 Volume */
+       { 0x00000716, 0x0000 }, /* R1814 (0x716) - AIF1TX3MIX Input 4 Source */
+       { 0x00000717, 0x0080 }, /* R1815 (0x717) - AIF1TX3MIX Input 4 Volume */
+       { 0x00000718, 0x0000 }, /* R1816 (0x718) - AIF1TX4MIX Input 1 Source */
+       { 0x00000719, 0x0080 }, /* R1817 (0x719) - AIF1TX4MIX Input 1 Volume */
+       { 0x0000071a, 0x0000 }, /* R1818 (0x71a) - AIF1TX4MIX Input 2 Source */
+       { 0x0000071b, 0x0080 }, /* R1819 (0x71b) - AIF1TX4MIX Input 2 Volume */
+       { 0x0000071c, 0x0000 }, /* R1820 (0x71c) - AIF1TX4MIX Input 3 Source */
+       { 0x0000071d, 0x0080 }, /* R1821 (0x71d) - AIF1TX4MIX Input 3 Volume */
+       { 0x0000071e, 0x0000 }, /* R1822 (0x71e) - AIF1TX4MIX Input 4 Source */
+       { 0x0000071f, 0x0080 }, /* R1823 (0x71f) - AIF1TX4MIX Input 4 Volume */
+       { 0x00000720, 0x0000 }, /* R1824 (0x720) - AIF1TX5MIX Input 1 Source */
+       { 0x00000721, 0x0080 }, /* R1825 (0x721) - AIF1TX5MIX Input 1 Volume */
+       { 0x00000722, 0x0000 }, /* R1826 (0x722) - AIF1TX5MIX Input 2 Source */
+       { 0x00000723, 0x0080 }, /* R1827 (0x723) - AIF1TX5MIX Input 2 Volume */
+       { 0x00000724, 0x0000 }, /* R1828 (0x724) - AIF1TX5MIX Input 3 Source */
+       { 0x00000725, 0x0080 }, /* R1829 (0x725) - AIF1TX5MIX Input 3 Volume */
+       { 0x00000726, 0x0000 }, /* R1830 (0x726) - AIF1TX5MIX Input 4 Source */
+       { 0x00000727, 0x0080 }, /* R1831 (0x727) - AIF1TX5MIX Input 4 Volume */
+       { 0x00000728, 0x0000 }, /* R1832 (0x728) - AIF1TX6MIX Input 1 Source */
+       { 0x00000729, 0x0080 }, /* R1833 (0x729) - AIF1TX6MIX Input 1 Volume */
+       { 0x0000072a, 0x0000 }, /* R1834 (0x72a) - AIF1TX6MIX Input 2 Source */
+       { 0x0000072b, 0x0080 }, /* R1835 (0x72b) - AIF1TX6MIX Input 2 Volume */
+       { 0x0000072c, 0x0000 }, /* R1836 (0x72c) - AIF1TX6MIX Input 3 Source */
+       { 0x0000072d, 0x0080 }, /* R1837 (0x72d) - AIF1TX6MIX Input 3 Volume */
+       { 0x0000072e, 0x0000 }, /* R1838 (0x72e) - AIF1TX6MIX Input 4 Source */
+       { 0x0000072f, 0x0080 }, /* R1839 (0x72f) - AIF1TX6MIX Input 4 Volume */
+       { 0x00000740, 0x0000 }, /* R1856 (0x740) - AIF2TX1MIX Input 1 Source */
+       { 0x00000741, 0x0080 }, /* R1857 (0x741) - AIF2TX1MIX Input 1 Volume */
+       { 0x00000742, 0x0000 }, /* R1858 (0x742) - AIF2TX1MIX Input 2 Source */
+       { 0x00000743, 0x0080 }, /* R1859 (0x743) - AIF2TX1MIX Input 2 Volume */
+       { 0x00000744, 0x0000 }, /* R1860 (0x744) - AIF2TX1MIX Input 3 Source */
+       { 0x00000745, 0x0080 }, /* R1861 (0x745) - AIF2TX1MIX Input 3 Volume */
+       { 0x00000746, 0x0000 }, /* R1862 (0x746) - AIF2TX1MIX Input 4 Source */
+       { 0x00000747, 0x0080 }, /* R1863 (0x747) - AIF2TX1MIX Input 4 Volume */
+       { 0x00000748, 0x0000 }, /* R1864 (0x748) - AIF2TX2MIX Input 1 Source */
+       { 0x00000749, 0x0080 }, /* R1865 (0x749) - AIF2TX2MIX Input 1 Volume */
+       { 0x0000074a, 0x0000 }, /* R1866 (0x74a) - AIF2TX2MIX Input 2 Source */
+       { 0x0000074b, 0x0080 }, /* R1867 (0x74b) - AIF2TX2MIX Input 2 Volume */
+       { 0x0000074c, 0x0000 }, /* R1868 (0x74c) - AIF2TX2MIX Input 3 Source */
+       { 0x0000074d, 0x0080 }, /* R1869 (0x74d) - AIF2TX2MIX Input 3 Volume */
+       { 0x0000074e, 0x0000 }, /* R1870 (0x74e) - AIF2TX2MIX Input 4 Source */
+       { 0x0000074f, 0x0080 }, /* R1871 (0x74f) - AIF2TX2MIX Input 4 Volume */
+       { 0x00000780, 0x0000 }, /* R1920 (0x780) - AIF3TX1MIX Input 1 Source */
+       { 0x00000781, 0x0080 }, /* R1921 (0x781) - AIF3TX1MIX Input 1 Volume */
+       { 0x00000782, 0x0000 }, /* R1922 (0x782) - AIF3TX1MIX Input 2 Source */
+       { 0x00000783, 0x0080 }, /* R1923 (0x783) - AIF3TX1MIX Input 2 Volume */
+       { 0x00000784, 0x0000 }, /* R1924 (0x784) - AIF3TX1MIX Input 3 Source */
+       { 0x00000785, 0x0080 }, /* R1925 (0x785) - AIF3TX1MIX Input 3 Volume */
+       { 0x00000786, 0x0000 }, /* R1926 (0x786) - AIF3TX1MIX Input 4 Source */
+       { 0x00000787, 0x0080 }, /* R1927 (0x787) - AIF3TX1MIX Input 4 Volume */
+       { 0x00000788, 0x0000 }, /* R1928 (0x788) - AIF3TX2MIX Input 1 Source */
+       { 0x00000789, 0x0080 }, /* R1929 (0x789) - AIF3TX2MIX Input 1 Volume */
+       { 0x0000078a, 0x0000 }, /* R1930 (0x78a) - AIF3TX2MIX Input 2 Source */
+       { 0x0000078b, 0x0080 }, /* R1931 (0x78b) - AIF3TX2MIX Input 2 Volume */
+       { 0x0000078c, 0x0000 }, /* R1932 (0x78c) - AIF3TX2MIX Input 3 Source */
+       { 0x0000078d, 0x0080 }, /* R1933 (0x78d) - AIF3TX2MIX Input 3 Volume */
+       { 0x0000078e, 0x0000 }, /* R1934 (0x78e) - AIF3TX2MIX Input 4 Source */
+       { 0x0000078f, 0x0080 }, /* R1935 (0x78f) - AIF3TX2MIX Input 4 Volume */
+       { 0x000007c0, 0x0000 }, /* R1984 (0x7c0) - SLIMTX1MIX Input 1 Source */
+       { 0x000007c1, 0x0080 }, /* R1985 (0x7c1) - SLIMTX1MIX Input 1 Volume */
+       { 0x000007c2, 0x0000 }, /* R1986 (0x7c2) - SLIMTX1MIX Input 2 Source */
+       { 0x000007c3, 0x0080 }, /* R1987 (0x7c3) - SLIMTX1MIX Input 2 Volume */
+       { 0x000007c4, 0x0000 }, /* R1988 (0x7c4) - SLIMTX1MIX Input 3 Source */
+       { 0x000007c5, 0x0080 }, /* R1989 (0x7c5) - SLIMTX1MIX Input 3 Volume */
+       { 0x000007c6, 0x0000 }, /* R1990 (0x7c6) - SLIMTX1MIX Input 4 Source */
+       { 0x000007c7, 0x0080 }, /* R1991 (0x7c7) - SLIMTX1MIX Input 4 Volume */
+       { 0x000007c8, 0x0000 }, /* R1992 (0x7c8) - SLIMTX2MIX Input 1 Source */
+       { 0x000007c9, 0x0080 }, /* R1993 (0x7c9) - SLIMTX2MIX Input 1 Volume */
+       { 0x000007ca, 0x0000 }, /* R1994 (0x7ca) - SLIMTX2MIX Input 2 Source */
+       { 0x000007cb, 0x0080 }, /* R1995 (0x7cb) - SLIMTX2MIX Input 2 Volume */
+       { 0x000007cc, 0x0000 }, /* R1996 (0x7cc) - SLIMTX2MIX Input 3 Source */
+       { 0x000007cd, 0x0080 }, /* R1997 (0x7cd) - SLIMTX2MIX Input 3 Volume */
+       { 0x000007ce, 0x0000 }, /* R1998 (0x7ce) - SLIMTX2MIX Input 4 Source */
+       { 0x000007cf, 0x0080 }, /* R1999 (0x7cf) - SLIMTX2MIX Input 4 Volume */
+       { 0x000007d0, 0x0000 }, /* R2000 (0x7d0) - SLIMTX3MIX Input 1 Source */
+       { 0x000007d1, 0x0080 }, /* R2001 (0x7d1) - SLIMTX3MIX Input 1 Volume */
+       { 0x000007d2, 0x0000 }, /* R2002 (0x7d2) - SLIMTX3MIX Input 2 Source */
+       { 0x000007d3, 0x0080 }, /* R2003 (0x7d3) - SLIMTX3MIX Input 2 Volume */
+       { 0x000007d4, 0x0000 }, /* R2004 (0x7d4) - SLIMTX3MIX Input 3 Source */
+       { 0x000007d5, 0x0080 }, /* R2005 (0x7d5) - SLIMTX3MIX Input 3 Volume */
+       { 0x000007d6, 0x0000 }, /* R2006 (0x7d6) - SLIMTX3MIX Input 4 Source */
+       { 0x000007d7, 0x0080 }, /* R2007 (0x7d7) - SLIMTX3MIX Input 4 Volume */
+       { 0x000007d8, 0x0000 }, /* R2008 (0x7d8) - SLIMTX4MIX Input 1 Source */
+       { 0x000007d9, 0x0080 }, /* R2009 (0x7d9) - SLIMTX4MIX Input 1 Volume */
+       { 0x000007da, 0x0000 }, /* R2010 (0x7da) - SLIMTX4MIX Input 2 Source */
+       { 0x000007db, 0x0080 }, /* R2011 (0x7db) - SLIMTX4MIX Input 2 Volume */
+       { 0x000007dc, 0x0000 }, /* R2012 (0x7dc) - SLIMTX4MIX Input 3 Source */
+       { 0x000007dd, 0x0080 }, /* R2013 (0x7dd) - SLIMTX4MIX Input 3 Volume */
+       { 0x000007de, 0x0000 }, /* R2014 (0x7de) - SLIMTX4MIX Input 4 Source */
+       { 0x000007df, 0x0080 }, /* R2015 (0x7df) - SLIMTX4MIX Input 4 Volume */
+       { 0x000007e0, 0x0000 }, /* R2016 (0x7e0) - SLIMTX5MIX Input 1 Source */
+       { 0x000007e1, 0x0080 }, /* R2017 (0x7e1) - SLIMTX5MIX Input 1 Volume */
+       { 0x000007e2, 0x0000 }, /* R2018 (0x7e2) - SLIMTX5MIX Input 2 Source */
+       { 0x000007e3, 0x0080 }, /* R2019 (0x7e3) - SLIMTX5MIX Input 2 Volume */
+       { 0x000007e4, 0x0000 }, /* R2020 (0x7e4) - SLIMTX5MIX Input 3 Source */
+       { 0x000007e5, 0x0080 }, /* R2021 (0x7e5) - SLIMTX5MIX Input 3 Volume */
+       { 0x000007e6, 0x0000 }, /* R2022 (0x7e6) - SLIMTX5MIX Input 4 Source */
+       { 0x000007e7, 0x0080 }, /* R2023 (0x7e7) - SLIMTX5MIX Input 4 Volume */
+       { 0x000007e8, 0x0000 }, /* R2024 (0x7e8) - SLIMTX6MIX Input 1 Source */
+       { 0x000007e9, 0x0080 }, /* R2025 (0x7e9) - SLIMTX6MIX Input 1 Volume */
+       { 0x000007ea, 0x0000 }, /* R2026 (0x7ea) - SLIMTX6MIX Input 2 Source */
+       { 0x000007eb, 0x0080 }, /* R2027 (0x7eb) - SLIMTX6MIX Input 2 Volume */
+       { 0x000007ec, 0x0000 }, /* R2028 (0x7ec) - SLIMTX6MIX Input 3 Source */
+       { 0x000007ed, 0x0080 }, /* R2029 (0x7ed) - SLIMTX6MIX Input 3 Volume */
+       { 0x000007ee, 0x0000 }, /* R2030 (0x7ee) - SLIMTX6MIX Input 4 Source */
+       { 0x000007ef, 0x0080 }, /* R2031 (0x7ef) - SLIMTX6MIX Input 4 Volume */
+       { 0x00000800, 0x0000 }, /* R2048 (0x800) - SPDIF1TX1MIX Input 1 Source*/
+       { 0x00000801, 0x0080 }, /* R2049 (0x801) - SPDIF1TX1MIX Input 1 Volume*/
+       { 0x00000808, 0x0000 }, /* R2056 (0x808) - SPDIF1TX2MIX Input 1 Source*/
+       { 0x00000809, 0x0080 }, /* R2057 (0x809) - SPDIF1TX2MIX Input 1 Volume*/
+       { 0x00000880, 0x0000 }, /* R2176 (0x880) - EQ1MIX Input 1 Source */
+       { 0x00000881, 0x0080 }, /* R2177 (0x881) - EQ1MIX Input 1 Volume */
+       { 0x00000882, 0x0000 }, /* R2178 (0x882) - EQ1MIX Input 2 Source */
+       { 0x00000883, 0x0080 }, /* R2179 (0x883) - EQ1MIX Input 2 Volume */
+       { 0x00000884, 0x0000 }, /* R2180 (0x884) - EQ1MIX Input 3 Source */
+       { 0x00000885, 0x0080 }, /* R2181 (0x885) - EQ1MIX Input 3 Volume */
+       { 0x00000886, 0x0000 }, /* R2182 (0x886) - EQ1MIX Input 4 Source */
+       { 0x00000887, 0x0080 }, /* R2183 (0x887) - EQ1MIX Input 4 Volume */
+       { 0x00000888, 0x0000 }, /* R2184 (0x888) - EQ2MIX Input 1 Source */
+       { 0x00000889, 0x0080 }, /* R2185 (0x889) - EQ2MIX Input 1 Volume */
+       { 0x0000088a, 0x0000 }, /* R2186 (0x88a) - EQ2MIX Input 2 Source */
+       { 0x0000088b, 0x0080 }, /* R2187 (0x88b) - EQ2MIX Input 2 Volume */
+       { 0x0000088c, 0x0000 }, /* R2188 (0x88c) - EQ2MIX Input 3 Source */
+       { 0x0000088d, 0x0080 }, /* R2189 (0x88d) - EQ2MIX Input 3 Volume */
+       { 0x0000088e, 0x0000 }, /* R2190 (0x88e) - EQ2MIX Input 4 Source */
+       { 0x0000088f, 0x0080 }, /* R2191 (0x88f) - EQ2MIX Input 4 Volume */
+       { 0x00000890, 0x0000 }, /* R2192 (0x890) - EQ3MIX Input 1 Source */
+       { 0x00000891, 0x0080 }, /* R2193 (0x891) - EQ3MIX Input 1 Volume */
+       { 0x00000892, 0x0000 }, /* R2194 (0x892) - EQ3MIX Input 2 Source */
+       { 0x00000893, 0x0080 }, /* R2195 (0x893) - EQ3MIX Input 2 Volume */
+       { 0x00000894, 0x0000 }, /* R2196 (0x894) - EQ3MIX Input 3 Source */
+       { 0x00000895, 0x0080 }, /* R2197 (0x895) - EQ3MIX Input 3 Volume */
+       { 0x00000896, 0x0000 }, /* R2198 (0x896) - EQ3MIX Input 4 Source */
+       { 0x00000897, 0x0080 }, /* R2199 (0x897) - EQ3MIX Input 4 Volume */
+       { 0x00000898, 0x0000 }, /* R2200 (0x898) - EQ4MIX Input 1 Source */
+       { 0x00000899, 0x0080 }, /* R2201 (0x899) - EQ4MIX Input 1 Volume */
+       { 0x0000089a, 0x0000 }, /* R2202 (0x89a) - EQ4MIX Input 2 Source */
+       { 0x0000089b, 0x0080 }, /* R2203 (0x89b) - EQ4MIX Input 2 Volume */
+       { 0x0000089c, 0x0000 }, /* R2204 (0x89c) - EQ4MIX Input 3 Source */
+       { 0x0000089d, 0x0080 }, /* R2205 (0x89d) - EQ4MIX Input 3 Volume */
+       { 0x0000089e, 0x0000 }, /* R2206 (0x89e) - EQ4MIX Input 4 Source */
+       { 0x0000089f, 0x0080 }, /* R2207 (0x89f) - EQ4MIX Input 4 Volume */
+       { 0x000008c0, 0x0000 }, /* R2240 (0x8c0) - DRC1LMIX Input 1 Source */
+       { 0x000008c1, 0x0080 }, /* R2241 (0x8c1) - DRC1LMIX Input 1 Volume */
+       { 0x000008c2, 0x0000 }, /* R2242 (0x8c2) - DRC1LMIX Input 2 Source */
+       { 0x000008c3, 0x0080 }, /* R2243 (0x8c3) - DRC1LMIX Input 2 Volume */
+       { 0x000008c4, 0x0000 }, /* R2244 (0x8c4) - DRC1LMIX Input 3 Source */
+       { 0x000008c5, 0x0080 }, /* R2245 (0x8c5) - DRC1LMIX Input 3 Volume */
+       { 0x000008c6, 0x0000 }, /* R2246 (0x8c6) - DRC1LMIX Input 4 Source */
+       { 0x000008c7, 0x0080 }, /* R2247 (0x8c7) - DRC1LMIX Input 4 Volume */
+       { 0x000008c8, 0x0000 }, /* R2248 (0x8c8) - DRC1RMIX Input 1 Source */
+       { 0x000008c9, 0x0080 }, /* R2249 (0x8c9) - DRC1RMIX Input 1 Volume */
+       { 0x000008ca, 0x0000 }, /* R2250 (0x8ca) - DRC1RMIX Input 2 Source */
+       { 0x000008cb, 0x0080 }, /* R2251 (0x8cb) - DRC1RMIX Input 2 Volume */
+       { 0x000008cc, 0x0000 }, /* R2252 (0x8cc) - DRC1RMIX Input 3 Source */
+       { 0x000008cd, 0x0080 }, /* R2253 (0x8cd) - DRC1RMIX Input 3 Volume */
+       { 0x000008ce, 0x0000 }, /* R2254 (0x8ce) - DRC1RMIX Input 4 Source */
+       { 0x000008cf, 0x0080 }, /* R2255 (0x8cf) - DRC1RMIX Input 4 Volume */
+       { 0x000008d0, 0x0000 }, /* R2256 (0x8d0) - DRC2LMIX Input 1 Source */
+       { 0x000008d1, 0x0080 }, /* R2257 (0x8d1) - DRC2LMIX Input 1 Volume */
+       { 0x000008d2, 0x0000 }, /* R2258 (0x8d2) - DRC2LMIX Input 2 Source */
+       { 0x000008d3, 0x0080 }, /* R2259 (0x8d3) - DRC2LMIX Input 2 Volume */
+       { 0x000008d4, 0x0000 }, /* R2260 (0x8d4) - DRC2LMIX Input 3 Source */
+       { 0x000008d5, 0x0080 }, /* R2261 (0x8d5) - DRC2LMIX Input 3 Volume */
+       { 0x000008d6, 0x0000 }, /* R2262 (0x8d6) - DRC2LMIX Input 4 Source */
+       { 0x000008d7, 0x0080 }, /* R2263 (0x8d7) - DRC2LMIX Input 4 Volume */
+       { 0x000008d8, 0x0000 }, /* R2264 (0x8d8) - DRC2RMIX Input 1 Source */
+       { 0x000008d9, 0x0080 }, /* R2265 (0x8d9) - DRC2RMIX Input 1 Volume */
+       { 0x000008da, 0x0000 }, /* R2266 (0x8da) - DRC2RMIX Input 2 Source */
+       { 0x000008db, 0x0080 }, /* R2267 (0x8db) - DRC2RMIX Input 2 Volume */
+       { 0x000008dc, 0x0000 }, /* R2268 (0x8dc) - DRC2RMIX Input 3 Source */
+       { 0x000008dd, 0x0080 }, /* R2269 (0x8dd) - DRC2RMIX Input 3 Volume */
+       { 0x000008de, 0x0000 }, /* R2270 (0x8de) - DRC2RMIX Input 4 Source */
+       { 0x000008df, 0x0080 }, /* R2271 (0x8df) - DRC2RMIX Input 4 Volume */
+       { 0x00000900, 0x0000 }, /* R2304 (0x900) - HPLP1MIX Input 1 Source */
+       { 0x00000901, 0x0080 }, /* R2305 (0x901) - HPLP1MIX Input 1 Volume */
+       { 0x00000902, 0x0000 }, /* R2306 (0x902) - HPLP1MIX Input 2 Source */
+       { 0x00000903, 0x0080 }, /* R2307 (0x903) - HPLP1MIX Input 2 Volume */
+       { 0x00000904, 0x0000 }, /* R2308 (0x904) - HPLP1MIX Input 3 Source */
+       { 0x00000905, 0x0080 }, /* R2309 (0x905) - HPLP1MIX Input 3 Volume */
+       { 0x00000906, 0x0000 }, /* R2310 (0x906) - HPLP1MIX Input 4 Source */
+       { 0x00000907, 0x0080 }, /* R2311 (0x907) - HPLP1MIX Input 4 Volume */
+       { 0x00000908, 0x0000 }, /* R2312 (0x908) - HPLP2MIX Input 1 Source */
+       { 0x00000909, 0x0080 }, /* R2313 (0x909) - HPLP2MIX Input 1 Volume */
+       { 0x0000090a, 0x0000 }, /* R2314 (0x90a) - HPLP2MIX Input 2 Source */
+       { 0x0000090b, 0x0080 }, /* R2315 (0x90b) - HPLP2MIX Input 2 Volume */
+       { 0x0000090c, 0x0000 }, /* R2316 (0x90c) - HPLP2MIX Input 3 Source */
+       { 0x0000090d, 0x0080 }, /* R2317 (0x90d) - HPLP2MIX Input 3 Volume */
+       { 0x0000090e, 0x0000 }, /* R2318 (0x90e) - HPLP2MIX Input 4 Source */
+       { 0x0000090f, 0x0080 }, /* R2319 (0x90f) - HPLP2MIX Input 4 Volume */
+       { 0x00000910, 0x0000 }, /* R2320 (0x910) - HPLP3MIX Input 1 Source */
+       { 0x00000911, 0x0080 }, /* R2321 (0x911) - HPLP3MIX Input 1 Volume */
+       { 0x00000912, 0x0000 }, /* R2322 (0x912) - HPLP3MIX Input 2 Source */
+       { 0x00000913, 0x0080 }, /* R2323 (0x913) - HPLP3MIX Input 2 Volume */
+       { 0x00000914, 0x0000 }, /* R2324 (0x914) - HPLP3MIX Input 3 Source */
+       { 0x00000915, 0x0080 }, /* R2325 (0x915) - HPLP3MIX Input 3 Volume */
+       { 0x00000916, 0x0000 }, /* R2326 (0x916) - HPLP3MIX Input 4 Source */
+       { 0x00000917, 0x0080 }, /* R2327 (0x917) - HPLP3MIX Input 4 Volume */
+       { 0x00000918, 0x0000 }, /* R2328 (0x918) - HPLP4MIX Input 1 Source */
+       { 0x00000919, 0x0080 }, /* R2329 (0x919) - HPLP4MIX Input 1 Volume */
+       { 0x0000091a, 0x0000 }, /* R2330 (0x91a) - HPLP4MIX Input 2 Source */
+       { 0x0000091b, 0x0080 }, /* R2331 (0x91b) - HPLP4MIX Input 2 Volume */
+       { 0x0000091c, 0x0000 }, /* R2332 (0x91c) - HPLP4MIX Input 3 Source */
+       { 0x0000091d, 0x0080 }, /* R2333 (0x91d) - HPLP4MIX Input 3 Volume */
+       { 0x0000091e, 0x0000 }, /* R2334 (0x91e) - HPLP4MIX Input 4 Source */
+       { 0x0000091f, 0x0080 }, /* R2335 (0x91f) - HPLP4MIX Input 4 Volume */
+       { 0x00000940, 0x0000 }, /* R2368 (0x940) - DSP1LMIX Input 1 Source */
+       { 0x00000941, 0x0080 }, /* R2369 (0x941) - DSP1LMIX Input 1 Volume */
+       { 0x00000942, 0x0000 }, /* R2370 (0x942) - DSP1LMIX Input 2 Source */
+       { 0x00000943, 0x0080 }, /* R2371 (0x943) - DSP1LMIX Input 2 Volume */
+       { 0x00000944, 0x0000 }, /* R2372 (0x944) - DSP1LMIX Input 3 Source */
+       { 0x00000945, 0x0080 }, /* R2373 (0x945) - DSP1LMIX Input 3 Volume */
+       { 0x00000946, 0x0000 }, /* R2374 (0x946) - DSP1LMIX Input 4 Source */
+       { 0x00000947, 0x0080 }, /* R2375 (0x947) - DSP1LMIX Input 4 Volume */
+       { 0x00000948, 0x0000 }, /* R2376 (0x948) - DSP1RMIX Input 1 Source */
+       { 0x00000949, 0x0080 }, /* R2377 (0x949) - DSP1RMIX Input 1 Volume */
+       { 0x0000094a, 0x0000 }, /* R2378 (0x94a) - DSP1RMIX Input 2 Source */
+       { 0x0000094b, 0x0080 }, /* R2379 (0x94b) - DSP1RMIX Input 2 Volume */
+       { 0x0000094c, 0x0000 }, /* R2380 (0x94c) - DSP1RMIX Input 3 Source */
+       { 0x0000094d, 0x0080 }, /* R2381 (0x94d) - DSP1RMIX Input 3 Volume */
+       { 0x0000094e, 0x0000 }, /* R2382 (0x94e) - DSP1RMIX Input 4 Source */
+       { 0x0000094f, 0x0080 }, /* R2383 (0x94f) - DSP1RMIX Input 4 Volume */
+       { 0x00000950, 0x0000 }, /* R2384 (0x950) - DSP1AUX1MIX Input 1 Source */
+       { 0x00000958, 0x0000 }, /* R2392 (0x958) - DSP1AUX2MIX Input 1 Source */
+       { 0x00000960, 0x0000 }, /* R2400 (0x960) - DSP1AUX3MIX Input 1 Source */
+       { 0x00000968, 0x0000 }, /* R2408 (0x968) - DSP1AUX4MIX Input 1 Source */
+       { 0x00000970, 0x0000 }, /* R2416 (0x970) - DSP1AUX5MIX Input 1 Source */
+       { 0x00000978, 0x0000 }, /* R2424 (0x978) - DSP1AUX6MIX Input 1 Source */
+       { 0x00000980, 0x0000 }, /* R2432 (0x980) - DSP2LMIX Input 1 Source */
+       { 0x00000981, 0x0080 }, /* R2433 (0x981) - DSP2LMIX Input 1 Volume */
+       { 0x00000982, 0x0000 }, /* R2434 (0x982) - DSP2LMIX Input 2 Source */
+       { 0x00000983, 0x0080 }, /* R2435 (0x983) - DSP2LMIX Input 2 Volume */
+       { 0x00000984, 0x0000 }, /* R2436 (0x984) - DSP2LMIX Input 3 Source */
+       { 0x00000985, 0x0080 }, /* R2437 (0x985) - DSP2LMIX Input 3 Volume */
+       { 0x00000986, 0x0000 }, /* R2438 (0x986) - DSP2LMIX Input 4 Source */
+       { 0x00000987, 0x0080 }, /* R2439 (0x987) - DSP2LMIX Input 4 Volume */
+       { 0x00000988, 0x0000 }, /* R2440 (0x988) - DSP2RMIX Input 1 Source */
+       { 0x00000989, 0x0080 }, /* R2441 (0x989) - DSP2RMIX Input 1 Volume */
+       { 0x0000098a, 0x0000 }, /* R2442 (0x98a) - DSP2RMIX Input 2 Source */
+       { 0x0000098b, 0x0080 }, /* R2443 (0x98b) - DSP2RMIX Input 2 Volume */
+       { 0x0000098c, 0x0000 }, /* R2444 (0x98c) - DSP2RMIX Input 3 Source */
+       { 0x0000098d, 0x0080 }, /* R2445 (0x98d) - DSP2RMIX Input 3 Volume */
+       { 0x0000098e, 0x0000 }, /* R2446 (0x98e) - DSP2RMIX Input 4 Source */
+       { 0x0000098f, 0x0080 }, /* R2447 (0x98f) - DSP2RMIX Input 4 Volume */
+       { 0x00000990, 0x0000 }, /* R2448 (0x990) - DSP2AUX1MIX Input 1 Source */
+       { 0x00000998, 0x0000 }, /* R2456 (0x998) - DSP2AUX2MIX Input 1 Source */
+       { 0x000009a0, 0x0000 }, /* R2464 (0x9a0) - DSP2AUX3MIX Input 1 Source */
+       { 0x000009a8, 0x0000 }, /* R2472 (0x9a8) - DSP2AUX4MIX Input 1 Source */
+       { 0x000009b0, 0x0000 }, /* R2480 (0x9b0) - DSP2AUX5MIX Input 1 Source */
+       { 0x000009b8, 0x0000 }, /* R2488 (0x9b8) - DSP2AUX6MIX Input 1 Source */
+       { 0x000009c0, 0x0000 }, /* R2496 (0x9c0) - DSP3LMIX Input 1 Source */
+       { 0x000009c1, 0x0080 }, /* R2497 (0x9c1) - DSP3LMIX Input 1 Volume */
+       { 0x000009c2, 0x0000 }, /* R2498 (0x9c2) - DSP3LMIX Input 2 Source */
+       { 0x000009c3, 0x0080 }, /* R2499 (0x9c3) - DSP3LMIX Input 2 Volume */
+       { 0x000009c4, 0x0000 }, /* R2500 (0x9c4) - DSP3LMIX Input 3 Source */
+       { 0x000009c5, 0x0080 }, /* R2501 (0x9c5) - DSP3LMIX Input 3 Volume */
+       { 0x000009c6, 0x0000 }, /* R2502 (0x9c6) - DSP3LMIX Input 4 Source */
+       { 0x000009c7, 0x0080 }, /* R2503 (0x9c7) - DSP3LMIX Input 4 Volume */
+       { 0x000009c8, 0x0000 }, /* R2504 (0x9c8) - DSP3RMIX Input 1 Source */
+       { 0x000009c9, 0x0080 }, /* R2505 (0x9c9) - DSP3RMIX Input 1 Volume */
+       { 0x000009ca, 0x0000 }, /* R2506 (0x9ca) - DSP3RMIX Input 2 Source */
+       { 0x000009cb, 0x0080 }, /* R2507 (0x9cb) - DSP3RMIX Input 2 Volume */
+       { 0x000009cc, 0x0000 }, /* R2508 (0x9cc) - DSP3RMIX Input 3 Source */
+       { 0x000009cd, 0x0080 }, /* R2509 (0x9cd) - DSP3RMIX Input 3 Volume */
+       { 0x000009ce, 0x0000 }, /* R2510 (0x9ce) - DSP3RMIX Input 4 Source */
+       { 0x000009cf, 0x0080 }, /* R2511 (0x9cf) - DSP3RMIX Input 4 Volume */
+       { 0x000009d0, 0x0000 }, /* R2512 (0x9d0) - DSP3AUX1MIX Input 1 Source */
+       { 0x000009d8, 0x0000 }, /* R2520 (0x9d8) - DSP3AUX2MIX Input 1 Source */
+       { 0x000009e0, 0x0000 }, /* R2528 (0x9e0) - DSP3AUX3MIX Input 1 Source */
+       { 0x000009e8, 0x0000 }, /* R2536 (0x9e8) - DSP3AUX4MIX Input 1 Source */
+       { 0x000009f0, 0x0000 }, /* R2544 (0x9f0) - DSP3AUX5MIX Input 1 Source */
+       { 0x000009f8, 0x0000 }, /* R2552 (0x9f8) - DSP3AUX6MIX Input 1 Source */
+       { 0x00000b00, 0x0000 }, /* R2816 (0xb00) - ISRC1DEC1MIX Input 1 Source*/
+       { 0x00000b08, 0x0000 }, /* R2824 (0xb08) - ISRC1DEC2MIX Input 1 Source*/
+       { 0x00000b10, 0x0000 }, /* R2832 (0xb10) - ISRC1DEC3MIX Input 1 Source*/
+       { 0x00000b18, 0x0000 }, /* R2840 (0xb18) - ISRC1DEC4MIX Input 1 Source*/
+       { 0x00000b20, 0x0000 }, /* R2848 (0xb20) - ISRC1INT1MIX Input 1 Source*/
+       { 0x00000b28, 0x0000 }, /* R2856 (0xb28) - ISRC1INT2MIX Input 1 Source*/
+       { 0x00000b30, 0x0000 }, /* R2864 (0xb30) - ISRC1INT3MIX Input 1 Source*/
+       { 0x00000b38, 0x0000 }, /* R2872 (0xb38) - ISRC1INT4MIX Input 1 Source*/
+       { 0x00000b40, 0x0000 }, /* R2880 (0xb40) - ISRC2DEC1MIX Input 1 Source*/
+       { 0x00000b48, 0x0000 }, /* R2888 (0xb48) - ISRC2DEC2MIX Input 1 Source*/
+       { 0x00000b50, 0x0000 }, /* R2896 (0xb50) - ISRC2DEC3MIX Input 1 Source*/
+       { 0x00000b58, 0x0000 }, /* R2904 (0xb58) - ISRC2DEC4MIX Input 1 Source*/
+       { 0x00000b60, 0x0000 }, /* R2912 (0xb60) - ISRC2INT1MIX Input 1 Source*/
+       { 0x00000b68, 0x0000 }, /* R2920 (0xb68) - ISRC2INT2MIX Input 1 Source*/
+       { 0x00000b70, 0x0000 }, /* R2928 (0xb70) - ISRC2INT3MIX Input 1 Source*/
+       { 0x00000b78, 0x0000 }, /* R2936 (0xb78) - ISRC2INT4MIX Input 1 Source*/
+       { 0x00000e00, 0x0000 }, /* R3584 (0xe00) - FX Ctrl1 */
+       { 0x00000e10, 0x6318 }, /* R3600 (0xe10) - EQ1_1 */
+       { 0x00000e11, 0x6300 }, /* R3601 (0xe11) - EQ1_2 */
+       { 0x00000e12, 0x0fc8 }, /* R3602 (0xe12) - EQ1_3 */
+       { 0x00000e13, 0x03fe }, /* R3603 (0xe13) - EQ1_4 */
+       { 0x00000e14, 0x00e0 }, /* R3604 (0xe14) - EQ1_5 */
+       { 0x00000e15, 0x1ec4 }, /* R3605 (0xe15) - EQ1_6 */
+       { 0x00000e16, 0xf136 }, /* R3606 (0xe16) - EQ1_7 */
+       { 0x00000e17, 0x0409 }, /* R3607 (0xe17) - EQ1_8 */
+       { 0x00000e18, 0x04cc }, /* R3608 (0xe18) - EQ1_9 */
+       { 0x00000e19, 0x1c9b }, /* R3609 (0xe19) - EQ1_10 */
+       { 0x00000e1a, 0xf337 }, /* R3610 (0xe1a) - EQ1_11 */
+       { 0x00000e1b, 0x040b }, /* R3611 (0xe1b) - EQ1_12 */
+       { 0x00000e1c, 0x0cbb }, /* R3612 (0xe1c) - EQ1_13 */
+       { 0x00000e1d, 0x16f8 }, /* R3613 (0xe1d) - EQ1_14 */
+       { 0x00000e1e, 0xf7d9 }, /* R3614 (0xe1e) - EQ1_15 */
+       { 0x00000e1f, 0x040a }, /* R3615 (0xe1f) - EQ1_16 */
+       { 0x00000e20, 0x1f14 }, /* R3616 (0xe20) - EQ1_17 */
+       { 0x00000e21, 0x058c }, /* R3617 (0xe21) - EQ1_18 */
+       { 0x00000e22, 0x0563 }, /* R3618 (0xe22) - EQ1_19 */
+       { 0x00000e23, 0x4000 }, /* R3619 (0xe23) - EQ1_20 */
+       { 0x00000e24, 0x0b75 }, /* R3620 (0xe24) - EQ1_21 */
+       { 0x00000e26, 0x6318 }, /* R3622 (0xe26) - EQ2_1 */
+       { 0x00000e27, 0x6300 }, /* R3623 (0xe27) - EQ2_2 */
+       { 0x00000e28, 0x0fc8 }, /* R3624 (0xe28) - EQ2_3 */
+       { 0x00000e29, 0x03fe }, /* R3625 (0xe29) - EQ2_4 */
+       { 0x00000e2a, 0x00e0 }, /* R3626 (0xe2a) - EQ2_5 */
+       { 0x00000e2b, 0x1ec4 }, /* R3627 (0xe2b) - EQ2_6 */
+       { 0x00000e2c, 0xf136 }, /* R3628 (0xe2c) - EQ2_7 */
+       { 0x00000e2d, 0x0409 }, /* R3629 (0xe2d) - EQ2_8 */
+       { 0x00000e2e, 0x04cc }, /* R3630 (0xe2e) - EQ2_9 */
+       { 0x00000e2f, 0x1c9b }, /* R3631 (0xe2f) - EQ2_10 */
+       { 0x00000e30, 0xf337 }, /* R3632 (0xe30) - EQ2_11 */
+       { 0x00000e31, 0x040b }, /* R3633 (0xe31) - EQ2_12 */
+       { 0x00000e32, 0x0cbb }, /* R3634 (0xe32) - EQ2_13 */
+       { 0x00000e33, 0x16f8 }, /* R3635 (0xe33) - EQ2_14 */
+       { 0x00000e34, 0xf7d9 }, /* R3636 (0xe34) - EQ2_15 */
+       { 0x00000e35, 0x040a }, /* R3637 (0xe35) - EQ2_16 */
+       { 0x00000e36, 0x1f14 }, /* R3638 (0xe36) - EQ2_17 */
+       { 0x00000e37, 0x058c }, /* R3639 (0xe37) - EQ2_18 */
+       { 0x00000e38, 0x0563 }, /* R3640 (0xe38) - EQ2_19 */
+       { 0x00000e39, 0x4000 }, /* R3641 (0xe39) - EQ2_20 */
+       { 0x00000e3a, 0x0b75 }, /* R3642 (0xe3a) - EQ2_21 */
+       { 0x00000e3c, 0x6318 }, /* R3644 (0xe3c) - EQ3_1 */
+       { 0x00000e3d, 0x6300 }, /* R3645 (0xe3d) - EQ3_2 */
+       { 0x00000e3e, 0x0fc8 }, /* R3646 (0xe3e) - EQ3_3 */
+       { 0x00000e3f, 0x03fe }, /* R3647 (0xe3f) - EQ3_4 */
+       { 0x00000e40, 0x00e0 }, /* R3648 (0xe40) - EQ3_5 */
+       { 0x00000e41, 0x1ec4 }, /* R3649 (0xe41) - EQ3_6 */
+       { 0x00000e42, 0xf136 }, /* R3650 (0xe42) - EQ3_7 */
+       { 0x00000e43, 0x0409 }, /* R3651 (0xe43) - EQ3_8 */
+       { 0x00000e44, 0x04cc }, /* R3652 (0xe44) - EQ3_9 */
+       { 0x00000e45, 0x1c9b }, /* R3653 (0xe45) - EQ3_10 */
+       { 0x00000e46, 0xf337 }, /* R3654 (0xe46) - EQ3_11 */
+       { 0x00000e47, 0x040b }, /* R3655 (0xe47) - EQ3_12 */
+       { 0x00000e48, 0x0cbb }, /* R3656 (0xe48) - EQ3_13 */
+       { 0x00000e49, 0x16f8 }, /* R3657 (0xe49) - EQ3_14 */
+       { 0x00000e4a, 0xf7d9 }, /* R3658 (0xe4a) - EQ3_15 */
+       { 0x00000e4b, 0x040a }, /* R3659 (0xe4b) - EQ3_16 */
+       { 0x00000e4c, 0x1f14 }, /* R3660 (0xe4c) - EQ3_17 */
+       { 0x00000e4d, 0x058c }, /* R3661 (0xe4d) - EQ3_18 */
+       { 0x00000e4e, 0x0563 }, /* R3662 (0xe4e) - EQ3_19 */
+       { 0x00000e4f, 0x4000 }, /* R3663 (0xe4f) - EQ3_20 */
+       { 0x00000e50, 0x0b75 }, /* R3664 (0xe50) - EQ3_21 */
+       { 0x00000e52, 0x6318 }, /* R3666 (0xe52) - EQ4_1 */
+       { 0x00000e53, 0x6300 }, /* R3667 (0xe53) - EQ4_2 */
+       { 0x00000e54, 0x0fc8 }, /* R3668 (0xe54) - EQ4_3 */
+       { 0x00000e55, 0x03fe }, /* R3669 (0xe55) - EQ4_4 */
+       { 0x00000e56, 0x00e0 }, /* R3670 (0xe56) - EQ4_5 */
+       { 0x00000e57, 0x1ec4 }, /* R3671 (0xe57) - EQ4_6 */
+       { 0x00000e58, 0xf136 }, /* R3672 (0xe58) - EQ4_7 */
+       { 0x00000e59, 0x0409 }, /* R3673 (0xe59) - EQ4_8 */
+       { 0x00000e5a, 0x04cc }, /* R3674 (0xe5a) - EQ4_9 */
+       { 0x00000e5b, 0x1c9b }, /* R3675 (0xe5b) - EQ4_10 */
+       { 0x00000e5c, 0xf337 }, /* R3676 (0xe5c) - EQ4_11 */
+       { 0x00000e5d, 0x040b }, /* R3677 (0xe5d) - EQ4_12 */
+       { 0x00000e5e, 0x0cbb }, /* R3678 (0xe5e) - EQ4_13 */
+       { 0x00000e5f, 0x16f8 }, /* R3679 (0xe5f) - EQ4_14 */
+       { 0x00000e60, 0xf7d9 }, /* R3680 (0xe60) - EQ4_15 */
+       { 0x00000e61, 0x040a }, /* R3681 (0xe61) - EQ4_16 */
+       { 0x00000e62, 0x1f14 }, /* R3682 (0xe62) - EQ4_17 */
+       { 0x00000e63, 0x058c }, /* R3683 (0xe63) - EQ4_18 */
+       { 0x00000e64, 0x0563 }, /* R3684 (0xe64) - EQ4_19 */
+       { 0x00000e65, 0x4000 }, /* R3685 (0xe65) - EQ4_20 */
+       { 0x00000e66, 0x0b75 }, /* R3686 (0xe66) - EQ4_21 */
+       { 0x00000e80, 0x0018 }, /* R3712 (0xe80) - DRC1 ctrl1 */
+       { 0x00000e81, 0x0933 }, /* R3713 (0xe81) - DRC1 ctrl2 */
+       { 0x00000e82, 0x0018 }, /* R3714 (0xe82) - DRC1 ctrl3 */
+       { 0x00000e83, 0x0000 }, /* R3715 (0xe83) - DRC1 ctrl4 */
+       { 0x00000e84, 0x0000 }, /* R3716 (0xe84) - DRC1 ctrl5 */
+       { 0x00000e88, 0x0018 }, /* R3720 (0xe88) - DRC2 ctrl1 */
+       { 0x00000e89, 0x0933 }, /* R3721 (0xe89) - DRC2 ctrl2 */
+       { 0x00000e8a, 0x0018 }, /* R3722 (0xe8a) - DRC2 ctrl3 */
+       { 0x00000e8b, 0x0000 }, /* R3723 (0xe8b) - DRC2 ctrl4 */
+       { 0x00000e8c, 0x0000 }, /* R3724 (0xe8c) - DRC2 ctrl5 */
+       { 0x00000ec0, 0x0000 }, /* R3776 (0xec0) - HPLPF1_1 */
+       { 0x00000ec1, 0x0000 }, /* R3777 (0xec1) - HPLPF1_2 */
+       { 0x00000ec4, 0x0000 }, /* R3780 (0xec4) - HPLPF2_1 */
+       { 0x00000ec5, 0x0000 }, /* R3781 (0xec5) - HPLPF2_2 */
+       { 0x00000ec8, 0x0000 }, /* R3784 (0xec8) - HPLPF3_1 */
+       { 0x00000ec9, 0x0000 }, /* R3785 (0xec9) - HPLPF3_2 */
+       { 0x00000ecc, 0x0000 }, /* R3788 (0xecc) - HPLPF4_1 */
+       { 0x00000ecd, 0x0000 }, /* R3789 (0xecd) - HPLPF4_2 */
+       { 0x00000ef0, 0x0000 }, /* R3824 (0xef0) - ISRC 1 CTRL 1 */
+       { 0x00000ef1, 0x0001 }, /* R3825 (0xef1) - ISRC 1 CTRL 2 */
+       { 0x00000ef2, 0x0000 }, /* R3826 (0xef2) - ISRC 1 CTRL 3 */
+       { 0x00000ef3, 0x0000 }, /* R3827 (0xef3) - ISRC 2 CTRL 1 */
+       { 0x00000ef4, 0x0001 }, /* R3828 (0xef4) - ISRC 2 CTRL 2 */
+       { 0x00000ef5, 0x0000 }, /* R3829 (0xef5) - ISRC 2 CTRL 3 */
+       { 0x00001300, 0x0000 }, /* R4864 (0x1300) - DAC Comp 1 */
+       { 0x00001302, 0x0000 }, /* R4866 (0x1302) - DAC Comp 2 */
+       { 0x00001380, 0x0000 }, /* R4992 (0x1380) - FRF Coefficient 1L 1 */
+       { 0x00001381, 0x0000 }, /* R4993 (0x1381) - FRF Coefficient 1L 2 */
+       { 0x00001382, 0x0000 }, /* R4994 (0x1382) - FRF Coefficient 1L 3 */
+       { 0x00001383, 0x0000 }, /* R4995 (0x1383) - FRF Coefficient 1L 4 */
+       { 0x00001390, 0x0000 }, /* R5008 (0x1390) - FRF Coefficient 1R 1 */
+       { 0x00001391, 0x0000 }, /* R5009 (0x1391) - FRF Coefficient 1R 2 */
+       { 0x00001392, 0x0000 }, /* R5010 (0x1392) - FRF Coefficient 1R 3 */
+       { 0x00001393, 0x0000 }, /* R5011 (0x1393) - FRF Coefficient 1R 4 */
+       { 0x000013a0, 0x0000 }, /* R5024 (0x13a0) - FRF Coefficient 4L 1 */
+       { 0x000013a1, 0x0000 }, /* R5025 (0x13a1) - FRF Coefficient 4L 2 */
+       { 0x000013a2, 0x0000 }, /* R5026 (0x13a2) - FRF Coefficient 4L 3 */
+       { 0x000013a3, 0x0000 }, /* R5027 (0x13a3) - FRF Coefficient 4L 4 */
+       { 0x000013b0, 0x0000 }, /* R5040 (0x13b0) - FRF Coefficient 5L 1 */
+       { 0x000013b1, 0x0000 }, /* R5041 (0x13b1) - FRF Coefficient 5L 2 */
+       { 0x000013b2, 0x0000 }, /* R5042 (0x13b2) - FRF Coefficient 5L 3 */
+       { 0x000013b3, 0x0000 }, /* R5043 (0x13b3) - FRF Coefficient 5L 4 */
+       { 0x000013c0, 0x0000 }, /* R5040 (0x13c0) - FRF Coefficient 5R 1 */
+       { 0x000013c1, 0x0000 }, /* R5041 (0x13c1) - FRF Coefficient 5R 2 */
+       { 0x000013c2, 0x0000 }, /* R5042 (0x13c2) - FRF Coefficient 5R 3 */
+       { 0x000013c3, 0x0000 }, /* R5043 (0x13c3) - FRF Coefficient 5R 4 */
+       { 0x00001700, 0x2001 }, /* R5888 (0x1700) - GPIO1 Control 1 */
+       { 0x00001701, 0xf000 }, /* R5889 (0x1701) - GPIO1 Control 2 */
+       { 0x00001702, 0x2001 }, /* R5890 (0x1702) - GPIO2 Control 1 */
+       { 0x00001703, 0xf000 }, /* R5891 (0x1703) - GPIO2 Control 2 */
+       { 0x00001704, 0x2001 }, /* R5892 (0x1704) - GPIO3 Control 1 */
+       { 0x00001705, 0xf000 }, /* R5893 (0x1705) - GPIO3 Control 2 */
+       { 0x00001706, 0x2001 }, /* R5894 (0x1706) - GPIO4 Control 1 */
+       { 0x00001707, 0xf000 }, /* R5895 (0x1707) - GPIO4 Control 2 */
+       { 0x00001708, 0x2001 }, /* R5896 (0x1708) - GPIO5 Control 1 */
+       { 0x00001709, 0xf000 }, /* R5897 (0x1709) - GPIO5 Control 2 */
+       { 0x0000170a, 0x2001 }, /* R5898 (0x170a) - GPIO6 Control 1 */
+       { 0x0000170b, 0xf000 }, /* R5899 (0x170b) - GPIO6 Control 2 */
+       { 0x0000170c, 0x2001 }, /* R5900 (0x170c) - GPIO7 Control 1 */
+       { 0x0000170d, 0xf000 }, /* R5901 (0x170d) - GPIO7 Control 2 */
+       { 0x0000170e, 0x2001 }, /* R5902 (0x170e) - GPIO8 Control 1 */
+       { 0x0000170f, 0xf000 }, /* R5903 (0x170f) - GPIO8 Control 2 */
+       { 0x00001710, 0x2001 }, /* R5904 (0x1710) - GPIO9 Control 1 */
+       { 0x00001711, 0xf000 }, /* R5905 (0x1711) - GPIO9 Control 2 */
+       { 0x00001712, 0x2001 }, /* R5906 (0x1712) - GPIO10 Control 1 */
+       { 0x00001713, 0xf000 }, /* R5907 (0x1713) - GPIO10 Control 2 */
+       { 0x00001714, 0x2001 }, /* R5908 (0x1714) - GPIO11 Control 1 */
+       { 0x00001715, 0xf000 }, /* R5909 (0x1715) - GPIO11 Control 2 */
+       { 0x00001716, 0x2001 }, /* R5910 (0x1716) - GPIO12 Control 1 */
+       { 0x00001717, 0xf000 }, /* R5911 (0x1717) - GPIO12 Control 2 */
+       { 0x00001718, 0x2001 }, /* R5912 (0x1718) - GPIO13 Control 1 */
+       { 0x00001719, 0xf000 }, /* R5913 (0x1719) - GPIO13 Control 2 */
+       { 0x0000171a, 0x2001 }, /* R5914 (0x171a) - GPIO14 Control 1 */
+       { 0x0000171b, 0xf000 }, /* R5915 (0x171b) - GPIO14 Control 2 */
+       { 0x0000171c, 0x2001 }, /* R5916 (0x171c) - GPIO15 Control 1 */
+       { 0x0000171d, 0xf000 }, /* R5917 (0x171d) - GPIO15 Control 2 */
+       { 0x0000171e, 0x2001 }, /* R5918 (0x171e) - GPIO16 Control 1 */
+       { 0x0000171f, 0xf000 }, /* R5919 (0x171f) - GPIO16 Control 2 */
+       { 0x00001840, 0xffff }, /* R6208 (0x1840) - IRQ1 Mask 1 */
+       { 0x00001841, 0xffff }, /* R6209 (0x1841) - IRQ1 Mask 2 */
+       { 0x00001842, 0xffff }, /* R6210 (0x1842) - IRQ1 Mask 3 */
+       { 0x00001843, 0xffff }, /* R6211 (0x1843) - IRQ1 Mask 4 */
+       { 0x00001844, 0xffff }, /* R6212 (0x1844) - IRQ1 Mask 5 */
+       { 0x00001845, 0xffff }, /* R6213 (0x1845) - IRQ1 Mask 6 */
+       { 0x00001846, 0xffff }, /* R6214 (0x1846) - IRQ1 Mask 7 */
+       { 0x00001847, 0xffff }, /* R6215 (0x1847) - IRQ1 Mask 8 */
+       { 0x00001848, 0xffff }, /* R6216 (0x1848) - IRQ1 Mask 9 */
+       { 0x00001849, 0xffff }, /* R6217 (0x1849) - IRQ1 Mask 10 */
+       { 0x0000184a, 0xffff }, /* R6218 (0x184a) - IRQ1 Mask 11 */
+       { 0x0000184b, 0xffff }, /* R6219 (0x184b) - IRQ1 Mask 12 */
+       { 0x0000184c, 0xffff }, /* R6220 (0x184c) - IRQ1 Mask 13 */
+       { 0x0000184d, 0xffff }, /* R6221 (0x184d) - IRQ1 Mask 14 */
+       { 0x0000184e, 0xffff }, /* R6222 (0x184e) - IRQ1 Mask 15 */
+       { 0x0000184f, 0xffff }, /* R6223 (0x184f) - IRQ1 Mask 16 */
+       { 0x00001850, 0xffff }, /* R6224 (0x1850) - IRQ1 Mask 17 */
+       { 0x00001851, 0xffff }, /* R6225 (0x1851) - IRQ1 Mask 18 */
+       { 0x00001852, 0xffff }, /* R6226 (0x1852) - IRQ1 Mask 19 */
+       { 0x00001853, 0xffff }, /* R6227 (0x1853) - IRQ1 Mask 20 */
+       { 0x00001854, 0xffff }, /* R6228 (0x1854) - IRQ1 Mask 21 */
+       { 0x00001855, 0xffff }, /* R6229 (0x1855) - IRQ1 Mask 22 */
+       { 0x00001856, 0xffff }, /* R6230 (0x1856) - IRQ1 Mask 23 */
+       { 0x00001857, 0xffff }, /* R6231 (0x1857) - IRQ1 Mask 24 */
+       { 0x00001858, 0xffff }, /* R6232 (0x1858) - IRQ1 Mask 25 */
+       { 0x00001859, 0xffff }, /* R6233 (0x1859) - IRQ1 Mask 26 */
+       { 0x0000185a, 0xffff }, /* R6234 (0x185a) - IRQ1 Mask 27 */
+       { 0x0000185b, 0xffff }, /* R6235 (0x185b) - IRQ1 Mask 28 */
+       { 0x0000185c, 0xffff }, /* R6236 (0x185c) - IRQ1 Mask 29 */
+       { 0x0000185d, 0xffff }, /* R6237 (0x185d) - IRQ1 Mask 30 */
+       { 0x0000185e, 0xffff }, /* R6238 (0x185e) - IRQ1 Mask 31 */
+       { 0x0000185f, 0xffff }, /* R6239 (0x185f) - IRQ1 Mask 32 */
+       { 0x00001860, 0xffff }, /* R6240 (0x1860) - IRQ1 Mask 33 */
+       { 0x00001a06, 0x0000 }, /* R6662 (0x1a06) - Interrupt Debounce 7 */
+       { 0x00001a80, 0x4400 }, /* R6784 (0x1a80) - IRQ1 CTRL */
+};
+
+static bool cs47l35_is_adsp_memory(unsigned int reg)
+{
+       switch (reg) {
+       case 0x080000 ... 0x085ffe:
+       case 0x0a0000 ... 0x0a7ffe:
+       case 0x0c0000 ... 0x0c1ffe:
+       case 0x0e0000 ... 0x0e1ffe:
+       case 0x100000 ... 0x10effe:
+       case 0x120000 ... 0x12bffe:
+       case 0x136000 ... 0x137ffe:
+       case 0x140000 ... 0x14bffe:
+       case 0x160000 ... 0x161ffe:
+       case 0x180000 ... 0x18effe:
+       case 0x1a0000 ... 0x1b1ffe:
+       case 0x1b6000 ... 0x1b7ffe:
+       case 0x1c0000 ... 0x1cbffe:
+       case 0x1e0000 ... 0x1e1ffe:
+               return true;
+       default:
+               return false;
+       }
+}
+
+static bool cs47l35_16bit_readable_register(struct device *dev,
+                                           unsigned int reg)
+{
+       switch (reg) {
+       case MADERA_SOFTWARE_RESET:
+       case MADERA_HARDWARE_REVISION:
+       case MADERA_WRITE_SEQUENCER_CTRL_0:
+       case MADERA_WRITE_SEQUENCER_CTRL_1:
+       case MADERA_WRITE_SEQUENCER_CTRL_2:
+       case MADERA_TONE_GENERATOR_1:
+       case MADERA_TONE_GENERATOR_2:
+       case MADERA_TONE_GENERATOR_3:
+       case MADERA_TONE_GENERATOR_4:
+       case MADERA_TONE_GENERATOR_5:
+       case MADERA_PWM_DRIVE_1:
+       case MADERA_PWM_DRIVE_2:
+       case MADERA_PWM_DRIVE_3:
+       case MADERA_SAMPLE_RATE_SEQUENCE_SELECT_1:
+       case MADERA_SAMPLE_RATE_SEQUENCE_SELECT_2:
+       case MADERA_SAMPLE_RATE_SEQUENCE_SELECT_3:
+       case MADERA_SAMPLE_RATE_SEQUENCE_SELECT_4:
+       case MADERA_ALWAYS_ON_TRIGGERS_SEQUENCE_SELECT_1:
+       case MADERA_ALWAYS_ON_TRIGGERS_SEQUENCE_SELECT_2:
+       case MADERA_HAPTICS_CONTROL_1:
+       case MADERA_HAPTICS_CONTROL_2:
+       case MADERA_HAPTICS_PHASE_1_INTENSITY:
+       case MADERA_HAPTICS_PHASE_1_DURATION:
+       case MADERA_HAPTICS_PHASE_2_INTENSITY:
+       case MADERA_HAPTICS_PHASE_2_DURATION:
+       case MADERA_HAPTICS_PHASE_3_INTENSITY:
+       case MADERA_HAPTICS_PHASE_3_DURATION:
+       case MADERA_HAPTICS_STATUS:
+       case MADERA_COMFORT_NOISE_GENERATOR:
+       case MADERA_CLOCK_32K_1:
+       case MADERA_SYSTEM_CLOCK_1:
+       case MADERA_SAMPLE_RATE_1:
+       case MADERA_SAMPLE_RATE_2:
+       case MADERA_SAMPLE_RATE_3:
+       case MADERA_SAMPLE_RATE_1_STATUS:
+       case MADERA_SAMPLE_RATE_2_STATUS:
+       case MADERA_SAMPLE_RATE_3_STATUS:
+       case MADERA_DSP_CLOCK_1:
+       case MADERA_DSP_CLOCK_2:
+       case MADERA_OUTPUT_SYSTEM_CLOCK:
+       case MADERA_OUTPUT_ASYNC_CLOCK:
+       case MADERA_RATE_ESTIMATOR_1:
+       case MADERA_RATE_ESTIMATOR_2:
+       case MADERA_RATE_ESTIMATOR_3:
+       case MADERA_RATE_ESTIMATOR_4:
+       case MADERA_RATE_ESTIMATOR_5:
+       case MADERA_FLL1_CONTROL_1:
+       case MADERA_FLL1_CONTROL_2:
+       case MADERA_FLL1_CONTROL_3:
+       case MADERA_FLL1_CONTROL_4:
+       case MADERA_FLL1_CONTROL_5:
+       case MADERA_FLL1_CONTROL_6:
+       case MADERA_FLL1_CONTROL_7:
+       case MADERA_FLL1_EFS_2:
+       case MADERA_FLL1_LOOP_FILTER_TEST_1:
+       case CS47L35_FLL1_SYNCHRONISER_1:
+       case CS47L35_FLL1_SYNCHRONISER_2:
+       case CS47L35_FLL1_SYNCHRONISER_3:
+       case CS47L35_FLL1_SYNCHRONISER_4:
+       case CS47L35_FLL1_SYNCHRONISER_5:
+       case CS47L35_FLL1_SYNCHRONISER_6:
+       case CS47L35_FLL1_SYNCHRONISER_7:
+       case CS47L35_FLL1_SPREAD_SPECTRUM:
+       case CS47L35_FLL1_GPIO_CLOCK:
+       case MADERA_MIC_CHARGE_PUMP_1:
+       case MADERA_HP_CHARGE_PUMP_8:
+       case MADERA_LDO2_CONTROL_1:
+       case MADERA_MIC_BIAS_CTRL_1:
+       case MADERA_MIC_BIAS_CTRL_2:
+       case MADERA_MIC_BIAS_CTRL_5:
+       case MADERA_MIC_BIAS_CTRL_6:
+       case MADERA_HP_CTRL_1L:
+       case MADERA_HP_CTRL_1R:
+       case MADERA_DCS_HP1L_CONTROL:
+       case MADERA_DCS_HP1R_CONTROL:
+       case MADERA_EDRE_HP_STEREO_CONTROL:
+       case MADERA_ACCESSORY_DETECT_MODE_1:
+       case MADERA_HEADPHONE_DETECT_1:
+       case MADERA_HEADPHONE_DETECT_2:
+       case MADERA_HEADPHONE_DETECT_3:
+       case MADERA_HEADPHONE_DETECT_5:
+       case MADERA_MICD_CLAMP_CONTROL:
+       case MADERA_MIC_DETECT_1_CONTROL_1:
+       case MADERA_MIC_DETECT_1_CONTROL_2:
+       case MADERA_MIC_DETECT_1_CONTROL_3:
+       case MADERA_MIC_DETECT_1_LEVEL_1:
+       case MADERA_MIC_DETECT_1_LEVEL_2:
+       case MADERA_MIC_DETECT_1_LEVEL_3:
+       case MADERA_MIC_DETECT_1_LEVEL_4:
+       case MADERA_MIC_DETECT_1_CONTROL_4:
+       case MADERA_GP_SWITCH_1:
+       case MADERA_JACK_DETECT_ANALOGUE:
+       case MADERA_INPUT_ENABLES:
+       case MADERA_INPUT_ENABLES_STATUS:
+       case MADERA_INPUT_RATE:
+       case MADERA_INPUT_VOLUME_RAMP:
+       case MADERA_HPF_CONTROL:
+       case MADERA_IN1L_CONTROL:
+       case MADERA_ADC_DIGITAL_VOLUME_1L:
+       case MADERA_DMIC1L_CONTROL:
+       case MADERA_IN1R_CONTROL:
+       case MADERA_ADC_DIGITAL_VOLUME_1R:
+       case MADERA_DMIC1R_CONTROL:
+       case MADERA_IN2L_CONTROL:
+       case MADERA_ADC_DIGITAL_VOLUME_2L:
+       case MADERA_DMIC2L_CONTROL:
+       case MADERA_IN2R_CONTROL:
+       case MADERA_ADC_DIGITAL_VOLUME_2R:
+       case MADERA_DMIC2R_CONTROL:
+       case MADERA_OUTPUT_ENABLES_1:
+       case MADERA_OUTPUT_STATUS_1:
+       case MADERA_RAW_OUTPUT_STATUS_1:
+       case MADERA_OUTPUT_RATE_1:
+       case MADERA_OUTPUT_VOLUME_RAMP:
+       case MADERA_OUTPUT_PATH_CONFIG_1L:
+       case MADERA_DAC_DIGITAL_VOLUME_1L:
+       case MADERA_NOISE_GATE_SELECT_1L:
+       case MADERA_OUTPUT_PATH_CONFIG_1R:
+       case MADERA_DAC_DIGITAL_VOLUME_1R:
+       case MADERA_NOISE_GATE_SELECT_1R:
+       case MADERA_OUTPUT_PATH_CONFIG_4L:
+       case MADERA_DAC_DIGITAL_VOLUME_4L:
+       case MADERA_NOISE_GATE_SELECT_4L:
+       case MADERA_OUTPUT_PATH_CONFIG_5L:
+       case MADERA_DAC_DIGITAL_VOLUME_5L:
+       case MADERA_NOISE_GATE_SELECT_5L:
+       case MADERA_OUTPUT_PATH_CONFIG_5R:
+       case MADERA_DAC_DIGITAL_VOLUME_5R:
+       case MADERA_NOISE_GATE_SELECT_5R:
+       case MADERA_DRE_ENABLE:
+       case MADERA_EDRE_ENABLE:
+       case MADERA_EDRE_MANUAL:
+       case MADERA_DAC_AEC_CONTROL_1:
+       case MADERA_NOISE_GATE_CONTROL:
+       case MADERA_PDM_SPK1_CTRL_1:
+       case MADERA_PDM_SPK1_CTRL_2:
+       case MADERA_HP1_SHORT_CIRCUIT_CTRL:
+       case MADERA_HP_TEST_CTRL_5:
+       case MADERA_HP_TEST_CTRL_6:
+       case MADERA_AIF1_BCLK_CTRL:
+       case MADERA_AIF1_TX_PIN_CTRL:
+       case MADERA_AIF1_RX_PIN_CTRL:
+       case MADERA_AIF1_RATE_CTRL:
+       case MADERA_AIF1_FORMAT:
+       case MADERA_AIF1_RX_BCLK_RATE:
+       case MADERA_AIF1_FRAME_CTRL_1:
+       case MADERA_AIF1_FRAME_CTRL_2:
+       case MADERA_AIF1_FRAME_CTRL_3:
+       case MADERA_AIF1_FRAME_CTRL_4:
+       case MADERA_AIF1_FRAME_CTRL_5:
+       case MADERA_AIF1_FRAME_CTRL_6:
+       case MADERA_AIF1_FRAME_CTRL_7:
+       case MADERA_AIF1_FRAME_CTRL_8:
+       case MADERA_AIF1_FRAME_CTRL_11:
+       case MADERA_AIF1_FRAME_CTRL_12:
+       case MADERA_AIF1_FRAME_CTRL_13:
+       case MADERA_AIF1_FRAME_CTRL_14:
+       case MADERA_AIF1_FRAME_CTRL_15:
+       case MADERA_AIF1_FRAME_CTRL_16:
+       case MADERA_AIF1_TX_ENABLES:
+       case MADERA_AIF1_RX_ENABLES:
+       case MADERA_AIF2_BCLK_CTRL:
+       case MADERA_AIF2_TX_PIN_CTRL:
+       case MADERA_AIF2_RX_PIN_CTRL:
+       case MADERA_AIF2_RATE_CTRL:
+       case MADERA_AIF2_FORMAT:
+       case MADERA_AIF2_RX_BCLK_RATE:
+       case MADERA_AIF2_FRAME_CTRL_1:
+       case MADERA_AIF2_FRAME_CTRL_2:
+       case MADERA_AIF2_FRAME_CTRL_3:
+       case MADERA_AIF2_FRAME_CTRL_4:
+       case MADERA_AIF2_FRAME_CTRL_11:
+       case MADERA_AIF2_FRAME_CTRL_12:
+       case MADERA_AIF2_TX_ENABLES:
+       case MADERA_AIF2_RX_ENABLES:
+       case MADERA_AIF3_BCLK_CTRL:
+       case MADERA_AIF3_TX_PIN_CTRL:
+       case MADERA_AIF3_RX_PIN_CTRL:
+       case MADERA_AIF3_RATE_CTRL:
+       case MADERA_AIF3_FORMAT:
+       case MADERA_AIF3_RX_BCLK_RATE:
+       case MADERA_AIF3_FRAME_CTRL_1:
+       case MADERA_AIF3_FRAME_CTRL_2:
+       case MADERA_AIF3_FRAME_CTRL_3:
+       case MADERA_AIF3_FRAME_CTRL_4:
+       case MADERA_AIF3_FRAME_CTRL_11:
+       case MADERA_AIF3_FRAME_CTRL_12:
+       case MADERA_AIF3_TX_ENABLES:
+       case MADERA_AIF3_RX_ENABLES:
+       case MADERA_SPD1_TX_CONTROL:
+       case MADERA_SPD1_TX_CHANNEL_STATUS_1:
+       case MADERA_SPD1_TX_CHANNEL_STATUS_2:
+       case MADERA_SPD1_TX_CHANNEL_STATUS_3:
+       case MADERA_SLIMBUS_FRAMER_REF_GEAR:
+       case MADERA_SLIMBUS_RATES_1:
+       case MADERA_SLIMBUS_RATES_2:
+       case MADERA_SLIMBUS_RATES_3:
+       case MADERA_SLIMBUS_RATES_5:
+       case MADERA_SLIMBUS_RATES_6:
+       case MADERA_SLIMBUS_RATES_7:
+       case MADERA_SLIMBUS_RX_CHANNEL_ENABLE:
+       case MADERA_SLIMBUS_TX_CHANNEL_ENABLE:
+       case MADERA_SLIMBUS_RX_PORT_STATUS:
+       case MADERA_SLIMBUS_TX_PORT_STATUS:
+       case MADERA_PWM1MIX_INPUT_1_SOURCE:
+       case MADERA_PWM1MIX_INPUT_1_VOLUME:
+       case MADERA_PWM1MIX_INPUT_2_SOURCE:
+       case MADERA_PWM1MIX_INPUT_2_VOLUME:
+       case MADERA_PWM1MIX_INPUT_3_SOURCE:
+       case MADERA_PWM1MIX_INPUT_3_VOLUME:
+       case MADERA_PWM1MIX_INPUT_4_SOURCE:
+       case MADERA_PWM1MIX_INPUT_4_VOLUME:
+       case MADERA_PWM2MIX_INPUT_1_SOURCE:
+       case MADERA_PWM2MIX_INPUT_1_VOLUME:
+       case MADERA_PWM2MIX_INPUT_2_SOURCE:
+       case MADERA_PWM2MIX_INPUT_2_VOLUME:
+       case MADERA_PWM2MIX_INPUT_3_SOURCE:
+       case MADERA_PWM2MIX_INPUT_3_VOLUME:
+       case MADERA_PWM2MIX_INPUT_4_SOURCE:
+       case MADERA_PWM2MIX_INPUT_4_VOLUME:
+       case MADERA_OUT1LMIX_INPUT_1_SOURCE:
+       case MADERA_OUT1LMIX_INPUT_1_VOLUME:
+       case MADERA_OUT1LMIX_INPUT_2_SOURCE:
+       case MADERA_OUT1LMIX_INPUT_2_VOLUME:
+       case MADERA_OUT1LMIX_INPUT_3_SOURCE:
+       case MADERA_OUT1LMIX_INPUT_3_VOLUME:
+       case MADERA_OUT1LMIX_INPUT_4_SOURCE:
+       case MADERA_OUT1LMIX_INPUT_4_VOLUME:
+       case MADERA_OUT1RMIX_INPUT_1_SOURCE:
+       case MADERA_OUT1RMIX_INPUT_1_VOLUME:
+       case MADERA_OUT1RMIX_INPUT_2_SOURCE:
+       case MADERA_OUT1RMIX_INPUT_2_VOLUME:
+       case MADERA_OUT1RMIX_INPUT_3_SOURCE:
+       case MADERA_OUT1RMIX_INPUT_3_VOLUME:
+       case MADERA_OUT1RMIX_INPUT_4_SOURCE:
+       case MADERA_OUT1RMIX_INPUT_4_VOLUME:
+       case MADERA_OUT4LMIX_INPUT_1_SOURCE:
+       case MADERA_OUT4LMIX_INPUT_1_VOLUME:
+       case MADERA_OUT4LMIX_INPUT_2_SOURCE:
+       case MADERA_OUT4LMIX_INPUT_2_VOLUME:
+       case MADERA_OUT4LMIX_INPUT_3_SOURCE:
+       case MADERA_OUT4LMIX_INPUT_3_VOLUME:
+       case MADERA_OUT4LMIX_INPUT_4_SOURCE:
+       case MADERA_OUT4LMIX_INPUT_4_VOLUME:
+       case MADERA_OUT5LMIX_INPUT_1_SOURCE:
+       case MADERA_OUT5LMIX_INPUT_1_VOLUME:
+       case MADERA_OUT5LMIX_INPUT_2_SOURCE:
+       case MADERA_OUT5LMIX_INPUT_2_VOLUME:
+       case MADERA_OUT5LMIX_INPUT_3_SOURCE:
+       case MADERA_OUT5LMIX_INPUT_3_VOLUME:
+       case MADERA_OUT5LMIX_INPUT_4_SOURCE:
+       case MADERA_OUT5LMIX_INPUT_4_VOLUME:
+       case MADERA_OUT5RMIX_INPUT_1_SOURCE:
+       case MADERA_OUT5RMIX_INPUT_1_VOLUME:
+       case MADERA_OUT5RMIX_INPUT_2_SOURCE:
+       case MADERA_OUT5RMIX_INPUT_2_VOLUME:
+       case MADERA_OUT5RMIX_INPUT_3_SOURCE:
+       case MADERA_OUT5RMIX_INPUT_3_VOLUME:
+       case MADERA_OUT5RMIX_INPUT_4_SOURCE:
+       case MADERA_OUT5RMIX_INPUT_4_VOLUME:
+       case MADERA_AIF1TX1MIX_INPUT_1_SOURCE:
+       case MADERA_AIF1TX1MIX_INPUT_1_VOLUME:
+       case MADERA_AIF1TX1MIX_INPUT_2_SOURCE:
+       case MADERA_AIF1TX1MIX_INPUT_2_VOLUME:
+       case MADERA_AIF1TX1MIX_INPUT_3_SOURCE:
+       case MADERA_AIF1TX1MIX_INPUT_3_VOLUME:
+       case MADERA_AIF1TX1MIX_INPUT_4_SOURCE:
+       case MADERA_AIF1TX1MIX_INPUT_4_VOLUME:
+       case MADERA_AIF1TX2MIX_INPUT_1_SOURCE:
+       case MADERA_AIF1TX2MIX_INPUT_1_VOLUME:
+       case MADERA_AIF1TX2MIX_INPUT_2_SOURCE:
+       case MADERA_AIF1TX2MIX_INPUT_2_VOLUME:
+       case MADERA_AIF1TX2MIX_INPUT_3_SOURCE:
+       case MADERA_AIF1TX2MIX_INPUT_3_VOLUME:
+       case MADERA_AIF1TX2MIX_INPUT_4_SOURCE:
+       case MADERA_AIF1TX2MIX_INPUT_4_VOLUME:
+       case MADERA_AIF1TX3MIX_INPUT_1_SOURCE:
+       case MADERA_AIF1TX3MIX_INPUT_1_VOLUME:
+       case MADERA_AIF1TX3MIX_INPUT_2_SOURCE:
+       case MADERA_AIF1TX3MIX_INPUT_2_VOLUME:
+       case MADERA_AIF1TX3MIX_INPUT_3_SOURCE:
+       case MADERA_AIF1TX3MIX_INPUT_3_VOLUME:
+       case MADERA_AIF1TX3MIX_INPUT_4_SOURCE:
+       case MADERA_AIF1TX3MIX_INPUT_4_VOLUME:
+       case MADERA_AIF1TX4MIX_INPUT_1_SOURCE:
+       case MADERA_AIF1TX4MIX_INPUT_1_VOLUME:
+       case MADERA_AIF1TX4MIX_INPUT_2_SOURCE:
+       case MADERA_AIF1TX4MIX_INPUT_2_VOLUME:
+       case MADERA_AIF1TX4MIX_INPUT_3_SOURCE:
+       case MADERA_AIF1TX4MIX_INPUT_3_VOLUME:
+       case MADERA_AIF1TX4MIX_INPUT_4_SOURCE:
+       case MADERA_AIF1TX4MIX_INPUT_4_VOLUME:
+       case MADERA_AIF1TX5MIX_INPUT_1_SOURCE:
+       case MADERA_AIF1TX5MIX_INPUT_1_VOLUME:
+       case MADERA_AIF1TX5MIX_INPUT_2_SOURCE:
+       case MADERA_AIF1TX5MIX_INPUT_2_VOLUME:
+       case MADERA_AIF1TX5MIX_INPUT_3_SOURCE:
+       case MADERA_AIF1TX5MIX_INPUT_3_VOLUME:
+       case MADERA_AIF1TX5MIX_INPUT_4_SOURCE:
+       case MADERA_AIF1TX5MIX_INPUT_4_VOLUME:
+       case MADERA_AIF1TX6MIX_INPUT_1_SOURCE:
+       case MADERA_AIF1TX6MIX_INPUT_1_VOLUME:
+       case MADERA_AIF1TX6MIX_INPUT_2_SOURCE:
+       case MADERA_AIF1TX6MIX_INPUT_2_VOLUME:
+       case MADERA_AIF1TX6MIX_INPUT_3_SOURCE:
+       case MADERA_AIF1TX6MIX_INPUT_3_VOLUME:
+       case MADERA_AIF1TX6MIX_INPUT_4_SOURCE:
+       case MADERA_AIF1TX6MIX_INPUT_4_VOLUME:
+       case MADERA_AIF2TX1MIX_INPUT_1_SOURCE:
+       case MADERA_AIF2TX1MIX_INPUT_1_VOLUME:
+       case MADERA_AIF2TX1MIX_INPUT_2_SOURCE:
+       case MADERA_AIF2TX1MIX_INPUT_2_VOLUME:
+       case MADERA_AIF2TX1MIX_INPUT_3_SOURCE:
+       case MADERA_AIF2TX1MIX_INPUT_3_VOLUME:
+       case MADERA_AIF2TX1MIX_INPUT_4_SOURCE:
+       case MADERA_AIF2TX1MIX_INPUT_4_VOLUME:
+       case MADERA_AIF2TX2MIX_INPUT_1_SOURCE:
+       case MADERA_AIF2TX2MIX_INPUT_1_VOLUME:
+       case MADERA_AIF2TX2MIX_INPUT_2_SOURCE:
+       case MADERA_AIF2TX2MIX_INPUT_2_VOLUME:
+       case MADERA_AIF2TX2MIX_INPUT_3_SOURCE:
+       case MADERA_AIF2TX2MIX_INPUT_3_VOLUME:
+       case MADERA_AIF2TX2MIX_INPUT_4_SOURCE:
+       case MADERA_AIF2TX2MIX_INPUT_4_VOLUME:
+       case MADERA_AIF3TX1MIX_INPUT_1_SOURCE:
+       case MADERA_AIF3TX1MIX_INPUT_1_VOLUME:
+       case MADERA_AIF3TX1MIX_INPUT_2_SOURCE:
+       case MADERA_AIF3TX1MIX_INPUT_2_VOLUME:
+       case MADERA_AIF3TX1MIX_INPUT_3_SOURCE:
+       case MADERA_AIF3TX1MIX_INPUT_3_VOLUME:
+       case MADERA_AIF3TX1MIX_INPUT_4_SOURCE:
+       case MADERA_AIF3TX1MIX_INPUT_4_VOLUME:
+       case MADERA_AIF3TX2MIX_INPUT_1_SOURCE:
+       case MADERA_AIF3TX2MIX_INPUT_1_VOLUME:
+       case MADERA_AIF3TX2MIX_INPUT_2_SOURCE:
+       case MADERA_AIF3TX2MIX_INPUT_2_VOLUME:
+       case MADERA_AIF3TX2MIX_INPUT_3_SOURCE:
+       case MADERA_AIF3TX2MIX_INPUT_3_VOLUME:
+       case MADERA_AIF3TX2MIX_INPUT_4_SOURCE:
+       case MADERA_AIF3TX2MIX_INPUT_4_VOLUME:
+       case MADERA_SLIMTX1MIX_INPUT_1_SOURCE:
+       case MADERA_SLIMTX1MIX_INPUT_1_VOLUME:
+       case MADERA_SLIMTX1MIX_INPUT_2_SOURCE:
+       case MADERA_SLIMTX1MIX_INPUT_2_VOLUME:
+       case MADERA_SLIMTX1MIX_INPUT_3_SOURCE:
+       case MADERA_SLIMTX1MIX_INPUT_3_VOLUME:
+       case MADERA_SLIMTX1MIX_INPUT_4_SOURCE:
+       case MADERA_SLIMTX1MIX_INPUT_4_VOLUME:
+       case MADERA_SLIMTX2MIX_INPUT_1_SOURCE:
+       case MADERA_SLIMTX2MIX_INPUT_1_VOLUME:
+       case MADERA_SLIMTX2MIX_INPUT_2_SOURCE:
+       case MADERA_SLIMTX2MIX_INPUT_2_VOLUME:
+       case MADERA_SLIMTX2MIX_INPUT_3_SOURCE:
+       case MADERA_SLIMTX2MIX_INPUT_3_VOLUME:
+       case MADERA_SLIMTX2MIX_INPUT_4_SOURCE:
+       case MADERA_SLIMTX2MIX_INPUT_4_VOLUME:
+       case MADERA_SLIMTX3MIX_INPUT_1_SOURCE:
+       case MADERA_SLIMTX3MIX_INPUT_1_VOLUME:
+       case MADERA_SLIMTX3MIX_INPUT_2_SOURCE:
+       case MADERA_SLIMTX3MIX_INPUT_2_VOLUME:
+       case MADERA_SLIMTX3MIX_INPUT_3_SOURCE:
+       case MADERA_SLIMTX3MIX_INPUT_3_VOLUME:
+       case MADERA_SLIMTX3MIX_INPUT_4_SOURCE:
+       case MADERA_SLIMTX3MIX_INPUT_4_VOLUME:
+       case MADERA_SLIMTX4MIX_INPUT_1_SOURCE:
+       case MADERA_SLIMTX4MIX_INPUT_1_VOLUME:
+       case MADERA_SLIMTX4MIX_INPUT_2_SOURCE:
+       case MADERA_SLIMTX4MIX_INPUT_2_VOLUME:
+       case MADERA_SLIMTX4MIX_INPUT_3_SOURCE:
+       case MADERA_SLIMTX4MIX_INPUT_3_VOLUME:
+       case MADERA_SLIMTX4MIX_INPUT_4_SOURCE:
+       case MADERA_SLIMTX4MIX_INPUT_4_VOLUME:
+       case MADERA_SLIMTX5MIX_INPUT_1_SOURCE:
+       case MADERA_SLIMTX5MIX_INPUT_1_VOLUME:
+       case MADERA_SLIMTX5MIX_INPUT_2_SOURCE:
+       case MADERA_SLIMTX5MIX_INPUT_2_VOLUME:
+       case MADERA_SLIMTX5MIX_INPUT_3_SOURCE:
+       case MADERA_SLIMTX5MIX_INPUT_3_VOLUME:
+       case MADERA_SLIMTX5MIX_INPUT_4_SOURCE:
+       case MADERA_SLIMTX5MIX_INPUT_4_VOLUME:
+       case MADERA_SLIMTX6MIX_INPUT_1_SOURCE:
+       case MADERA_SLIMTX6MIX_INPUT_1_VOLUME:
+       case MADERA_SLIMTX6MIX_INPUT_2_SOURCE:
+       case MADERA_SLIMTX6MIX_INPUT_2_VOLUME:
+       case MADERA_SLIMTX6MIX_INPUT_3_SOURCE:
+       case MADERA_SLIMTX6MIX_INPUT_3_VOLUME:
+       case MADERA_SLIMTX6MIX_INPUT_4_SOURCE:
+       case MADERA_SLIMTX6MIX_INPUT_4_VOLUME:
+       case MADERA_SPDIF1TX1MIX_INPUT_1_SOURCE:
+       case MADERA_SPDIF1TX1MIX_INPUT_1_VOLUME:
+       case MADERA_SPDIF1TX2MIX_INPUT_1_SOURCE:
+       case MADERA_SPDIF1TX2MIX_INPUT_1_VOLUME:
+       case MADERA_EQ1MIX_INPUT_1_SOURCE:
+       case MADERA_EQ1MIX_INPUT_1_VOLUME:
+       case MADERA_EQ1MIX_INPUT_2_SOURCE:
+       case MADERA_EQ1MIX_INPUT_2_VOLUME:
+       case MADERA_EQ1MIX_INPUT_3_SOURCE:
+       case MADERA_EQ1MIX_INPUT_3_VOLUME:
+       case MADERA_EQ1MIX_INPUT_4_SOURCE:
+       case MADERA_EQ1MIX_INPUT_4_VOLUME:
+       case MADERA_EQ2MIX_INPUT_1_SOURCE:
+       case MADERA_EQ2MIX_INPUT_1_VOLUME:
+       case MADERA_EQ2MIX_INPUT_2_SOURCE:
+       case MADERA_EQ2MIX_INPUT_2_VOLUME:
+       case MADERA_EQ2MIX_INPUT_3_SOURCE:
+       case MADERA_EQ2MIX_INPUT_3_VOLUME:
+       case MADERA_EQ2MIX_INPUT_4_SOURCE:
+       case MADERA_EQ2MIX_INPUT_4_VOLUME:
+       case MADERA_EQ3MIX_INPUT_1_SOURCE:
+       case MADERA_EQ3MIX_INPUT_1_VOLUME:
+       case MADERA_EQ3MIX_INPUT_2_SOURCE:
+       case MADERA_EQ3MIX_INPUT_2_VOLUME:
+       case MADERA_EQ3MIX_INPUT_3_SOURCE:
+       case MADERA_EQ3MIX_INPUT_3_VOLUME:
+       case MADERA_EQ3MIX_INPUT_4_SOURCE:
+       case MADERA_EQ3MIX_INPUT_4_VOLUME:
+       case MADERA_EQ4MIX_INPUT_1_SOURCE:
+       case MADERA_EQ4MIX_INPUT_1_VOLUME:
+       case MADERA_EQ4MIX_INPUT_2_SOURCE:
+       case MADERA_EQ4MIX_INPUT_2_VOLUME:
+       case MADERA_EQ4MIX_INPUT_3_SOURCE:
+       case MADERA_EQ4MIX_INPUT_3_VOLUME:
+       case MADERA_EQ4MIX_INPUT_4_SOURCE:
+       case MADERA_EQ4MIX_INPUT_4_VOLUME:
+       case MADERA_DRC1LMIX_INPUT_1_SOURCE:
+       case MADERA_DRC1LMIX_INPUT_1_VOLUME:
+       case MADERA_DRC1LMIX_INPUT_2_SOURCE:
+       case MADERA_DRC1LMIX_INPUT_2_VOLUME:
+       case MADERA_DRC1LMIX_INPUT_3_SOURCE:
+       case MADERA_DRC1LMIX_INPUT_3_VOLUME:
+       case MADERA_DRC1LMIX_INPUT_4_SOURCE:
+       case MADERA_DRC1LMIX_INPUT_4_VOLUME:
+       case MADERA_DRC1RMIX_INPUT_1_SOURCE:
+       case MADERA_DRC1RMIX_INPUT_1_VOLUME:
+       case MADERA_DRC1RMIX_INPUT_2_SOURCE:
+       case MADERA_DRC1RMIX_INPUT_2_VOLUME:
+       case MADERA_DRC1RMIX_INPUT_3_SOURCE:
+       case MADERA_DRC1RMIX_INPUT_3_VOLUME:
+       case MADERA_DRC1RMIX_INPUT_4_SOURCE:
+       case MADERA_DRC1RMIX_INPUT_4_VOLUME:
+       case MADERA_DRC2LMIX_INPUT_1_SOURCE:
+       case MADERA_DRC2LMIX_INPUT_1_VOLUME:
+       case MADERA_DRC2LMIX_INPUT_2_SOURCE:
+       case MADERA_DRC2LMIX_INPUT_2_VOLUME:
+       case MADERA_DRC2LMIX_INPUT_3_SOURCE:
+       case MADERA_DRC2LMIX_INPUT_3_VOLUME:
+       case MADERA_DRC2LMIX_INPUT_4_SOURCE:
+       case MADERA_DRC2LMIX_INPUT_4_VOLUME:
+       case MADERA_DRC2RMIX_INPUT_1_SOURCE:
+       case MADERA_DRC2RMIX_INPUT_1_VOLUME:
+       case MADERA_DRC2RMIX_INPUT_2_SOURCE:
+       case MADERA_DRC2RMIX_INPUT_2_VOLUME:
+       case MADERA_DRC2RMIX_INPUT_3_SOURCE:
+       case MADERA_DRC2RMIX_INPUT_3_VOLUME:
+       case MADERA_DRC2RMIX_INPUT_4_SOURCE:
+       case MADERA_DRC2RMIX_INPUT_4_VOLUME:
+       case MADERA_HPLP1MIX_INPUT_1_SOURCE:
+       case MADERA_HPLP1MIX_INPUT_1_VOLUME:
+       case MADERA_HPLP1MIX_INPUT_2_SOURCE:
+       case MADERA_HPLP1MIX_INPUT_2_VOLUME:
+       case MADERA_HPLP1MIX_INPUT_3_SOURCE:
+       case MADERA_HPLP1MIX_INPUT_3_VOLUME:
+       case MADERA_HPLP1MIX_INPUT_4_SOURCE:
+       case MADERA_HPLP1MIX_INPUT_4_VOLUME:
+       case MADERA_HPLP2MIX_INPUT_1_SOURCE:
+       case MADERA_HPLP2MIX_INPUT_1_VOLUME:
+       case MADERA_HPLP2MIX_INPUT_2_SOURCE:
+       case MADERA_HPLP2MIX_INPUT_2_VOLUME:
+       case MADERA_HPLP2MIX_INPUT_3_SOURCE:
+       case MADERA_HPLP2MIX_INPUT_3_VOLUME:
+       case MADERA_HPLP2MIX_INPUT_4_SOURCE:
+       case MADERA_HPLP2MIX_INPUT_4_VOLUME:
+       case MADERA_HPLP3MIX_INPUT_1_SOURCE:
+       case MADERA_HPLP3MIX_INPUT_1_VOLUME:
+       case MADERA_HPLP3MIX_INPUT_2_SOURCE:
+       case MADERA_HPLP3MIX_INPUT_2_VOLUME:
+       case MADERA_HPLP3MIX_INPUT_3_SOURCE:
+       case MADERA_HPLP3MIX_INPUT_3_VOLUME:
+       case MADERA_HPLP3MIX_INPUT_4_SOURCE:
+       case MADERA_HPLP3MIX_INPUT_4_VOLUME:
+       case MADERA_HPLP4MIX_INPUT_1_SOURCE:
+       case MADERA_HPLP4MIX_INPUT_1_VOLUME:
+       case MADERA_HPLP4MIX_INPUT_2_SOURCE:
+       case MADERA_HPLP4MIX_INPUT_2_VOLUME:
+       case MADERA_HPLP4MIX_INPUT_3_SOURCE:
+       case MADERA_HPLP4MIX_INPUT_3_VOLUME:
+       case MADERA_HPLP4MIX_INPUT_4_SOURCE:
+       case MADERA_HPLP4MIX_INPUT_4_VOLUME:
+       case MADERA_DSP1LMIX_INPUT_1_SOURCE:
+       case MADERA_DSP1LMIX_INPUT_1_VOLUME:
+       case MADERA_DSP1LMIX_INPUT_2_SOURCE:
+       case MADERA_DSP1LMIX_INPUT_2_VOLUME:
+       case MADERA_DSP1LMIX_INPUT_3_SOURCE:
+       case MADERA_DSP1LMIX_INPUT_3_VOLUME:
+       case MADERA_DSP1LMIX_INPUT_4_SOURCE:
+       case MADERA_DSP1LMIX_INPUT_4_VOLUME:
+       case MADERA_DSP1RMIX_INPUT_1_SOURCE:
+       case MADERA_DSP1RMIX_INPUT_1_VOLUME:
+       case MADERA_DSP1RMIX_INPUT_2_SOURCE:
+       case MADERA_DSP1RMIX_INPUT_2_VOLUME:
+       case MADERA_DSP1RMIX_INPUT_3_SOURCE:
+       case MADERA_DSP1RMIX_INPUT_3_VOLUME:
+       case MADERA_DSP1RMIX_INPUT_4_SOURCE:
+       case MADERA_DSP1RMIX_INPUT_4_VOLUME:
+       case MADERA_DSP1AUX1MIX_INPUT_1_SOURCE:
+       case MADERA_DSP1AUX2MIX_INPUT_1_SOURCE:
+       case MADERA_DSP1AUX3MIX_INPUT_1_SOURCE:
+       case MADERA_DSP1AUX4MIX_INPUT_1_SOURCE:
+       case MADERA_DSP1AUX5MIX_INPUT_1_SOURCE:
+       case MADERA_DSP1AUX6MIX_INPUT_1_SOURCE:
+       case MADERA_DSP2LMIX_INPUT_1_SOURCE:
+       case MADERA_DSP2LMIX_INPUT_1_VOLUME:
+       case MADERA_DSP2LMIX_INPUT_2_SOURCE:
+       case MADERA_DSP2LMIX_INPUT_2_VOLUME:
+       case MADERA_DSP2LMIX_INPUT_3_SOURCE:
+       case MADERA_DSP2LMIX_INPUT_3_VOLUME:
+       case MADERA_DSP2LMIX_INPUT_4_SOURCE:
+       case MADERA_DSP2LMIX_INPUT_4_VOLUME:
+       case MADERA_DSP2RMIX_INPUT_1_SOURCE:
+       case MADERA_DSP2RMIX_INPUT_1_VOLUME:
+       case MADERA_DSP2RMIX_INPUT_2_SOURCE:
+       case MADERA_DSP2RMIX_INPUT_2_VOLUME:
+       case MADERA_DSP2RMIX_INPUT_3_SOURCE:
+       case MADERA_DSP2RMIX_INPUT_3_VOLUME:
+       case MADERA_DSP2RMIX_INPUT_4_SOURCE:
+       case MADERA_DSP2RMIX_INPUT_4_VOLUME:
+       case MADERA_DSP2AUX1MIX_INPUT_1_SOURCE:
+       case MADERA_DSP2AUX2MIX_INPUT_1_SOURCE:
+       case MADERA_DSP2AUX3MIX_INPUT_1_SOURCE:
+       case MADERA_DSP2AUX4MIX_INPUT_1_SOURCE:
+       case MADERA_DSP2AUX5MIX_INPUT_1_SOURCE:
+       case MADERA_DSP2AUX6MIX_INPUT_1_SOURCE:
+       case MADERA_DSP3LMIX_INPUT_1_SOURCE:
+       case MADERA_DSP3LMIX_INPUT_1_VOLUME:
+       case MADERA_DSP3LMIX_INPUT_2_SOURCE:
+       case MADERA_DSP3LMIX_INPUT_2_VOLUME:
+       case MADERA_DSP3LMIX_INPUT_3_SOURCE:
+       case MADERA_DSP3LMIX_INPUT_3_VOLUME:
+       case MADERA_DSP3LMIX_INPUT_4_SOURCE:
+       case MADERA_DSP3LMIX_INPUT_4_VOLUME:
+       case MADERA_DSP3RMIX_INPUT_1_SOURCE:
+       case MADERA_DSP3RMIX_INPUT_1_VOLUME:
+       case MADERA_DSP3RMIX_INPUT_2_SOURCE:
+       case MADERA_DSP3RMIX_INPUT_2_VOLUME:
+       case MADERA_DSP3RMIX_INPUT_3_SOURCE:
+       case MADERA_DSP3RMIX_INPUT_3_VOLUME:
+       case MADERA_DSP3RMIX_INPUT_4_SOURCE:
+       case MADERA_DSP3RMIX_INPUT_4_VOLUME:
+       case MADERA_DSP3AUX1MIX_INPUT_1_SOURCE:
+       case MADERA_DSP3AUX2MIX_INPUT_1_SOURCE:
+       case MADERA_DSP3AUX3MIX_INPUT_1_SOURCE:
+       case MADERA_DSP3AUX4MIX_INPUT_1_SOURCE:
+       case MADERA_DSP3AUX5MIX_INPUT_1_SOURCE:
+       case MADERA_DSP3AUX6MIX_INPUT_1_SOURCE:
+       case MADERA_ISRC1DEC1MIX_INPUT_1_SOURCE:
+       case MADERA_ISRC1DEC2MIX_INPUT_1_SOURCE:
+       case MADERA_ISRC1DEC3MIX_INPUT_1_SOURCE:
+       case MADERA_ISRC1DEC4MIX_INPUT_1_SOURCE:
+       case MADERA_ISRC1INT1MIX_INPUT_1_SOURCE:
+       case MADERA_ISRC1INT2MIX_INPUT_1_SOURCE:
+       case MADERA_ISRC1INT3MIX_INPUT_1_SOURCE:
+       case MADERA_ISRC1INT4MIX_INPUT_1_SOURCE:
+       case MADERA_ISRC2DEC1MIX_INPUT_1_SOURCE:
+       case MADERA_ISRC2DEC2MIX_INPUT_1_SOURCE:
+       case MADERA_ISRC2DEC3MIX_INPUT_1_SOURCE:
+       case MADERA_ISRC2DEC4MIX_INPUT_1_SOURCE:
+       case MADERA_ISRC2INT1MIX_INPUT_1_SOURCE:
+       case MADERA_ISRC2INT2MIX_INPUT_1_SOURCE:
+       case MADERA_ISRC2INT3MIX_INPUT_1_SOURCE:
+       case MADERA_ISRC2INT4MIX_INPUT_1_SOURCE:
+       case MADERA_FX_CTRL1:
+       case MADERA_FX_CTRL2:
+       case MADERA_EQ1_1 ... MADERA_EQ1_21:
+       case MADERA_EQ2_1 ... MADERA_EQ2_21:
+       case MADERA_EQ3_1 ... MADERA_EQ3_21:
+       case MADERA_EQ4_1 ... MADERA_EQ4_21:
+       case MADERA_DRC1_CTRL1:
+       case MADERA_DRC1_CTRL2:
+       case MADERA_DRC1_CTRL3:
+       case MADERA_DRC1_CTRL4:
+       case MADERA_DRC1_CTRL5:
+       case MADERA_DRC2_CTRL1:
+       case MADERA_DRC2_CTRL2:
+       case MADERA_DRC2_CTRL3:
+       case MADERA_DRC2_CTRL4:
+       case MADERA_DRC2_CTRL5:
+       case MADERA_HPLPF1_1:
+       case MADERA_HPLPF1_2:
+       case MADERA_HPLPF2_1:
+       case MADERA_HPLPF2_2:
+       case MADERA_HPLPF3_1:
+       case MADERA_HPLPF3_2:
+       case MADERA_HPLPF4_1:
+       case MADERA_HPLPF4_2:
+       case MADERA_ISRC_1_CTRL_1:
+       case MADERA_ISRC_1_CTRL_2:
+       case MADERA_ISRC_1_CTRL_3:
+       case MADERA_ISRC_2_CTRL_1:
+       case MADERA_ISRC_2_CTRL_2:
+       case MADERA_ISRC_2_CTRL_3:
+       case MADERA_DAC_COMP_1:
+       case MADERA_DAC_COMP_2:
+       case MADERA_FRF_COEFFICIENT_1L_1:
+       case MADERA_FRF_COEFFICIENT_1L_2:
+       case MADERA_FRF_COEFFICIENT_1L_3:
+       case MADERA_FRF_COEFFICIENT_1L_4:
+       case MADERA_FRF_COEFFICIENT_1R_1:
+       case MADERA_FRF_COEFFICIENT_1R_2:
+       case MADERA_FRF_COEFFICIENT_1R_3:
+       case MADERA_FRF_COEFFICIENT_1R_4:
+       case CS47L35_FRF_COEFFICIENT_4L_1:
+       case CS47L35_FRF_COEFFICIENT_4L_2:
+       case CS47L35_FRF_COEFFICIENT_4L_3:
+       case CS47L35_FRF_COEFFICIENT_4L_4:
+       case CS47L35_FRF_COEFFICIENT_5L_1:
+       case CS47L35_FRF_COEFFICIENT_5L_2:
+       case CS47L35_FRF_COEFFICIENT_5L_3:
+       case CS47L35_FRF_COEFFICIENT_5L_4:
+       case CS47L35_FRF_COEFFICIENT_5R_1:
+       case CS47L35_FRF_COEFFICIENT_5R_2:
+       case CS47L35_FRF_COEFFICIENT_5R_3:
+       case CS47L35_FRF_COEFFICIENT_5R_4:
+       case MADERA_GPIO1_CTRL_1 ... MADERA_GPIO16_CTRL_2:
+       case MADERA_IRQ1_STATUS_1 ... MADERA_IRQ1_STATUS_33:
+       case MADERA_IRQ1_MASK_1 ... MADERA_IRQ1_MASK_33:
+       case MADERA_IRQ1_RAW_STATUS_1 ... MADERA_IRQ1_RAW_STATUS_33:
+       case MADERA_INTERRUPT_DEBOUNCE_7:
+       case MADERA_IRQ1_CTRL:
+               return true;
+       default:
+               return false;
+       }
+}
+
+static bool cs47l35_16bit_volatile_register(struct device *dev,
+                                           unsigned int reg)
+{
+       switch (reg) {
+       case MADERA_SOFTWARE_RESET:
+       case MADERA_HARDWARE_REVISION:
+       case MADERA_WRITE_SEQUENCER_CTRL_0:
+       case MADERA_WRITE_SEQUENCER_CTRL_1:
+       case MADERA_WRITE_SEQUENCER_CTRL_2:
+       case MADERA_HAPTICS_STATUS:
+       case MADERA_SAMPLE_RATE_1_STATUS:
+       case MADERA_SAMPLE_RATE_2_STATUS:
+       case MADERA_SAMPLE_RATE_3_STATUS:
+       case MADERA_HP_CTRL_1L:
+       case MADERA_HP_CTRL_1R:
+       case MADERA_DCS_HP1L_CONTROL:
+       case MADERA_DCS_HP1R_CONTROL:
+       case MADERA_MIC_DETECT_1_CONTROL_3:
+       case MADERA_MIC_DETECT_1_CONTROL_4:
+       case MADERA_HEADPHONE_DETECT_2:
+       case MADERA_HEADPHONE_DETECT_3:
+       case MADERA_HEADPHONE_DETECT_5:
+       case MADERA_INPUT_ENABLES_STATUS:
+       case MADERA_OUTPUT_STATUS_1:
+       case MADERA_RAW_OUTPUT_STATUS_1:
+       case MADERA_SPD1_TX_CHANNEL_STATUS_1:
+       case MADERA_SPD1_TX_CHANNEL_STATUS_2:
+       case MADERA_SPD1_TX_CHANNEL_STATUS_3:
+       case MADERA_SLIMBUS_RX_PORT_STATUS:
+       case MADERA_SLIMBUS_TX_PORT_STATUS:
+       case MADERA_FX_CTRL2:
+       case MADERA_IRQ1_STATUS_1 ... MADERA_IRQ1_STATUS_33:
+       case MADERA_IRQ1_RAW_STATUS_1 ... MADERA_IRQ1_RAW_STATUS_33:
+               return true;
+       default:
+               return false;
+       }
+}
+
+static bool cs47l35_32bit_readable_register(struct device *dev,
+                                           unsigned int reg)
+{
+       switch (reg) {
+       case MADERA_WSEQ_SEQUENCE_1 ... MADERA_WSEQ_SEQUENCE_252:
+       case CS47L35_OTP_HPDET_CAL_1 ... CS47L35_OTP_HPDET_CAL_2:
+       case MADERA_DSP1_CONFIG_1 ... MADERA_DSP1_SCRATCH_2:
+       case MADERA_DSP2_CONFIG_1 ... MADERA_DSP2_SCRATCH_2:
+       case MADERA_DSP3_CONFIG_1 ... MADERA_DSP3_SCRATCH_2:
+               return true;
+       default:
+               return cs47l35_is_adsp_memory(reg);
+       }
+}
+
+static bool cs47l35_32bit_volatile_register(struct device *dev,
+                                           unsigned int reg)
+{
+       switch (reg) {
+       case MADERA_WSEQ_SEQUENCE_1 ... MADERA_WSEQ_SEQUENCE_252:
+       case CS47L35_OTP_HPDET_CAL_1 ... CS47L35_OTP_HPDET_CAL_2:
+       case MADERA_DSP1_CONFIG_1 ... MADERA_DSP1_SCRATCH_2:
+       case MADERA_DSP2_CONFIG_1 ... MADERA_DSP2_SCRATCH_2:
+       case MADERA_DSP3_CONFIG_1 ... MADERA_DSP3_SCRATCH_2:
+               return true;
+       default:
+               return cs47l35_is_adsp_memory(reg);
+       }
+}
+
+const struct regmap_config cs47l35_16bit_spi_regmap = {
+       .name = "cs47l35_16bit",
+       .reg_bits = 32,
+       .pad_bits = 16,
+       .val_bits = 16,
+       .reg_format_endian = REGMAP_ENDIAN_BIG,
+       .val_format_endian = REGMAP_ENDIAN_BIG,
+
+       .max_register = 0x1b00,
+       .readable_reg = cs47l35_16bit_readable_register,
+       .volatile_reg = cs47l35_16bit_volatile_register,
+
+       .cache_type = REGCACHE_RBTREE,
+       .reg_defaults = cs47l35_reg_default,
+       .num_reg_defaults = ARRAY_SIZE(cs47l35_reg_default),
+};
+EXPORT_SYMBOL_GPL(cs47l35_16bit_spi_regmap);
+
+const struct regmap_config cs47l35_16bit_i2c_regmap = {
+       .name = "cs47l35_16bit",
+       .reg_bits = 32,
+       .val_bits = 16,
+       .reg_format_endian = REGMAP_ENDIAN_BIG,
+       .val_format_endian = REGMAP_ENDIAN_BIG,
+
+       .max_register = 0x1b00,
+       .readable_reg = cs47l35_16bit_readable_register,
+       .volatile_reg = cs47l35_16bit_volatile_register,
+
+       .cache_type = REGCACHE_RBTREE,
+       .reg_defaults = cs47l35_reg_default,
+       .num_reg_defaults = ARRAY_SIZE(cs47l35_reg_default),
+};
+EXPORT_SYMBOL_GPL(cs47l35_16bit_i2c_regmap);
+
+const struct regmap_config cs47l35_32bit_spi_regmap = {
+       .name = "cs47l35_32bit",
+       .reg_bits = 32,
+       .reg_stride = 2,
+       .pad_bits = 16,
+       .val_bits = 32,
+       .reg_format_endian = REGMAP_ENDIAN_BIG,
+       .val_format_endian = REGMAP_ENDIAN_BIG,
+
+       .max_register = MADERA_DSP3_SCRATCH_2,
+       .readable_reg = cs47l35_32bit_readable_register,
+       .volatile_reg = cs47l35_32bit_volatile_register,
+
+       .cache_type = REGCACHE_RBTREE,
+};
+EXPORT_SYMBOL_GPL(cs47l35_32bit_spi_regmap);
+
+const struct regmap_config cs47l35_32bit_i2c_regmap = {
+       .name = "cs47l35_32bit",
+       .reg_bits = 32,
+       .reg_stride = 2,
+       .val_bits = 32,
+       .reg_format_endian = REGMAP_ENDIAN_BIG,
+       .val_format_endian = REGMAP_ENDIAN_BIG,
+
+       .max_register = MADERA_DSP3_SCRATCH_2,
+       .readable_reg = cs47l35_32bit_readable_register,
+       .volatile_reg = cs47l35_32bit_volatile_register,
+
+       .cache_type = REGCACHE_RBTREE,
+};
+EXPORT_SYMBOL_GPL(cs47l35_32bit_i2c_regmap);
diff --git a/drivers/mfd/cs47l85-tables.c b/drivers/mfd/cs47l85-tables.c
new file mode 100644 (file)
index 0000000..4380314
--- /dev/null
@@ -0,0 +1,3009 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Regmap tables for CS47L85 codec
+ *
+ * Copyright (C) 2015-2017 Cirrus Logic
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2.
+ */
+
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+
+#include <linux/mfd/madera/core.h>
+#include <linux/mfd/madera/registers.h>
+
+#include "madera.h"
+
+static const struct reg_sequence cs47l85_reva_16_patch[] = {
+       { 0x80,  0x0003 },
+       { 0x213, 0x03E4 },
+       { 0x177, 0x0281 },
+       { 0x197, 0x0281 },
+       { 0x1B7, 0x0281 },
+       { 0x4B1, 0x010A },
+       { 0x4CF, 0x0933 },
+       { 0x36C, 0x011B },
+       { 0x4B8, 0x1120 },
+       { 0x4A0, 0x3280 },
+       { 0x4A1, 0x3200 },
+       { 0x4A2, 0x3200 },
+       { 0x441, 0xC050 },
+       { 0x4A4, 0x000B },
+       { 0x4A5, 0x000B },
+       { 0x4A6, 0x000B },
+       { 0x4E2, 0x1E1D },
+       { 0x4E3, 0x1E1D },
+       { 0x4E4, 0x1E1D },
+       { 0x293, 0x0080 },
+       { 0x17D, 0x0303 },
+       { 0x19D, 0x0303 },
+       { 0x27E, 0x0000 },
+       { 0x80,  0x0000 },
+       { 0x80,  0x0000 },
+       { 0x448, 0x003f },
+};
+
+static const struct reg_sequence cs47l85_revc_16_patch[] = {
+       { 0x27E, 0x0000 },
+       { 0x2C2, 0x0005 },
+       { 0x448, 0x003f },
+};
+
+static const struct reg_sequence cs47l85_reva_32_patch[] = {
+       { 0x3000, 0xC2253632 },
+       { 0x3002, 0xC2300001 },
+       { 0x3004, 0x8225100E },
+       { 0x3006, 0x22251803 },
+       { 0x3008, 0x82310B00 },
+       { 0x300A, 0xE231023B },
+       { 0x300C, 0x02313B01 },
+       { 0x300E, 0x62300000 },
+       { 0x3010, 0xE2314288 },
+       { 0x3012, 0x02310B00 },
+       { 0x3014, 0x02310B00 },
+       { 0x3016, 0x04050100 },
+       { 0x3018, 0x42310C02 },
+       { 0x301A, 0xE2310227 },
+       { 0x301C, 0x02313B01 },
+       { 0x301E, 0xE2314266 },
+       { 0x3020, 0xE2315294 },
+       { 0x3022, 0x02310B00 },
+       { 0x3024, 0x02310B00 },
+       { 0x3026, 0x02251100 },
+       { 0x3028, 0x02251401 },
+       { 0x302A, 0x02250200 },
+       { 0x302C, 0x02251001 },
+       { 0x302E, 0x02250200 },
+       { 0x3030, 0xE2310266 },
+       { 0x3032, 0x82314B15 },
+       { 0x3034, 0x82310B15 },
+       { 0x3036, 0xE2315294 },
+       { 0x3038, 0x02310B00 },
+       { 0x303A, 0x8225160D },
+       { 0x303C, 0x0225F501 },
+       { 0x303E, 0x8225061C },
+       { 0x3040, 0x02251000 },
+       { 0x3042, 0x04051101 },
+       { 0x3044, 0x02251800 },
+       { 0x3046, 0x42251203 },
+       { 0x3048, 0x02251101 },
+       { 0x304A, 0xC2251300 },
+       { 0x304C, 0x2225FB02 },
+       { 0x3050, 0xC2263632 },
+       { 0x3052, 0xC2300001 },
+       { 0x3054, 0x8226100E },
+       { 0x3056, 0x22261803 },
+       { 0x3058, 0x82310B02 },
+       { 0x305A, 0xE231023B },
+       { 0x305C, 0x02313B01 },
+       { 0x305E, 0x62300000 },
+       { 0x3060, 0xE2314288 },
+       { 0x3062, 0x02310B00 },
+       { 0x3064, 0x02310B00 },
+       { 0x3066, 0x04050000 },
+       { 0x3068, 0x42310C03 },
+       { 0x306A, 0xE2310227 },
+       { 0x306C, 0x02313B01 },
+       { 0x306E, 0xE2314266 },
+       { 0x3070, 0xE2315294 },
+       { 0x3072, 0x02310B00 },
+       { 0x3074, 0x02310B00 },
+       { 0x3076, 0x02261100 },
+       { 0x3078, 0x02261401 },
+       { 0x307A, 0x02260200 },
+       { 0x307C, 0x02261001 },
+       { 0x307E, 0x02260200 },
+       { 0x3080, 0xE2310266 },
+       { 0x3082, 0x82314B17 },
+       { 0x3084, 0x82310B17 },
+       { 0x3086, 0xE2315294 },
+       { 0x3088, 0x02310B00 },
+       { 0x308A, 0x8226160D },
+       { 0x308C, 0x0226F501 },
+       { 0x308E, 0x8226061C },
+       { 0x3090, 0x02261000 },
+       { 0x3092, 0x04051101 },
+       { 0x3094, 0x02261800 },
+       { 0x3096, 0x42261203 },
+       { 0x3098, 0x02261101 },
+       { 0x309A, 0xC2261300 },
+       { 0x309C, 0x2226FB02 },
+       { 0x309E, 0x0000F000 },
+       { 0x30A0, 0xC2273632 },
+       { 0x30A2, 0xC2400001 },
+       { 0x30A4, 0x8227100E },
+       { 0x30A6, 0x22271803 },
+       { 0x30A8, 0x82410B00 },
+       { 0x30AA, 0xE241023B },
+       { 0x30AC, 0x02413B01 },
+       { 0x30AE, 0x62400000 },
+       { 0x30B0, 0xE2414288 },
+       { 0x30B2, 0x02410B00 },
+       { 0x30B4, 0x02410B00 },
+       { 0x30B6, 0x04050300 },
+       { 0x30B8, 0x42410C02 },
+       { 0x30BA, 0xE2410227 },
+       { 0x30BC, 0x02413B01 },
+       { 0x30BE, 0xE2414266 },
+       { 0x30C0, 0xE2415294 },
+       { 0x30C2, 0x02410B00 },
+       { 0x30C4, 0x02410B00 },
+       { 0x30C6, 0x02271100 },
+       { 0x30C8, 0x02271401 },
+       { 0x30CA, 0x02270200 },
+       { 0x30CC, 0x02271001 },
+       { 0x30CE, 0x02270200 },
+       { 0x30D0, 0xE2410266 },
+       { 0x30D2, 0x82414B15 },
+       { 0x30D4, 0x82410B15 },
+       { 0x30D6, 0xE2415294 },
+       { 0x30D8, 0x02410B00 },
+       { 0x30DA, 0x8227160D },
+       { 0x30DC, 0x0227F501 },
+       { 0x30DE, 0x8227061C },
+       { 0x30E0, 0x02271000 },
+       { 0x30E2, 0x04051101 },
+       { 0x30E4, 0x02271800 },
+       { 0x30E6, 0x42271203 },
+       { 0x30E8, 0x02271101 },
+       { 0x30EA, 0xC2271300 },
+       { 0x30EC, 0x2227FB02 },
+       { 0x30F0, 0xC2283632 },
+       { 0x30F2, 0xC2400001 },
+       { 0x30F4, 0x8228100E },
+       { 0x30F6, 0x22281803 },
+       { 0x30F8, 0x82410B02 },
+       { 0x30FA, 0xE241023B },
+       { 0x30FC, 0x02413B01 },
+       { 0x30FE, 0x62400000 },
+       { 0x3100, 0xE2414288 },
+       { 0x3102, 0x02410B00 },
+       { 0x3104, 0x02410B00 },
+       { 0x3106, 0x04050200 },
+       { 0x3108, 0x42410C03 },
+       { 0x310A, 0xE2410227 },
+       { 0x310C, 0x02413B01 },
+       { 0x310E, 0xE2414266 },
+       { 0x3110, 0xE2415294 },
+       { 0x3112, 0x02410B00 },
+       { 0x3114, 0x02410B00 },
+       { 0x3116, 0x02281100 },
+       { 0x3118, 0x02281401 },
+       { 0x311A, 0x02280200 },
+       { 0x311C, 0x02281001 },
+       { 0x311E, 0x02280200 },
+       { 0x3120, 0xE2410266 },
+       { 0x3122, 0x82414B17 },
+       { 0x3124, 0x82410B17 },
+       { 0x3126, 0xE2415294 },
+       { 0x3128, 0x02410B00 },
+       { 0x312A, 0x8228160D },
+       { 0x312C, 0x0228F501 },
+       { 0x312E, 0x8228061C },
+       { 0x3130, 0x02281000 },
+       { 0x3132, 0x04051101 },
+       { 0x3134, 0x02281800 },
+       { 0x3136, 0x42281203 },
+       { 0x3138, 0x02281101 },
+       { 0x313A, 0xC2281300 },
+       { 0x313C, 0x2228FB02 },
+       { 0x3140, 0xC2293632 },
+       { 0x3142, 0xC2500001 },
+       { 0x3144, 0x8229100E },
+       { 0x3146, 0x22291803 },
+       { 0x3148, 0x82510B00 },
+       { 0x314A, 0xE251023B },
+       { 0x314C, 0x02513B01 },
+       { 0x314E, 0x62500000 },
+       { 0x3150, 0xE2514288 },
+       { 0x3152, 0x02510B00 },
+       { 0x3154, 0x02510B00 },
+       { 0x3156, 0x04050500 },
+       { 0x3158, 0x42510C02 },
+       { 0x315A, 0xE2510227 },
+       { 0x315C, 0x02513B01 },
+       { 0x315E, 0xE2514266 },
+       { 0x3160, 0xE2515294 },
+       { 0x3162, 0x02510B00 },
+       { 0x3164, 0x02510B00 },
+       { 0x3166, 0x02291100 },
+       { 0x3168, 0x02291401 },
+       { 0x316A, 0x02290200 },
+       { 0x316C, 0x02291001 },
+       { 0x316E, 0x02290200 },
+       { 0x3170, 0xE2510266 },
+       { 0x3172, 0x82514B15 },
+       { 0x3174, 0x82510B15 },
+       { 0x3176, 0xE2515294 },
+       { 0x3178, 0x02510B00 },
+       { 0x317A, 0x8229160D },
+       { 0x317C, 0x0229F501 },
+       { 0x317E, 0x8229061C },
+       { 0x3180, 0x02291000 },
+       { 0x3182, 0x04051101 },
+       { 0x3184, 0x02291800 },
+       { 0x3186, 0x42291203 },
+       { 0x3188, 0x02291101 },
+       { 0x318A, 0xC2291300 },
+       { 0x318C, 0x2229FB02 },
+       { 0x3190, 0xC22A3632 },
+       { 0x3192, 0xC2500001 },
+       { 0x3194, 0x822A100E },
+       { 0x3196, 0x222A1803 },
+       { 0x3198, 0x82510B02 },
+       { 0x319A, 0xE251023B },
+       { 0x319C, 0x02513B01 },
+       { 0x319E, 0x62500000 },
+       { 0x31A0, 0xE2514288 },
+       { 0x31A2, 0x02510B00 },
+       { 0x31A4, 0x02510B00 },
+       { 0x31A6, 0x04050400 },
+       { 0x31A8, 0x42510C03 },
+       { 0x31AA, 0xE2510227 },
+       { 0x31AC, 0x02513B01 },
+       { 0x31AE, 0xE2514266 },
+       { 0x31B0, 0xE2515294 },
+       { 0x31B2, 0x02510B00 },
+       { 0x31B4, 0x02510B00 },
+       { 0x31B6, 0x022A1100 },
+       { 0x31B8, 0x022A1401 },
+       { 0x31BA, 0x022A0200 },
+       { 0x31BC, 0x022A1001 },
+       { 0x31BE, 0x022A0200 },
+       { 0x31C0, 0xE2510266 },
+       { 0x31C2, 0x82514B17 },
+       { 0x31C4, 0x82510B17 },
+       { 0x31C6, 0xE2515294 },
+       { 0x31C8, 0x02510B00 },
+       { 0x31CA, 0x822A160D },
+       { 0x31CC, 0x022AF501 },
+       { 0x31CE, 0x822A061C },
+       { 0x31D0, 0x022A1000 },
+       { 0x31D2, 0x04051101 },
+       { 0x31D4, 0x022A1800 },
+       { 0x31D6, 0x422A1203 },
+       { 0x31D8, 0x022A1101 },
+       { 0x31DA, 0xC22A1300 },
+       { 0x31DC, 0x222AFB02 },
+};
+
+static const struct reg_sequence cs47l85_revc_32_patch[] = {
+       { 0x3380, 0xE4103066 },
+       { 0x3382, 0xE4103070 },
+       { 0x3384, 0xE4103078 },
+       { 0x3386, 0xE4103080 },
+       { 0x3388, 0xE410F080 },
+       { 0x338A, 0xE4143066 },
+       { 0x338C, 0xE4143070 },
+       { 0x338E, 0xE4143078 },
+       { 0x3390, 0xE4143080 },
+       { 0x3392, 0xE414F080 },
+       { 0x3394, 0xE4103078 },
+       { 0x3396, 0xE4103070 },
+       { 0x3398, 0xE4103066 },
+       { 0x339A, 0xE410F056 },
+       { 0x339C, 0xE4143078 },
+       { 0x339E, 0xE4143070 },
+       { 0x33A0, 0xE4143066 },
+       { 0x33A2, 0xE414F056 },
+};
+
+int cs47l85_patch(struct madera *madera)
+{
+       int ret = 0;
+       const struct reg_sequence *patch16;
+       const struct reg_sequence *patch32;
+       unsigned int num16, num32;
+
+       switch (madera->rev) {
+       case 0:
+       case 1:
+               patch16 = cs47l85_reva_16_patch;
+               num16 = ARRAY_SIZE(cs47l85_reva_16_patch);
+
+               patch32 = cs47l85_reva_32_patch;
+               num32 = ARRAY_SIZE(cs47l85_reva_32_patch);
+               break;
+       default:
+               patch16 = cs47l85_revc_16_patch;
+               num16 = ARRAY_SIZE(cs47l85_revc_16_patch);
+
+               patch32 = cs47l85_revc_32_patch;
+               num32 = ARRAY_SIZE(cs47l85_revc_32_patch);
+               break;
+       }
+
+       ret = regmap_register_patch(madera->regmap, patch16, num16);
+       if (ret < 0) {
+               dev_err(madera->dev,
+                       "Error in applying 16-bit patch: %d\n", ret);
+               return ret;
+       }
+
+       ret = regmap_register_patch(madera->regmap_32bit, patch32, num32);
+       if (ret < 0) {
+               dev_err(madera->dev,
+                       "Error in applying 32-bit patch: %d\n", ret);
+               return ret;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(cs47l85_patch);
+
+static const struct reg_default cs47l85_reg_default[] = {
+       { 0x00000020, 0x0000 }, /* R32 (0x20) - Tone Generator 1 */
+       { 0x00000021, 0x1000 }, /* R33 (0x21) - Tone Generator 2 */
+       { 0x00000022, 0x0000 }, /* R34 (0x22) - Tone Generator 3 */
+       { 0x00000023, 0x1000 }, /* R35 (0x23) - Tone Generator 4 */
+       { 0x00000024, 0x0000 }, /* R36 (0x24) - Tone Generator 5 */
+       { 0x00000030, 0x0000 }, /* R48 (0x30) - PWM Drive 1 */
+       { 0x00000031, 0x0100 }, /* R49 (0x31) - PWM Drive 2 */
+       { 0x00000032, 0x0100 }, /* R50 (0x32) - PWM Drive 3 */
+       { 0x00000061, 0x01ff }, /* R97 (0x61) - Sample Rate Sequence Select 1 */
+       { 0x00000062, 0x01ff }, /* R98 (0x62) - Sample Rate Sequence Select 2 */
+       { 0x00000063, 0x01ff }, /* R99 (0x63) - Sample Rate Sequence Select 3 */
+       { 0x00000064, 0x01ff }, /* R100 (0x64) - Sample Rate Sequence Select 4 */
+       { 0x00000066, 0x01ff }, /* R102 (0x66) - Always On Triggers Sequence Select 1*/
+       { 0x00000067, 0x01ff }, /* R103 (0x67) - Always On Triggers Sequence Select 2*/
+       { 0x00000090, 0x0000 }, /* R144 (0x90) - Haptics Control 1 */
+       { 0x00000091, 0x7fff }, /* R145 (0x91) - Haptics Control 2 */
+       { 0x00000092, 0x0000 }, /* R146 (0x92) - Haptics phase 1 intensity */
+       { 0x00000093, 0x0000 }, /* R147 (0x93) - Haptics phase 1 duration */
+       { 0x00000094, 0x0000 }, /* R148 (0x94) - Haptics phase 2 intensity */
+       { 0x00000095, 0x0000 }, /* R149 (0x95) - Haptics phase 2 duration */
+       { 0x00000096, 0x0000 }, /* R150 (0x96) - Haptics phase 3 intensity */
+       { 0x00000097, 0x0000 }, /* R151 (0x97) - Haptics phase 3 duration */
+       { 0x000000a0, 0x0000 }, /* R160 (0xa0) - Comfort Noise Generator */
+       { 0x00000100, 0x0002 }, /* R256 (0x100) - Clock 32k 1 */
+       { 0x00000101, 0x0404 }, /* R257 (0x101) - System Clock 1 */
+       { 0x00000102, 0x0011 }, /* R258 (0x102) - Sample rate 1 */
+       { 0x00000103, 0x0011 }, /* R259 (0x103) - Sample rate 2 */
+       { 0x00000104, 0x0011 }, /* R260 (0x104) - Sample rate 3 */
+       { 0x00000112, 0x0305 }, /* R274 (0x112) - Async clock 1 */
+       { 0x00000113, 0x0011 }, /* R275 (0x113) - Async sample rate 1 */
+       { 0x00000114, 0x0011 }, /* R276 (0x114) - Async sample rate 2 */
+       { 0x00000120, 0x0305 }, /* R288 (0x120) - DSP Clock 1 */
+       { 0x00000122, 0x0000 }, /* R290 (0x122) - DSP Clock 2 */
+       { 0x00000149, 0x0000 }, /* R329 (0x149) - Output system clock */
+       { 0x0000014a, 0x0000 }, /* R330 (0x14a) - Output async clock */
+       { 0x00000152, 0x0000 }, /* R338 (0x152) - Rate Estimator 1 */
+       { 0x00000153, 0x0000 }, /* R339 (0x153) - Rate Estimator 2 */
+       { 0x00000154, 0x0000 }, /* R340 (0x154) - Rate Estimator 3 */
+       { 0x00000155, 0x0000 }, /* R341 (0x155) - Rate Estimator 4 */
+       { 0x00000156, 0x0000 }, /* R342 (0x156) - Rate Estimator 5 */
+       { 0x00000171, 0x0002 }, /* R369 (0x171) - FLL1 Control 1 */
+       { 0x00000172, 0x0008 }, /* R370 (0x172) - FLL1 Control 2 */
+       { 0x00000173, 0x0018 }, /* R371 (0x173) - FLL1 Control 3 */
+       { 0x00000174, 0x007d }, /* R372 (0x174) - FLL1 Control 4 */
+       { 0x00000175, 0x0000 }, /* R373 (0x175) - FLL1 Control 5 */
+       { 0x00000176, 0x0000 }, /* R374 (0x176) - FLL1 Control 6 */
+       { 0x00000177, 0x0281 }, /* R375 (0x177) - FLL1 Loop Filter Test 1 */
+       { 0x00000179, 0x0000 }, /* R377 (0x179) - FLL1 Control 7 */
+       { 0x00000181, 0x0000 }, /* R385 (0x181) - FLL1 Synchroniser 1 */
+       { 0x00000182, 0x0000 }, /* R386 (0x182) - FLL1 Synchroniser 2 */
+       { 0x00000183, 0x0000 }, /* R387 (0x183) - FLL1 Synchroniser 3 */
+       { 0x00000184, 0x0000 }, /* R388 (0x184) - FLL1 Synchroniser 4 */
+       { 0x00000185, 0x0000 }, /* R389 (0x185) - FLL1 Synchroniser 5 */
+       { 0x00000186, 0x0000 }, /* R390 (0x186) - FLL1 Synchroniser 6 */
+       { 0x00000187, 0x0001 }, /* R391 (0x187) - FLL1 Synchroniser 7 */
+       { 0x00000189, 0x0000 }, /* R393 (0x189) - FLL1 Spread Spectrum */
+       { 0x0000018a, 0x000c }, /* R394 (0x18a) - FLL1 GPIO Clock */
+       { 0x00000191, 0x0002 }, /* R401 (0x191) - FLL2 Control 1 */
+       { 0x00000192, 0x0008 }, /* R402 (0x192) - FLL2 Control 2 */
+       { 0x00000193, 0x0018 }, /* R403 (0x193) - FLL2 Control 3 */
+       { 0x00000194, 0x007d }, /* R404 (0x194) - FLL2 Control 4 */
+       { 0x00000195, 0x0000 }, /* R405 (0x195) - FLL2 Control 5 */
+       { 0x00000196, 0x0000 }, /* R406 (0x196) - FLL2 Control 6 */
+       { 0x00000197, 0x0281 }, /* R407 (0x197) - FLL2 Loop Filter Test 1 */
+       { 0x00000199, 0x0000 }, /* R409 (0x199) - FLL2 Control 7 */
+       { 0x000001a1, 0x0000 }, /* R417 (0x1a1) - FLL2 Synchroniser 1 */
+       { 0x000001a2, 0x0000 }, /* R418 (0x1a2) - FLL2 Synchroniser 2 */
+       { 0x000001a3, 0x0000 }, /* R419 (0x1a3) - FLL2 Synchroniser 3 */
+       { 0x000001a4, 0x0000 }, /* R420 (0x1a4) - FLL2 Synchroniser 4 */
+       { 0x000001a5, 0x0000 }, /* R421 (0x1a5) - FLL2 Synchroniser 5 */
+       { 0x000001a6, 0x0000 }, /* R422 (0x1a6) - FLL2 Synchroniser 6 */
+       { 0x000001a7, 0x0001 }, /* R423 (0x1a7) - FLL2 Synchroniser 7 */
+       { 0x000001a9, 0x0000 }, /* R425 (0x1a9) - FLL2 Spread Spectrum */
+       { 0x000001aa, 0x000c }, /* R426 (0x1aa) - FLL2 GPIO Clock */
+       { 0x000001b1, 0x0002 }, /* R433 (0x1b1) - FLL3 Control 1 */
+       { 0x000001b2, 0x0008 }, /* R434 (0x1b2) - FLL3 Control 2 */
+       { 0x000001b3, 0x0018 }, /* R435 (0x1b3) - FLL3 Control 3 */
+       { 0x000001b4, 0x007d }, /* R436 (0x1b4) - FLL3 Control 4 */
+       { 0x000001b5, 0x0000 }, /* R437 (0x1b5) - FLL3 Control 5 */
+       { 0x000001b6, 0x0000 }, /* R438 (0x1b6) - FLL3 Control 6 */
+       { 0x000001b7, 0x0281 }, /* R439 (0x1b7) - FLL3 Loop Filter Test 1 */
+       { 0x000001b9, 0x0000 }, /* R441 (0x1b9) - FLL3 Control 7 */
+       { 0x000001c1, 0x0000 }, /* R449 (0x1c1) - FLL3 Synchroniser 1 */
+       { 0x000001c2, 0x0000 }, /* R450 (0x1c2) - FLL3 Synchroniser 2 */
+       { 0x000001c3, 0x0000 }, /* R451 (0x1c3) - FLL3 Synchroniser 3 */
+       { 0x000001c4, 0x0000 }, /* R452 (0x1c4) - FLL3 Synchroniser 4 */
+       { 0x000001c5, 0x0000 }, /* R453 (0x1c5) - FLL3 Synchroniser 5 */
+       { 0x000001c6, 0x0000 }, /* R454 (0x1c6) - FLL3 Synchroniser 6 */
+       { 0x000001c7, 0x0001 }, /* R455 (0x1c7) - FLL3 Synchroniser 7 */
+       { 0x000001c9, 0x0000 }, /* R457 (0x1c9) - FLL3 Spread Spectrum */
+       { 0x000001ca, 0x000C }, /* R458 (0x1ca) - FLL3 GPIO Clock */
+       { 0x00000200, 0x0006 }, /* R512 (0x200) - Mic Charge Pump 1 */
+       { 0x0000020b, 0x0400 }, /* R523 (0x20B) - HP Charge Pump 8 */
+       { 0x00000210, 0x0184 }, /* R528 (0x210) - LDO1 Control 1 */
+       { 0x00000213, 0x03e4 }, /* R531 (0x213) - LDO2 Control 1 */
+       { 0x00000218, 0x00e6 }, /* R536 (0x218) - Mic Bias Ctrl 1 */
+       { 0x00000219, 0x00e6 }, /* R537 (0x219) - Mic Bias Ctrl 2 */
+       { 0x0000021a, 0x00e6 }, /* R538 (0x21a) - Mic Bias Ctrl 3 */
+       { 0x0000021b, 0x00e6 }, /* R539 (0x21b) - Mic Bias Ctrl 4 */
+       { 0x0000027e, 0x0000 }, /* R638 (0x27e) - EDRE HP stereo control */
+       { 0x00000293, 0x0000 }, /* R659 (0x293) - Accessory Detect Mode 1 */
+       { 0x0000029b, 0x0000 }, /* R667 (0x29b) - Headphone Detect 1 */
+       { 0x000002a3, 0x1102 }, /* R675 (0x2a3) - Mic Detect Control 1 */
+       { 0x000002a4, 0x009f }, /* R676 (0x2a4) - Mic Detect Control 2 */
+       { 0x000002a6, 0x3737 }, /* R678 (0x2a6) - Mic Detect Level 1 */
+       { 0x000002a7, 0x2c37 }, /* R679 (0x2a7) - Mic Detect Level 2 */
+       { 0x000002a8, 0x1422 }, /* R680 (0x2a8) - Mic Detect Level 3 */
+       { 0x000002a9, 0x030a }, /* R681 (0x2a9) - Mic Detect Level 4 */
+       { 0x000002c6, 0x0010 }, /* R710 (0x2c6) - Mic Clamp control */
+       { 0x000002c8, 0x0000 }, /* R712 (0x2c8) - GP switch 1 */
+       { 0x000002d3, 0x0000 }, /* R723 (0x2d3) - Jack detect analogue */
+       { 0x00000300, 0x0000 }, /* R768 (0x300) - Input Enables */
+       { 0x00000308, 0x0000 }, /* R776 (0x308) - Input Rate */
+       { 0x00000309, 0x0022 }, /* R777 (0x309) - Input Volume Ramp */
+       { 0x0000030c, 0x0002 }, /* R780 (0x30c) - HPF Control */
+       { 0x00000310, 0x0080 }, /* R784 (0x310) - IN1L Control */
+       { 0x00000311, 0x0180 }, /* R785 (0x311) - ADC Digital Volume 1L */
+       { 0x00000312, 0x0500 }, /* R786 (0x312) - DMIC1L Control */
+       { 0x00000314, 0x0080 }, /* R788 (0x314) - IN1R Control */
+       { 0x00000315, 0x0180 }, /* R789 (0x315) - ADC Digital Volume 1R */
+       { 0x00000316, 0x0000 }, /* R790 (0x316) - DMIC1R Control */
+       { 0x00000318, 0x0080 }, /* R792 (0x318) - IN2L Control */
+       { 0x00000319, 0x0180 }, /* R793 (0x319) - ADC Digital Volume 2L */
+       { 0x0000031a, 0x0500 }, /* R794 (0x31a) - DMIC2L Control */
+       { 0x0000031c, 0x0080 }, /* R796 (0x31c) - IN2R Control */
+       { 0x0000031d, 0x0180 }, /* R797 (0x31d) - ADC Digital Volume 2R */
+       { 0x0000031e, 0x0000 }, /* R798 (0x31e) - DMIC2R Control */
+       { 0x00000320, 0x0080 }, /* R800 (0x320) - IN3L Control */
+       { 0x00000321, 0x0180 }, /* R801 (0x321) - ADC Digital Volume 3L */
+       { 0x00000322, 0x0500 }, /* R802 (0x322) - DMIC3L Control */
+       { 0x00000324, 0x0080 }, /* R804 (0x324) - IN3R Control */
+       { 0x00000325, 0x0180 }, /* R805 (0x325) - ADC Digital Volume 3R */
+       { 0x00000326, 0x0000 }, /* R806 (0x326) - DMIC3R Control */
+       { 0x00000328, 0x0000 }, /* R808 (0x328) - IN4 Control */
+       { 0x00000329, 0x0180 }, /* R809 (0x329) - ADC Digital Volume 4L */
+       { 0x0000032a, 0x0500 }, /* R810 (0x32a) - DMIC4L Control */
+       { 0x0000032c, 0x0000 }, /* R812 (0x32c) - IN4R Control */
+       { 0x0000032d, 0x0180 }, /* R813 (0x32d) - ADC Digital Volume 4R */
+       { 0x0000032e, 0x0000 }, /* R814 (0x32e) - DMIC4R Control */
+       { 0x00000330, 0x0000 }, /* R816 (0x330) - IN5L Control */
+       { 0x00000331, 0x0180 }, /* R817 (0x331) - ADC Digital Volume 5L */
+       { 0x00000332, 0x0500 }, /* R818 (0x332) - DMIC5L Control */
+       { 0x00000334, 0x0000 }, /* R820 (0x334) - IN5R Control */
+       { 0x00000335, 0x0180 }, /* R821 (0x335) - ADC Digital Volume 5R */
+       { 0x00000336, 0x0000 }, /* R822 (0x336) - DMIC5R Control */
+       { 0x00000338, 0x0000 }, /* R824 (0x338) - IN6L Control */
+       { 0x00000339, 0x0180 }, /* R825 (0x339) - ADC Digital Volume 6L */
+       { 0x0000033a, 0x0500 }, /* R826 (0x33a) - DMIC6L Control */
+       { 0x0000033c, 0x0000 }, /* R828 (0x33c) - IN6R Control */
+       { 0x0000033d, 0x0180 }, /* R829 (0x33d) - ADC Digital Volume 6R */
+       { 0x0000033e, 0x0000 }, /* R830 (0x33e) - DMIC6R Control */
+       { 0x00000400, 0x0000 }, /* R1024 (0x400) - Output Enables 1 */
+       { 0x00000408, 0x0000 }, /* R1032 (0x408) - Output Rate 1 */
+       { 0x00000409, 0x0022 }, /* R1033 (0x409) - Output Volume Ramp */
+       { 0x00000410, 0x0080 }, /* R1040 (0x410) - Output Path Config 1L */
+       { 0x00000411, 0x0180 }, /* R1041 (0x411) - DAC Digital Volume 1L */
+       { 0x00000413, 0x0001 }, /* R1043 (0x413) - Noise Gate Select 1L */
+       { 0x00000414, 0x0080 }, /* R1044 (0x414) - Output Path Config 1R */
+       { 0x00000415, 0x0180 }, /* R1045 (0x415) - DAC Digital Volume 1R */
+       { 0x00000417, 0x0002 }, /* R1047 (0x417) - Noise Gate Select 1R */
+       { 0x00000418, 0x0080 }, /* R1048 (0x418) - Output Path Config 2L */
+       { 0x00000419, 0x0180 }, /* R1049 (0x419) - DAC Digital Volume 2L */
+       { 0x0000041b, 0x0004 }, /* R1051 (0x41b) - Noise Gate Select 2L */
+       { 0x0000041c, 0x0080 }, /* R1052 (0x41c) - Output Path Config 2R */
+       { 0x0000041d, 0x0180 }, /* R1053 (0x41d) - DAC Digital Volume 2R */
+       { 0x0000041f, 0x0008 }, /* R1055 (0x41f) - Noise Gate Select 2R */
+       { 0x00000420, 0x0080 }, /* R1056 (0x420) - Output Path Config 3L */
+       { 0x00000421, 0x0180 }, /* R1057 (0x421) - DAC Digital Volume 3L */
+       { 0x00000423, 0x0010 }, /* R1059 (0x423) - Noise Gate Select 3L */
+       { 0x00000424, 0x0080 }, /* R1060 (0x424) - Output Path Config 3R */
+       { 0x00000425, 0x0180 }, /* R1061 (0x425) - DAC Digital Volume 3R */
+       { 0x00000427, 0x0020 }, /* R1063 (0x427) - Noise Gate Select 3R */
+       { 0x00000428, 0x0000 }, /* R1064 (0x428) - Output Path Config 4L */
+       { 0x00000429, 0x0180 }, /* R1065 (0x429) - DAC Digital Volume 4L */
+       { 0x0000042b, 0x0040 }, /* R1067 (0x42b) - Noise Gate Select 4L */
+       { 0x0000042c, 0x0000 }, /* R1068 (0x42c) - Output Path Config 4R */
+       { 0x0000042d, 0x0180 }, /* R1069 (0x42d) - DAC Digital Volume 4R */
+       { 0x0000042f, 0x0080 }, /* R1071 (0x42f) - Noise Gate Select 4R */
+       { 0x00000430, 0x0000 }, /* R1072 (0x430) - Output Path Config 5L */
+       { 0x00000431, 0x0180 }, /* R1073 (0x431) - DAC Digital Volume 5L */
+       { 0x00000433, 0x0100 }, /* R1075 (0x433) - Noise Gate Select 5L */
+       { 0x00000434, 0x0000 }, /* R1076 (0x434) - Output Path Config 5R */
+       { 0x00000435, 0x0180 }, /* R1077 (0x435) - DAC Digital Volume 5R */
+       { 0x00000437, 0x0200 }, /* R1079 (0x437) - Noise Gate Select 5R */
+       { 0x00000438, 0x0000 }, /* R1080 (0x438) - Output Path Config 6L */
+       { 0x00000439, 0x0180 }, /* R1081 (0x439) - DAC Digital Volume 6L */
+       { 0x0000043b, 0x0400 }, /* R1083 (0x43b) - Noise Gate Select 6L */
+       { 0x0000043c, 0x0000 }, /* R1084 (0x43c) - Output Path Config 6R */
+       { 0x0000043d, 0x0180 }, /* R1085 (0x43d) - DAC Digital Volume 6R */
+       { 0x0000043f, 0x0800 }, /* R1087 (0x43f) - Noise Gate Select 6R */
+       { 0x00000440, 0x003f }, /* R1088 (0x440) - DRE Enable */
+       { 0x00000448, 0x003f }, /* 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 */
+       { 0x00000492, 0x0069 }, /* R1170 (0x492) - PDM SPK2 CTRL 1 */
+       { 0x00000493, 0x0000 }, /* R1171 (0x493) - PDM SPK2 CTRL 2 */
+       { 0x000004a0, 0x3210 }, /* R1184 (0x4a0) - HP1 Short Circuit Ctrl */
+       { 0x000004a1, 0x3200 }, /* R1185 (0x4a1) - HP2 Short Circuit Ctrl */
+       { 0x000004a2, 0x3200 }, /* R1186 (0x4a2) - HP3 Short Circuit Ctrl */
+       { 0x000004a8, 0x7020 }, /* R1192 (0x4a8) - HP Test Ctrl 5 */
+       { 0x000004a9, 0x7020 }, /* R1193 (0x4a9) - HP Test Ctrl 6 */
+       { 0x00000500, 0x000c }, /* R1280 (0x500) - AIF1 BCLK Ctrl */
+       { 0x00000501, 0x0000 }, /* R1281 (0x501) - AIF1 Tx Pin Ctrl */
+       { 0x00000502, 0x0000 }, /* R1282 (0x502) - AIF1 Rx Pin Ctrl */
+       { 0x00000503, 0x0000 }, /* R1283 (0x503) - AIF1 Rate Ctrl */
+       { 0x00000504, 0x0000 }, /* R1284 (0x504) - AIF1 Format */
+       { 0x00000506, 0x0040 }, /* R1286 (0x506) - AIF1 Rx BCLK Rate */
+       { 0x00000507, 0x1818 }, /* R1287 (0x507) - AIF1 Frame Ctrl 1 */
+       { 0x00000508, 0x1818 }, /* R1288 (0x508) - AIF1 Frame Ctrl 2 */
+       { 0x00000509, 0x0000 }, /* R1289 (0x509) - AIF1 Frame Ctrl 3 */
+       { 0x0000050a, 0x0001 }, /* R1290 (0x50a) - AIF1 Frame Ctrl 4 */
+       { 0x0000050b, 0x0002 }, /* R1291 (0x50b) - AIF1 Frame Ctrl 5 */
+       { 0x0000050c, 0x0003 }, /* R1292 (0x50c) - AIF1 Frame Ctrl 6 */
+       { 0x0000050d, 0x0004 }, /* R1293 (0x50d) - AIF1 Frame Ctrl 7 */
+       { 0x0000050e, 0x0005 }, /* R1294 (0x50e) - AIF1 Frame Ctrl 8 */
+       { 0x0000050f, 0x0006 }, /* R1295 (0x50f) - AIF1 Frame Ctrl 9 */
+       { 0x00000510, 0x0007 }, /* R1296 (0x510) - AIF1 Frame Ctrl 10 */
+       { 0x00000511, 0x0000 }, /* R1297 (0x511) - AIF1 Frame Ctrl 11 */
+       { 0x00000512, 0x0001 }, /* R1298 (0x512) - AIF1 Frame Ctrl 12 */
+       { 0x00000513, 0x0002 }, /* R1299 (0x513) - AIF1 Frame Ctrl 13 */
+       { 0x00000514, 0x0003 }, /* R1300 (0x514) - AIF1 Frame Ctrl 14 */
+       { 0x00000515, 0x0004 }, /* R1301 (0x515) - AIF1 Frame Ctrl 15 */
+       { 0x00000516, 0x0005 }, /* R1302 (0x516) - AIF1 Frame Ctrl 16 */
+       { 0x00000517, 0x0006 }, /* R1303 (0x517) - AIF1 Frame Ctrl 17 */
+       { 0x00000518, 0x0007 }, /* R1304 (0x518) - AIF1 Frame Ctrl 18 */
+       { 0x00000519, 0x0000 }, /* R1305 (0x519) - AIF1 Tx Enables */
+       { 0x0000051a, 0x0000 }, /* R1306 (0x51a) - AIF1 Rx Enables */
+       { 0x00000540, 0x000c }, /* R1344 (0x540) - AIF2 BCLK Ctrl */
+       { 0x00000541, 0x0000 }, /* R1345 (0x541) - AIF2 Tx Pin Ctrl */
+       { 0x00000542, 0x0000 }, /* R1346 (0x542) - AIF2 Rx Pin Ctrl */
+       { 0x00000543, 0x0000 }, /* R1347 (0x543) - AIF2 Rate Ctrl */
+       { 0x00000544, 0x0000 }, /* R1348 (0x544) - AIF2 Format */
+       { 0x00000546, 0x0040 }, /* R1350 (0x546) - AIF2 Rx BCLK Rate */
+       { 0x00000547, 0x1818 }, /* R1351 (0x547) - AIF2 Frame Ctrl 1 */
+       { 0x00000548, 0x1818 }, /* R1352 (0x548) - AIF2 Frame Ctrl 2 */
+       { 0x00000549, 0x0000 }, /* R1353 (0x549) - AIF2 Frame Ctrl 3 */
+       { 0x0000054a, 0x0001 }, /* R1354 (0x54a) - AIF2 Frame Ctrl 4 */
+       { 0x0000054b, 0x0002 }, /* R1355 (0x54b) - AIF2 Frame Ctrl 5 */
+       { 0x0000054c, 0x0003 }, /* R1356 (0x54c) - AIF2 Frame Ctrl 6 */
+       { 0x0000054d, 0x0004 }, /* R1357 (0x54d) - AIF2 Frame Ctrl 7 */
+       { 0x0000054e, 0x0005 }, /* R1358 (0x54e) - AIF2 Frame Ctrl 8 */
+       { 0x0000054f, 0x0006 }, /* R1359 (0x54f) - AIF2 Frame Ctrl 9 */
+       { 0x00000550, 0x0007 }, /* R1360 (0x550) - AIF2 Frame Ctrl 10 */
+       { 0x00000551, 0x0000 }, /* R1361 (0x551) - AIF2 Frame Ctrl 11 */
+       { 0x00000552, 0x0001 }, /* R1362 (0x552) - AIF2 Frame Ctrl 12 */
+       { 0x00000553, 0x0002 }, /* R1363 (0x553) - AIF2 Frame Ctrl 13 */
+       { 0x00000554, 0x0003 }, /* R1364 (0x554) - AIF2 Frame Ctrl 14 */
+       { 0x00000555, 0x0004 }, /* R1365 (0x555) - AIF2 Frame Ctrl 15 */
+       { 0x00000556, 0x0005 }, /* R1366 (0x556) - AIF2 Frame Ctrl 16 */
+       { 0x00000557, 0x0006 }, /* R1367 (0x557) - AIF2 Frame Ctrl 17 */
+       { 0x00000558, 0x0007 }, /* R1368 (0x558) - AIF2 Frame Ctrl 18 */
+       { 0x00000559, 0x0000 }, /* R1369 (0x559) - AIF2 Tx Enables */
+       { 0x0000055a, 0x0000 }, /* R1370 (0x55a) - AIF2 Rx Enables */
+       { 0x00000580, 0x000c }, /* R1408 (0x580) - AIF3 BCLK Ctrl */
+       { 0x00000581, 0x0000 }, /* R1409 (0x581) - AIF3 Tx Pin Ctrl */
+       { 0x00000582, 0x0000 }, /* R1410 (0x582) - AIF3 Rx Pin Ctrl */
+       { 0x00000583, 0x0000 }, /* R1411 (0x583) - AIF3 Rate Ctrl */
+       { 0x00000584, 0x0000 }, /* R1412 (0x584) - AIF3 Format */
+       { 0x00000586, 0x0040 }, /* R1414 (0x586) - AIF3 Rx BCLK Rate */
+       { 0x00000587, 0x1818 }, /* R1415 (0x587) - AIF3 Frame Ctrl 1 */
+       { 0x00000588, 0x1818 }, /* R1416 (0x588) - AIF3 Frame Ctrl 2 */
+       { 0x00000589, 0x0000 }, /* R1417 (0x589) - AIF3 Frame Ctrl 3 */
+       { 0x0000058a, 0x0001 }, /* R1418 (0x58a) - AIF3 Frame Ctrl 4 */
+       { 0x00000591, 0x0000 }, /* R1425 (0x591) - AIF3 Frame Ctrl 11 */
+       { 0x00000592, 0x0001 }, /* R1426 (0x592) - AIF3 Frame Ctrl 12 */
+       { 0x00000599, 0x0000 }, /* R1433 (0x599) - AIF3 Tx Enables */
+       { 0x0000059a, 0x0000 }, /* R1434 (0x59a) - AIF3 Rx Enables */
+       { 0x000005a0, 0x000c }, /* R1440 (0x5a0) - AIF4 BCLK Ctrl */
+       { 0x000005a1, 0x0000 }, /* R1441 (0x5a1) - AIF4 Tx Pin Ctrl */
+       { 0x000005a2, 0x0000 }, /* R1442 (0x5a2) - AIF4 Rx Pin Ctrl */
+       { 0x000005a3, 0x0000 }, /* R1443 (0x5a3) - AIF4 Rate Ctrl */
+       { 0x000005a4, 0x0000 }, /* R1444 (0x5a4) - AIF4 Format */
+       { 0x000005a6, 0x0040 }, /* R1446 (0x5a6) - AIF4 Rx BCLK Rate */
+       { 0x000005a7, 0x1818 }, /* R1447 (0x5a7) - AIF4 Frame Ctrl 1 */
+       { 0x000005a8, 0x1818 }, /* R1448 (0x5a8) - AIF4 Frame Ctrl 2 */
+       { 0x000005a9, 0x0000 }, /* R1449 (0x5a9) - AIF4 Frame Ctrl 3 */
+       { 0x000005aa, 0x0001 }, /* R1450 (0x5aa) - AIF4 Frame Ctrl 4 */
+       { 0x000005b1, 0x0000 }, /* R1457 (0x5b1) - AIF4 Frame Ctrl 11 */
+       { 0x000005b2, 0x0001 }, /* R1458 (0x5b2) - AIF4 Frame Ctrl 12 */
+       { 0x000005b9, 0x0000 }, /* R1465 (0x5b9) - AIF4 Tx Enables */
+       { 0x000005ba, 0x0000 }, /* R1466 (0x5ba) - AIF4 Rx Enables */
+       { 0x000005c2, 0x0000 }, /* R1474 (0x5c2) - SPD1 TX Control */
+       { 0x000005e3, 0x0000 }, /* R1507 (0x5e3) - SLIMbus Framer Ref Gear */
+       { 0x000005e5, 0x0000 }, /* R1509 (0x5e5) - SLIMbus Rates 1 */
+       { 0x000005e6, 0x0000 }, /* R1510 (0x5e6) - SLIMbus Rates 2 */
+       { 0x000005e7, 0x0000 }, /* R1511 (0x5e7) - SLIMbus Rates 3 */
+       { 0x000005e8, 0x0000 }, /* R1512 (0x5e8) - SLIMbus Rates 4 */
+       { 0x000005e9, 0x0000 }, /* R1513 (0x5e9) - SLIMbus Rates 5 */
+       { 0x000005ea, 0x0000 }, /* R1514 (0x5ea) - SLIMbus Rates 6 */
+       { 0x000005eb, 0x0000 }, /* R1515 (0x5eb) - SLIMbus Rates 7 */
+       { 0x000005ec, 0x0000 }, /* R1516 (0x5ec) - SLIMbus Rates 8 */
+       { 0x000005f5, 0x0000 }, /* R1525 (0x5f5) - SLIMbus RX Channel Enable */
+       { 0x000005f6, 0x0000 }, /* R1526 (0x5F6) - SLIMbus TX Channel Enable */
+       { 0x00000640, 0x0000 }, /* R1600 (0x640) - PWM1MIX Input 1 Source */
+       { 0x00000641, 0x0080 }, /* R1601 (0x641) - PWM1MIX Input 1 Volume */
+       { 0x00000642, 0x0000 }, /* R1602 (0x642) - PWM1MIX Input 2 Source */
+       { 0x00000643, 0x0080 }, /* R1603 (0x643) - PWM1MIX Input 2 Volume */
+       { 0x00000644, 0x0000 }, /* R1604 (0x644) - PWM1MIX Input 3 Source */
+       { 0x00000645, 0x0080 }, /* R1605 (0x645) - PWM1MIX Input 3 Volume */
+       { 0x00000646, 0x0000 }, /* R1606 (0x646) - PWM1MIX Input 4 Source */
+       { 0x00000647, 0x0080 }, /* R1607 (0x647) - PWM1MIX Input 4 Volume */
+       { 0x00000648, 0x0000 }, /* R1608 (0x648) - PWM2MIX Input 1 Source */
+       { 0x00000649, 0x0080 }, /* R1609 (0x649) - PWM2MIX Input 1 Volume */
+       { 0x0000064a, 0x0000 }, /* R1610 (0x64a) - PWM2MIX Input 2 Source */
+       { 0x0000064b, 0x0080 }, /* R1611 (0x64b) - PWM2MIX Input 2 Volume */
+       { 0x0000064c, 0x0000 }, /* R1612 (0x64c) - PWM2MIX Input 3 Source */
+       { 0x0000064d, 0x0080 }, /* R1613 (0x64d) - PWM2MIX Input 3 Volume */
+       { 0x0000064e, 0x0000 }, /* R1614 (0x64e) - PWM2MIX Input 4 Source */
+       { 0x0000064f, 0x0080 }, /* R1615 (0x64f) - PWM2MIX Input 4 Volume */
+       { 0x00000680, 0x0000 }, /* R1664 (0x680) - OUT1LMIX Input 1 Source */
+       { 0x00000681, 0x0080 }, /* R1665 (0x681) - OUT1LMIX Input 1 Volume */
+       { 0x00000682, 0x0000 }, /* R1666 (0x682) - OUT1LMIX Input 2 Source */
+       { 0x00000683, 0x0080 }, /* R1667 (0x683) - OUT1LMIX Input 2 Volume */
+       { 0x00000684, 0x0000 }, /* R1668 (0x684) - OUT1LMIX Input 3 Source */
+       { 0x00000685, 0x0080 }, /* R1669 (0x685) - OUT1LMIX Input 3 Volume */
+       { 0x00000686, 0x0000 }, /* R1670 (0x686) - OUT1LMIX Input 4 Source */
+       { 0x00000687, 0x0080 }, /* R1671 (0x687) - OUT1LMIX Input 4 Volume */
+       { 0x00000688, 0x0000 }, /* R1672 (0x688) - OUT1RMIX Input 1 Source */
+       { 0x00000689, 0x0080 }, /* R1673 (0x689) - OUT1RMIX Input 1 Volume */
+       { 0x0000068a, 0x0000 }, /* R1674 (0x68a) - OUT1RMIX Input 2 Source */
+       { 0x0000068b, 0x0080 }, /* R1675 (0x68b) - OUT1RMIX Input 2 Volume */
+       { 0x0000068c, 0x0000 }, /* R1672 (0x68c) - OUT1RMIX Input 3 Source */
+       { 0x0000068d, 0x0080 }, /* R1673 (0x68d) - OUT1RMIX Input 3 Volume */
+       { 0x0000068e, 0x0000 }, /* R1674 (0x68e) - OUT1RMIX Input 4 Source */
+       { 0x0000068f, 0x0080 }, /* R1675 (0x68f) - OUT1RMIX Input 4 Volume */
+       { 0x00000690, 0x0000 }, /* R1680 (0x690) - OUT2LMIX Input 1 Source */
+       { 0x00000691, 0x0080 }, /* R1681 (0x691) - OUT2LMIX Input 1 Volume */
+       { 0x00000692, 0x0000 }, /* R1682 (0x692) - OUT2LMIX Input 2 Source */
+       { 0x00000693, 0x0080 }, /* R1683 (0x693) - OUT2LMIX Input 2 Volume */
+       { 0x00000694, 0x0000 }, /* R1684 (0x694) - OUT2LMIX Input 3 Source */
+       { 0x00000695, 0x0080 }, /* R1685 (0x695) - OUT2LMIX Input 3 Volume */
+       { 0x00000696, 0x0000 }, /* R1686 (0x696) - OUT2LMIX Input 4 Source */
+       { 0x00000697, 0x0080 }, /* R1687 (0x697) - OUT2LMIX Input 4 Volume */
+       { 0x00000698, 0x0000 }, /* R1688 (0x698) - OUT2RMIX Input 1 Source */
+       { 0x00000699, 0x0080 }, /* R1689 (0x699) - OUT2RMIX Input 1 Volume */
+       { 0x0000069a, 0x0000 }, /* R1690 (0x69a) - OUT2RMIX Input 2 Source */
+       { 0x0000069b, 0x0080 }, /* R1691 (0x69b) - OUT2RMIX Input 2 Volume */
+       { 0x0000069c, 0x0000 }, /* R1692 (0x69c) - OUT2RMIX Input 3 Source */
+       { 0x0000069d, 0x0080 }, /* R1693 (0x69d) - OUT2RMIX Input 3 Volume */
+       { 0x0000069e, 0x0000 }, /* R1694 (0x69e) - OUT2RMIX Input 4 Source */
+       { 0x0000069f, 0x0080 }, /* R1695 (0x69f) - OUT2RMIX Input 4 Volume */
+       { 0x000006a0, 0x0000 }, /* R1696 (0x6a0) - OUT3LMIX Input 1 Source */
+       { 0x000006a1, 0x0080 }, /* R1697 (0x6a1) - OUT3LMIX Input 1 Volume */
+       { 0x000006a2, 0x0000 }, /* R1698 (0x6a2) - OUT3LMIX Input 2 Source */
+       { 0x000006a3, 0x0080 }, /* R1699 (0x6a3) - OUT3LMIX Input 2 Volume */
+       { 0x000006a4, 0x0000 }, /* R1700 (0x6a4) - OUT3LMIX Input 3 Source */
+       { 0x000006a5, 0x0080 }, /* R1701 (0x6a5) - OUT3LMIX Input 3 Volume */
+       { 0x000006a6, 0x0000 }, /* R1702 (0x6a6) - OUT3LMIX Input 4 Source */
+       { 0x000006a7, 0x0080 }, /* R1703 (0x6a7) - OUT3LMIX Input 4 Volume */
+       { 0x000006a8, 0x0000 }, /* R1704 (0x6a8) - OUT3RMIX Input 1 Source */
+       { 0x000006a9, 0x0080 }, /* R1705 (0x6a9) - OUT3RMIX Input 1 Volume */
+       { 0x000006aa, 0x0000 }, /* R1706 (0x6aa) - OUT3RMIX Input 2 Source */
+       { 0x000006ab, 0x0080 }, /* R1707 (0x6ab) - OUT3RMIX Input 2 Volume */
+       { 0x000006ac, 0x0000 }, /* R1708 (0x6ac) - OUT3RMIX Input 3 Source */
+       { 0x000006ad, 0x0080 }, /* R1709 (0x6ad) - OUT3RMIX Input 3 Volume */
+       { 0x000006ae, 0x0000 }, /* R1710 (0x6ae) - OUT3RMIX Input 4 Source */
+       { 0x000006af, 0x0080 }, /* R1711 (0x6af) - OUT3RMIX Input 4 Volume */
+       { 0x000006b0, 0x0000 }, /* R1712 (0x6b0) - OUT4LMIX Input 1 Source */
+       { 0x000006b1, 0x0080 }, /* R1713 (0x6b1) - OUT4LMIX Input 1 Volume */
+       { 0x000006b2, 0x0000 }, /* R1714 (0x6b2) - OUT4LMIX Input 2 Source */
+       { 0x000006b3, 0x0080 }, /* R1715 (0x6b3) - OUT4LMIX Input 2 Volume */
+       { 0x000006b4, 0x0000 }, /* R1716 (0x6b4) - OUT4LMIX Input 3 Source */
+       { 0x000006b5, 0x0080 }, /* R1717 (0x6b5) - OUT4LMIX Input 3 Volume */
+       { 0x000006b6, 0x0000 }, /* R1718 (0x6b6) - OUT4LMIX Input 4 Source */
+       { 0x000006b7, 0x0080 }, /* R1719 (0x6b7) - OUT4LMIX Input 4 Volume */
+       { 0x000006b8, 0x0000 }, /* R1720 (0x6b8) - OUT4RMIX Input 1 Source */
+       { 0x000006b9, 0x0080 }, /* R1721 (0x6b9) - OUT4RMIX Input 1 Volume */
+       { 0x000006ba, 0x0000 }, /* R1722 (0x6ba) - OUT4RMIX Input 2 Source */
+       { 0x000006bb, 0x0080 }, /* R1723 (0x6bb) - OUT4RMIX Input 2 Volume */
+       { 0x000006bc, 0x0000 }, /* R1724 (0x6bc) - OUT4RMIX Input 3 Source */
+       { 0x000006bd, 0x0080 }, /* R1725 (0x6bd) - OUT4RMIX Input 3 Volume */
+       { 0x000006be, 0x0000 }, /* R1726 (0x6be) - OUT4RMIX Input 4 Source */
+       { 0x000006bf, 0x0080 }, /* R1727 (0x6bf) - OUT4RMIX Input 4 Volume */
+       { 0x000006c0, 0x0000 }, /* R1728 (0x6c0) - OUT5LMIX Input 1 Source */
+       { 0x000006c1, 0x0080 }, /* R1729 (0x6c1) - OUT5LMIX Input 1 Volume */
+       { 0x000006c2, 0x0000 }, /* R1730 (0x6c2) - OUT5LMIX Input 2 Source */
+       { 0x000006c3, 0x0080 }, /* R1731 (0x6c3) - OUT5LMIX Input 2 Volume */
+       { 0x000006c4, 0x0000 }, /* R1732 (0x6c4) - OUT5LMIX Input 3 Source */
+       { 0x000006c5, 0x0080 }, /* R1733 (0x6c5) - OUT5LMIX Input 3 Volume */
+       { 0x000006c6, 0x0000 }, /* R1734 (0x6c6) - OUT5LMIX Input 4 Source */
+       { 0x000006c7, 0x0080 }, /* R1735 (0x6c7) - OUT5LMIX Input 4 Volume */
+       { 0x000006c8, 0x0000 }, /* R1736 (0x6c8) - OUT5RMIX Input 1 Source */
+       { 0x000006c9, 0x0080 }, /* R1737 (0x6c9) - OUT5RMIX Input 1 Volume */
+       { 0x000006ca, 0x0000 }, /* R1738 (0x6ca) - OUT5RMIX Input 2 Source */
+       { 0x000006cb, 0x0080 }, /* R1739 (0x6cb) - OUT5RMIX Input 2 Volume */
+       { 0x000006cc, 0x0000 }, /* R1740 (0x6cc) - OUT5RMIX Input 3 Source */
+       { 0x000006cd, 0x0080 }, /* R1741 (0x6cd) - OUT5RMIX Input 3 Volume */
+       { 0x000006ce, 0x0000 }, /* R1742 (0x6ce) - OUT5RMIX Input 4 Source */
+       { 0x000006cf, 0x0080 }, /* R1743 (0x6cf) - OUT5RMIX Input 4 Volume */
+       { 0x000006d0, 0x0000 }, /* R1744 (0x6d0) - OUT6LMIX Input 1 Source */
+       { 0x000006d1, 0x0080 }, /* R1745 (0x6d1) - OUT6LMIX Input 1 Volume */
+       { 0x000006d2, 0x0000 }, /* R1746 (0x6d2) - OUT6LMIX Input 2 Source */
+       { 0x000006d3, 0x0080 }, /* R1747 (0x6d3) - OUT6LMIX Input 2 Volume */
+       { 0x000006d4, 0x0000 }, /* R1748 (0x6d4) - OUT6LMIX Input 3 Source */
+       { 0x000006d5, 0x0080 }, /* R1749 (0x6d5) - OUT6LMIX Input 3 Volume */
+       { 0x000006d6, 0x0000 }, /* R1750 (0x6d6) - OUT6LMIX Input 4 Source */
+       { 0x000006d7, 0x0080 }, /* R1751 (0x6d7) - OUT6LMIX Input 4 Volume */
+       { 0x000006d8, 0x0000 }, /* R1752 (0x6d8) - OUT6RMIX Input 1 Source */
+       { 0x000006d9, 0x0080 }, /* R1753 (0x6d9) - OUT6RMIX Input 1 Volume */
+       { 0x000006da, 0x0000 }, /* R1754 (0x6da) - OUT6RMIX Input 2 Source */
+       { 0x000006db, 0x0080 }, /* R1755 (0x6db) - OUT6RMIX Input 2 Volume */
+       { 0x000006dc, 0x0000 }, /* R1756 (0x6dc) - OUT6RMIX Input 3 Source */
+       { 0x000006dd, 0x0080 }, /* R1757 (0x6dd) - OUT6RMIX Input 3 Volume */
+       { 0x000006de, 0x0000 }, /* R1758 (0x6de) - OUT6RMIX Input 4 Source */
+       { 0x000006df, 0x0080 }, /* R1759 (0x6df) - OUT6RMIX Input 4 Volume */
+       { 0x00000700, 0x0000 }, /* R1792 (0x700) - AIF1TX1MIX Input 1 Source */
+       { 0x00000701, 0x0080 }, /* R1793 (0x701) - AIF1TX1MIX Input 1 Volume */
+       { 0x00000702, 0x0000 }, /* R1794 (0x702) - AIF1TX1MIX Input 2 Source */
+       { 0x00000703, 0x0080 }, /* R1795 (0x703) - AIF1TX1MIX Input 2 Volume */
+       { 0x00000704, 0x0000 }, /* R1796 (0x704) - AIF1TX1MIX Input 3 Source */
+       { 0x00000705, 0x0080 }, /* R1797 (0x705) - AIF1TX1MIX Input 3 Volume */
+       { 0x00000706, 0x0000 }, /* R1798 (0x706) - AIF1TX1MIX Input 4 Source */
+       { 0x00000707, 0x0080 }, /* R1799 (0x707) - AIF1TX1MIX Input 4 Volume */
+       { 0x00000708, 0x0000 }, /* R1800 (0x708) - AIF1TX2MIX Input 1 Source */
+       { 0x00000709, 0x0080 }, /* R1801 (0x709) - AIF1TX2MIX Input 1 Volume */
+       { 0x0000070a, 0x0000 }, /* R1802 (0x70a) - AIF1TX2MIX Input 2 Source */
+       { 0x0000070b, 0x0080 }, /* R1803 (0x70b) - AIF1TX2MIX Input 2 Volume */
+       { 0x0000070c, 0x0000 }, /* R1804 (0x70c) - AIF1TX2MIX Input 3 Source */
+       { 0x0000070d, 0x0080 }, /* R1805 (0x70d) - AIF1TX2MIX Input 3 Volume */
+       { 0x0000070e, 0x0000 }, /* R1806 (0x70e) - AIF1TX2MIX Input 4 Source */
+       { 0x0000070f, 0x0080 }, /* R1807 (0x70f) - AIF1TX2MIX Input 4 Volume */
+       { 0x00000710, 0x0000 }, /* R1808 (0x710) - AIF1TX3MIX Input 1 Source */
+       { 0x00000711, 0x0080 }, /* R1809 (0x711) - AIF1TX3MIX Input 1 Volume */
+       { 0x00000712, 0x0000 }, /* R1810 (0x712) - AIF1TX3MIX Input 2 Source */
+       { 0x00000713, 0x0080 }, /* R1811 (0x713) - AIF1TX3MIX Input 2 Volume */
+       { 0x00000714, 0x0000 }, /* R1812 (0x714) - AIF1TX3MIX Input 3 Source */
+       { 0x00000715, 0x0080 }, /* R1813 (0x715) - AIF1TX3MIX Input 3 Volume */
+       { 0x00000716, 0x0000 }, /* R1814 (0x716) - AIF1TX3MIX Input 4 Source */
+       { 0x00000717, 0x0080 }, /* R1815 (0x717) - AIF1TX3MIX Input 4 Volume */
+       { 0x00000718, 0x0000 }, /* R1816 (0x718) - AIF1TX4MIX Input 1 Source */
+       { 0x00000719, 0x0080 }, /* R1817 (0x719) - AIF1TX4MIX Input 1 Volume */
+       { 0x0000071a, 0x0000 }, /* R1818 (0x71a) - AIF1TX4MIX Input 2 Source */
+       { 0x0000071b, 0x0080 }, /* R1819 (0x71b) - AIF1TX4MIX Input 2 Volume */
+       { 0x0000071c, 0x0000 }, /* R1820 (0x71c) - AIF1TX4MIX Input 3 Source */
+       { 0x0000071d, 0x0080 }, /* R1821 (0x71d) - AIF1TX4MIX Input 3 Volume */
+       { 0x0000071e, 0x0000 }, /* R1822 (0x71e) - AIF1TX4MIX Input 4 Source */
+       { 0x0000071f, 0x0080 }, /* R1823 (0x71f) - AIF1TX4MIX Input 4 Volume */
+       { 0x00000720, 0x0000 }, /* R1824 (0x720) - AIF1TX5MIX Input 1 Source */
+       { 0x00000721, 0x0080 }, /* R1825 (0x721) - AIF1TX5MIX Input 1 Volume */
+       { 0x00000722, 0x0000 }, /* R1826 (0x722) - AIF1TX5MIX Input 2 Source */
+       { 0x00000723, 0x0080 }, /* R1827 (0x723) - AIF1TX5MIX Input 2 Volume */
+       { 0x00000724, 0x0000 }, /* R1828 (0x724) - AIF1TX5MIX Input 3 Source */
+       { 0x00000725, 0x0080 }, /* R1829 (0x725) - AIF1TX5MIX Input 3 Volume */
+       { 0x00000726, 0x0000 }, /* R1830 (0x726) - AIF1TX5MIX Input 4 Source */
+       { 0x00000727, 0x0080 }, /* R1831 (0x727) - AIF1TX5MIX Input 4 Volume */
+       { 0x00000728, 0x0000 }, /* R1832 (0x728) - AIF1TX6MIX Input 1 Source */
+       { 0x00000729, 0x0080 }, /* R1833 (0x729) - AIF1TX6MIX Input 1 Volume */
+       { 0x0000072a, 0x0000 }, /* R1834 (0x72a) - AIF1TX6MIX Input 2 Source */
+       { 0x0000072b, 0x0080 }, /* R1835 (0x72b) - AIF1TX6MIX Input 2 Volume */
+       { 0x0000072c, 0x0000 }, /* R1836 (0x72c) - AIF1TX6MIX Input 3 Source */
+       { 0x0000072d, 0x0080 }, /* R1837 (0x72d) - AIF1TX6MIX Input 3 Volume */
+       { 0x0000072e, 0x0000 }, /* R1838 (0x72e) - AIF1TX6MIX Input 4 Source */
+       { 0x0000072f, 0x0080 }, /* R1839 (0x72f) - AIF1TX6MIX Input 4 Volume */
+       { 0x00000730, 0x0000 }, /* R1840 (0x730) - AIF1TX7MIX Input 1 Source */
+       { 0x00000731, 0x0080 }, /* R1841 (0x731) - AIF1TX7MIX Input 1 Volume */
+       { 0x00000732, 0x0000 }, /* R1842 (0x732) - AIF1TX7MIX Input 2 Source */
+       { 0x00000733, 0x0080 }, /* R1843 (0x733) - AIF1TX7MIX Input 2 Volume */
+       { 0x00000734, 0x0000 }, /* R1844 (0x734) - AIF1TX7MIX Input 3 Source */
+       { 0x00000735, 0x0080 }, /* R1845 (0x735) - AIF1TX7MIX Input 3 Volume */
+       { 0x00000736, 0x0000 }, /* R1846 (0x736) - AIF1TX7MIX Input 4 Source */
+       { 0x00000737, 0x0080 }, /* R1847 (0x737) - AIF1TX7MIX Input 4 Volume */
+       { 0x00000738, 0x0000 }, /* R1848 (0x738) - AIF1TX8MIX Input 1 Source */
+       { 0x00000739, 0x0080 }, /* R1849 (0x739) - AIF1TX8MIX Input 1 Volume */
+       { 0x0000073a, 0x0000 }, /* R1850 (0x73a) - AIF1TX8MIX Input 2 Source */
+       { 0x0000073b, 0x0080 }, /* R1851 (0x73b) - AIF1TX8MIX Input 2 Volume */
+       { 0x0000073c, 0x0000 }, /* R1852 (0x73c) - AIF1TX8MIX Input 3 Source */
+       { 0x0000073d, 0x0080 }, /* R1853 (0x73d) - AIF1TX8MIX Input 3 Volume */
+       { 0x0000073e, 0x0000 }, /* R1854 (0x73e) - AIF1TX8MIX Input 4 Source */
+       { 0x0000073f, 0x0080 }, /* R1855 (0x73f) - AIF1TX8MIX Input 4 Volume */
+       { 0x00000740, 0x0000 }, /* R1856 (0x740) - AIF2TX1MIX Input 1 Source */
+       { 0x00000741, 0x0080 }, /* R1857 (0x741) - AIF2TX1MIX Input 1 Volume */
+       { 0x00000742, 0x0000 }, /* R1858 (0x742) - AIF2TX1MIX Input 2 Source */
+       { 0x00000743, 0x0080 }, /* R1859 (0x743) - AIF2TX1MIX Input 2 Volume */
+       { 0x00000744, 0x0000 }, /* R1860 (0x744) - AIF2TX1MIX Input 3 Source */
+       { 0x00000745, 0x0080 }, /* R1861 (0x745) - AIF2TX1MIX Input 3 Volume */
+       { 0x00000746, 0x0000 }, /* R1862 (0x746) - AIF2TX1MIX Input 4 Source */
+       { 0x00000747, 0x0080 }, /* R1863 (0x747) - AIF2TX1MIX Input 4 Volume */
+       { 0x00000748, 0x0000 }, /* R1864 (0x748) - AIF2TX2MIX Input 1 Source */
+       { 0x00000749, 0x0080 }, /* R1865 (0x749) - AIF2TX2MIX Input 1 Volume */
+       { 0x0000074a, 0x0000 }, /* R1866 (0x74a) - AIF2TX2MIX Input 2 Source */
+       { 0x0000074b, 0x0080 }, /* R1867 (0x74b) - AIF2TX2MIX Input 2 Volume */
+       { 0x0000074c, 0x0000 }, /* R1868 (0x74c) - AIF2TX2MIX Input 3 Source */
+       { 0x0000074d, 0x0080 }, /* R1869 (0x74d) - AIF2TX2MIX Input 3 Volume */
+       { 0x0000074e, 0x0000 }, /* R1870 (0x74e) - AIF2TX2MIX Input 4 Source */
+       { 0x0000074f, 0x0080 }, /* R1871 (0x74f) - AIF2TX2MIX Input 4 Volume */
+       { 0x00000750, 0x0000 }, /* R1872 (0x750) - AIF2TX3MIX Input 1 Source */
+       { 0x00000751, 0x0080 }, /* R1873 (0x751) - AIF2TX3MIX Input 1 Volume */
+       { 0x00000752, 0x0000 }, /* R1874 (0x752) - AIF2TX3MIX Input 2 Source */
+       { 0x00000753, 0x0080 }, /* R1875 (0x753) - AIF2TX3MIX Input 2 Volume */
+       { 0x00000754, 0x0000 }, /* R1876 (0x754) - AIF2TX3MIX Input 3 Source */
+       { 0x00000755, 0x0080 }, /* R1877 (0x755) - AIF2TX3MIX Input 3 Volume */
+       { 0x00000756, 0x0000 }, /* R1878 (0x756) - AIF2TX3MIX Input 4 Source */
+       { 0x00000757, 0x0080 }, /* R1879 (0x757) - AIF2TX3MIX Input 4 Volume */
+       { 0x00000758, 0x0000 }, /* R1880 (0x758) - AIF2TX4MIX Input 1 Source */
+       { 0x00000759, 0x0080 }, /* R1881 (0x759) - AIF2TX4MIX Input 1 Volume */
+       { 0x0000075a, 0x0000 }, /* R1882 (0x75a) - AIF2TX4MIX Input 2 Source */
+       { 0x0000075b, 0x0080 }, /* R1883 (0x75b) - AIF2TX4MIX Input 2 Volume */
+       { 0x0000075c, 0x0000 }, /* R1884 (0x75c) - AIF2TX4MIX Input 3 Source */
+       { 0x0000075d, 0x0080 }, /* R1885 (0x75d) - AIF2TX4MIX Input 3 Volume */
+       { 0x0000075e, 0x0000 }, /* R1886 (0x75e) - AIF2TX4MIX Input 4 Source */
+       { 0x0000075f, 0x0080 }, /* R1887 (0x75f) - AIF2TX4MIX Input 4 Volume */
+       { 0x00000760, 0x0000 }, /* R1888 (0x760) - AIF2TX5MIX Input 1 Source */
+       { 0x00000761, 0x0080 }, /* R1889 (0x761) - AIF2TX5MIX Input 1 Volume */
+       { 0x00000762, 0x0000 }, /* R1890 (0x762) - AIF2TX5MIX Input 2 Source */
+       { 0x00000763, 0x0080 }, /* R1891 (0x763) - AIF2TX5MIX Input 2 Volume */
+       { 0x00000764, 0x0000 }, /* R1892 (0x764) - AIF2TX5MIX Input 3 Source */
+       { 0x00000765, 0x0080 }, /* R1893 (0x765) - AIF2TX5MIX Input 3 Volume */
+       { 0x00000766, 0x0000 }, /* R1894 (0x766) - AIF2TX5MIX Input 4 Source */
+       { 0x00000767, 0x0080 }, /* R1895 (0x767) - AIF2TX5MIX Input 4 Volume */
+       { 0x00000768, 0x0000 }, /* R1896 (0x768) - AIF2TX6MIX Input 1 Source */
+       { 0x00000769, 0x0080 }, /* R1897 (0x769) - AIF2TX6MIX Input 1 Volume */
+       { 0x0000076a, 0x0000 }, /* R1898 (0x76a) - AIF2TX6MIX Input 2 Source */
+       { 0x0000076b, 0x0080 }, /* R1899 (0x76b) - AIF2TX6MIX Input 2 Volume */
+       { 0x0000076c, 0x0000 }, /* R1900 (0x76c) - AIF2TX6MIX Input 3 Source */
+       { 0x0000076d, 0x0080 }, /* R1901 (0x76d) - AIF2TX6MIX Input 3 Volume */
+       { 0x0000076e, 0x0000 }, /* R1902 (0x76e) - AIF2TX6MIX Input 4 Source */
+       { 0x0000076f, 0x0080 }, /* R1903 (0x76f) - AIF2TX6MIX Input 4 Volume */
+       { 0x00000770, 0x0000 }, /* R1904 (0x770) - AIF2TX7MIX Input 1 Source */
+       { 0x00000771, 0x0080 }, /* R1905 (0x771) - AIF2TX7MIX Input 1 Volume */
+       { 0x00000772, 0x0000 }, /* R1906 (0x772) - AIF2TX7MIX Input 2 Source */
+       { 0x00000773, 0x0080 }, /* R1907 (0x773) - AIF2TX7MIX Input 2 Volume */
+       { 0x00000774, 0x0000 }, /* R1908 (0x774) - AIF2TX7MIX Input 3 Source */
+       { 0x00000775, 0x0080 }, /* R1909 (0x775) - AIF2TX7MIX Input 3 Volume */
+       { 0x00000776, 0x0000 }, /* R1910 (0x776) - AIF2TX7MIX Input 4 Source */
+       { 0x00000777, 0x0080 }, /* R1911 (0x777) - AIF2TX7MIX Input 4 Volume */
+       { 0x00000778, 0x0000 }, /* R1912 (0x778) - AIF2TX8MIX Input 1 Source */
+       { 0x00000779, 0x0080 }, /* R1913 (0x779) - AIF2TX8MIX Input 1 Volume */
+       { 0x0000077a, 0x0000 }, /* R1914 (0x77a) - AIF2TX8MIX Input 2 Source */
+       { 0x0000077b, 0x0080 }, /* R1915 (0x77b) - AIF2TX8MIX Input 2 Volume */
+       { 0x0000077c, 0x0000 }, /* R1916 (0x77c) - AIF2TX8MIX Input 3 Source */
+       { 0x0000077d, 0x0080 }, /* R1917 (0x77d) - AIF2TX8MIX Input 3 Volume */
+       { 0x0000077e, 0x0000 }, /* R1918 (0x77e) - AIF2TX8MIX Input 4 Source */
+       { 0x0000077f, 0x0080 }, /* R1919 (0x77f) - AIF2TX8MIX Input 4 Volume */
+       { 0x00000780, 0x0000 }, /* R1920 (0x780) - AIF3TX1MIX Input 1 Source */
+       { 0x00000781, 0x0080 }, /* R1921 (0x781) - AIF3TX1MIX Input 1 Volume */
+       { 0x00000782, 0x0000 }, /* R1922 (0x782) - AIF3TX1MIX Input 2 Source */
+       { 0x00000783, 0x0080 }, /* R1923 (0x783) - AIF3TX1MIX Input 2 Volume */
+       { 0x00000784, 0x0000 }, /* R1924 (0x784) - AIF3TX1MIX Input 3 Source */
+       { 0x00000785, 0x0080 }, /* R1925 (0x785) - AIF3TX1MIX Input 3 Volume */
+       { 0x00000786, 0x0000 }, /* R1926 (0x786) - AIF3TX1MIX Input 4 Source */
+       { 0x00000787, 0x0080 }, /* R1927 (0x787) - AIF3TX1MIX Input 4 Volume */
+       { 0x00000788, 0x0000 }, /* R1928 (0x788) - AIF3TX2MIX Input 1 Source */
+       { 0x00000789, 0x0080 }, /* R1929 (0x789) - AIF3TX2MIX Input 1 Volume */
+       { 0x0000078a, 0x0000 }, /* R1930 (0x78a) - AIF3TX2MIX Input 2 Source */
+       { 0x0000078b, 0x0080 }, /* R1931 (0x78b) - AIF3TX2MIX Input 2 Volume */
+       { 0x0000078c, 0x0000 }, /* R1932 (0x78c) - AIF3TX2MIX Input 3 Source */
+       { 0x0000078d, 0x0080 }, /* R1933 (0x78d) - AIF3TX2MIX Input 3 Volume */
+       { 0x0000078e, 0x0000 }, /* R1934 (0x78e) - AIF3TX2MIX Input 4 Source */
+       { 0x0000078f, 0x0080 }, /* R1935 (0x78f) - AIF3TX2MIX Input 4 Volume */
+       { 0x000007a0, 0x0000 }, /* R1952 (0x7a0) - AIF4TX1MIX Input 1 Source */
+       { 0x000007a1, 0x0080 }, /* R1953 (0x7a1) - AIF4TX1MIX Input 1 Volume */
+       { 0x000007a2, 0x0000 }, /* R1954 (0x7a2) - AIF4TX1MIX Input 2 Source */
+       { 0x000007a3, 0x0080 }, /* R1955 (0x7a3) - AIF4TX1MIX Input 2 Volume */
+       { 0x000007a4, 0x0000 }, /* R1956 (0x7a4) - AIF4TX1MIX Input 3 Source */
+       { 0x000007a5, 0x0080 }, /* R1957 (0x7a5) - AIF4TX1MIX Input 3 Volume */
+       { 0x000007a6, 0x0000 }, /* R1958 (0x7a6) - AIF4TX1MIX Input 4 Source */
+       { 0x000007a7, 0x0080 }, /* R1959 (0x7a7) - AIF4TX1MIX Input 4 Volume */
+       { 0x000007a8, 0x0000 }, /* R1960 (0x7a8) - AIF4TX2MIX Input 1 Source */
+       { 0x000007a9, 0x0080 }, /* R1961 (0x7a9) - AIF4TX2MIX Input 1 Volume */
+       { 0x000007aa, 0x0000 }, /* R1962 (0x7aa) - AIF4TX2MIX Input 2 Source */
+       { 0x000007ab, 0x0080 }, /* R1963 (0x7ab) - AIF4TX2MIX Input 2 Volume */
+       { 0x000007ac, 0x0000 }, /* R1964 (0x7ac) - AIF4TX2MIX Input 3 Source */
+       { 0x000007ad, 0x0080 }, /* R1965 (0x7ad) - AIF4TX2MIX Input 3 Volume */
+       { 0x000007ae, 0x0000 }, /* R1966 (0x7ae) - AIF4TX2MIX Input 4 Source */
+       { 0x000007af, 0x0080 }, /* R1967 (0x7af) - AIF4TX2MIX Input 4 Volume */
+       { 0x000007c0, 0x0000 }, /* R1984 (0x7c0) - SLIMTX1MIX Input 1 Source */
+       { 0x000007c1, 0x0080 }, /* R1985 (0x7c1) - SLIMTX1MIX Input 1 Volume */
+       { 0x000007c2, 0x0000 }, /* R1986 (0x7c2) - SLIMTX1MIX Input 2 Source */
+       { 0x000007c3, 0x0080 }, /* R1987 (0x7c3) - SLIMTX1MIX Input 2 Volume */
+       { 0x000007c4, 0x0000 }, /* R1988 (0x7c4) - SLIMTX1MIX Input 3 Source */
+       { 0x000007c5, 0x0080 }, /* R1989 (0x7c5) - SLIMTX1MIX Input 3 Volume */
+       { 0x000007c6, 0x0000 }, /* R1990 (0x7c6) - SLIMTX1MIX Input 4 Source */
+       { 0x000007c7, 0x0080 }, /* R1991 (0x7c7) - SLIMTX1MIX Input 4 Volume */
+       { 0x000007c8, 0x0000 }, /* R1992 (0x7c8) - SLIMTX2MIX Input 1 Source */
+       { 0x000007c9, 0x0080 }, /* R1993 (0x7c9) - SLIMTX2MIX Input 1 Volume */
+       { 0x000007ca, 0x0000 }, /* R1994 (0x7ca) - SLIMTX2MIX Input 2 Source */
+       { 0x000007cb, 0x0080 }, /* R1995 (0x7cb) - SLIMTX2MIX Input 2 Volume */
+       { 0x000007cc, 0x0000 }, /* R1996 (0x7cc) - SLIMTX2MIX Input 3 Source */
+       { 0x000007cd, 0x0080 }, /* R1997 (0x7cd) - SLIMTX2MIX Input 3 Volume */
+       { 0x000007ce, 0x0000 }, /* R1998 (0x7ce) - SLIMTX2MIX Input 4 Source */
+       { 0x000007cf, 0x0080 }, /* R1999 (0x7cf) - SLIMTX2MIX Input 4 Volume */
+       { 0x000007d0, 0x0000 }, /* R2000 (0x7d0) - SLIMTX3MIX Input 1 Source */
+       { 0x000007d1, 0x0080 }, /* R2001 (0x7d1) - SLIMTX3MIX Input 1 Volume */
+       { 0x000007d2, 0x0000 }, /* R2002 (0x7d2) - SLIMTX3MIX Input 2 Source */
+       { 0x000007d3, 0x0080 }, /* R2003 (0x7d3) - SLIMTX3MIX Input 2 Volume */
+       { 0x000007d4, 0x0000 }, /* R2004 (0x7d4) - SLIMTX3MIX Input 3 Source */
+       { 0x000007d5, 0x0080 }, /* R2005 (0x7d5) - SLIMTX3MIX Input 3 Volume */
+       { 0x000007d6, 0x0000 }, /* R2006 (0x7d6) - SLIMTX3MIX Input 4 Source */
+       { 0x000007d7, 0x0080 }, /* R2007 (0x7d7) - SLIMTX3MIX Input 4 Volume */
+       { 0x000007d8, 0x0000 }, /* R2008 (0x7d8) - SLIMTX4MIX Input 1 Source */
+       { 0x000007d9, 0x0080 }, /* R2009 (0x7d9) - SLIMTX4MIX Input 1 Volume */
+       { 0x000007da, 0x0000 }, /* R2010 (0x7da) - SLIMTX4MIX Input 2 Source */
+       { 0x000007db, 0x0080 }, /* R2011 (0x7db) - SLIMTX4MIX Input 2 Volume */
+       { 0x000007dc, 0x0000 }, /* R2012 (0x7dc) - SLIMTX4MIX Input 3 Source */
+       { 0x000007dd, 0x0080 }, /* R2013 (0x7dd) - SLIMTX4MIX Input 3 Volume */
+       { 0x000007de, 0x0000 }, /* R2014 (0x7de) - SLIMTX4MIX Input 4 Source */
+       { 0x000007df, 0x0080 }, /* R2015 (0x7df) - SLIMTX4MIX Input 4 Volume */
+       { 0x000007e0, 0x0000 }, /* R2016 (0x7e0) - SLIMTX5MIX Input 1 Source */
+       { 0x000007e1, 0x0080 }, /* R2017 (0x7e1) - SLIMTX5MIX Input 1 Volume */
+       { 0x000007e2, 0x0000 }, /* R2018 (0x7e2) - SLIMTX5MIX Input 2 Source */
+       { 0x000007e3, 0x0080 }, /* R2019 (0x7e3) - SLIMTX5MIX Input 2 Volume */
+       { 0x000007e4, 0x0000 }, /* R2020 (0x7e4) - SLIMTX5MIX Input 3 Source */
+       { 0x000007e5, 0x0080 }, /* R2021 (0x7e5) - SLIMTX5MIX Input 3 Volume */
+       { 0x000007e6, 0x0000 }, /* R2022 (0x7e6) - SLIMTX5MIX Input 4 Source */
+       { 0x000007e7, 0x0080 }, /* R2023 (0x7e7) - SLIMTX5MIX Input 4 Volume */
+       { 0x000007e8, 0x0000 }, /* R2024 (0x7e8) - SLIMTX6MIX Input 1 Source */
+       { 0x000007e9, 0x0080 }, /* R2025 (0x7e9) - SLIMTX6MIX Input 1 Volume */
+       { 0x000007ea, 0x0000 }, /* R2026 (0x7ea) - SLIMTX6MIX Input 2 Source */
+       { 0x000007eb, 0x0080 }, /* R2027 (0x7eb) - SLIMTX6MIX Input 2 Volume */
+       { 0x000007ec, 0x0000 }, /* R2028 (0x7ec) - SLIMTX6MIX Input 3 Source */
+       { 0x000007ed, 0x0080 }, /* R2029 (0x7ed) - SLIMTX6MIX Input 3 Volume */
+       { 0x000007ee, 0x0000 }, /* R2030 (0x7ee) - SLIMTX6MIX Input 4 Source */
+       { 0x000007ef, 0x0080 }, /* R2031 (0x7ef) - SLIMTX6MIX Input 4 Volume */
+       { 0x000007f0, 0x0000 }, /* R2032 (0x7f0) - SLIMTX7MIX Input 1 Source */
+       { 0x000007f1, 0x0080 }, /* R2033 (0x7f1) - SLIMTX7MIX Input 1 Volume */
+       { 0x000007f2, 0x0000 }, /* R2034 (0x7f2) - SLIMTX7MIX Input 2 Source */
+       { 0x000007f3, 0x0080 }, /* R2035 (0x7f3) - SLIMTX7MIX Input 2 Volume */
+       { 0x000007f4, 0x0000 }, /* R2036 (0x7f4) - SLIMTX7MIX Input 3 Source */
+       { 0x000007f5, 0x0080 }, /* R2037 (0x7f5) - SLIMTX7MIX Input 3 Volume */
+       { 0x000007f6, 0x0000 }, /* R2038 (0x7f6) - SLIMTX7MIX Input 4 Source */
+       { 0x000007f7, 0x0080 }, /* R2039 (0x7f7) - SLIMTX7MIX Input 4 Volume */
+       { 0x000007f8, 0x0000 }, /* R2040 (0x7f8) - SLIMTX8MIX Input 1 Source */
+       { 0x000007f9, 0x0080 }, /* R2041 (0x7f9) - SLIMTX8MIX Input 1 Volume */
+       { 0x000007fa, 0x0000 }, /* R2042 (0x7fa) - SLIMTX8MIX Input 2 Source */
+       { 0x000007fb, 0x0080 }, /* R2043 (0x7fb) - SLIMTX8MIX Input 2 Volume */
+       { 0x000007fc, 0x0000 }, /* R2044 (0x7fc) - SLIMTX8MIX Input 3 Source */
+       { 0x000007fd, 0x0080 }, /* R2045 (0x7fd) - SLIMTX8MIX Input 3 Volume */
+       { 0x000007fe, 0x0000 }, /* R2046 (0x7fe) - SLIMTX8MIX Input 4 Source */
+       { 0x000007ff, 0x0080 }, /* R2047 (0x7ff) - SLIMTX8MIX Input 4 Volume */
+       { 0x00000800, 0x0000 }, /* R2048 (0x800) - SPDIF1TX1MIX Input 1 Source */
+       { 0x00000801, 0x0080 }, /* R2049 (0x801) - SPDIF1TX1MIX Input 1 Volume */
+       { 0x00000808, 0x0000 }, /* R2056 (0x808) - SPDIF1TX2MIX Input 1 Source */
+       { 0x00000809, 0x0080 }, /* R2057 (0x809) - SPDIF1TX2MIX Input 1 Volume */
+       { 0x00000880, 0x0000 }, /* R2176 (0x880) - EQ1MIX Input 1 Source */
+       { 0x00000881, 0x0080 }, /* R2177 (0x881) - EQ1MIX Input 1 Volume */
+       { 0x00000882, 0x0000 }, /* R2178 (0x882) - EQ1MIX Input 2 Source */
+       { 0x00000883, 0x0080 }, /* R2179 (0x883) - EQ1MIX Input 2 Volume */
+       { 0x00000884, 0x0000 }, /* R2180 (0x884) - EQ1MIX Input 3 Source */
+       { 0x00000885, 0x0080 }, /* R2181 (0x885) - EQ1MIX Input 3 Volume */
+       { 0x00000886, 0x0000 }, /* R2182 (0x886) - EQ1MIX Input 4 Source */
+       { 0x00000887, 0x0080 }, /* R2183 (0x887) - EQ1MIX Input 4 Volume */
+       { 0x00000888, 0x0000 }, /* R2184 (0x888) - EQ2MIX Input 1 Source */
+       { 0x00000889, 0x0080 }, /* R2185 (0x889) - EQ2MIX Input 1 Volume */
+       { 0x0000088a, 0x0000 }, /* R2186 (0x88a) - EQ2MIX Input 2 Source */
+       { 0x0000088b, 0x0080 }, /* R2187 (0x88b) - EQ2MIX Input 2 Volume */
+       { 0x0000088c, 0x0000 }, /* R2188 (0x88c) - EQ2MIX Input 3 Source */
+       { 0x0000088d, 0x0080 }, /* R2189 (0x88d) - EQ2MIX Input 3 Volume */
+       { 0x0000088e, 0x0000 }, /* R2190 (0x88e) - EQ2MIX Input 4 Source */
+       { 0x0000088f, 0x0080 }, /* R2191 (0x88f) - EQ2MIX Input 4 Volume */
+       { 0x00000890, 0x0000 }, /* R2192 (0x890) - EQ3MIX Input 1 Source */
+       { 0x00000891, 0x0080 }, /* R2193 (0x891) - EQ3MIX Input 1 Volume */
+       { 0x00000892, 0x0000 }, /* R2194 (0x892) - EQ3MIX Input 2 Source */
+       { 0x00000893, 0x0080 }, /* R2195 (0x893) - EQ3MIX Input 2 Volume */
+       { 0x00000894, 0x0000 }, /* R2196 (0x894) - EQ3MIX Input 3 Source */
+       { 0x00000895, 0x0080 }, /* R2197 (0x895) - EQ3MIX Input 3 Volume */
+       { 0x00000896, 0x0000 }, /* R2198 (0x896) - EQ3MIX Input 4 Source */
+       { 0x00000897, 0x0080 }, /* R2199 (0x897) - EQ3MIX Input 4 Volume */
+       { 0x00000898, 0x0000 }, /* R2200 (0x898) - EQ4MIX Input 1 Source */
+       { 0x00000899, 0x0080 }, /* R2201 (0x899) - EQ4MIX Input 1 Volume */
+       { 0x0000089a, 0x0000 }, /* R2202 (0x89a) - EQ4MIX Input 2 Source */
+       { 0x0000089b, 0x0080 }, /* R2203 (0x89b) - EQ4MIX Input 2 Volume */
+       { 0x0000089c, 0x0000 }, /* R2204 (0x89c) - EQ4MIX Input 3 Source */
+       { 0x0000089d, 0x0080 }, /* R2205 (0x89d) - EQ4MIX Input 3 Volume */
+       { 0x0000089e, 0x0000 }, /* R2206 (0x89e) - EQ4MIX Input 4 Source */
+       { 0x0000089f, 0x0080 }, /* R2207 (0x89f) - EQ4MIX Input 4 Volume */
+       { 0x000008c0, 0x0000 }, /* R2240 (0x8c0) - DRC1LMIX Input 1 Source */
+       { 0x000008c1, 0x0080 }, /* R2241 (0x8c1) - DRC1LMIX Input 1 Volume */
+       { 0x000008c2, 0x0000 }, /* R2242 (0x8c2) - DRC1LMIX Input 2 Source */
+       { 0x000008c3, 0x0080 }, /* R2243 (0x8c3) - DRC1LMIX Input 2 Volume */
+       { 0x000008c4, 0x0000 }, /* R2244 (0x8c4) - DRC1LMIX Input 3 Source */
+       { 0x000008c5, 0x0080 }, /* R2245 (0x8c5) - DRC1LMIX Input 3 Volume */
+       { 0x000008c6, 0x0000 }, /* R2246 (0x8c6) - DRC1LMIX Input 4 Source */
+       { 0x000008c7, 0x0080 }, /* R2247 (0x8c7) - DRC1LMIX Input 4 Volume */
+       { 0x000008c8, 0x0000 }, /* R2248 (0x8c8) - DRC1RMIX Input 1 Source */
+       { 0x000008c9, 0x0080 }, /* R2249 (0x8c9) - DRC1RMIX Input 1 Volume */
+       { 0x000008ca, 0x0000 }, /* R2250 (0x8ca) - DRC1RMIX Input 2 Source */
+       { 0x000008cb, 0x0080 }, /* R2251 (0x8cb) - DRC1RMIX Input 2 Volume */
+       { 0x000008cc, 0x0000 }, /* R2252 (0x8cc) - DRC1RMIX Input 3 Source */
+       { 0x000008cd, 0x0080 }, /* R2253 (0x8cd) - DRC1RMIX Input 3 Volume */
+       { 0x000008ce, 0x0000 }, /* R2254 (0x8ce) - DRC1RMIX Input 4 Source */
+       { 0x000008cf, 0x0080 }, /* R2255 (0x8cf) - DRC1RMIX Input 4 Volume */
+       { 0x000008d0, 0x0000 }, /* R2256 (0x8d0) - DRC2LMIX Input 1 Source */
+       { 0x000008d1, 0x0080 }, /* R2257 (0x8d1) - DRC2LMIX Input 1 Volume */
+       { 0x000008d2, 0x0000 }, /* R2258 (0x8d2) - DRC2LMIX Input 2 Source */
+       { 0x000008d3, 0x0080 }, /* R2259 (0x8d3) - DRC2LMIX Input 2 Volume */
+       { 0x000008d4, 0x0000 }, /* R2260 (0x8d4) - DRC2LMIX Input 3 Source */
+       { 0x000008d5, 0x0080 }, /* R2261 (0x8d5) - DRC2LMIX Input 3 Volume */
+       { 0x000008d6, 0x0000 }, /* R2262 (0x8d6) - DRC2LMIX Input 4 Source */
+       { 0x000008d7, 0x0080 }, /* R2263 (0x8d7) - DRC2LMIX Input 4 Volume */
+       { 0x000008d8, 0x0000 }, /* R2264 (0x8d8) - DRC2RMIX Input 1 Source */
+       { 0x000008d9, 0x0080 }, /* R2265 (0x8d9) - DRC2RMIX Input 1 Volume */
+       { 0x000008da, 0x0000 }, /* R2266 (0x8da) - DRC2RMIX Input 2 Source */
+       { 0x000008db, 0x0080 }, /* R2267 (0x8db) - DRC2RMIX Input 2 Volume */
+       { 0x000008dc, 0x0000 }, /* R2268 (0x8dc) - DRC2RMIX Input 3 Source */
+       { 0x000008dd, 0x0080 }, /* R2269 (0x8dd) - DRC2RMIX Input 3 Volume */
+       { 0x000008de, 0x0000 }, /* R2270 (0x8de) - DRC2RMIX Input 4 Source */
+       { 0x000008df, 0x0080 }, /* R2271 (0x8df) - DRC2RMIX Input 4 Volume */
+       { 0x00000900, 0x0000 }, /* R2304 (0x900) - HPLP1MIX Input 1 Source */
+       { 0x00000901, 0x0080 }, /* R2305 (0x901) - HPLP1MIX Input 1 Volume */
+       { 0x00000902, 0x0000 }, /* R2306 (0x902) - HPLP1MIX Input 2 Source */
+       { 0x00000903, 0x0080 }, /* R2307 (0x903) - HPLP1MIX Input 2 Volume */
+       { 0x00000904, 0x0000 }, /* R2308 (0x904) - HPLP1MIX Input 3 Source */
+       { 0x00000905, 0x0080 }, /* R2309 (0x905) - HPLP1MIX Input 3 Volume */
+       { 0x00000906, 0x0000 }, /* R2310 (0x906) - HPLP1MIX Input 4 Source */
+       { 0x00000907, 0x0080 }, /* R2311 (0x907) - HPLP1MIX Input 4 Volume */
+       { 0x00000908, 0x0000 }, /* R2312 (0x908) - HPLP2MIX Input 1 Source */
+       { 0x00000909, 0x0080 }, /* R2313 (0x909) - HPLP2MIX Input 1 Volume */
+       { 0x0000090a, 0x0000 }, /* R2314 (0x90a) - HPLP2MIX Input 2 Source */
+       { 0x0000090b, 0x0080 }, /* R2315 (0x90b) - HPLP2MIX Input 2 Volume */
+       { 0x0000090c, 0x0000 }, /* R2316 (0x90c) - HPLP2MIX Input 3 Source */
+       { 0x0000090d, 0x0080 }, /* R2317 (0x90d) - HPLP2MIX Input 3 Volume */
+       { 0x0000090e, 0x0000 }, /* R2318 (0x90e) - HPLP2MIX Input 4 Source */
+       { 0x0000090f, 0x0080 }, /* R2319 (0x90f) - HPLP2MIX Input 4 Volume */
+       { 0x00000910, 0x0000 }, /* R2320 (0x910) - HPLP3MIX Input 1 Source */
+       { 0x00000911, 0x0080 }, /* R2321 (0x911) - HPLP3MIX Input 1 Volume */
+       { 0x00000912, 0x0000 }, /* R2322 (0x912) - HPLP3MIX Input 2 Source */
+       { 0x00000913, 0x0080 }, /* R2323 (0x913) - HPLP3MIX Input 2 Volume */
+       { 0x00000914, 0x0000 }, /* R2324 (0x914) - HPLP3MIX Input 3 Source */
+       { 0x00000915, 0x0080 }, /* R2325 (0x915) - HPLP3MIX Input 3 Volume */
+       { 0x00000916, 0x0000 }, /* R2326 (0x916) - HPLP3MIX Input 4 Source */
+       { 0x00000917, 0x0080 }, /* R2327 (0x917) - HPLP3MIX Input 4 Volume */
+       { 0x00000918, 0x0000 }, /* R2328 (0x918) - HPLP4MIX Input 1 Source */
+       { 0x00000919, 0x0080 }, /* R2329 (0x919) - HPLP4MIX Input 1 Volume */
+       { 0x0000091a, 0x0000 }, /* R2330 (0x91a) - HPLP4MIX Input 2 Source */
+       { 0x0000091b, 0x0080 }, /* R2331 (0x91b) - HPLP4MIX Input 2 Volume */
+       { 0x0000091c, 0x0000 }, /* R2332 (0x91c) - HPLP4MIX Input 3 Source */
+       { 0x0000091d, 0x0080 }, /* R2333 (0x91d) - HPLP4MIX Input 3 Volume */
+       { 0x0000091e, 0x0000 }, /* R2334 (0x91e) - HPLP4MIX Input 4 Source */
+       { 0x0000091f, 0x0080 }, /* R2335 (0x91f) - HPLP4MIX Input 4 Volume */
+       { 0x00000940, 0x0000 }, /* R2368 (0x940) - DSP1LMIX Input 1 Source */
+       { 0x00000941, 0x0080 }, /* R2369 (0x941) - DSP1LMIX Input 1 Volume */
+       { 0x00000942, 0x0000 }, /* R2370 (0x942) - DSP1LMIX Input 2 Source */
+       { 0x00000943, 0x0080 }, /* R2371 (0x943) - DSP1LMIX Input 2 Volume */
+       { 0x00000944, 0x0000 }, /* R2372 (0x944) - DSP1LMIX Input 3 Source */
+       { 0x00000945, 0x0080 }, /* R2373 (0x945) - DSP1LMIX Input 3 Volume */
+       { 0x00000946, 0x0000 }, /* R2374 (0x946) - DSP1LMIX Input 4 Source */
+       { 0x00000947, 0x0080 }, /* R2375 (0x947) - DSP1LMIX Input 4 Volume */
+       { 0x00000948, 0x0000 }, /* R2376 (0x948) - DSP1RMIX Input 1 Source */
+       { 0x00000949, 0x0080 }, /* R2377 (0x949) - DSP1RMIX Input 1 Volume */
+       { 0x0000094a, 0x0000 }, /* R2378 (0x94a) - DSP1RMIX Input 2 Source */
+       { 0x0000094b, 0x0080 }, /* R2379 (0x94b) - DSP1RMIX Input 2 Volume */
+       { 0x0000094c, 0x0000 }, /* R2380 (0x94c) - DSP1RMIX Input 3 Source */
+       { 0x0000094d, 0x0080 }, /* R2381 (0x94d) - DSP1RMIX Input 3 Volume */
+       { 0x0000094e, 0x0000 }, /* R2382 (0x94e) - DSP1RMIX Input 4 Source */
+       { 0x0000094f, 0x0080 }, /* R2383 (0x94f) - DSP1RMIX Input 4 Volume */
+       { 0x00000950, 0x0000 }, /* R2384 (0x950) - DSP1AUX1MIX Input 1 Source */
+       { 0x00000958, 0x0000 }, /* R2392 (0x958) - DSP1AUX2MIX Input 1 Source */
+       { 0x00000960, 0x0000 }, /* R2400 (0x960) - DSP1AUX3MIX Input 1 Source */
+       { 0x00000968, 0x0000 }, /* R2408 (0x968) - DSP1AUX4MIX Input 1 Source */
+       { 0x00000970, 0x0000 }, /* R2416 (0x970) - DSP1AUX5MIX Input 1 Source */
+       { 0x00000978, 0x0000 }, /* R2424 (0x978) - DSP1AUX6MIX Input 1 Source */
+       { 0x00000980, 0x0000 }, /* R2432 (0x980) - DSP2LMIX Input 1 Source */
+       { 0x00000981, 0x0080 }, /* R2433 (0x981) - DSP2LMIX Input 1 Volume */
+       { 0x00000982, 0x0000 }, /* R2434 (0x982) - DSP2LMIX Input 2 Source */
+       { 0x00000983, 0x0080 }, /* R2435 (0x983) - DSP2LMIX Input 2 Volume */
+       { 0x00000984, 0x0000 }, /* R2436 (0x984) - DSP2LMIX Input 3 Source */
+       { 0x00000985, 0x0080 }, /* R2437 (0x985) - DSP2LMIX Input 3 Volume */
+       { 0x00000986, 0x0000 }, /* R2438 (0x986) - DSP2LMIX Input 4 Source */
+       { 0x00000987, 0x0080 }, /* R2439 (0x987) - DSP2LMIX Input 4 Volume */
+       { 0x00000988, 0x0000 }, /* R2440 (0x988) - DSP2RMIX Input 1 Source */
+       { 0x00000989, 0x0080 }, /* R2441 (0x989) - DSP2RMIX Input 1 Volume */
+       { 0x0000098a, 0x0000 }, /* R2442 (0x98a) - DSP2RMIX Input 2 Source */
+       { 0x0000098b, 0x0080 }, /* R2443 (0x98b) - DSP2RMIX Input 2 Volume */
+       { 0x0000098c, 0x0000 }, /* R2444 (0x98c) - DSP2RMIX Input 3 Source */
+       { 0x0000098d, 0x0080 }, /* R2445 (0x98d) - DSP2RMIX Input 3 Volume */
+       { 0x0000098e, 0x0000 }, /* R2446 (0x98e) - DSP2RMIX Input 4 Source */
+       { 0x0000098f, 0x0080 }, /* R2447 (0x98f) - DSP2RMIX Input 4 Volume */
+       { 0x00000990, 0x0000 }, /* R2448 (0x990) - DSP2AUX1MIX Input 1 Source */
+       { 0x00000998, 0x0000 }, /* R2456 (0x998) - DSP2AUX2MIX Input 1 Source */
+       { 0x000009a0, 0x0000 }, /* R2464 (0x9a0) - DSP2AUX3MIX Input 1 Source */
+       { 0x000009a8, 0x0000 }, /* R2472 (0x9a8) - DSP2AUX4MIX Input 1 Source */
+       { 0x000009b0, 0x0000 }, /* R2480 (0x9b0) - DSP2AUX5MIX Input 1 Source */
+       { 0x000009b8, 0x0000 }, /* R2488 (0x9b8) - DSP2AUX6MIX Input 1 Source */
+       { 0x000009c0, 0x0000 }, /* R2496 (0x9c0) - DSP3LMIX Input 1 Source */
+       { 0x000009c1, 0x0080 }, /* R2497 (0x9c1) - DSP3LMIX Input 1 Volume */
+       { 0x000009c2, 0x0000 }, /* R2498 (0x9c2) - DSP3LMIX Input 2 Source */
+       { 0x000009c3, 0x0080 }, /* R2499 (0x9c3) - DSP3LMIX Input 2 Volume */
+       { 0x000009c4, 0x0000 }, /* R2500 (0x9c4) - DSP3LMIX Input 3 Source */
+       { 0x000009c5, 0x0080 }, /* R2501 (0x9c5) - DSP3LMIX Input 3 Volume */
+       { 0x000009c6, 0x0000 }, /* R2502 (0x9c6) - DSP3LMIX Input 4 Source */
+       { 0x000009c7, 0x0080 }, /* R2503 (0x9c7) - DSP3LMIX Input 4 Volume */
+       { 0x000009c8, 0x0000 }, /* R2504 (0x9c8) - DSP3RMIX Input 1 Source */
+       { 0x000009c9, 0x0080 }, /* R2505 (0x9c9) - DSP3RMIX Input 1 Volume */
+       { 0x000009ca, 0x0000 }, /* R2506 (0x9ca) - DSP3RMIX Input 2 Source */
+       { 0x000009cb, 0x0080 }, /* R2507 (0x9cb) - DSP3RMIX Input 2 Volume */
+       { 0x000009cc, 0x0000 }, /* R2508 (0x9cc) - DSP3RMIX Input 3 Source */
+       { 0x000009cd, 0x0080 }, /* R2509 (0x9cd) - DSP3RMIX Input 3 Volume */
+       { 0x000009ce, 0x0000 }, /* R2510 (0x9ce) - DSP3RMIX Input 4 Source */
+       { 0x000009cf, 0x0080 }, /* R2511 (0x9cf) - DSP3RMIX Input 4 Volume */
+       { 0x000009d0, 0x0000 }, /* R2512 (0x9d0) - DSP3AUX1MIX Input 1 Source */
+       { 0x000009d8, 0x0000 }, /* R2520 (0x9d8) - DSP3AUX2MIX Input 1 Source */
+       { 0x000009e0, 0x0000 }, /* R2528 (0x9e0) - DSP3AUX3MIX Input 1 Source */
+       { 0x000009e8, 0x0000 }, /* R2536 (0x9e8) - DSP3AUX4MIX Input 1 Source */
+       { 0x000009f0, 0x0000 }, /* R2544 (0x9f0) - DSP3AUX5MIX Input 1 Source */
+       { 0x000009f8, 0x0000 }, /* R2552 (0x9f8) - DSP3AUX6MIX Input 1 Source */
+       { 0x00000a00, 0x0000 }, /* R2560 (0xa00) - DSP4LMIX Input 1 Source */
+       { 0x00000a01, 0x0080 }, /* R2561 (0xa01) - DSP4LMIX Input 1 Volume */
+       { 0x00000a02, 0x0000 }, /* R2562 (0xa02) - DSP4LMIX Input 2 Source */
+       { 0x00000a03, 0x0080 }, /* R2563 (0xa03) - DSP4LMIX Input 2 Volume */
+       { 0x00000a04, 0x0000 }, /* R2564 (0xa04) - DSP4LMIX Input 3 Source */
+       { 0x00000a05, 0x0080 }, /* R2565 (0xa05) - DSP4LMIX Input 3 Volume */
+       { 0x00000a06, 0x0000 }, /* R2566 (0xa06) - DSP4LMIX Input 4 Source */
+       { 0x00000a07, 0x0080 }, /* R2567 (0xa07) - DSP4LMIX Input 4 Volume */
+       { 0x00000a08, 0x0000 }, /* R2568 (0xa08) - DSP4RMIX Input 1 Source */
+       { 0x00000a09, 0x0080 }, /* R2569 (0xa09) - DSP4RMIX Input 1 Volume */
+       { 0x00000a0a, 0x0000 }, /* R2570 (0xa0a) - DSP4RMIX Input 2 Source */
+       { 0x00000a0b, 0x0080 }, /* R2571 (0xa0b) - DSP4RMIX Input 2 Volume */
+       { 0x00000a0c, 0x0000 }, /* R2572 (0xa0c) - DSP4RMIX Input 3 Source */
+       { 0x00000a0d, 0x0080 }, /* R2573 (0xa0d) - DSP4RMIX Input 3 Volume */
+       { 0x00000a0e, 0x0000 }, /* R2574 (0xa0e) - DSP4RMIX Input 4 Source */
+       { 0x00000a0f, 0x0080 }, /* R2575 (0xa0f) - DSP4RMIX Input 4 Volume */
+       { 0x00000a10, 0x0000 }, /* R2576 (0xa10) - DSP4AUX1MIX Input 1 Source */
+       { 0x00000a18, 0x0000 }, /* R2584 (0xa18) - DSP4AUX2MIX Input 1 Source */
+       { 0x00000a20, 0x0000 }, /* R2592 (0xa20) - DSP4AUX3MIX Input 1 Source */
+       { 0x00000a28, 0x0000 }, /* R2600 (0xa28) - DSP4AUX4MIX Input 1 Source */
+       { 0x00000a30, 0x0000 }, /* R2608 (0xa30) - DSP4AUX5MIX Input 1 Source */
+       { 0x00000a38, 0x0000 }, /* R2616 (0xa38) - DSP4AUX6MIX Input 1 Source */
+       { 0x00000a40, 0x0000 }, /* R2624 (0xa40) - DSP5LMIX Input 1 Source */
+       { 0x00000a41, 0x0080 }, /* R2625 (0xa41) - DSP5LMIX Input 1 Volume */
+       { 0x00000a42, 0x0000 }, /* R2626 (0xa42) - DSP5LMIX Input 2 Source */
+       { 0x00000a43, 0x0080 }, /* R2627 (0xa43) - DSP5LMIX Input 2 Volume */
+       { 0x00000a44, 0x0000 }, /* R2628 (0xa44) - DSP5LMIX Input 3 Source */
+       { 0x00000a45, 0x0080 }, /* R2629 (0xa45) - DSP5LMIX Input 3 Volume */
+       { 0x00000a46, 0x0000 }, /* R2630 (0xa46) - DSP5LMIX Input 4 Source */
+       { 0x00000a47, 0x0080 }, /* R2631 (0xa47) - DSP5LMIX Input 4 Volume */
+       { 0x00000a48, 0x0000 }, /* R2632 (0xa48) - DSP5RMIX Input 1 Source */
+       { 0x00000a49, 0x0080 }, /* R2633 (0xa49) - DSP5RMIX Input 1 Volume */
+       { 0x00000a4a, 0x0000 }, /* R2634 (0xa4a) - DSP5RMIX Input 2 Source */
+       { 0x00000a4b, 0x0080 }, /* R2635 (0xa4b) - DSP5RMIX Input 2 Volume */
+       { 0x00000a4c, 0x0000 }, /* R2636 (0xa4c) - DSP5RMIX Input 3 Source */
+       { 0x00000a4d, 0x0080 }, /* R2637 (0xa4d) - DSP5RMIX Input 3 Volume */
+       { 0x00000a4e, 0x0000 }, /* R2638 (0xa4e) - DSP5RMIX Input 4 Source */
+       { 0x00000a4f, 0x0080 }, /* R2639 (0xa4f) - DSP5RMIX Input 4 Volume */
+       { 0x00000a50, 0x0000 }, /* R2640 (0xa50) - DSP5AUX1MIX Input 1 Source */
+       { 0x00000a58, 0x0000 }, /* R2658 (0xa58) - DSP5AUX2MIX Input 1 Source */
+       { 0x00000a60, 0x0000 }, /* R2656 (0xa60) - DSP5AUX3MIX Input 1 Source */
+       { 0x00000a68, 0x0000 }, /* R2664 (0xa68) - DSP5AUX4MIX Input 1 Source */
+       { 0x00000a70, 0x0000 }, /* R2672 (0xa70) - DSP5AUX5MIX Input 1 Source */
+       { 0x00000a78, 0x0000 }, /* R2680 (0xa78) - DSP5AUX6MIX Input 1 Source */
+       { 0x00000a80, 0x0000 }, /* R2688 (0xa80) - ASRC1_1LMIX Input 1 Source */
+       { 0x00000a88, 0x0000 }, /* R2696 (0xa88) - ASRC1_1RMIX Input 1 Source */
+       { 0x00000a90, 0x0000 }, /* R2704 (0xa90) - ASRC1_2LMIX Input 1 Source */
+       { 0x00000a98, 0x0000 }, /* R2712 (0xa98) - ASRC1_2RMIX Input 1 Source */
+       { 0x00000aa0, 0x0000 }, /* R2720 (0xaa0) - ASRC2_1LMIX Input 1 Source */
+       { 0x00000aa8, 0x0000 }, /* R2728 (0xaa8) - ASRC2_1RMIX Input 1 Source */
+       { 0x00000ab0, 0x0000 }, /* R2736 (0xab0) - ASRC2_2LMIX Input 1 Source */
+       { 0x00000ab8, 0x0000 }, /* R2744 (0xab8) - ASRC2_2RMIX Input 1 Source */
+       { 0x00000b00, 0x0000 }, /* R2816 (0xb00) - ISRC1DEC1MIX Input 1 Source*/
+       { 0x00000b08, 0x0000 }, /* R2824 (0xb08) - ISRC1DEC2MIX Input 1 Source*/
+       { 0x00000b10, 0x0000 }, /* R2832 (0xb10) - ISRC1DEC3MIX Input 1 Source*/
+       { 0x00000b18, 0x0000 }, /* R2840 (0xb18) - ISRC1DEC4MIX Input 1 Source*/
+       { 0x00000b20, 0x0000 }, /* R2848 (0xb20) - ISRC1INT1MIX Input 1 Source*/
+       { 0x00000b28, 0x0000 }, /* R2856 (0xb28) - ISRC1INT2MIX Input 1 Source*/
+       { 0x00000b30, 0x0000 }, /* R2864 (0xb30) - ISRC1INT3MIX Input 1 Source*/
+       { 0x00000b38, 0x0000 }, /* R2872 (0xb38) - ISRC1INT4MIX Input 1 Source*/
+       { 0x00000b40, 0x0000 }, /* R2880 (0xb40) - ISRC2DEC1MIX Input 1 Source*/
+       { 0x00000b48, 0x0000 }, /* R2888 (0xb48) - ISRC2DEC2MIX Input 1 Source*/
+       { 0x00000b50, 0x0000 }, /* R2896 (0xb50) - ISRC2DEC3MIX Input 1 Source*/
+       { 0x00000b58, 0x0000 }, /* R2904 (0xb58) - ISRC2DEC4MIX Input 1 Source*/
+       { 0x00000b60, 0x0000 }, /* R2912 (0xb60) - ISRC2INT1MIX Input 1 Source*/
+       { 0x00000b68, 0x0000 }, /* R2920 (0xb68) - ISRC2INT2MIX Input 1 Source*/
+       { 0x00000b70, 0x0000 }, /* R2928 (0xb70) - ISRC2INT3MIX Input 1 Source*/
+       { 0x00000b78, 0x0000 }, /* R2936 (0xb78) - ISRC2INT4MIX Input 1 Source*/
+       { 0x00000b80, 0x0000 }, /* R2944 (0xb80) - ISRC3DEC1MIX Input 1 Source*/
+       { 0x00000b88, 0x0000 }, /* R2952 (0xb88) - ISRC3DEC2MIX Input 1 Source*/
+       { 0x00000ba0, 0x0000 }, /* R2976 (0xb80) - ISRC3INT1MIX Input 1 Source*/
+       { 0x00000ba8, 0x0000 }, /* R2984 (0xb88) - ISRC3INT2MIX Input 1 Source*/
+       { 0x00000bc0, 0x0000 }, /* R3008 (0xbc0) - ISRC4DEC1MIX Input 1 Source */
+       { 0x00000bc8, 0x0000 }, /* R3016 (0xbc8) - ISRC4DEC2MIX Input 1 Source */
+       { 0x00000be0, 0x0000 }, /* R3040 (0xbe0) - ISRC4INT1MIX Input 1 Source */
+       { 0x00000be8, 0x0000 }, /* R3048 (0xbe8) - ISRC4INT2MIX Input 1 Source */
+       { 0x00000c00, 0x0000 }, /* R3072 (0xc00) - DSP6LMIX Input 1 Source */
+       { 0x00000c01, 0x0080 }, /* R3073 (0xc01) - DSP6LMIX Input 1 Volume */
+       { 0x00000c02, 0x0000 }, /* R3074 (0xc02) - DSP6LMIX Input 2 Source */
+       { 0x00000c03, 0x0080 }, /* R3075 (0xc03) - DSP6LMIX Input 2 Volume */
+       { 0x00000c04, 0x0000 }, /* R3076 (0xc04) - DSP6LMIX Input 3 Source */
+       { 0x00000c05, 0x0080 }, /* R3077 (0xc05) - DSP6LMIX Input 3 Volume */
+       { 0x00000c06, 0x0000 }, /* R3078 (0xc06) - DSP6LMIX Input 4 Source */
+       { 0x00000c07, 0x0080 }, /* R3079 (0xc07) - DSP6LMIX Input 4 Volume */
+       { 0x00000c08, 0x0000 }, /* R3080 (0xc08) - DSP6RMIX Input 1 Source */
+       { 0x00000c09, 0x0080 }, /* R3081 (0xc09) - DSP6RMIX Input 1 Volume */
+       { 0x00000c0a, 0x0000 }, /* R3082 (0xc0a) - DSP6RMIX Input 2 Source */
+       { 0x00000c0b, 0x0080 }, /* R3083 (0xc0b) - DSP6RMIX Input 2 Volume */
+       { 0x00000c0c, 0x0000 }, /* R3084 (0xc0c) - DSP6RMIX Input 3 Source */
+       { 0x00000c0d, 0x0080 }, /* R3085 (0xc0d) - DSP6RMIX Input 3 Volume */
+       { 0x00000c0e, 0x0000 }, /* R3086 (0xc0e) - DSP6RMIX Input 4 Source */
+       { 0x00000c0f, 0x0080 }, /* R3087 (0xc0f) - DSP6RMIX Input 4 Volume */
+       { 0x00000c10, 0x0000 }, /* R3088 (0xc10) - DSP6AUX1MIX Input 1 Source */
+       { 0x00000c18, 0x0000 }, /* R3088 (0xc18) - DSP6AUX2MIX Input 1 Source */
+       { 0x00000c20, 0x0000 }, /* R3088 (0xc20) - DSP6AUX3MIX Input 1 Source */
+       { 0x00000c28, 0x0000 }, /* R3088 (0xc28) - DSP6AUX4MIX Input 1 Source */
+       { 0x00000c30, 0x0000 }, /* R3088 (0xc30) - DSP6AUX5MIX Input 1 Source */
+       { 0x00000c38, 0x0000 }, /* R3088 (0xc38) - DSP6AUX6MIX Input 1 Source */
+       { 0x00000c40, 0x0000 }, /* R3136 (0xc40) - DSP7LMIX Input 1 Source */
+       { 0x00000c41, 0x0080 }, /* R3137 (0xc41) - DSP7LMIX Input 1 Volume */
+       { 0x00000c42, 0x0000 }, /* R3138 (0xc42) - DSP7LMIX Input 2 Source */
+       { 0x00000c43, 0x0080 }, /* R3139 (0xc43) - DSP7LMIX Input 2 Volume */
+       { 0x00000c44, 0x0000 }, /* R3140 (0xc44) - DSP7LMIX Input 3 Source */
+       { 0x00000c45, 0x0080 }, /* R3141 (0xc45) - DSP7lMIX Input 3 Volume */
+       { 0x00000c46, 0x0000 }, /* R3142 (0xc46) - DSP7lMIX Input 4 Source */
+       { 0x00000c47, 0x0080 }, /* R3143 (0xc47) - DSP7LMIX Input 4 Volume */
+       { 0x00000c48, 0x0000 }, /* R3144 (0xc48) - DSP7RMIX Input 1 Source */
+       { 0x00000c49, 0x0080 }, /* R3145 (0xc49) - DSP7RMIX Input 1 Volume */
+       { 0x00000c4a, 0x0000 }, /* R3146 (0xc4a) - DSP7RMIX Input 2 Source */
+       { 0x00000c4b, 0x0080 }, /* R3147 (0xc4b) - DSP7RMIX Input 2 Volume */
+       { 0x00000c4c, 0x0000 }, /* R3148 (0xc4c) - DSP7RMIX Input 3 Source */
+       { 0x00000c4d, 0x0080 }, /* R3159 (0xc4d) - DSP7RMIX Input 3 Volume */
+       { 0x00000c4e, 0x0000 }, /* R3150 (0xc4e) - DSP7RMIX Input 4 Source */
+       { 0x00000c4f, 0x0080 }, /* R3151 (0xc4f) - DSP7RMIX Input 4 Volume */
+       { 0x00000c50, 0x0000 }, /* R3152 (0xc50) - DSP7AUX1MIX Input 1 Source */
+       { 0x00000c58, 0x0000 }, /* R3160 (0xc58) - DSP7AUX2MIX Input 1 Source */
+       { 0x00000c60, 0x0000 }, /* R3168 (0xc60) - DSP7AUX3MIX Input 1 Source */
+       { 0x00000c68, 0x0000 }, /* R3176 (0xc68) - DSP7AUX4MIX Input 1 Source */
+       { 0x00000c70, 0x0000 }, /* R3184 (0xc70) - DSP7AUX5MIX Input 1 Source */
+       { 0x00000c78, 0x0000 }, /* R3192 (0xc78) - DSP7AUX6MIX Input 1 Source */
+       { 0x00000e00, 0x0000 }, /* R3584 (0xe00) - FX Ctrl1 */
+       { 0x00000e10, 0x6318 }, /* R3600 (0xe10) - EQ1_1 */
+       { 0x00000e11, 0x6300 }, /* R3601 (0xe11) - EQ1_2 */
+       { 0x00000e12, 0x0fc8 }, /* R3602 (0xe12) - EQ1_3 */
+       { 0x00000e13, 0x03fe }, /* R3603 (0xe13) - EQ1_4 */
+       { 0x00000e14, 0x00e0 }, /* R3604 (0xe14) - EQ1_5 */
+       { 0x00000e15, 0x1ec4 }, /* R3605 (0xe15) - EQ1_6 */
+       { 0x00000e16, 0xf136 }, /* R3606 (0xe16) - EQ1_7 */
+       { 0x00000e17, 0x0409 }, /* R3607 (0xe17) - EQ1_8 */
+       { 0x00000e18, 0x04cc }, /* R3608 (0xe18) - EQ1_9 */
+       { 0x00000e19, 0x1c9b }, /* R3609 (0xe19) - EQ1_10 */
+       { 0x00000e1a, 0xf337 }, /* R3610 (0xe1a) - EQ1_11 */
+       { 0x00000e1b, 0x040b }, /* R3611 (0xe1b) - EQ1_12 */
+       { 0x00000e1c, 0x0cbb }, /* R3612 (0xe1c) - EQ1_13 */
+       { 0x00000e1d, 0x16f8 }, /* R3613 (0xe1d) - EQ1_14 */
+       { 0x00000e1e, 0xf7d9 }, /* R3614 (0xe1e) - EQ1_15 */
+       { 0x00000e1f, 0x040a }, /* R3615 (0xe1f) - EQ1_16 */
+       { 0x00000e20, 0x1f14 }, /* R3616 (0xe20) - EQ1_17 */
+       { 0x00000e21, 0x058c }, /* R3617 (0xe21) - EQ1_18 */
+       { 0x00000e22, 0x0563 }, /* R3618 (0xe22) - EQ1_19 */
+       { 0x00000e23, 0x4000 }, /* R3619 (0xe23) - EQ1_20 */
+       { 0x00000e24, 0x0b75 }, /* R3620 (0xe24) - EQ1_21 */
+       { 0x00000e26, 0x6318 }, /* R3622 (0xe26) - EQ2_1 */
+       { 0x00000e27, 0x6300 }, /* R3623 (0xe27) - EQ2_2 */
+       { 0x00000e28, 0x0fc8 }, /* R3624 (0xe28) - EQ2_3 */
+       { 0x00000e29, 0x03fe }, /* R3625 (0xe29) - EQ2_4 */
+       { 0x00000e2a, 0x00e0 }, /* R3626 (0xe2a) - EQ2_5 */
+       { 0x00000e2b, 0x1ec4 }, /* R3627 (0xe2b) - EQ2_6 */
+       { 0x00000e2c, 0xf136 }, /* R3628 (0xe2c) - EQ2_7 */
+       { 0x00000e2d, 0x0409 }, /* R3629 (0xe2d) - EQ2_8 */
+       { 0x00000e2e, 0x04cc }, /* R3630 (0xe2e) - EQ2_9 */
+       { 0x00000e2f, 0x1c9b }, /* R3631 (0xe2f) - EQ2_10 */
+       { 0x00000e30, 0xf337 }, /* R3632 (0xe30) - EQ2_11 */
+       { 0x00000e31, 0x040b }, /* R3633 (0xe31) - EQ2_12 */
+       { 0x00000e32, 0x0cbb }, /* R3634 (0xe32) - EQ2_13 */
+       { 0x00000e33, 0x16f8 }, /* R3635 (0xe33) - EQ2_14 */
+       { 0x00000e34, 0xf7d9 }, /* R3636 (0xe34) - EQ2_15 */
+       { 0x00000e35, 0x040a }, /* R3637 (0xe35) - EQ2_16 */
+       { 0x00000e36, 0x1f14 }, /* R3638 (0xe36) - EQ2_17 */
+       { 0x00000e37, 0x058c }, /* R3639 (0xe37) - EQ2_18 */
+       { 0x00000e38, 0x0563 }, /* R3640 (0xe38) - EQ2_19 */
+       { 0x00000e39, 0x4000 }, /* R3641 (0xe39) - EQ2_20 */
+       { 0x00000e3a, 0x0b75 }, /* R3642 (0xe3a) - EQ2_21 */
+       { 0x00000e3c, 0x6318 }, /* R3644 (0xe3c) - EQ3_1 */
+       { 0x00000e3d, 0x6300 }, /* R3645 (0xe3d) - EQ3_2 */
+       { 0x00000e3e, 0x0fc8 }, /* R3646 (0xe3e) - EQ3_3 */
+       { 0x00000e3f, 0x03fe }, /* R3647 (0xe3f) - EQ3_4 */
+       { 0x00000e40, 0x00e0 }, /* R3648 (0xe40) - EQ3_5 */
+       { 0x00000e41, 0x1ec4 }, /* R3649 (0xe41) - EQ3_6 */
+       { 0x00000e42, 0xf136 }, /* R3650 (0xe42) - EQ3_7 */
+       { 0x00000e43, 0x0409 }, /* R3651 (0xe43) - EQ3_8 */
+       { 0x00000e44, 0x04cc }, /* R3652 (0xe44) - EQ3_9 */
+       { 0x00000e45, 0x1c9b }, /* R3653 (0xe45) - EQ3_10 */
+       { 0x00000e46, 0xf337 }, /* R3654 (0xe46) - EQ3_11 */
+       { 0x00000e47, 0x040b }, /* R3655 (0xe47) - EQ3_12 */
+       { 0x00000e48, 0x0cbb }, /* R3656 (0xe48) - EQ3_13 */
+       { 0x00000e49, 0x16f8 }, /* R3657 (0xe49) - EQ3_14 */
+       { 0x00000e4a, 0xf7d9 }, /* R3658 (0xe4a) - EQ3_15 */
+       { 0x00000e4b, 0x040a }, /* R3659 (0xe4b) - EQ3_16 */
+       { 0x00000e4c, 0x1f14 }, /* R3660 (0xe4c) - EQ3_17 */
+       { 0x00000e4d, 0x058c }, /* R3661 (0xe4d) - EQ3_18 */
+       { 0x00000e4e, 0x0563 }, /* R3662 (0xe4e) - EQ3_19 */
+       { 0x00000e4f, 0x4000 }, /* R3663 (0xe4f) - EQ3_20 */
+       { 0x00000e50, 0x0b75 }, /* R3664 (0xe50) - EQ3_21 */
+       { 0x00000e52, 0x6318 }, /* R3666 (0xe52) - EQ4_1 */
+       { 0x00000e53, 0x6300 }, /* R3667 (0xe53) - EQ4_2 */
+       { 0x00000e54, 0x0fc8 }, /* R3668 (0xe54) - EQ4_3 */
+       { 0x00000e55, 0x03fe }, /* R3669 (0xe55) - EQ4_4 */
+       { 0x00000e56, 0x00e0 }, /* R3670 (0xe56) - EQ4_5 */
+       { 0x00000e57, 0x1ec4 }, /* R3671 (0xe57) - EQ4_6 */
+       { 0x00000e58, 0xf136 }, /* R3672 (0xe58) - EQ4_7 */
+       { 0x00000e59, 0x0409 }, /* R3673 (0xe59) - EQ4_8 */
+       { 0x00000e5a, 0x04cc }, /* R3674 (0xe5a) - EQ4_9 */
+       { 0x00000e5b, 0x1c9b }, /* R3675 (0xe5b) - EQ4_10 */
+       { 0x00000e5c, 0xf337 }, /* R3676 (0xe5c) - EQ4_11 */
+       { 0x00000e5d, 0x040b }, /* R3677 (0xe5d) - EQ4_12 */
+       { 0x00000e5e, 0x0cbb }, /* R3678 (0xe5e) - EQ4_13 */
+       { 0x00000e5f, 0x16f8 }, /* R3679 (0xe5f) - EQ4_14 */
+       { 0x00000e60, 0xf7d9 }, /* R3680 (0xe60) - EQ4_15 */
+       { 0x00000e61, 0x040a }, /* R3681 (0xe61) - EQ4_16 */
+       { 0x00000e62, 0x1f14 }, /* R3682 (0xe62) - EQ4_17 */
+       { 0x00000e63, 0x058c }, /* R3683 (0xe63) - EQ4_18 */
+       { 0x00000e64, 0x0563 }, /* R3684 (0xe64) - EQ4_19 */
+       { 0x00000e65, 0x4000 }, /* R3685 (0xe65) - EQ4_20 */
+       { 0x00000e66, 0x0b75 }, /* R3686 (0xe66) - EQ4_21 */
+       { 0x00000e80, 0x0018 }, /* R3712 (0xe80) - DRC1 ctrl1 */
+       { 0x00000e81, 0x0933 }, /* R3713 (0xe81) - DRC1 ctrl2 */
+       { 0x00000e82, 0x0018 }, /* R3714 (0xe82) - DRC1 ctrl3 */
+       { 0x00000e83, 0x0000 }, /* R3715 (0xe83) - DRC1 ctrl4 */
+       { 0x00000e84, 0x0000 }, /* R3716 (0xe84) - DRC1 ctrl5 */
+       { 0x00000e88, 0x0933 }, /* R3720 (0xe88) - DRC2 ctrl1 */
+       { 0x00000e89, 0x0018 }, /* R3721 (0xe89) - DRC2 ctrl2 */
+       { 0x00000e8a, 0x0000 }, /* R3722 (0xe8a) - DRC2 ctrl3 */
+       { 0x00000e8b, 0x0000 }, /* R3723 (0xe8b) - DRC2 ctrl4 */
+       { 0x00000e8c, 0x0040 }, /* R3724 (0xe8c) - DRC2 ctrl5 */
+       { 0x00000ec0, 0x0000 }, /* R3776 (0xec0) - HPLPF1_1 */
+       { 0x00000ec1, 0x0000 }, /* R3777 (0xec1) - HPLPF1_2 */
+       { 0x00000ec4, 0x0000 }, /* R3780 (0xec4) - HPLPF2_1 */
+       { 0x00000ec5, 0x0000 }, /* R3781 (0xec5) - HPLPF2_2 */
+       { 0x00000ec8, 0x0000 }, /* R3784 (0xec8) - HPLPF3_1 */
+       { 0x00000ec9, 0x0000 }, /* R3785 (0xec9) - HPLPF3_2 */
+       { 0x00000ecc, 0x0000 }, /* R3788 (0xecc) - HPLPF4_1 */
+       { 0x00000ecd, 0x0000 }, /* R3789 (0xecd) - HPLPF4_2 */
+       { 0x00000ed0, 0x0000 }, /* R3792 (0xed0) - ASRC2_ENABLE */
+       { 0x00000ed2, 0x0000 }, /* R3794 (0xed2) - ASRC2_RATE1 */
+       { 0x00000ed3, 0x4000 }, /* R3795 (0xed3) - ASRC2_RATE2 */
+       { 0x00000ee0, 0x0000 }, /* R3808 (0xee0) - ASRC1_ENABLE */
+       { 0x00000ee2, 0x0000 }, /* R3810 (0xee2) - ASRC1_RATE1 */
+       { 0x00000ee3, 0x4000 }, /* R3811 (0xee3) - ASRC1_RATE2 */
+       { 0x00000ef0, 0x0000 }, /* R3824 (0xef0) - ISRC 1 CTRL 1 */
+       { 0x00000ef1, 0x0001 }, /* R3825 (0xef1) - ISRC 1 CTRL 2 */
+       { 0x00000ef2, 0x0000 }, /* R3826 (0xef2) - ISRC 1 CTRL 3 */
+       { 0x00000ef3, 0x0000 }, /* R3827 (0xef3) - ISRC 2 CTRL 1 */
+       { 0x00000ef4, 0x0001 }, /* R3828 (0xef4) - ISRC 2 CTRL 2 */
+       { 0x00000ef5, 0x0000 }, /* R3829 (0xef5) - ISRC 2 CTRL 3 */
+       { 0x00000ef6, 0x0000 }, /* R3830 (0xef6) - ISRC 3 CTRL 1 */
+       { 0x00000ef7, 0x0001 }, /* R3831 (0xef7) - ISRC 3 CTRL 2 */
+       { 0x00000ef8, 0x0000 }, /* R3832 (0xef8) - ISRC 3 CTRL 3 */
+       { 0x00000ef9, 0x0000 }, /* R3833 (0xef9) - ISRC 4 CTRL 1 */
+       { 0x00000efa, 0x0001 }, /* R3834 (0xefa) - ISRC 4 CTRL 2 */
+       { 0x00000efb, 0x0000 }, /* R3835 (0xefb) - ISRC 4 CTRL 3 */
+       { 0x00000f01, 0x0000 }, /* R3841 (0xf01) - ANC_SRC */
+       { 0x00000f02, 0x0000 }, /* R3842 (0xf02) - DSP Status */
+       { 0x00000f08, 0x001c }, /* R3848 (0xf08) - ANC Coefficient */
+       { 0x00000f09, 0x0000 }, /* R3849 (0xf09) - ANC Coefficient */
+       { 0x00000f0a, 0x0000 }, /* R3850 (0xf0a) - ANC Coefficient */
+       { 0x00000f0b, 0x0000 }, /* R3851 (0xf0b) - ANC Coefficient */
+       { 0x00000f0c, 0x0000 }, /* R3852 (0xf0c) - ANC Coefficient */
+       { 0x00000f0d, 0x0000 }, /* R3853 (0xf0d) - ANC Coefficient */
+       { 0x00000f0e, 0x0000 }, /* R3854 (0xf0e) - ANC Coefficient */
+       { 0x00000f0f, 0x0000 }, /* R3855 (0xf0f) - ANC Coefficient */
+       { 0x00000f10, 0x0000 }, /* R3856 (0xf10) - ANC Coefficient */
+       { 0x00000f11, 0x0000 }, /* R3857 (0xf11) - ANC Coefficient */
+       { 0x00000f12, 0x0000 }, /* R3858 (0xf12) - ANC Coefficient */
+       { 0x00000f15, 0x0000 }, /* R3861 (0xf15) - FCL Filter Control */
+       { 0x00000f17, 0x0004 }, /* R3863 (0xf17) - FCL ADC Reformatter Control */
+       { 0x00000f18, 0x0004 }, /* R3864 (0xf18) - ANC Coefficient */
+       { 0x00000f19, 0x0002 }, /* R3865 (0xf19) - ANC Coefficient */
+       { 0x00000f1a, 0x0000 }, /* R3866 (0xf1a) - ANC Coefficient */
+       { 0x00000f1b, 0x0010 }, /* R3867 (0xf1b) - ANC Coefficient */
+       { 0x00000f1c, 0x0000 }, /* R3868 (0xf1c) - ANC Coefficient */
+       { 0x00000f1d, 0x0000 }, /* R3869 (0xf1d) - ANC Coefficient */
+       { 0x00000f1e, 0x0000 }, /* R3870 (0xf1e) - ANC Coefficient */
+       { 0x00000f1f, 0x0000 }, /* R3871 (0xf1f) - ANC Coefficient */
+       { 0x00000f20, 0x0000 }, /* R3872 (0xf20) - ANC Coefficient */
+       { 0x00000f21, 0x0000 }, /* R3873 (0xf21) - ANC Coefficient */
+       { 0x00000f22, 0x0000 }, /* R3874 (0xf22) - ANC Coefficient */
+       { 0x00000f23, 0x0000 }, /* R3875 (0xf23) - ANC Coefficient */
+       { 0x00000f24, 0x0000 }, /* R3876 (0xf24) - ANC Coefficient */
+       { 0x00000f25, 0x0000 }, /* R3877 (0xf25) - ANC Coefficient */
+       { 0x00000f26, 0x0000 }, /* R3878 (0xf26) - ANC Coefficient */
+       { 0x00000f27, 0x0000 }, /* R3879 (0xf27) - ANC Coefficient */
+       { 0x00000f28, 0x0000 }, /* R3880 (0xf28) - ANC Coefficient */
+       { 0x00000f29, 0x0000 }, /* R3881 (0xf29) - ANC Coefficient */
+       { 0x00000f2a, 0x0000 }, /* R3882 (0xf2a) - ANC Coefficient */
+       { 0x00000f2b, 0x0000 }, /* R3883 (0xf2b) - ANC Coefficient */
+       { 0x00000f2c, 0x0000 }, /* R3884 (0xf2c) - ANC Coefficient */
+       { 0x00000f2d, 0x0000 }, /* R3885 (0xf2d) - ANC Coefficient */
+       { 0x00000f2e, 0x0000 }, /* R3886 (0xf2e) - ANC Coefficient */
+       { 0x00000f2f, 0x0000 }, /* R3887 (0xf2f) - ANC Coefficient */
+       { 0x00000f30, 0x0000 }, /* R3888 (0xf30) - ANC Coefficient */
+       { 0x00000f31, 0x0000 }, /* R3889 (0xf31) - ANC Coefficient */
+       { 0x00000f32, 0x0000 }, /* R3890 (0xf32) - ANC Coefficient */
+       { 0x00000f33, 0x0000 }, /* R3891 (0xf33) - ANC Coefficient */
+       { 0x00000f34, 0x0000 }, /* R3892 (0xf34) - ANC Coefficient */
+       { 0x00000f35, 0x0000 }, /* R3893 (0xf35) - ANC Coefficient */
+       { 0x00000f36, 0x0000 }, /* R3894 (0xf36) - ANC Coefficient */
+       { 0x00000f37, 0x0000 }, /* R3895 (0xf37) - ANC Coefficient */
+       { 0x00000f38, 0x0000 }, /* R3896 (0xf38) - ANC Coefficient */
+       { 0x00000f39, 0x0000 }, /* R3897 (0xf39) - ANC Coefficient */
+       { 0x00000f3a, 0x0000 }, /* R3898 (0xf3a) - ANC Coefficient */
+       { 0x00000f3b, 0x0000 }, /* R3899 (0xf3b) - ANC Coefficient */
+       { 0x00000f3c, 0x0000 }, /* R3900 (0xf3c) - ANC Coefficient */
+       { 0x00000f3d, 0x0000 }, /* R3901 (0xf3d) - ANC Coefficient */
+       { 0x00000f3e, 0x0000 }, /* R3902 (0xf3e) - ANC Coefficient */
+       { 0x00000f3f, 0x0000 }, /* R3903 (0xf3f) - ANC Coefficient */
+       { 0x00000f40, 0x0000 }, /* R3904 (0xf40) - ANC Coefficient */
+       { 0x00000f41, 0x0000 }, /* R3905 (0xf41) - ANC Coefficient */
+       { 0x00000f42, 0x0000 }, /* R3906 (0xf42) - ANC Coefficient */
+       { 0x00000f43, 0x0000 }, /* R3907 (0xf43) - ANC Coefficient */
+       { 0x00000f44, 0x0000 }, /* R3908 (0xf44) - ANC Coefficient */
+       { 0x00000f45, 0x0000 }, /* R3909 (0xf45) - ANC Coefficient */
+       { 0x00000f46, 0x0000 }, /* R3910 (0xf46) - ANC Coefficient */
+       { 0x00000f47, 0x0000 }, /* R3911 (0xf47) - ANC Coefficient */
+       { 0x00000f48, 0x0000 }, /* R3912 (0xf48) - ANC Coefficient */
+       { 0x00000f49, 0x0000 }, /* R3913 (0xf49) - ANC Coefficient */
+       { 0x00000f4a, 0x0000 }, /* R3914 (0xf4a) - ANC Coefficient */
+       { 0x00000f4b, 0x0000 }, /* R3915 (0xf4b) - ANC Coefficient */
+       { 0x00000f4c, 0x0000 }, /* R3916 (0xf4c) - ANC Coefficient */
+       { 0x00000f4d, 0x0000 }, /* R3917 (0xf4d) - ANC Coefficient */
+       { 0x00000f4e, 0x0000 }, /* R3918 (0xf4e) - ANC Coefficient */
+       { 0x00000f4f, 0x0000 }, /* R3919 (0xf4f) - ANC Coefficient */
+       { 0x00000f50, 0x0000 }, /* R3920 (0xf50) - ANC Coefficient */
+       { 0x00000f51, 0x0000 }, /* R3921 (0xf51) - ANC Coefficient */
+       { 0x00000f52, 0x0000 }, /* R3922 (0xf52) - ANC Coefficient */
+       { 0x00000f53, 0x0000 }, /* R3923 (0xf53) - ANC Coefficient */
+       { 0x00000f54, 0x0000 }, /* R3924 (0xf54) - ANC Coefficient */
+       { 0x00000f55, 0x0000 }, /* R3925 (0xf55) - ANC Coefficient */
+       { 0x00000f56, 0x0000 }, /* R3926 (0xf56) - ANC Coefficient */
+       { 0x00000f57, 0x0000 }, /* R3927 (0xf57) - ANC Coefficient */
+       { 0x00000f58, 0x0000 }, /* R3928 (0xf58) - ANC Coefficient */
+       { 0x00000f59, 0x0000 }, /* R3929 (0xf59) - ANC Coefficient */
+       { 0x00000f5a, 0x0000 }, /* R3930 (0xf5a) - ANC Coefficient */
+       { 0x00000f5b, 0x0000 }, /* R3931 (0xf5b) - ANC Coefficient */
+       { 0x00000f5c, 0x0000 }, /* R3932 (0xf5c) - ANC Coefficient */
+       { 0x00000f5d, 0x0000 }, /* R3933 (0xf5d) - ANC Coefficient */
+       { 0x00000f5e, 0x0000 }, /* R3934 (0xf5e) - ANC Coefficient */
+       { 0x00000f5f, 0x0000 }, /* R3935 (0xf5f) - ANC Coefficient */
+       { 0x00000f60, 0x0000 }, /* R3936 (0xf60) - ANC Coefficient */
+       { 0x00000f61, 0x0000 }, /* R3937 (0xf61) - ANC Coefficient */
+       { 0x00000f62, 0x0000 }, /* R3938 (0xf62) - ANC Coefficient */
+       { 0x00000f63, 0x0000 }, /* R3939 (0xf63) - ANC Coefficient */
+       { 0x00000f64, 0x0000 }, /* R3940 (0xf64) - ANC Coefficient */
+       { 0x00000f65, 0x0000 }, /* R3941 (0xf65) - ANC Coefficient */
+       { 0x00000f66, 0x0000 }, /* R3942 (0xf66) - ANC Coefficient */
+       { 0x00000f67, 0x0000 }, /* R3943 (0xf67) - ANC Coefficient */
+       { 0x00000f68, 0x0000 }, /* R3944 (0xf68) - ANC Coefficient */
+       { 0x00000f69, 0x0000 }, /* R3945 (0xf69) - ANC Coefficient */
+       { 0x00000f71, 0x0000 }, /* R3953 (0xf71) - FCR Filter Control */
+       { 0x00000f73, 0x0004 }, /* R3955 (0xf73) - FCR ADC Reformatter Control */
+       { 0x00000f74, 0x0004 }, /* R3956 (0xf74) - ANC Coefficient */
+       { 0x00000f75, 0x0002 }, /* R3957 (0xf75) - ANC Coefficient */
+       { 0x00000f76, 0x0000 }, /* R3958 (0xf76) - ANC Coefficient */
+       { 0x00000f77, 0x0010 }, /* R3959 (0xf77) - ANC Coefficient */
+       { 0x00000f78, 0x0000 }, /* R3960 (0xf78) - ANC Coefficient */
+       { 0x00000f79, 0x0000 }, /* R3961 (0xf79) - ANC Coefficient */
+       { 0x00000f7a, 0x0000 }, /* R3962 (0xf7a) - ANC Coefficient */
+       { 0x00000f7b, 0x0000 }, /* R3963 (0xf7b) - ANC Coefficient */
+       { 0x00000f7c, 0x0000 }, /* R3964 (0xf7c) - ANC Coefficient */
+       { 0x00000f7d, 0x0000 }, /* R3965 (0xf7d) - ANC Coefficient */
+       { 0x00000f7e, 0x0000 }, /* R3966 (0xf7e) - ANC Coefficient */
+       { 0x00000f7f, 0x0000 }, /* R3967 (0xf7f) - ANC Coefficient */
+       { 0x00000f80, 0x0000 }, /* R3968 (0xf80) - ANC Coefficient */
+       { 0x00000f81, 0x0000 }, /* R3969 (0xf81) - ANC Coefficient */
+       { 0x00000f82, 0x0000 }, /* R3970 (0xf82) - ANC Coefficient */
+       { 0x00000f83, 0x0000 }, /* R3971 (0xf83) - ANC Coefficient */
+       { 0x00000f84, 0x0000 }, /* R3972 (0xf84) - ANC Coefficient */
+       { 0x00000f85, 0x0000 }, /* R3973 (0xf85) - ANC Coefficient */
+       { 0x00000f86, 0x0000 }, /* R3974 (0xf86) - ANC Coefficient */
+       { 0x00000f87, 0x0000 }, /* R3975 (0xf87) - ANC Coefficient */
+       { 0x00000f88, 0x0000 }, /* R3976 (0xf88) - ANC Coefficient */
+       { 0x00000f89, 0x0000 }, /* R3977 (0xf89) - ANC Coefficient */
+       { 0x00000f8a, 0x0000 }, /* R3978 (0xf8a) - ANC Coefficient */
+       { 0x00000f8b, 0x0000 }, /* R3979 (0xf8b) - ANC Coefficient */
+       { 0x00000f8c, 0x0000 }, /* R3980 (0xf8c) - ANC Coefficient */
+       { 0x00000f8d, 0x0000 }, /* R3981 (0xf8d) - ANC Coefficient */
+       { 0x00000f8e, 0x0000 }, /* R3982 (0xf8e) - ANC Coefficient */
+       { 0x00000f8f, 0x0000 }, /* R3983 (0xf8f) - ANC Coefficient */
+       { 0x00000f90, 0x0000 }, /* R3984 (0xf90) - ANC Coefficient */
+       { 0x00000f91, 0x0000 }, /* R3985 (0xf91) - ANC Coefficient */
+       { 0x00000f92, 0x0000 }, /* R3986 (0xf92) - ANC Coefficient */
+       { 0x00000f93, 0x0000 }, /* R3987 (0xf93) - ANC Coefficient */
+       { 0x00000f94, 0x0000 }, /* R3988 (0xf94) - ANC Coefficient */
+       { 0x00000f95, 0x0000 }, /* R3989 (0xf95) - ANC Coefficient */
+       { 0x00000f96, 0x0000 }, /* R3990 (0xf96) - ANC Coefficient */
+       { 0x00000f97, 0x0000 }, /* R3991 (0xf97) - ANC Coefficient */
+       { 0x00000f98, 0x0000 }, /* R3992 (0xf98) - ANC Coefficient */
+       { 0x00000f99, 0x0000 }, /* R3993 (0xf99) - ANC Coefficient */
+       { 0x00000f9a, 0x0000 }, /* R3994 (0xf9a) - ANC Coefficient */
+       { 0x00000f9b, 0x0000 }, /* R3995 (0xf9b) - ANC Coefficient */
+       { 0x00000f9c, 0x0000 }, /* R3996 (0xf9c) - ANC Coefficient */
+       { 0x00000f9d, 0x0000 }, /* R3997 (0xf9d) - ANC Coefficient */
+       { 0x00000f9e, 0x0000 }, /* R3998 (0xf9e) - ANC Coefficient */
+       { 0x00000f9f, 0x0000 }, /* R3999 (0xf9f) - ANC Coefficient */
+       { 0x00000fa0, 0x0000 }, /* R4000 (0xfa0) - ANC Coefficient */
+       { 0x00000fa1, 0x0000 }, /* R4001 (0xfa1) - ANC Coefficient */
+       { 0x00000fa2, 0x0000 }, /* R4002 (0xfa2) - ANC Coefficient */
+       { 0x00000fa3, 0x0000 }, /* R4003 (0xfa3) - ANC Coefficient */
+       { 0x00000fa4, 0x0000 }, /* R4004 (0xfa4) - ANC Coefficient */
+       { 0x00000fa5, 0x0000 }, /* R4005 (0xfa5) - ANC Coefficient */
+       { 0x00000fa6, 0x0000 }, /* R4006 (0xfa6) - ANC Coefficient */
+       { 0x00000fa7, 0x0000 }, /* R4007 (0xfa7) - ANC Coefficient */
+       { 0x00000fa8, 0x0000 }, /* R4008 (0xfa8) - ANC Coefficient */
+       { 0x00000fa9, 0x0000 }, /* R4009 (0xfa9) - ANC Coefficient */
+       { 0x00000faa, 0x0000 }, /* R4010 (0xfaa) - ANC Coefficient */
+       { 0x00000fab, 0x0000 }, /* R4011 (0xfab) - ANC Coefficient */
+       { 0x00000fac, 0x0000 }, /* R4012 (0xfac) - ANC Coefficient */
+       { 0x00000fad, 0x0000 }, /* R4013 (0xfad) - ANC Coefficient */
+       { 0x00000fae, 0x0000 }, /* R4014 (0xfae) - ANC Coefficient */
+       { 0x00000faf, 0x0000 }, /* R4015 (0xfaf) - ANC Coefficient */
+       { 0x00000fb0, 0x0000 }, /* R4016 (0xfb0) - ANC Coefficient */
+       { 0x00000fb1, 0x0000 }, /* R4017 (0xfb1) - ANC Coefficient */
+       { 0x00000fb2, 0x0000 }, /* R4018 (0xfb2) - ANC Coefficient */
+       { 0x00000fb3, 0x0000 }, /* R4019 (0xfb3) - ANC Coefficient */
+       { 0x00000fb4, 0x0000 }, /* R4020 (0xfb4) - ANC Coefficient */
+       { 0x00000fb5, 0x0000 }, /* R4021 (0xfb5) - ANC Coefficient */
+       { 0x00000fb6, 0x0000 }, /* R4022 (0xfb6) - ANC Coefficient */
+       { 0x00000fb7, 0x0000 }, /* R4023 (0xfb7) - ANC Coefficient */
+       { 0x00000fb8, 0x0000 }, /* R4024 (0xfb8) - ANC Coefficient */
+       { 0x00000fb9, 0x0000 }, /* R4025 (0xfb9) - ANC Coefficient */
+       { 0x00000fba, 0x0000 }, /* R4026 (0xfba) - ANC Coefficient */
+       { 0x00000fbb, 0x0000 }, /* R4027 (0xfbb) - ANC Coefficient */
+       { 0x00000fbc, 0x0000 }, /* R4028 (0xfbc) - ANC Coefficient */
+       { 0x00000fbd, 0x0000 }, /* R4029 (0xfbd) - ANC Coefficient */
+       { 0x00000fbe, 0x0000 }, /* R4030 (0xfbe) - ANC Coefficient */
+       { 0x00000fbf, 0x0000 }, /* R4031 (0xfbf) - ANC Coefficient */
+       { 0x00000fc0, 0x0000 }, /* R4032 (0xfc0) - ANC Coefficient */
+       { 0x00000fc1, 0x0000 }, /* R4033 (0xfc1) - ANC Coefficient */
+       { 0x00000fc2, 0x0000 }, /* R4034 (0xfc2) - ANC Coefficient */
+       { 0x00000fc3, 0x0000 }, /* R4035 (0xfc3) - ANC Coefficient */
+       { 0x00000fc4, 0x0000 }, /* R4036 (0xfc4) - ANC Coefficient */
+       { 0x00000fc5, 0x0000 }, /* R4037 (0xfc5) - ANC Coefficient */
+       { 0x00001300, 0x0000 }, /* R4864 (0x1300) - DAC Comp 1 */
+       { 0x00001302, 0x0000 }, /* R4866 (0x1302) - DAC Comp 2 */
+       { 0x00001380, 0x0000 }, /* R4992 (0x1380) - FRF Coefficient 1L 1 */
+       { 0x00001381, 0x0000 }, /* R4993 (0x1381) - FRF Coefficient 1L 2 */
+       { 0x00001382, 0x0000 }, /* R4994 (0x1382) - FRF Coefficient 1L 3 */
+       { 0x00001383, 0x0000 }, /* R4995 (0x1383) - FRF Coefficient 1L 4 */
+       { 0x00001390, 0x0000 }, /* R5008 (0x1390) - FRF Coefficient 1R 1 */
+       { 0x00001391, 0x0000 }, /* R5009 (0x1391) - FRF Coefficient 1R 2 */
+       { 0x00001392, 0x0000 }, /* R5010 (0x1392) - FRF Coefficient 1R 3 */
+       { 0x00001393, 0x0000 }, /* R5011 (0x1393) - FRF Coefficient 1R 4 */
+       { 0x000013a0, 0x0000 }, /* R5024 (0x13a0) - FRF Coefficient 2L 1 */
+       { 0x000013a1, 0x0000 }, /* R5025 (0x13a1) - FRF Coefficient 2L 2 */
+       { 0x000013a2, 0x0000 }, /* R5026 (0x13a2) - FRF Coefficient 2L 3 */
+       { 0x000013a3, 0x0000 }, /* R5027 (0x13a3) - FRF Coefficient 2L 4 */
+       { 0x000013b0, 0x0000 }, /* R5040 (0x13b0) - FRF Coefficient 2R 1 */
+       { 0x000013b1, 0x0000 }, /* R5041 (0x13b1) - FRF Coefficient 2R 2 */
+       { 0x000013b2, 0x0000 }, /* R5042 (0x13b2) - FRF Coefficient 2R 3 */
+       { 0x000013b3, 0x0000 }, /* R5043 (0x13b3) - FRF Coefficient 2R 4 */
+       { 0x000013c0, 0x0000 }, /* R5040 (0x13c0) - FRF Coefficient 3L 1 */
+       { 0x000013c1, 0x0000 }, /* R5041 (0x13c1) - FRF Coefficient 3L 2 */
+       { 0x000013c2, 0x0000 }, /* R5042 (0x13c2) - FRF Coefficient 3L 3 */
+       { 0x000013c3, 0x0000 }, /* R5043 (0x13c3) - FRF Coefficient 3L 4 */
+       { 0x000013d0, 0x0000 }, /* R5072 (0x13d0) - FRF Coefficient 3R 1 */
+       { 0x000013d1, 0x0000 }, /* R5073 (0x13d1) - FRF Coefficient 3R 2 */
+       { 0x000013d2, 0x0000 }, /* R5074 (0x13d2) - FRF Coefficient 3R 3 */
+       { 0x000013d3, 0x0000 }, /* R5075 (0x13d3) - FRF Coefficient 3R 4 */
+       { 0x000013e0, 0x0000 }, /* R5088 (0x13e0) - FRF Coefficient 4L 1 */
+       { 0x000013e1, 0x0000 }, /* R5089 (0x13e1) - FRF Coefficient 4L 2 */
+       { 0x000013e2, 0x0000 }, /* R5090 (0x13e2) - FRF Coefficient 4L 3 */
+       { 0x000013e3, 0x0000 }, /* R5091 (0x13e3) - FRF Coefficient 4L 4 */
+       { 0x000013f0, 0x0000 }, /* R5104 (0x13f0) - FRF Coefficient 4R 1 */
+       { 0x000013f1, 0x0000 }, /* R5105 (0x13f1) - FRF Coefficient 4R 2 */
+       { 0x000013f2, 0x0000 }, /* R5106 (0x13f2) - FRF Coefficient 4R 3 */
+       { 0x000013f3, 0x0000 }, /* R5107 (0x13f3) - FRF Coefficient 4R 4 */
+       { 0x00001400, 0x0000 }, /* R5120 (0x1400) - FRF Coefficient 5L 1 */
+       { 0x00001401, 0x0000 }, /* R5121 (0x1401) - FRF Coefficient 5L 2 */
+       { 0x00001402, 0x0000 }, /* R5122 (0x1402) - FRF Coefficient 5L 3 */
+       { 0x00001403, 0x0000 }, /* R5123 (0x1403) - FRF Coefficient 5L 4 */
+       { 0x00001410, 0x0000 }, /* R5136 (0x1410) - FRF Coefficient 5R 1 */
+       { 0x00001411, 0x0000 }, /* R5137 (0x1411) - FRF Coefficient 5R 2 */
+       { 0x00001412, 0x0000 }, /* R5138 (0x1412) - FRF Coefficient 5R 3 */
+       { 0x00001413, 0x0000 }, /* R5139 (0x1413) - FRF Coefficient 5R 4 */
+       { 0x00001420, 0x0000 }, /* R5152 (0x1420) - FRF Coefficient 6L 1 */
+       { 0x00001421, 0x0000 }, /* R5153 (0x1421) - FRF Coefficient 6L 2 */
+       { 0x00001422, 0x0000 }, /* R5154 (0x1422) - FRF Coefficient 6L 3 */
+       { 0x00001423, 0x0000 }, /* R5155 (0x1423) - FRF Coefficient 6L 4 */
+       { 0x00001430, 0x0000 }, /* R5168 (0x1430) - FRF Coefficient 6R 1 */
+       { 0x00001431, 0x0000 }, /* R5169 (0x1431) - FRF Coefficient 6R 2 */
+       { 0x00001432, 0x0000 }, /* R5170 (0x1432) - FRF Coefficient 6R 3 */
+       { 0x00001433, 0x0000 }, /* R5171 (0x1433) - FRF Coefficient 6R 4 */
+       { 0x00001700, 0x2001 }, /* R5888 (0x1700) - GPIO1 Control 1 */
+       { 0x00001701, 0xe000 }, /* R5889 (0x1701) - GPIO1 Control 2 */
+       { 0x00001702, 0x2001 }, /* R5890 (0x1702) - GPIO2 Control 1 */
+       { 0x00001703, 0xe000 }, /* R5891 (0x1703) - GPIO2 Control 2 */
+       { 0x00001704, 0x2001 }, /* R5892 (0x1704) - GPIO3 Control 1 */
+       { 0x00001705, 0xe000 }, /* R5893 (0x1705) - GPIO3 Control 2 */
+       { 0x00001706, 0x2001 }, /* R5894 (0x1706) - GPIO4 Control 1 */
+       { 0x00001707, 0xe000 }, /* R5895 (0x1707) - GPIO4 Control 2 */
+       { 0x00001708, 0x2001 }, /* R5896 (0x1708) - GPIO5 Control 1 */
+       { 0x00001709, 0xe000 }, /* R5897 (0x1709) - GPIO5 Control 2 */
+       { 0x0000170a, 0x2001 }, /* R5898 (0x170a) - GPIO6 Control 1 */
+       { 0x0000170b, 0xe000 }, /* R5899 (0x170b) - GPIO6 Control 2 */
+       { 0x0000170c, 0x2001 }, /* R5900 (0x170c) - GPIO7 Control 1 */
+       { 0x0000170d, 0xe000 }, /* R5901 (0x170d) - GPIO7 Control 2 */
+       { 0x0000170e, 0x2001 }, /* R5902 (0x170e) - GPIO8 Control 1 */
+       { 0x0000170f, 0xe000 }, /* R5903 (0x170f) - GPIO8 Control 2 */
+       { 0x00001710, 0x2001 }, /* R5904 (0x1710) - GPIO9 Control 1 */
+       { 0x00001711, 0xe000 }, /* R5905 (0x1711) - GPIO9 Control 2 */
+       { 0x00001712, 0x2001 }, /* R5906 (0x1712) - GPIO10 Control 1 */
+       { 0x00001713, 0xe000 }, /* R5907 (0x1713) - GPIO10 Control 2 */
+       { 0x00001714, 0x2001 }, /* R5908 (0x1714) - GPIO11 Control 1 */
+       { 0x00001715, 0xe000 }, /* R5909 (0x1715) - GPIO11 Control 2 */
+       { 0x00001716, 0x2001 }, /* R5910 (0x1716) - GPIO12 Control 1 */
+       { 0x00001717, 0xe000 }, /* R5911 (0x1717) - GPIO12 Control 2 */
+       { 0x00001718, 0x2001 }, /* R5912 (0x1718) - GPIO13 Control 1 */
+       { 0x00001719, 0xE000 }, /* R5913 (0x1719) - GPIO13 Control 2 */
+       { 0x0000171a, 0x2001 }, /* R5914 (0x171a) - GPIO14 Control 1 */
+       { 0x0000171b, 0xE000 }, /* R5915 (0x171b) - GPIO14 Control 2 */
+       { 0x0000171c, 0x2001 }, /* R5916 (0x171c) - GPIO15 Control 1 */
+       { 0x0000171d, 0xE000 }, /* R5917 (0x171d) - GPIO15 Control 2 */
+       { 0x0000171e, 0x2001 }, /* R5918 (0x171e) - GPIO16 Control 1 */
+       { 0x0000171f, 0xE000 }, /* R5919 (0x171f) - GPIO16 Control 2 */
+       { 0x00001720, 0x2001 }, /* R5920 (0x1720) - GPIO17 Control 1 */
+       { 0x00001721, 0xe000 }, /* R5921 (0x1721) - GPIO17 Control 2 */
+       { 0x00001722, 0x2001 }, /* R5922 (0x1722) - GPIO18 Control 1 */
+       { 0x00001723, 0xe000 }, /* R5923 (0x1723) - GPIO18 Control 2 */
+       { 0x00001724, 0x2001 }, /* R5924 (0x1724) - GPIO19 Control 1 */
+       { 0x00001725, 0xe000 }, /* R5925 (0x1725) - GPIO19 Control 2 */
+       { 0x00001726, 0x2001 }, /* R5926 (0x1726) - GPIO20 Control 1 */
+       { 0x00001727, 0xe000 }, /* R5927 (0x1727) - GPIO20 Control 2 */
+       { 0x00001728, 0x2001 }, /* R5928 (0x1728) - GPIO21 Control 1 */
+       { 0x00001729, 0xe000 }, /* R5929 (0x1729) - GPIO21 Control 2 */
+       { 0x0000172a, 0x2001 }, /* R5930 (0x172a) - GPIO22 Control 1 */
+       { 0x0000172b, 0xe000 }, /* R5931 (0x172b) - GPIO22 Control 2 */
+       { 0x0000172c, 0x2001 }, /* R5932 (0x172c) - GPIO23 Control 1 */
+       { 0x0000172d, 0xe000 }, /* R5933 (0x172d) - GPIO23 Control 2 */
+       { 0x0000172e, 0x2001 }, /* R5934 (0x172e) - GPIO24 Control 1 */
+       { 0x0000172f, 0xe000 }, /* R5935 (0x172f) - GPIO24 Control 2 */
+       { 0x00001730, 0x2001 }, /* R5936 (0x1730) - GPIO25 Control 1 */
+       { 0x00001731, 0xe000 }, /* R5937 (0x1731) - GPIO25 Control 2 */
+       { 0x00001732, 0x2001 }, /* R5938 (0x1732) - GPIO26 Control 1 */
+       { 0x00001733, 0xe000 }, /* R5939 (0x1733) - GPIO26 Control 2 */
+       { 0x00001734, 0x2001 }, /* R5940 (0x1734) - GPIO27 Control 1 */
+       { 0x00001735, 0xe000 }, /* R5941 (0x1735) - GPIO27 Control 2 */
+       { 0x00001736, 0x2001 }, /* R5942 (0x1736) - GPIO28 Control 1 */
+       { 0x00001737, 0xe000 }, /* R5943 (0x1737) - GPIO28 Control 2 */
+       { 0x00001738, 0x2001 }, /* R5944 (0x1738) - GPIO29 Control 1 */
+       { 0x00001739, 0xe000 }, /* R5945 (0x1739) - GPIO29 Control 2 */
+       { 0x0000173a, 0x2001 }, /* R5946 (0x173a) - GPIO30 Control 1 */
+       { 0x0000173b, 0xe000 }, /* R5947 (0x173b) - GPIO30 Control 2 */
+       { 0x0000173c, 0x2001 }, /* R5948 (0x173c) - GPIO31 Control 1 */
+       { 0x0000173d, 0xe000 }, /* R5949 (0x173d) - GPIO31 Control 2 */
+       { 0x0000173e, 0x2001 }, /* R5950 (0x173e) - GPIO32 Control 1 */
+       { 0x0000173f, 0xe000 }, /* R5951 (0x173f) - GPIO32 Control 2 */
+       { 0x00001740, 0x2001 }, /* R5952 (0x1740) - GPIO33 Control 1 */
+       { 0x00001741, 0xe000 }, /* R5953 (0x1741) - GPIO33 Control 2 */
+       { 0x00001742, 0x2001 }, /* R5954 (0x1742) - GPIO34 Control 1 */
+       { 0x00001743, 0xe000 }, /* R5955 (0x1743) - GPIO34 Control 2 */
+       { 0x00001744, 0x2001 }, /* R5956 (0x1744) - GPIO35 Control 1 */
+       { 0x00001745, 0xe000 }, /* R5957 (0x1745) - GPIO35 Control 2 */
+       { 0x00001746, 0x2001 }, /* R5958 (0x1746) - GPIO36 Control 1 */
+       { 0x00001747, 0xe000 }, /* R5959 (0x1747) - GPIO36 Control 2 */
+       { 0x00001748, 0x2001 }, /* R5960 (0x1748) - GPIO37 Control 1 */
+       { 0x00001749, 0xe000 }, /* R5961 (0x1749) - GPIO37 Control 2 */
+       { 0x0000174a, 0x2001 }, /* R5962 (0x174a) - GPIO38 Control 1 */
+       { 0x0000174b, 0xe000 }, /* R5963 (0x174b) - GPIO38 Control 2 */
+       { 0x0000174c, 0x2001 }, /* R5964 (0x174c) - GPIO39 Control 1 */
+       { 0x0000174d, 0xe000 }, /* R5965 (0x174d) - GPIO39 Control 2 */
+       { 0x0000174e, 0x2001 }, /* R5966 (0x174e) - GPIO40 Control 1 */
+       { 0x0000174f, 0xe000 }, /* R5967 (0x174f) - GPIO40 Control 2 */
+       { 0x00001840, 0xffff }, /* R6208 (0x1840) - IRQ1 Mask 1 */
+       { 0x00001841, 0xffff }, /* R6209 (0x1841) - IRQ1 Mask 2 */
+       { 0x00001842, 0xffff }, /* R6210 (0x1842) - IRQ1 Mask 3 */
+       { 0x00001843, 0xffff }, /* R6211 (0x1843) - IRQ1 Mask 4 */
+       { 0x00001844, 0xffff }, /* R6212 (0x1844) - IRQ1 Mask 5 */
+       { 0x00001845, 0xffff }, /* R6213 (0x1845) - IRQ1 Mask 6 */
+       { 0x00001846, 0xffff }, /* R6214 (0x1846) - IRQ1 Mask 7 */
+       { 0x00001847, 0xffff }, /* R6215 (0x1847) - IRQ1 Mask 8 */
+       { 0x00001848, 0xffff }, /* R6216 (0x1848) - IRQ1 Mask 9 */
+       { 0x00001849, 0xffff }, /* R6217 (0x1849) - IRQ1 Mask 10 */
+       { 0x0000184a, 0xffff }, /* R6218 (0x184a) - IRQ1 Mask 11 */
+       { 0x0000184b, 0xffff }, /* R6219 (0x184b) - IRQ1 Mask 12 */
+       { 0x0000184c, 0xffff }, /* R6220 (0x184c) - IRQ1 Mask 13 */
+       { 0x0000184d, 0xffff }, /* R6221 (0x184d) - IRQ1 Mask 14 */
+       { 0x0000184e, 0xffff }, /* R6222 (0x184e) - IRQ1 Mask 15 */
+       { 0x0000184f, 0xffff }, /* R6223 (0x184f) - IRQ1 Mask 16 */
+       { 0x00001850, 0xffff }, /* R6224 (0x1850) - IRQ1 Mask 17 */
+       { 0x00001851, 0xffff }, /* R6225 (0x1851) - IRQ1 Mask 18 */
+       { 0x00001852, 0xffff }, /* R6226 (0x1852) - IRQ1 Mask 19 */
+       { 0x00001853, 0xffff }, /* R6227 (0x1853) - IRQ1 Mask 20 */
+       { 0x00001854, 0xffff }, /* R6228 (0x1854) - IRQ1 Mask 21 */
+       { 0x00001855, 0xffff }, /* R6229 (0x1855) - IRQ1 Mask 22 */
+       { 0x00001856, 0xffff }, /* R6230 (0x1856) - IRQ1 Mask 23 */
+       { 0x00001857, 0xffff }, /* R6231 (0x1857) - IRQ1 Mask 24 */
+       { 0x00001858, 0xffff }, /* R6232 (0x1858) - IRQ1 Mask 25 */
+       { 0x00001859, 0xffff }, /* R6233 (0x1859) - IRQ1 Mask 26 */
+       { 0x0000185a, 0xffff }, /* R6234 (0x185a) - IRQ1 Mask 27 */
+       { 0x0000185b, 0xffff }, /* R6235 (0x185b) - IRQ1 Mask 28 */
+       { 0x0000185c, 0xffff }, /* R6236 (0x185c) - IRQ1 Mask 29 */
+       { 0x0000185d, 0xffff }, /* R6237 (0x185d) - IRQ1 Mask 30 */
+       { 0x0000185e, 0xffff }, /* R6238 (0x185e) - IRQ1 Mask 31 */
+       { 0x0000185f, 0xffff }, /* R6239 (0x185f) - IRQ1 Mask 32 */
+       { 0x00001860, 0xffff }, /* R6240 (0x1860) - IRQ1 Mask 33 */
+       { 0x00001a06, 0x0000 }, /* R6662 (0x1a06) - Interrupt Debounce 7 */
+       { 0x00001a80, 0x4400 }, /* R6784 (0x1a80) - IRQ1 CTRL */
+};
+
+static bool cs47l85_is_adsp_memory(unsigned int reg)
+{
+       switch (reg) {
+       case 0x080000 ... 0x085ffe:
+       case 0x0a0000 ... 0x0a7ffe:
+       case 0x0c0000 ... 0x0c1ffe:
+       case 0x0e0000 ... 0x0e1ffe:
+       case 0x100000 ... 0x10effe:
+       case 0x120000 ... 0x12bffe:
+       case 0x136000 ... 0x137ffe:
+       case 0x140000 ... 0x14bffe:
+       case 0x160000 ... 0x161ffe:
+       case 0x180000 ... 0x18effe:
+       case 0x1a0000 ... 0x1b1ffe:
+       case 0x1b6000 ... 0x1b7ffe:
+       case 0x1c0000 ... 0x1cbffe:
+       case 0x1e0000 ... 0x1e1ffe:
+       case 0x200000 ... 0x208ffe:
+       case 0x220000 ... 0x231ffe:
+       case 0x240000 ... 0x24bffe:
+       case 0x260000 ... 0x261ffe:
+       case 0x280000 ... 0x288ffe:
+       case 0x2a0000 ... 0x2a9ffe:
+       case 0x2c0000 ... 0x2c3ffe:
+       case 0x2e0000 ... 0x2e1ffe:
+       case 0x300000 ... 0x305ffe:
+       case 0x320000 ... 0x333ffe:
+       case 0x340000 ... 0x34bffe:
+       case 0x360000 ... 0x361ffe:
+       case 0x380000 ... 0x388ffe:
+       case 0x3a0000 ... 0x3a7ffe:
+       case 0x3c0000 ... 0x3c1ffe:
+       case 0x3e0000 ... 0x3e1ffe:
+               return true;
+       default:
+               return false;
+       }
+}
+
+static bool cs47l85_16bit_readable_register(struct device *dev,
+                                           unsigned int reg)
+{
+       switch (reg) {
+       case MADERA_SOFTWARE_RESET:
+       case MADERA_HARDWARE_REVISION:
+       case MADERA_WRITE_SEQUENCER_CTRL_0:
+       case MADERA_WRITE_SEQUENCER_CTRL_1:
+       case MADERA_WRITE_SEQUENCER_CTRL_2:
+       case MADERA_TONE_GENERATOR_1:
+       case MADERA_TONE_GENERATOR_2:
+       case MADERA_TONE_GENERATOR_3:
+       case MADERA_TONE_GENERATOR_4:
+       case MADERA_TONE_GENERATOR_5:
+       case MADERA_PWM_DRIVE_1:
+       case MADERA_PWM_DRIVE_2:
+       case MADERA_PWM_DRIVE_3:
+       case MADERA_SAMPLE_RATE_SEQUENCE_SELECT_1:
+       case MADERA_SAMPLE_RATE_SEQUENCE_SELECT_2:
+       case MADERA_SAMPLE_RATE_SEQUENCE_SELECT_3:
+       case MADERA_SAMPLE_RATE_SEQUENCE_SELECT_4:
+       case MADERA_ALWAYS_ON_TRIGGERS_SEQUENCE_SELECT_1:
+       case MADERA_ALWAYS_ON_TRIGGERS_SEQUENCE_SELECT_2:
+       case MADERA_HAPTICS_CONTROL_1:
+       case MADERA_HAPTICS_CONTROL_2:
+       case MADERA_HAPTICS_PHASE_1_INTENSITY:
+       case MADERA_HAPTICS_PHASE_1_DURATION:
+       case MADERA_HAPTICS_PHASE_2_INTENSITY:
+       case MADERA_HAPTICS_PHASE_2_DURATION:
+       case MADERA_HAPTICS_PHASE_3_INTENSITY:
+       case MADERA_HAPTICS_PHASE_3_DURATION:
+       case MADERA_HAPTICS_STATUS:
+       case MADERA_COMFORT_NOISE_GENERATOR:
+       case MADERA_CLOCK_32K_1:
+       case MADERA_SYSTEM_CLOCK_1:
+       case MADERA_SAMPLE_RATE_1:
+       case MADERA_SAMPLE_RATE_2:
+       case MADERA_SAMPLE_RATE_3:
+       case MADERA_SAMPLE_RATE_1_STATUS:
+       case MADERA_SAMPLE_RATE_2_STATUS:
+       case MADERA_SAMPLE_RATE_3_STATUS:
+       case MADERA_ASYNC_CLOCK_1:
+       case MADERA_ASYNC_SAMPLE_RATE_1:
+       case MADERA_ASYNC_SAMPLE_RATE_1_STATUS:
+       case MADERA_ASYNC_SAMPLE_RATE_2:
+       case MADERA_ASYNC_SAMPLE_RATE_2_STATUS:
+       case MADERA_DSP_CLOCK_1:
+       case MADERA_DSP_CLOCK_2:
+       case MADERA_OUTPUT_SYSTEM_CLOCK:
+       case MADERA_OUTPUT_ASYNC_CLOCK:
+       case MADERA_RATE_ESTIMATOR_1:
+       case MADERA_RATE_ESTIMATOR_2:
+       case MADERA_RATE_ESTIMATOR_3:
+       case MADERA_RATE_ESTIMATOR_4:
+       case MADERA_RATE_ESTIMATOR_5:
+       case MADERA_FLL1_CONTROL_1:
+       case MADERA_FLL1_CONTROL_2:
+       case MADERA_FLL1_CONTROL_3:
+       case MADERA_FLL1_CONTROL_4:
+       case MADERA_FLL1_CONTROL_5:
+       case MADERA_FLL1_CONTROL_6:
+       case MADERA_FLL1_CONTROL_7:
+       case MADERA_FLL1_LOOP_FILTER_TEST_1:
+       case MADERA_FLL1_SYNCHRONISER_1:
+       case MADERA_FLL1_SYNCHRONISER_2:
+       case MADERA_FLL1_SYNCHRONISER_3:
+       case MADERA_FLL1_SYNCHRONISER_4:
+       case MADERA_FLL1_SYNCHRONISER_5:
+       case MADERA_FLL1_SYNCHRONISER_6:
+       case MADERA_FLL1_SYNCHRONISER_7:
+       case MADERA_FLL1_SPREAD_SPECTRUM:
+       case MADERA_FLL1_GPIO_CLOCK:
+       case MADERA_FLL2_CONTROL_1:
+       case MADERA_FLL2_CONTROL_2:
+       case MADERA_FLL2_CONTROL_3:
+       case MADERA_FLL2_CONTROL_4:
+       case MADERA_FLL2_CONTROL_5:
+       case MADERA_FLL2_CONTROL_6:
+       case MADERA_FLL2_CONTROL_7:
+       case MADERA_FLL2_LOOP_FILTER_TEST_1:
+       case MADERA_FLL2_SYNCHRONISER_1:
+       case MADERA_FLL2_SYNCHRONISER_2:
+       case MADERA_FLL2_SYNCHRONISER_3:
+       case MADERA_FLL2_SYNCHRONISER_4:
+       case MADERA_FLL2_SYNCHRONISER_5:
+       case MADERA_FLL2_SYNCHRONISER_6:
+       case MADERA_FLL2_SYNCHRONISER_7:
+       case MADERA_FLL2_SPREAD_SPECTRUM:
+       case MADERA_FLL2_GPIO_CLOCK:
+       case MADERA_FLL3_CONTROL_1:
+       case MADERA_FLL3_CONTROL_2:
+       case MADERA_FLL3_CONTROL_3:
+       case MADERA_FLL3_CONTROL_4:
+       case MADERA_FLL3_CONTROL_5:
+       case MADERA_FLL3_CONTROL_6:
+       case MADERA_FLL3_CONTROL_7:
+       case MADERA_FLL3_LOOP_FILTER_TEST_1:
+       case MADERA_FLL3_SYNCHRONISER_1:
+       case MADERA_FLL3_SYNCHRONISER_2:
+       case MADERA_FLL3_SYNCHRONISER_3:
+       case MADERA_FLL3_SYNCHRONISER_4:
+       case MADERA_FLL3_SYNCHRONISER_5:
+       case MADERA_FLL3_SYNCHRONISER_6:
+       case MADERA_FLL3_SYNCHRONISER_7:
+       case MADERA_FLL3_SPREAD_SPECTRUM:
+       case MADERA_FLL3_GPIO_CLOCK:
+       case MADERA_MIC_CHARGE_PUMP_1:
+       case MADERA_HP_CHARGE_PUMP_8:
+       case MADERA_LDO1_CONTROL_1:
+       case MADERA_LDO2_CONTROL_1:
+       case MADERA_MIC_BIAS_CTRL_1:
+       case MADERA_MIC_BIAS_CTRL_2:
+       case MADERA_MIC_BIAS_CTRL_3:
+       case MADERA_MIC_BIAS_CTRL_4:
+       case MADERA_HP_CTRL_1L:
+       case MADERA_HP_CTRL_1R:
+       case MADERA_HP_CTRL_2L:
+       case MADERA_HP_CTRL_2R:
+       case MADERA_HP_CTRL_3L:
+       case MADERA_HP_CTRL_3R:
+       case MADERA_DCS_HP1L_CONTROL:
+       case MADERA_DCS_HP1R_CONTROL:
+       case MADERA_EDRE_HP_STEREO_CONTROL:
+       case MADERA_ACCESSORY_DETECT_MODE_1:
+       case MADERA_HEADPHONE_DETECT_1:
+       case MADERA_HEADPHONE_DETECT_2:
+       case MADERA_HEADPHONE_DETECT_3:
+       case MADERA_HEADPHONE_DETECT_5:
+       case MADERA_MICD_CLAMP_CONTROL:
+       case MADERA_MIC_DETECT_1_CONTROL_1:
+       case MADERA_MIC_DETECT_1_CONTROL_2:
+       case MADERA_MIC_DETECT_1_CONTROL_3:
+       case MADERA_MIC_DETECT_1_LEVEL_1:
+       case MADERA_MIC_DETECT_1_LEVEL_2:
+       case MADERA_MIC_DETECT_1_LEVEL_3:
+       case MADERA_MIC_DETECT_1_LEVEL_4:
+       case MADERA_MIC_DETECT_1_CONTROL_4:
+       case MADERA_GP_SWITCH_1:
+       case MADERA_JACK_DETECT_ANALOGUE:
+       case MADERA_INPUT_ENABLES:
+       case MADERA_INPUT_ENABLES_STATUS:
+       case MADERA_INPUT_RATE:
+       case MADERA_INPUT_VOLUME_RAMP:
+       case MADERA_HPF_CONTROL:
+       case MADERA_IN1L_CONTROL:
+       case MADERA_ADC_DIGITAL_VOLUME_1L:
+       case MADERA_DMIC1L_CONTROL:
+       case MADERA_IN1R_CONTROL:
+       case MADERA_ADC_DIGITAL_VOLUME_1R:
+       case MADERA_DMIC1R_CONTROL:
+       case MADERA_IN2L_CONTROL:
+       case MADERA_ADC_DIGITAL_VOLUME_2L:
+       case MADERA_DMIC2L_CONTROL:
+       case MADERA_IN2R_CONTROL:
+       case MADERA_ADC_DIGITAL_VOLUME_2R:
+       case MADERA_DMIC2R_CONTROL:
+       case MADERA_IN3L_CONTROL:
+       case MADERA_ADC_DIGITAL_VOLUME_3L:
+       case MADERA_DMIC3L_CONTROL:
+       case MADERA_IN3R_CONTROL:
+       case MADERA_ADC_DIGITAL_VOLUME_3R:
+       case MADERA_DMIC3R_CONTROL:
+       case MADERA_IN4L_CONTROL:
+       case MADERA_ADC_DIGITAL_VOLUME_4L:
+       case MADERA_DMIC4L_CONTROL:
+       case MADERA_IN4R_CONTROL:
+       case MADERA_ADC_DIGITAL_VOLUME_4R:
+       case MADERA_DMIC4R_CONTROL:
+       case MADERA_IN5L_CONTROL:
+       case MADERA_ADC_DIGITAL_VOLUME_5L:
+       case MADERA_DMIC5L_CONTROL:
+       case MADERA_IN5R_CONTROL:
+       case MADERA_ADC_DIGITAL_VOLUME_5R:
+       case MADERA_DMIC5R_CONTROL:
+       case MADERA_IN6L_CONTROL:
+       case MADERA_ADC_DIGITAL_VOLUME_6L:
+       case MADERA_DMIC6L_CONTROL:
+       case MADERA_IN6R_CONTROL:
+       case MADERA_ADC_DIGITAL_VOLUME_6R:
+       case MADERA_DMIC6R_CONTROL:
+       case MADERA_OUTPUT_ENABLES_1:
+       case MADERA_OUTPUT_STATUS_1:
+       case MADERA_RAW_OUTPUT_STATUS_1:
+       case MADERA_OUTPUT_RATE_1:
+       case MADERA_OUTPUT_VOLUME_RAMP:
+       case MADERA_OUTPUT_PATH_CONFIG_1L:
+       case MADERA_DAC_DIGITAL_VOLUME_1L:
+       case MADERA_NOISE_GATE_SELECT_1L:
+       case MADERA_OUTPUT_PATH_CONFIG_1R:
+       case MADERA_DAC_DIGITAL_VOLUME_1R:
+       case MADERA_NOISE_GATE_SELECT_1R:
+       case MADERA_OUTPUT_PATH_CONFIG_2L:
+       case MADERA_DAC_DIGITAL_VOLUME_2L:
+       case MADERA_NOISE_GATE_SELECT_2L:
+       case MADERA_OUTPUT_PATH_CONFIG_2R:
+       case MADERA_DAC_DIGITAL_VOLUME_2R:
+       case MADERA_NOISE_GATE_SELECT_2R:
+       case MADERA_OUTPUT_PATH_CONFIG_3L:
+       case MADERA_DAC_DIGITAL_VOLUME_3L:
+       case MADERA_NOISE_GATE_SELECT_3L:
+       case MADERA_OUTPUT_PATH_CONFIG_3R:
+       case MADERA_DAC_DIGITAL_VOLUME_3R:
+       case MADERA_NOISE_GATE_SELECT_3R:
+       case MADERA_OUTPUT_PATH_CONFIG_4L:
+       case MADERA_DAC_DIGITAL_VOLUME_4L:
+       case MADERA_NOISE_GATE_SELECT_4L:
+       case MADERA_OUTPUT_PATH_CONFIG_4R:
+       case MADERA_DAC_DIGITAL_VOLUME_4R:
+       case MADERA_NOISE_GATE_SELECT_4R:
+       case MADERA_OUTPUT_PATH_CONFIG_5L:
+       case MADERA_DAC_DIGITAL_VOLUME_5L:
+       case MADERA_NOISE_GATE_SELECT_5L:
+       case MADERA_OUTPUT_PATH_CONFIG_5R:
+       case MADERA_DAC_DIGITAL_VOLUME_5R:
+       case MADERA_NOISE_GATE_SELECT_5R:
+       case MADERA_OUTPUT_PATH_CONFIG_6L:
+       case MADERA_DAC_DIGITAL_VOLUME_6L:
+       case MADERA_NOISE_GATE_SELECT_6L:
+       case MADERA_OUTPUT_PATH_CONFIG_6R:
+       case MADERA_DAC_DIGITAL_VOLUME_6R:
+       case MADERA_NOISE_GATE_SELECT_6R:
+       case MADERA_DRE_ENABLE:
+       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:
+       case MADERA_PDM_SPK2_CTRL_1:
+       case MADERA_PDM_SPK2_CTRL_2:
+       case MADERA_HP1_SHORT_CIRCUIT_CTRL:
+       case MADERA_HP2_SHORT_CIRCUIT_CTRL:
+       case MADERA_HP3_SHORT_CIRCUIT_CTRL:
+       case MADERA_HP_TEST_CTRL_5:
+       case MADERA_HP_TEST_CTRL_6:
+       case MADERA_AIF1_BCLK_CTRL:
+       case MADERA_AIF1_TX_PIN_CTRL:
+       case MADERA_AIF1_RX_PIN_CTRL:
+       case MADERA_AIF1_RATE_CTRL:
+       case MADERA_AIF1_FORMAT:
+       case MADERA_AIF1_RX_BCLK_RATE:
+       case MADERA_AIF1_FRAME_CTRL_1:
+       case MADERA_AIF1_FRAME_CTRL_2:
+       case MADERA_AIF1_FRAME_CTRL_3:
+       case MADERA_AIF1_FRAME_CTRL_4:
+       case MADERA_AIF1_FRAME_CTRL_5:
+       case MADERA_AIF1_FRAME_CTRL_6:
+       case MADERA_AIF1_FRAME_CTRL_7:
+       case MADERA_AIF1_FRAME_CTRL_8:
+       case MADERA_AIF1_FRAME_CTRL_9:
+       case MADERA_AIF1_FRAME_CTRL_10:
+       case MADERA_AIF1_FRAME_CTRL_11:
+       case MADERA_AIF1_FRAME_CTRL_12:
+       case MADERA_AIF1_FRAME_CTRL_13:
+       case MADERA_AIF1_FRAME_CTRL_14:
+       case MADERA_AIF1_FRAME_CTRL_15:
+       case MADERA_AIF1_FRAME_CTRL_16:
+       case MADERA_AIF1_FRAME_CTRL_17:
+       case MADERA_AIF1_FRAME_CTRL_18:
+       case MADERA_AIF1_TX_ENABLES:
+       case MADERA_AIF1_RX_ENABLES:
+       case MADERA_AIF2_BCLK_CTRL:
+       case MADERA_AIF2_TX_PIN_CTRL:
+       case MADERA_AIF2_RX_PIN_CTRL:
+       case MADERA_AIF2_RATE_CTRL:
+       case MADERA_AIF2_FORMAT:
+       case MADERA_AIF2_RX_BCLK_RATE:
+       case MADERA_AIF2_FRAME_CTRL_1:
+       case MADERA_AIF2_FRAME_CTRL_2:
+       case MADERA_AIF2_FRAME_CTRL_3:
+       case MADERA_AIF2_FRAME_CTRL_4:
+       case MADERA_AIF2_FRAME_CTRL_5:
+       case MADERA_AIF2_FRAME_CTRL_6:
+       case MADERA_AIF2_FRAME_CTRL_7:
+       case MADERA_AIF2_FRAME_CTRL_8:
+       case MADERA_AIF2_FRAME_CTRL_9:
+       case MADERA_AIF2_FRAME_CTRL_10:
+       case MADERA_AIF2_FRAME_CTRL_11:
+       case MADERA_AIF2_FRAME_CTRL_12:
+       case MADERA_AIF2_FRAME_CTRL_13:
+       case MADERA_AIF2_FRAME_CTRL_14:
+       case MADERA_AIF2_FRAME_CTRL_15:
+       case MADERA_AIF2_FRAME_CTRL_16:
+       case MADERA_AIF2_FRAME_CTRL_17:
+       case MADERA_AIF2_FRAME_CTRL_18:
+       case MADERA_AIF2_TX_ENABLES:
+       case MADERA_AIF2_RX_ENABLES:
+       case MADERA_AIF3_BCLK_CTRL:
+       case MADERA_AIF3_TX_PIN_CTRL:
+       case MADERA_AIF3_RX_PIN_CTRL:
+       case MADERA_AIF3_RATE_CTRL:
+       case MADERA_AIF3_FORMAT:
+       case MADERA_AIF3_RX_BCLK_RATE:
+       case MADERA_AIF3_FRAME_CTRL_1:
+       case MADERA_AIF3_FRAME_CTRL_2:
+       case MADERA_AIF3_FRAME_CTRL_3:
+       case MADERA_AIF3_FRAME_CTRL_4:
+       case MADERA_AIF3_FRAME_CTRL_11:
+       case MADERA_AIF3_FRAME_CTRL_12:
+       case MADERA_AIF3_TX_ENABLES:
+       case MADERA_AIF3_RX_ENABLES:
+       case MADERA_AIF4_BCLK_CTRL:
+       case MADERA_AIF4_TX_PIN_CTRL:
+       case MADERA_AIF4_RX_PIN_CTRL:
+       case MADERA_AIF4_RATE_CTRL:
+       case MADERA_AIF4_FORMAT:
+       case MADERA_AIF4_RX_BCLK_RATE:
+       case MADERA_AIF4_FRAME_CTRL_1:
+       case MADERA_AIF4_FRAME_CTRL_2:
+       case MADERA_AIF4_FRAME_CTRL_3:
+       case MADERA_AIF4_FRAME_CTRL_4:
+       case MADERA_AIF4_FRAME_CTRL_11:
+       case MADERA_AIF4_FRAME_CTRL_12:
+       case MADERA_AIF4_TX_ENABLES:
+       case MADERA_AIF4_RX_ENABLES:
+       case MADERA_SPD1_TX_CONTROL:
+       case MADERA_SPD1_TX_CHANNEL_STATUS_1:
+       case MADERA_SPD1_TX_CHANNEL_STATUS_2:
+       case MADERA_SPD1_TX_CHANNEL_STATUS_3:
+       case MADERA_SLIMBUS_FRAMER_REF_GEAR:
+       case MADERA_SLIMBUS_RATES_1:
+       case MADERA_SLIMBUS_RATES_2:
+       case MADERA_SLIMBUS_RATES_3:
+       case MADERA_SLIMBUS_RATES_4:
+       case MADERA_SLIMBUS_RATES_5:
+       case MADERA_SLIMBUS_RATES_6:
+       case MADERA_SLIMBUS_RATES_7:
+       case MADERA_SLIMBUS_RATES_8:
+       case MADERA_SLIMBUS_RX_CHANNEL_ENABLE:
+       case MADERA_SLIMBUS_TX_CHANNEL_ENABLE:
+       case MADERA_SLIMBUS_RX_PORT_STATUS:
+       case MADERA_SLIMBUS_TX_PORT_STATUS:
+       case MADERA_PWM1MIX_INPUT_1_SOURCE:
+       case MADERA_PWM1MIX_INPUT_1_VOLUME:
+       case MADERA_PWM1MIX_INPUT_2_SOURCE:
+       case MADERA_PWM1MIX_INPUT_2_VOLUME:
+       case MADERA_PWM1MIX_INPUT_3_SOURCE:
+       case MADERA_PWM1MIX_INPUT_3_VOLUME:
+       case MADERA_PWM1MIX_INPUT_4_SOURCE:
+       case MADERA_PWM1MIX_INPUT_4_VOLUME:
+       case MADERA_PWM2MIX_INPUT_1_SOURCE:
+       case MADERA_PWM2MIX_INPUT_1_VOLUME:
+       case MADERA_PWM2MIX_INPUT_2_SOURCE:
+       case MADERA_PWM2MIX_INPUT_2_VOLUME:
+       case MADERA_PWM2MIX_INPUT_3_SOURCE:
+       case MADERA_PWM2MIX_INPUT_3_VOLUME:
+       case MADERA_PWM2MIX_INPUT_4_SOURCE:
+       case MADERA_PWM2MIX_INPUT_4_VOLUME:
+       case MADERA_OUT1LMIX_INPUT_1_SOURCE:
+       case MADERA_OUT1LMIX_INPUT_1_VOLUME:
+       case MADERA_OUT1LMIX_INPUT_2_SOURCE:
+       case MADERA_OUT1LMIX_INPUT_2_VOLUME:
+       case MADERA_OUT1LMIX_INPUT_3_SOURCE:
+       case MADERA_OUT1LMIX_INPUT_3_VOLUME:
+       case MADERA_OUT1LMIX_INPUT_4_SOURCE:
+       case MADERA_OUT1LMIX_INPUT_4_VOLUME:
+       case MADERA_OUT1RMIX_INPUT_1_SOURCE:
+       case MADERA_OUT1RMIX_INPUT_1_VOLUME:
+       case MADERA_OUT1RMIX_INPUT_2_SOURCE:
+       case MADERA_OUT1RMIX_INPUT_2_VOLUME:
+       case MADERA_OUT1RMIX_INPUT_3_SOURCE:
+       case MADERA_OUT1RMIX_INPUT_3_VOLUME:
+       case MADERA_OUT1RMIX_INPUT_4_SOURCE:
+       case MADERA_OUT1RMIX_INPUT_4_VOLUME:
+       case MADERA_OUT2LMIX_INPUT_1_SOURCE:
+       case MADERA_OUT2LMIX_INPUT_1_VOLUME:
+       case MADERA_OUT2LMIX_INPUT_2_SOURCE:
+       case MADERA_OUT2LMIX_INPUT_2_VOLUME:
+       case MADERA_OUT2LMIX_INPUT_3_SOURCE:
+       case MADERA_OUT2LMIX_INPUT_3_VOLUME:
+       case MADERA_OUT2LMIX_INPUT_4_SOURCE:
+       case MADERA_OUT2LMIX_INPUT_4_VOLUME:
+       case MADERA_OUT2RMIX_INPUT_1_SOURCE:
+       case MADERA_OUT2RMIX_INPUT_1_VOLUME:
+       case MADERA_OUT2RMIX_INPUT_2_SOURCE:
+       case MADERA_OUT2RMIX_INPUT_2_VOLUME:
+       case MADERA_OUT2RMIX_INPUT_3_SOURCE:
+       case MADERA_OUT2RMIX_INPUT_3_VOLUME:
+       case MADERA_OUT2RMIX_INPUT_4_SOURCE:
+       case MADERA_OUT2RMIX_INPUT_4_VOLUME:
+       case MADERA_OUT3LMIX_INPUT_1_SOURCE:
+       case MADERA_OUT3LMIX_INPUT_1_VOLUME:
+       case MADERA_OUT3LMIX_INPUT_2_SOURCE:
+       case MADERA_OUT3LMIX_INPUT_2_VOLUME:
+       case MADERA_OUT3LMIX_INPUT_3_SOURCE:
+       case MADERA_OUT3LMIX_INPUT_3_VOLUME:
+       case MADERA_OUT3LMIX_INPUT_4_SOURCE:
+       case MADERA_OUT3LMIX_INPUT_4_VOLUME:
+       case MADERA_OUT3RMIX_INPUT_1_SOURCE:
+       case MADERA_OUT3RMIX_INPUT_1_VOLUME:
+       case MADERA_OUT3RMIX_INPUT_2_SOURCE:
+       case MADERA_OUT3RMIX_INPUT_2_VOLUME:
+       case MADERA_OUT3RMIX_INPUT_3_SOURCE:
+       case MADERA_OUT3RMIX_INPUT_3_VOLUME:
+       case MADERA_OUT3RMIX_INPUT_4_SOURCE:
+       case MADERA_OUT3RMIX_INPUT_4_VOLUME:
+       case MADERA_OUT4LMIX_INPUT_1_SOURCE:
+       case MADERA_OUT4LMIX_INPUT_1_VOLUME:
+       case MADERA_OUT4LMIX_INPUT_2_SOURCE:
+       case MADERA_OUT4LMIX_INPUT_2_VOLUME:
+       case MADERA_OUT4LMIX_INPUT_3_SOURCE:
+       case MADERA_OUT4LMIX_INPUT_3_VOLUME:
+       case MADERA_OUT4LMIX_INPUT_4_SOURCE:
+       case MADERA_OUT4LMIX_INPUT_4_VOLUME:
+       case MADERA_OUT4RMIX_INPUT_1_SOURCE:
+       case MADERA_OUT4RMIX_INPUT_1_VOLUME:
+       case MADERA_OUT4RMIX_INPUT_2_SOURCE:
+       case MADERA_OUT4RMIX_INPUT_2_VOLUME:
+       case MADERA_OUT4RMIX_INPUT_3_SOURCE:
+       case MADERA_OUT4RMIX_INPUT_3_VOLUME:
+       case MADERA_OUT4RMIX_INPUT_4_SOURCE:
+       case MADERA_OUT4RMIX_INPUT_4_VOLUME:
+       case MADERA_OUT5LMIX_INPUT_1_SOURCE:
+       case MADERA_OUT5LMIX_INPUT_1_VOLUME:
+       case MADERA_OUT5LMIX_INPUT_2_SOURCE:
+       case MADERA_OUT5LMIX_INPUT_2_VOLUME:
+       case MADERA_OUT5LMIX_INPUT_3_SOURCE:
+       case MADERA_OUT5LMIX_INPUT_3_VOLUME:
+       case MADERA_OUT5LMIX_INPUT_4_SOURCE:
+       case MADERA_OUT5LMIX_INPUT_4_VOLUME:
+       case MADERA_OUT5RMIX_INPUT_1_SOURCE:
+       case MADERA_OUT5RMIX_INPUT_1_VOLUME:
+       case MADERA_OUT5RMIX_INPUT_2_SOURCE:
+       case MADERA_OUT5RMIX_INPUT_2_VOLUME:
+       case MADERA_OUT5RMIX_INPUT_3_SOURCE:
+       case MADERA_OUT5RMIX_INPUT_3_VOLUME:
+       case MADERA_OUT5RMIX_INPUT_4_SOURCE:
+       case MADERA_OUT5RMIX_INPUT_4_VOLUME:
+       case MADERA_OUT6LMIX_INPUT_1_SOURCE:
+       case MADERA_OUT6LMIX_INPUT_1_VOLUME:
+       case MADERA_OUT6LMIX_INPUT_2_SOURCE:
+       case MADERA_OUT6LMIX_INPUT_2_VOLUME:
+       case MADERA_OUT6LMIX_INPUT_3_SOURCE:
+       case MADERA_OUT6LMIX_INPUT_3_VOLUME:
+       case MADERA_OUT6LMIX_INPUT_4_SOURCE:
+       case MADERA_OUT6LMIX_INPUT_4_VOLUME:
+       case MADERA_OUT6RMIX_INPUT_1_SOURCE:
+       case MADERA_OUT6RMIX_INPUT_1_VOLUME:
+       case MADERA_OUT6RMIX_INPUT_2_SOURCE:
+       case MADERA_OUT6RMIX_INPUT_2_VOLUME:
+       case MADERA_OUT6RMIX_INPUT_3_SOURCE:
+       case MADERA_OUT6RMIX_INPUT_3_VOLUME:
+       case MADERA_OUT6RMIX_INPUT_4_SOURCE:
+       case MADERA_OUT6RMIX_INPUT_4_VOLUME:
+       case MADERA_AIF1TX1MIX_INPUT_1_SOURCE:
+       case MADERA_AIF1TX1MIX_INPUT_1_VOLUME:
+       case MADERA_AIF1TX1MIX_INPUT_2_SOURCE:
+       case MADERA_AIF1TX1MIX_INPUT_2_VOLUME:
+       case MADERA_AIF1TX1MIX_INPUT_3_SOURCE:
+       case MADERA_AIF1TX1MIX_INPUT_3_VOLUME:
+       case MADERA_AIF1TX1MIX_INPUT_4_SOURCE:
+       case MADERA_AIF1TX1MIX_INPUT_4_VOLUME:
+       case MADERA_AIF1TX2MIX_INPUT_1_SOURCE:
+       case MADERA_AIF1TX2MIX_INPUT_1_VOLUME:
+       case MADERA_AIF1TX2MIX_INPUT_2_SOURCE:
+       case MADERA_AIF1TX2MIX_INPUT_2_VOLUME:
+       case MADERA_AIF1TX2MIX_INPUT_3_SOURCE:
+       case MADERA_AIF1TX2MIX_INPUT_3_VOLUME:
+       case MADERA_AIF1TX2MIX_INPUT_4_SOURCE:
+       case MADERA_AIF1TX2MIX_INPUT_4_VOLUME:
+       case MADERA_AIF1TX3MIX_INPUT_1_SOURCE:
+       case MADERA_AIF1TX3MIX_INPUT_1_VOLUME:
+       case MADERA_AIF1TX3MIX_INPUT_2_SOURCE:
+       case MADERA_AIF1TX3MIX_INPUT_2_VOLUME:
+       case MADERA_AIF1TX3MIX_INPUT_3_SOURCE:
+       case MADERA_AIF1TX3MIX_INPUT_3_VOLUME:
+       case MADERA_AIF1TX3MIX_INPUT_4_SOURCE:
+       case MADERA_AIF1TX3MIX_INPUT_4_VOLUME:
+       case MADERA_AIF1TX4MIX_INPUT_1_SOURCE:
+       case MADERA_AIF1TX4MIX_INPUT_1_VOLUME:
+       case MADERA_AIF1TX4MIX_INPUT_2_SOURCE:
+       case MADERA_AIF1TX4MIX_INPUT_2_VOLUME:
+       case MADERA_AIF1TX4MIX_INPUT_3_SOURCE:
+       case MADERA_AIF1TX4MIX_INPUT_3_VOLUME:
+       case MADERA_AIF1TX4MIX_INPUT_4_SOURCE:
+       case MADERA_AIF1TX4MIX_INPUT_4_VOLUME:
+       case MADERA_AIF1TX5MIX_INPUT_1_SOURCE:
+       case MADERA_AIF1TX5MIX_INPUT_1_VOLUME:
+       case MADERA_AIF1TX5MIX_INPUT_2_SOURCE:
+       case MADERA_AIF1TX5MIX_INPUT_2_VOLUME:
+       case MADERA_AIF1TX5MIX_INPUT_3_SOURCE:
+       case MADERA_AIF1TX5MIX_INPUT_3_VOLUME:
+       case MADERA_AIF1TX5MIX_INPUT_4_SOURCE:
+       case MADERA_AIF1TX5MIX_INPUT_4_VOLUME:
+       case MADERA_AIF1TX6MIX_INPUT_1_SOURCE:
+       case MADERA_AIF1TX6MIX_INPUT_1_VOLUME:
+       case MADERA_AIF1TX6MIX_INPUT_2_SOURCE:
+       case MADERA_AIF1TX6MIX_INPUT_2_VOLUME:
+       case MADERA_AIF1TX6MIX_INPUT_3_SOURCE:
+       case MADERA_AIF1TX6MIX_INPUT_3_VOLUME:
+       case MADERA_AIF1TX6MIX_INPUT_4_SOURCE:
+       case MADERA_AIF1TX6MIX_INPUT_4_VOLUME:
+       case MADERA_AIF1TX7MIX_INPUT_1_SOURCE:
+       case MADERA_AIF1TX7MIX_INPUT_1_VOLUME:
+       case MADERA_AIF1TX7MIX_INPUT_2_SOURCE:
+       case MADERA_AIF1TX7MIX_INPUT_2_VOLUME:
+       case MADERA_AIF1TX7MIX_INPUT_3_SOURCE:
+       case MADERA_AIF1TX7MIX_INPUT_3_VOLUME:
+       case MADERA_AIF1TX7MIX_INPUT_4_SOURCE:
+       case MADERA_AIF1TX7MIX_INPUT_4_VOLUME:
+       case MADERA_AIF1TX8MIX_INPUT_1_SOURCE:
+       case MADERA_AIF1TX8MIX_INPUT_1_VOLUME:
+       case MADERA_AIF1TX8MIX_INPUT_2_SOURCE:
+       case MADERA_AIF1TX8MIX_INPUT_2_VOLUME:
+       case MADERA_AIF1TX8MIX_INPUT_3_SOURCE:
+       case MADERA_AIF1TX8MIX_INPUT_3_VOLUME:
+       case MADERA_AIF1TX8MIX_INPUT_4_SOURCE:
+       case MADERA_AIF1TX8MIX_INPUT_4_VOLUME:
+       case MADERA_AIF2TX1MIX_INPUT_1_SOURCE:
+       case MADERA_AIF2TX1MIX_INPUT_1_VOLUME:
+       case MADERA_AIF2TX1MIX_INPUT_2_SOURCE:
+       case MADERA_AIF2TX1MIX_INPUT_2_VOLUME:
+       case MADERA_AIF2TX1MIX_INPUT_3_SOURCE:
+       case MADERA_AIF2TX1MIX_INPUT_3_VOLUME:
+       case MADERA_AIF2TX1MIX_INPUT_4_SOURCE:
+       case MADERA_AIF2TX1MIX_INPUT_4_VOLUME:
+       case MADERA_AIF2TX2MIX_INPUT_1_SOURCE:
+       case MADERA_AIF2TX2MIX_INPUT_1_VOLUME:
+       case MADERA_AIF2TX2MIX_INPUT_2_SOURCE:
+       case MADERA_AIF2TX2MIX_INPUT_2_VOLUME:
+       case MADERA_AIF2TX2MIX_INPUT_3_SOURCE:
+       case MADERA_AIF2TX2MIX_INPUT_3_VOLUME:
+       case MADERA_AIF2TX2MIX_INPUT_4_SOURCE:
+       case MADERA_AIF2TX2MIX_INPUT_4_VOLUME:
+       case MADERA_AIF2TX3MIX_INPUT_1_SOURCE:
+       case MADERA_AIF2TX3MIX_INPUT_1_VOLUME:
+       case MADERA_AIF2TX3MIX_INPUT_2_SOURCE:
+       case MADERA_AIF2TX3MIX_INPUT_2_VOLUME:
+       case MADERA_AIF2TX3MIX_INPUT_3_SOURCE:
+       case MADERA_AIF2TX3MIX_INPUT_3_VOLUME:
+       case MADERA_AIF2TX3MIX_INPUT_4_SOURCE:
+       case MADERA_AIF2TX3MIX_INPUT_4_VOLUME:
+       case MADERA_AIF2TX4MIX_INPUT_1_SOURCE:
+       case MADERA_AIF2TX4MIX_INPUT_1_VOLUME:
+       case MADERA_AIF2TX4MIX_INPUT_2_SOURCE:
+       case MADERA_AIF2TX4MIX_INPUT_2_VOLUME:
+       case MADERA_AIF2TX4MIX_INPUT_3_SOURCE:
+       case MADERA_AIF2TX4MIX_INPUT_3_VOLUME:
+       case MADERA_AIF2TX4MIX_INPUT_4_SOURCE:
+       case MADERA_AIF2TX4MIX_INPUT_4_VOLUME:
+       case MADERA_AIF2TX5MIX_INPUT_1_SOURCE:
+       case MADERA_AIF2TX5MIX_INPUT_1_VOLUME:
+       case MADERA_AIF2TX5MIX_INPUT_2_SOURCE:
+       case MADERA_AIF2TX5MIX_INPUT_2_VOLUME:
+       case MADERA_AIF2TX5MIX_INPUT_3_SOURCE:
+       case MADERA_AIF2TX5MIX_INPUT_3_VOLUME:
+       case MADERA_AIF2TX5MIX_INPUT_4_SOURCE:
+       case MADERA_AIF2TX5MIX_INPUT_4_VOLUME:
+       case MADERA_AIF2TX6MIX_INPUT_1_SOURCE:
+       case MADERA_AIF2TX6MIX_INPUT_1_VOLUME:
+       case MADERA_AIF2TX6MIX_INPUT_2_SOURCE:
+       case MADERA_AIF2TX6MIX_INPUT_2_VOLUME:
+       case MADERA_AIF2TX6MIX_INPUT_3_SOURCE:
+       case MADERA_AIF2TX6MIX_INPUT_3_VOLUME:
+       case MADERA_AIF2TX6MIX_INPUT_4_SOURCE:
+       case MADERA_AIF2TX6MIX_INPUT_4_VOLUME:
+       case MADERA_AIF2TX7MIX_INPUT_1_SOURCE:
+       case MADERA_AIF2TX7MIX_INPUT_1_VOLUME:
+       case MADERA_AIF2TX7MIX_INPUT_2_SOURCE:
+       case MADERA_AIF2TX7MIX_INPUT_2_VOLUME:
+       case MADERA_AIF2TX7MIX_INPUT_3_SOURCE:
+       case MADERA_AIF2TX7MIX_INPUT_3_VOLUME:
+       case MADERA_AIF2TX7MIX_INPUT_4_SOURCE:
+       case MADERA_AIF2TX7MIX_INPUT_4_VOLUME:
+       case MADERA_AIF2TX8MIX_INPUT_1_SOURCE:
+       case MADERA_AIF2TX8MIX_INPUT_1_VOLUME:
+       case MADERA_AIF2TX8MIX_INPUT_2_SOURCE:
+       case MADERA_AIF2TX8MIX_INPUT_2_VOLUME:
+       case MADERA_AIF2TX8MIX_INPUT_3_SOURCE:
+       case MADERA_AIF2TX8MIX_INPUT_3_VOLUME:
+       case MADERA_AIF2TX8MIX_INPUT_4_SOURCE:
+       case MADERA_AIF2TX8MIX_INPUT_4_VOLUME:
+       case MADERA_AIF3TX1MIX_INPUT_1_SOURCE:
+       case MADERA_AIF3TX1MIX_INPUT_1_VOLUME:
+       case MADERA_AIF3TX1MIX_INPUT_2_SOURCE:
+       case MADERA_AIF3TX1MIX_INPUT_2_VOLUME:
+       case MADERA_AIF3TX1MIX_INPUT_3_SOURCE:
+       case MADERA_AIF3TX1MIX_INPUT_3_VOLUME:
+       case MADERA_AIF3TX1MIX_INPUT_4_SOURCE:
+       case MADERA_AIF3TX1MIX_INPUT_4_VOLUME:
+       case MADERA_AIF3TX2MIX_INPUT_1_SOURCE:
+       case MADERA_AIF3TX2MIX_INPUT_1_VOLUME:
+       case MADERA_AIF3TX2MIX_INPUT_2_SOURCE:
+       case MADERA_AIF3TX2MIX_INPUT_2_VOLUME:
+       case MADERA_AIF3TX2MIX_INPUT_3_SOURCE:
+       case MADERA_AIF3TX2MIX_INPUT_3_VOLUME:
+       case MADERA_AIF3TX2MIX_INPUT_4_SOURCE:
+       case MADERA_AIF3TX2MIX_INPUT_4_VOLUME:
+       case MADERA_AIF4TX1MIX_INPUT_1_SOURCE:
+       case MADERA_AIF4TX1MIX_INPUT_1_VOLUME:
+       case MADERA_AIF4TX1MIX_INPUT_2_SOURCE:
+       case MADERA_AIF4TX1MIX_INPUT_2_VOLUME:
+       case MADERA_AIF4TX1MIX_INPUT_3_SOURCE:
+       case MADERA_AIF4TX1MIX_INPUT_3_VOLUME:
+       case MADERA_AIF4TX1MIX_INPUT_4_SOURCE:
+       case MADERA_AIF4TX1MIX_INPUT_4_VOLUME:
+       case MADERA_AIF4TX2MIX_INPUT_1_SOURCE:
+       case MADERA_AIF4TX2MIX_INPUT_1_VOLUME:
+       case MADERA_AIF4TX2MIX_INPUT_2_SOURCE:
+       case MADERA_AIF4TX2MIX_INPUT_2_VOLUME:
+       case MADERA_AIF4TX2MIX_INPUT_3_SOURCE:
+       case MADERA_AIF4TX2MIX_INPUT_3_VOLUME:
+       case MADERA_AIF4TX2MIX_INPUT_4_SOURCE:
+       case MADERA_AIF4TX2MIX_INPUT_4_VOLUME:
+       case MADERA_SLIMTX1MIX_INPUT_1_SOURCE:
+       case MADERA_SLIMTX1MIX_INPUT_1_VOLUME:
+       case MADERA_SLIMTX1MIX_INPUT_2_SOURCE:
+       case MADERA_SLIMTX1MIX_INPUT_2_VOLUME:
+       case MADERA_SLIMTX1MIX_INPUT_3_SOURCE:
+       case MADERA_SLIMTX1MIX_INPUT_3_VOLUME:
+       case MADERA_SLIMTX1MIX_INPUT_4_SOURCE:
+       case MADERA_SLIMTX1MIX_INPUT_4_VOLUME:
+       case MADERA_SLIMTX2MIX_INPUT_1_SOURCE:
+       case MADERA_SLIMTX2MIX_INPUT_1_VOLUME:
+       case MADERA_SLIMTX2MIX_INPUT_2_SOURCE:
+       case MADERA_SLIMTX2MIX_INPUT_2_VOLUME:
+       case MADERA_SLIMTX2MIX_INPUT_3_SOURCE:
+       case MADERA_SLIMTX2MIX_INPUT_3_VOLUME:
+       case MADERA_SLIMTX2MIX_INPUT_4_SOURCE:
+       case MADERA_SLIMTX2MIX_INPUT_4_VOLUME:
+       case MADERA_SLIMTX3MIX_INPUT_1_SOURCE:
+       case MADERA_SLIMTX3MIX_INPUT_1_VOLUME:
+       case MADERA_SLIMTX3MIX_INPUT_2_SOURCE:
+       case MADERA_SLIMTX3MIX_INPUT_2_VOLUME:
+       case MADERA_SLIMTX3MIX_INPUT_3_SOURCE:
+       case MADERA_SLIMTX3MIX_INPUT_3_VOLUME:
+       case MADERA_SLIMTX3MIX_INPUT_4_SOURCE:
+       case MADERA_SLIMTX3MIX_INPUT_4_VOLUME:
+       case MADERA_SLIMTX4MIX_INPUT_1_SOURCE:
+       case MADERA_SLIMTX4MIX_INPUT_1_VOLUME:
+       case MADERA_SLIMTX4MIX_INPUT_2_SOURCE:
+       case MADERA_SLIMTX4MIX_INPUT_2_VOLUME:
+       case MADERA_SLIMTX4MIX_INPUT_3_SOURCE:
+       case MADERA_SLIMTX4MIX_INPUT_3_VOLUME:
+       case MADERA_SLIMTX4MIX_INPUT_4_SOURCE:
+       case MADERA_SLIMTX4MIX_INPUT_4_VOLUME:
+       case MADERA_SLIMTX5MIX_INPUT_1_SOURCE:
+       case MADERA_SLIMTX5MIX_INPUT_1_VOLUME:
+       case MADERA_SLIMTX5MIX_INPUT_2_SOURCE:
+       case MADERA_SLIMTX5MIX_INPUT_2_VOLUME:
+       case MADERA_SLIMTX5MIX_INPUT_3_SOURCE:
+       case MADERA_SLIMTX5MIX_INPUT_3_VOLUME:
+       case MADERA_SLIMTX5MIX_INPUT_4_SOURCE:
+       case MADERA_SLIMTX5MIX_INPUT_4_VOLUME:
+       case MADERA_SLIMTX6MIX_INPUT_1_SOURCE:
+       case MADERA_SLIMTX6MIX_INPUT_1_VOLUME:
+       case MADERA_SLIMTX6MIX_INPUT_2_SOURCE:
+       case MADERA_SLIMTX6MIX_INPUT_2_VOLUME:
+       case MADERA_SLIMTX6MIX_INPUT_3_SOURCE:
+       case MADERA_SLIMTX6MIX_INPUT_3_VOLUME:
+       case MADERA_SLIMTX6MIX_INPUT_4_SOURCE:
+       case MADERA_SLIMTX6MIX_INPUT_4_VOLUME:
+       case MADERA_SLIMTX7MIX_INPUT_1_SOURCE:
+       case MADERA_SLIMTX7MIX_INPUT_1_VOLUME:
+       case MADERA_SLIMTX7MIX_INPUT_2_SOURCE:
+       case MADERA_SLIMTX7MIX_INPUT_2_VOLUME:
+       case MADERA_SLIMTX7MIX_INPUT_3_SOURCE:
+       case MADERA_SLIMTX7MIX_INPUT_3_VOLUME:
+       case MADERA_SLIMTX7MIX_INPUT_4_SOURCE:
+       case MADERA_SLIMTX7MIX_INPUT_4_VOLUME:
+       case MADERA_SLIMTX8MIX_INPUT_1_SOURCE:
+       case MADERA_SLIMTX8MIX_INPUT_1_VOLUME:
+       case MADERA_SLIMTX8MIX_INPUT_2_SOURCE:
+       case MADERA_SLIMTX8MIX_INPUT_2_VOLUME:
+       case MADERA_SLIMTX8MIX_INPUT_3_SOURCE:
+       case MADERA_SLIMTX8MIX_INPUT_3_VOLUME:
+       case MADERA_SLIMTX8MIX_INPUT_4_SOURCE:
+       case MADERA_SLIMTX8MIX_INPUT_4_VOLUME:
+       case MADERA_SPDIF1TX1MIX_INPUT_1_SOURCE:
+       case MADERA_SPDIF1TX1MIX_INPUT_1_VOLUME:
+       case MADERA_SPDIF1TX2MIX_INPUT_1_SOURCE:
+       case MADERA_SPDIF1TX2MIX_INPUT_1_VOLUME:
+       case MADERA_EQ1MIX_INPUT_1_SOURCE:
+       case MADERA_EQ1MIX_INPUT_1_VOLUME:
+       case MADERA_EQ1MIX_INPUT_2_SOURCE:
+       case MADERA_EQ1MIX_INPUT_2_VOLUME:
+       case MADERA_EQ1MIX_INPUT_3_SOURCE:
+       case MADERA_EQ1MIX_INPUT_3_VOLUME:
+       case MADERA_EQ1MIX_INPUT_4_SOURCE:
+       case MADERA_EQ1MIX_INPUT_4_VOLUME:
+       case MADERA_EQ2MIX_INPUT_1_SOURCE:
+       case MADERA_EQ2MIX_INPUT_1_VOLUME:
+       case MADERA_EQ2MIX_INPUT_2_SOURCE:
+       case MADERA_EQ2MIX_INPUT_2_VOLUME:
+       case MADERA_EQ2MIX_INPUT_3_SOURCE:
+       case MADERA_EQ2MIX_INPUT_3_VOLUME:
+       case MADERA_EQ2MIX_INPUT_4_SOURCE:
+       case MADERA_EQ2MIX_INPUT_4_VOLUME:
+       case MADERA_EQ3MIX_INPUT_1_SOURCE:
+       case MADERA_EQ3MIX_INPUT_1_VOLUME:
+       case MADERA_EQ3MIX_INPUT_2_SOURCE:
+       case MADERA_EQ3MIX_INPUT_2_VOLUME:
+       case MADERA_EQ3MIX_INPUT_3_SOURCE:
+       case MADERA_EQ3MIX_INPUT_3_VOLUME:
+       case MADERA_EQ3MIX_INPUT_4_SOURCE:
+       case MADERA_EQ3MIX_INPUT_4_VOLUME:
+       case MADERA_EQ4MIX_INPUT_1_SOURCE:
+       case MADERA_EQ4MIX_INPUT_1_VOLUME:
+       case MADERA_EQ4MIX_INPUT_2_SOURCE:
+       case MADERA_EQ4MIX_INPUT_2_VOLUME:
+       case MADERA_EQ4MIX_INPUT_3_SOURCE:
+       case MADERA_EQ4MIX_INPUT_3_VOLUME:
+       case MADERA_EQ4MIX_INPUT_4_SOURCE:
+       case MADERA_EQ4MIX_INPUT_4_VOLUME:
+       case MADERA_DRC1LMIX_INPUT_1_SOURCE:
+       case MADERA_DRC1LMIX_INPUT_1_VOLUME:
+       case MADERA_DRC1LMIX_INPUT_2_SOURCE:
+       case MADERA_DRC1LMIX_INPUT_2_VOLUME:
+       case MADERA_DRC1LMIX_INPUT_3_SOURCE:
+       case MADERA_DRC1LMIX_INPUT_3_VOLUME:
+       case MADERA_DRC1LMIX_INPUT_4_SOURCE:
+       case MADERA_DRC1LMIX_INPUT_4_VOLUME:
+       case MADERA_DRC1RMIX_INPUT_1_SOURCE:
+       case MADERA_DRC1RMIX_INPUT_1_VOLUME:
+       case MADERA_DRC1RMIX_INPUT_2_SOURCE:
+       case MADERA_DRC1RMIX_INPUT_2_VOLUME:
+       case MADERA_DRC1RMIX_INPUT_3_SOURCE:
+       case MADERA_DRC1RMIX_INPUT_3_VOLUME:
+       case MADERA_DRC1RMIX_INPUT_4_SOURCE:
+       case MADERA_DRC1RMIX_INPUT_4_VOLUME:
+       case MADERA_DRC2LMIX_INPUT_1_SOURCE:
+       case MADERA_DRC2LMIX_INPUT_1_VOLUME:
+       case MADERA_DRC2LMIX_INPUT_2_SOURCE:
+       case MADERA_DRC2LMIX_INPUT_2_VOLUME:
+       case MADERA_DRC2LMIX_INPUT_3_SOURCE:
+       case MADERA_DRC2LMIX_INPUT_3_VOLUME:
+       case MADERA_DRC2LMIX_INPUT_4_SOURCE:
+       case MADERA_DRC2LMIX_INPUT_4_VOLUME:
+       case MADERA_DRC2RMIX_INPUT_1_SOURCE:
+       case MADERA_DRC2RMIX_INPUT_1_VOLUME:
+       case MADERA_DRC2RMIX_INPUT_2_SOURCE:
+       case MADERA_DRC2RMIX_INPUT_2_VOLUME:
+       case MADERA_DRC2RMIX_INPUT_3_SOURCE:
+       case MADERA_DRC2RMIX_INPUT_3_VOLUME:
+       case MADERA_DRC2RMIX_INPUT_4_SOURCE:
+       case MADERA_DRC2RMIX_INPUT_4_VOLUME:
+       case MADERA_HPLP1MIX_INPUT_1_SOURCE:
+       case MADERA_HPLP1MIX_INPUT_1_VOLUME:
+       case MADERA_HPLP1MIX_INPUT_2_SOURCE:
+       case MADERA_HPLP1MIX_INPUT_2_VOLUME:
+       case MADERA_HPLP1MIX_INPUT_3_SOURCE:
+       case MADERA_HPLP1MIX_INPUT_3_VOLUME:
+       case MADERA_HPLP1MIX_INPUT_4_SOURCE:
+       case MADERA_HPLP1MIX_INPUT_4_VOLUME:
+       case MADERA_HPLP2MIX_INPUT_1_SOURCE:
+       case MADERA_HPLP2MIX_INPUT_1_VOLUME:
+       case MADERA_HPLP2MIX_INPUT_2_SOURCE:
+       case MADERA_HPLP2MIX_INPUT_2_VOLUME:
+       case MADERA_HPLP2MIX_INPUT_3_SOURCE:
+       case MADERA_HPLP2MIX_INPUT_3_VOLUME:
+       case MADERA_HPLP2MIX_INPUT_4_SOURCE:
+       case MADERA_HPLP2MIX_INPUT_4_VOLUME:
+       case MADERA_HPLP3MIX_INPUT_1_SOURCE:
+       case MADERA_HPLP3MIX_INPUT_1_VOLUME:
+       case MADERA_HPLP3MIX_INPUT_2_SOURCE:
+       case MADERA_HPLP3MIX_INPUT_2_VOLUME:
+       case MADERA_HPLP3MIX_INPUT_3_SOURCE:
+       case MADERA_HPLP3MIX_INPUT_3_VOLUME:
+       case MADERA_HPLP3MIX_INPUT_4_SOURCE:
+       case MADERA_HPLP3MIX_INPUT_4_VOLUME:
+       case MADERA_HPLP4MIX_INPUT_1_SOURCE:
+       case MADERA_HPLP4MIX_INPUT_1_VOLUME:
+       case MADERA_HPLP4MIX_INPUT_2_SOURCE:
+       case MADERA_HPLP4MIX_INPUT_2_VOLUME:
+       case MADERA_HPLP4MIX_INPUT_3_SOURCE:
+       case MADERA_HPLP4MIX_INPUT_3_VOLUME:
+       case MADERA_HPLP4MIX_INPUT_4_SOURCE:
+       case MADERA_HPLP4MIX_INPUT_4_VOLUME:
+       case MADERA_DSP1LMIX_INPUT_1_SOURCE:
+       case MADERA_DSP1LMIX_INPUT_1_VOLUME:
+       case MADERA_DSP1LMIX_INPUT_2_SOURCE:
+       case MADERA_DSP1LMIX_INPUT_2_VOLUME:
+       case MADERA_DSP1LMIX_INPUT_3_SOURCE:
+       case MADERA_DSP1LMIX_INPUT_3_VOLUME:
+       case MADERA_DSP1LMIX_INPUT_4_SOURCE:
+       case MADERA_DSP1LMIX_INPUT_4_VOLUME:
+       case MADERA_DSP1RMIX_INPUT_1_SOURCE:
+       case MADERA_DSP1RMIX_INPUT_1_VOLUME:
+       case MADERA_DSP1RMIX_INPUT_2_SOURCE:
+       case MADERA_DSP1RMIX_INPUT_2_VOLUME:
+       case MADERA_DSP1RMIX_INPUT_3_SOURCE:
+       case MADERA_DSP1RMIX_INPUT_3_VOLUME:
+       case MADERA_DSP1RMIX_INPUT_4_SOURCE:
+       case MADERA_DSP1RMIX_INPUT_4_VOLUME:
+       case MADERA_DSP1AUX1MIX_INPUT_1_SOURCE:
+       case MADERA_DSP1AUX2MIX_INPUT_1_SOURCE:
+       case MADERA_DSP1AUX3MIX_INPUT_1_SOURCE:
+       case MADERA_DSP1AUX4MIX_INPUT_1_SOURCE:
+       case MADERA_DSP1AUX5MIX_INPUT_1_SOURCE:
+       case MADERA_DSP1AUX6MIX_INPUT_1_SOURCE:
+       case MADERA_DSP2LMIX_INPUT_1_SOURCE:
+       case MADERA_DSP2LMIX_INPUT_1_VOLUME:
+       case MADERA_DSP2LMIX_INPUT_2_SOURCE:
+       case MADERA_DSP2LMIX_INPUT_2_VOLUME:
+       case MADERA_DSP2LMIX_INPUT_3_SOURCE:
+       case MADERA_DSP2LMIX_INPUT_3_VOLUME:
+       case MADERA_DSP2LMIX_INPUT_4_SOURCE:
+       case MADERA_DSP2LMIX_INPUT_4_VOLUME:
+       case MADERA_DSP2RMIX_INPUT_1_SOURCE:
+       case MADERA_DSP2RMIX_INPUT_1_VOLUME:
+       case MADERA_DSP2RMIX_INPUT_2_SOURCE:
+       case MADERA_DSP2RMIX_INPUT_2_VOLUME:
+       case MADERA_DSP2RMIX_INPUT_3_SOURCE:
+       case MADERA_DSP2RMIX_INPUT_3_VOLUME:
+       case MADERA_DSP2RMIX_INPUT_4_SOURCE:
+       case MADERA_DSP2RMIX_INPUT_4_VOLUME:
+       case MADERA_DSP2AUX1MIX_INPUT_1_SOURCE:
+       case MADERA_DSP2AUX2MIX_INPUT_1_SOURCE:
+       case MADERA_DSP2AUX3MIX_INPUT_1_SOURCE:
+       case MADERA_DSP2AUX4MIX_INPUT_1_SOURCE:
+       case MADERA_DSP2AUX5MIX_INPUT_1_SOURCE:
+       case MADERA_DSP2AUX6MIX_INPUT_1_SOURCE:
+       case MADERA_DSP3LMIX_INPUT_1_SOURCE:
+       case MADERA_DSP3LMIX_INPUT_1_VOLUME:
+       case MADERA_DSP3LMIX_INPUT_2_SOURCE:
+       case MADERA_DSP3LMIX_INPUT_2_VOLUME:
+       case MADERA_DSP3LMIX_INPUT_3_SOURCE:
+       case MADERA_DSP3LMIX_INPUT_3_VOLUME:
+       case MADERA_DSP3LMIX_INPUT_4_SOURCE:
+       case MADERA_DSP3LMIX_INPUT_4_VOLUME:
+       case MADERA_DSP3RMIX_INPUT_1_SOURCE:
+       case MADERA_DSP3RMIX_INPUT_1_VOLUME:
+       case MADERA_DSP3RMIX_INPUT_2_SOURCE:
+       case MADERA_DSP3RMIX_INPUT_2_VOLUME:
+       case MADERA_DSP3RMIX_INPUT_3_SOURCE:
+       case MADERA_DSP3RMIX_INPUT_3_VOLUME:
+       case MADERA_DSP3RMIX_INPUT_4_SOURCE:
+       case MADERA_DSP3RMIX_INPUT_4_VOLUME:
+       case MADERA_DSP3AUX1MIX_INPUT_1_SOURCE:
+       case MADERA_DSP3AUX2MIX_INPUT_1_SOURCE:
+       case MADERA_DSP3AUX3MIX_INPUT_1_SOURCE:
+       case MADERA_DSP3AUX4MIX_INPUT_1_SOURCE:
+       case MADERA_DSP3AUX5MIX_INPUT_1_SOURCE:
+       case MADERA_DSP3AUX6MIX_INPUT_1_SOURCE:
+       case MADERA_DSP4LMIX_INPUT_1_SOURCE:
+       case MADERA_DSP4LMIX_INPUT_1_VOLUME:
+       case MADERA_DSP4LMIX_INPUT_2_SOURCE:
+       case MADERA_DSP4LMIX_INPUT_2_VOLUME:
+       case MADERA_DSP4LMIX_INPUT_3_SOURCE:
+       case MADERA_DSP4LMIX_INPUT_3_VOLUME:
+       case MADERA_DSP4LMIX_INPUT_4_SOURCE:
+       case MADERA_DSP4LMIX_INPUT_4_VOLUME:
+       case MADERA_DSP4RMIX_INPUT_1_SOURCE:
+       case MADERA_DSP4RMIX_INPUT_1_VOLUME:
+       case MADERA_DSP4RMIX_INPUT_2_SOURCE:
+       case MADERA_DSP4RMIX_INPUT_2_VOLUME:
+       case MADERA_DSP4RMIX_INPUT_3_SOURCE:
+       case MADERA_DSP4RMIX_INPUT_3_VOLUME:
+       case MADERA_DSP4RMIX_INPUT_4_SOURCE:
+       case MADERA_DSP4RMIX_INPUT_4_VOLUME:
+       case MADERA_DSP4AUX1MIX_INPUT_1_SOURCE:
+       case MADERA_DSP4AUX2MIX_INPUT_1_SOURCE:
+       case MADERA_DSP4AUX3MIX_INPUT_1_SOURCE:
+       case MADERA_DSP4AUX4MIX_INPUT_1_SOURCE:
+       case MADERA_DSP4AUX5MIX_INPUT_1_SOURCE:
+       case MADERA_DSP4AUX6MIX_INPUT_1_SOURCE:
+       case MADERA_DSP5LMIX_INPUT_1_SOURCE:
+       case MADERA_DSP5LMIX_INPUT_1_VOLUME:
+       case MADERA_DSP5LMIX_INPUT_2_SOURCE:
+       case MADERA_DSP5LMIX_INPUT_2_VOLUME:
+       case MADERA_DSP5LMIX_INPUT_3_SOURCE:
+       case MADERA_DSP5LMIX_INPUT_3_VOLUME:
+       case MADERA_DSP5LMIX_INPUT_4_SOURCE:
+       case MADERA_DSP5LMIX_INPUT_4_VOLUME:
+       case MADERA_DSP5RMIX_INPUT_1_SOURCE:
+       case MADERA_DSP5RMIX_INPUT_1_VOLUME:
+       case MADERA_DSP5RMIX_INPUT_2_SOURCE:
+       case MADERA_DSP5RMIX_INPUT_2_VOLUME:
+       case MADERA_DSP5RMIX_INPUT_3_SOURCE:
+       case MADERA_DSP5RMIX_INPUT_3_VOLUME:
+       case MADERA_DSP5RMIX_INPUT_4_SOURCE:
+       case MADERA_DSP5RMIX_INPUT_4_VOLUME:
+       case MADERA_DSP5AUX1MIX_INPUT_1_SOURCE:
+       case MADERA_DSP5AUX2MIX_INPUT_1_SOURCE:
+       case MADERA_DSP5AUX3MIX_INPUT_1_SOURCE:
+       case MADERA_DSP5AUX4MIX_INPUT_1_SOURCE:
+       case MADERA_DSP5AUX5MIX_INPUT_1_SOURCE:
+       case MADERA_DSP5AUX6MIX_INPUT_1_SOURCE:
+       case MADERA_ASRC1_1LMIX_INPUT_1_SOURCE:
+       case MADERA_ASRC1_1RMIX_INPUT_1_SOURCE:
+       case MADERA_ASRC1_2LMIX_INPUT_1_SOURCE:
+       case MADERA_ASRC1_2RMIX_INPUT_1_SOURCE:
+       case MADERA_ASRC2_1LMIX_INPUT_1_SOURCE:
+       case MADERA_ASRC2_1RMIX_INPUT_1_SOURCE:
+       case MADERA_ASRC2_2LMIX_INPUT_1_SOURCE:
+       case MADERA_ASRC2_2RMIX_INPUT_1_SOURCE:
+       case MADERA_ISRC1DEC1MIX_INPUT_1_SOURCE:
+       case MADERA_ISRC1DEC2MIX_INPUT_1_SOURCE:
+       case MADERA_ISRC1DEC3MIX_INPUT_1_SOURCE:
+       case MADERA_ISRC1DEC4MIX_INPUT_1_SOURCE:
+       case MADERA_ISRC1INT1MIX_INPUT_1_SOURCE:
+       case MADERA_ISRC1INT2MIX_INPUT_1_SOURCE:
+       case MADERA_ISRC1INT3MIX_INPUT_1_SOURCE:
+       case MADERA_ISRC1INT4MIX_INPUT_1_SOURCE:
+       case MADERA_ISRC2DEC1MIX_INPUT_1_SOURCE:
+       case MADERA_ISRC2DEC2MIX_INPUT_1_SOURCE:
+       case MADERA_ISRC2DEC3MIX_INPUT_1_SOURCE:
+       case MADERA_ISRC2DEC4MIX_INPUT_1_SOURCE:
+       case MADERA_ISRC2INT1MIX_INPUT_1_SOURCE:
+       case MADERA_ISRC2INT2MIX_INPUT_1_SOURCE:
+       case MADERA_ISRC2INT3MIX_INPUT_1_SOURCE:
+       case MADERA_ISRC2INT4MIX_INPUT_1_SOURCE:
+       case MADERA_ISRC3DEC1MIX_INPUT_1_SOURCE:
+       case MADERA_ISRC3DEC2MIX_INPUT_1_SOURCE:
+       case MADERA_ISRC3INT1MIX_INPUT_1_SOURCE:
+       case MADERA_ISRC3INT2MIX_INPUT_1_SOURCE:
+       case MADERA_ISRC4DEC1MIX_INPUT_1_SOURCE:
+       case MADERA_ISRC4DEC2MIX_INPUT_1_SOURCE:
+       case MADERA_ISRC4INT1MIX_INPUT_1_SOURCE:
+       case MADERA_ISRC4INT2MIX_INPUT_1_SOURCE:
+       case MADERA_DSP6LMIX_INPUT_1_SOURCE:
+       case MADERA_DSP6LMIX_INPUT_1_VOLUME:
+       case MADERA_DSP6LMIX_INPUT_2_SOURCE:
+       case MADERA_DSP6LMIX_INPUT_2_VOLUME:
+       case MADERA_DSP6LMIX_INPUT_3_SOURCE:
+       case MADERA_DSP6LMIX_INPUT_3_VOLUME:
+       case MADERA_DSP6LMIX_INPUT_4_SOURCE:
+       case MADERA_DSP6LMIX_INPUT_4_VOLUME:
+       case MADERA_DSP6RMIX_INPUT_1_SOURCE:
+       case MADERA_DSP6RMIX_INPUT_1_VOLUME:
+       case MADERA_DSP6RMIX_INPUT_2_SOURCE:
+       case MADERA_DSP6RMIX_INPUT_2_VOLUME:
+       case MADERA_DSP6RMIX_INPUT_3_SOURCE:
+       case MADERA_DSP6RMIX_INPUT_3_VOLUME:
+       case MADERA_DSP6RMIX_INPUT_4_SOURCE:
+       case MADERA_DSP6RMIX_INPUT_4_VOLUME:
+       case MADERA_DSP6AUX1MIX_INPUT_1_SOURCE:
+       case MADERA_DSP6AUX2MIX_INPUT_1_SOURCE:
+       case MADERA_DSP6AUX3MIX_INPUT_1_SOURCE:
+       case MADERA_DSP6AUX4MIX_INPUT_1_SOURCE:
+       case MADERA_DSP6AUX5MIX_INPUT_1_SOURCE:
+       case MADERA_DSP6AUX6MIX_INPUT_1_SOURCE:
+       case MADERA_DSP7LMIX_INPUT_1_SOURCE:
+       case MADERA_DSP7LMIX_INPUT_1_VOLUME:
+       case MADERA_DSP7LMIX_INPUT_2_SOURCE:
+       case MADERA_DSP7LMIX_INPUT_2_VOLUME:
+       case MADERA_DSP7LMIX_INPUT_3_SOURCE:
+       case MADERA_DSP7LMIX_INPUT_3_VOLUME:
+       case MADERA_DSP7LMIX_INPUT_4_SOURCE:
+       case MADERA_DSP7LMIX_INPUT_4_VOLUME:
+       case MADERA_DSP7RMIX_INPUT_1_SOURCE:
+       case MADERA_DSP7RMIX_INPUT_1_VOLUME:
+       case MADERA_DSP7RMIX_INPUT_2_SOURCE:
+       case MADERA_DSP7RMIX_INPUT_2_VOLUME:
+       case MADERA_DSP7RMIX_INPUT_3_SOURCE:
+       case MADERA_DSP7RMIX_INPUT_3_VOLUME:
+       case MADERA_DSP7RMIX_INPUT_4_SOURCE:
+       case MADERA_DSP7RMIX_INPUT_4_VOLUME:
+       case MADERA_DSP7AUX1MIX_INPUT_1_SOURCE:
+       case MADERA_DSP7AUX2MIX_INPUT_1_SOURCE:
+       case MADERA_DSP7AUX3MIX_INPUT_1_SOURCE:
+       case MADERA_DSP7AUX4MIX_INPUT_1_SOURCE:
+       case MADERA_DSP7AUX5MIX_INPUT_1_SOURCE:
+       case MADERA_DSP7AUX6MIX_INPUT_1_SOURCE:
+       case MADERA_FX_CTRL1:
+       case MADERA_FX_CTRL2:
+       case MADERA_EQ1_1 ... MADERA_EQ1_21:
+       case MADERA_EQ2_1 ... MADERA_EQ2_21:
+       case MADERA_EQ3_1 ... MADERA_EQ3_21:
+       case MADERA_EQ4_1 ... MADERA_EQ4_21:
+       case MADERA_DRC1_CTRL1:
+       case MADERA_DRC1_CTRL2:
+       case MADERA_DRC1_CTRL3:
+       case MADERA_DRC1_CTRL4:
+       case MADERA_DRC1_CTRL5:
+       case MADERA_DRC2_CTRL1:
+       case MADERA_DRC2_CTRL2:
+       case MADERA_DRC2_CTRL3:
+       case MADERA_DRC2_CTRL4:
+       case MADERA_DRC2_CTRL5:
+       case MADERA_HPLPF1_1:
+       case MADERA_HPLPF1_2:
+       case MADERA_HPLPF2_1:
+       case MADERA_HPLPF2_2:
+       case MADERA_HPLPF3_1:
+       case MADERA_HPLPF3_2:
+       case MADERA_HPLPF4_1:
+       case MADERA_HPLPF4_2:
+       case MADERA_ASRC1_ENABLE:
+       case MADERA_ASRC1_STATUS:
+       case MADERA_ASRC1_RATE1:
+       case MADERA_ASRC1_RATE2:
+       case MADERA_ASRC2_ENABLE:
+       case MADERA_ASRC2_STATUS:
+       case MADERA_ASRC2_RATE1:
+       case MADERA_ASRC2_RATE2:
+       case MADERA_ISRC_1_CTRL_1:
+       case MADERA_ISRC_1_CTRL_2:
+       case MADERA_ISRC_1_CTRL_3:
+       case MADERA_ISRC_2_CTRL_1:
+       case MADERA_ISRC_2_CTRL_2:
+       case MADERA_ISRC_2_CTRL_3:
+       case MADERA_ISRC_3_CTRL_1:
+       case MADERA_ISRC_3_CTRL_2:
+       case MADERA_ISRC_3_CTRL_3:
+       case MADERA_ISRC_4_CTRL_1:
+       case MADERA_ISRC_4_CTRL_2:
+       case MADERA_ISRC_4_CTRL_3:
+       case MADERA_CLOCK_CONTROL:
+       case MADERA_ANC_SRC:
+       case MADERA_DSP_STATUS:
+       case MADERA_ANC_COEFF_START ... MADERA_ANC_COEFF_END:
+       case MADERA_FCL_FILTER_CONTROL:
+       case MADERA_FCL_ADC_REFORMATTER_CONTROL:
+       case MADERA_FCL_COEFF_START ... MADERA_FCL_COEFF_END:
+       case MADERA_FCR_FILTER_CONTROL:
+       case MADERA_FCR_ADC_REFORMATTER_CONTROL:
+       case MADERA_FCR_COEFF_START ... MADERA_FCR_COEFF_END:
+       case MADERA_DAC_COMP_1:
+       case MADERA_DAC_COMP_2:
+       case MADERA_FRF_COEFFICIENT_1L_1:
+       case MADERA_FRF_COEFFICIENT_1L_2:
+       case MADERA_FRF_COEFFICIENT_1L_3:
+       case MADERA_FRF_COEFFICIENT_1L_4:
+       case MADERA_FRF_COEFFICIENT_1R_1:
+       case MADERA_FRF_COEFFICIENT_1R_2:
+       case MADERA_FRF_COEFFICIENT_1R_3:
+       case MADERA_FRF_COEFFICIENT_1R_4:
+       case MADERA_FRF_COEFFICIENT_2L_1:
+       case MADERA_FRF_COEFFICIENT_2L_2:
+       case MADERA_FRF_COEFFICIENT_2L_3:
+       case MADERA_FRF_COEFFICIENT_2L_4:
+       case MADERA_FRF_COEFFICIENT_2R_1:
+       case MADERA_FRF_COEFFICIENT_2R_2:
+       case MADERA_FRF_COEFFICIENT_2R_3:
+       case MADERA_FRF_COEFFICIENT_2R_4:
+       case MADERA_FRF_COEFFICIENT_3L_1:
+       case MADERA_FRF_COEFFICIENT_3L_2:
+       case MADERA_FRF_COEFFICIENT_3L_3:
+       case MADERA_FRF_COEFFICIENT_3L_4:
+       case MADERA_FRF_COEFFICIENT_3R_1:
+       case MADERA_FRF_COEFFICIENT_3R_2:
+       case MADERA_FRF_COEFFICIENT_3R_3:
+       case MADERA_FRF_COEFFICIENT_3R_4:
+       case MADERA_FRF_COEFFICIENT_4L_1:
+       case MADERA_FRF_COEFFICIENT_4L_2:
+       case MADERA_FRF_COEFFICIENT_4L_3:
+       case MADERA_FRF_COEFFICIENT_4L_4:
+       case MADERA_FRF_COEFFICIENT_4R_1:
+       case MADERA_FRF_COEFFICIENT_4R_2:
+       case MADERA_FRF_COEFFICIENT_4R_3:
+       case MADERA_FRF_COEFFICIENT_4R_4:
+       case MADERA_FRF_COEFFICIENT_5L_1:
+       case MADERA_FRF_COEFFICIENT_5L_2:
+       case MADERA_FRF_COEFFICIENT_5L_3:
+       case MADERA_FRF_COEFFICIENT_5L_4:
+       case MADERA_FRF_COEFFICIENT_5R_1:
+       case MADERA_FRF_COEFFICIENT_5R_2:
+       case MADERA_FRF_COEFFICIENT_5R_3:
+       case MADERA_FRF_COEFFICIENT_5R_4:
+       case MADERA_FRF_COEFFICIENT_6L_1:
+       case MADERA_FRF_COEFFICIENT_6L_2:
+       case MADERA_FRF_COEFFICIENT_6L_3:
+       case MADERA_FRF_COEFFICIENT_6L_4:
+       case MADERA_FRF_COEFFICIENT_6R_1:
+       case MADERA_FRF_COEFFICIENT_6R_2:
+       case MADERA_FRF_COEFFICIENT_6R_3:
+       case MADERA_FRF_COEFFICIENT_6R_4:
+       case MADERA_GPIO1_CTRL_1 ... MADERA_GPIO40_CTRL_2:
+       case MADERA_IRQ1_STATUS_1 ... MADERA_IRQ1_STATUS_33:
+       case MADERA_IRQ1_MASK_1 ... MADERA_IRQ1_MASK_33:
+       case MADERA_IRQ1_RAW_STATUS_1 ... MADERA_IRQ1_RAW_STATUS_33:
+       case MADERA_INTERRUPT_DEBOUNCE_7:
+       case MADERA_IRQ1_CTRL:
+               return true;
+       default:
+               return false;
+       }
+}
+
+static bool cs47l85_16bit_volatile_register(struct device *dev,
+                                           unsigned int reg)
+{
+       switch (reg) {
+       case MADERA_SOFTWARE_RESET:
+       case MADERA_HARDWARE_REVISION:
+       case MADERA_WRITE_SEQUENCER_CTRL_0:
+       case MADERA_WRITE_SEQUENCER_CTRL_1:
+       case MADERA_WRITE_SEQUENCER_CTRL_2:
+       case MADERA_HAPTICS_STATUS:
+       case MADERA_SAMPLE_RATE_1_STATUS:
+       case MADERA_SAMPLE_RATE_2_STATUS:
+       case MADERA_SAMPLE_RATE_3_STATUS:
+       case MADERA_ASYNC_SAMPLE_RATE_1_STATUS:
+       case MADERA_ASYNC_SAMPLE_RATE_2_STATUS:
+       case MADERA_HP_CTRL_1L:
+       case MADERA_HP_CTRL_1R:
+       case MADERA_HP_CTRL_2L:
+       case MADERA_HP_CTRL_2R:
+       case MADERA_HP_CTRL_3L:
+       case MADERA_HP_CTRL_3R:
+       case MADERA_DCS_HP1L_CONTROL:
+       case MADERA_DCS_HP1R_CONTROL:
+       case MADERA_MIC_DETECT_1_CONTROL_3:
+       case MADERA_MIC_DETECT_1_CONTROL_4:
+       case MADERA_HEADPHONE_DETECT_2:
+       case MADERA_HEADPHONE_DETECT_3:
+       case MADERA_HEADPHONE_DETECT_5:
+       case MADERA_INPUT_ENABLES_STATUS:
+       case MADERA_OUTPUT_STATUS_1:
+       case MADERA_RAW_OUTPUT_STATUS_1:
+       case MADERA_SPD1_TX_CHANNEL_STATUS_1:
+       case MADERA_SPD1_TX_CHANNEL_STATUS_2:
+       case MADERA_SPD1_TX_CHANNEL_STATUS_3:
+       case MADERA_SLIMBUS_RX_PORT_STATUS:
+       case MADERA_SLIMBUS_TX_PORT_STATUS:
+       case MADERA_FX_CTRL2:
+       case MADERA_ASRC2_STATUS:
+       case MADERA_ASRC1_STATUS:
+       case MADERA_CLOCK_CONTROL:
+       case MADERA_IRQ1_STATUS_1 ...MADERA_IRQ1_STATUS_33:
+       case MADERA_IRQ1_RAW_STATUS_1 ... MADERA_IRQ1_RAW_STATUS_33:
+               return true;
+       default:
+               return false;
+       }
+}
+
+static bool cs47l85_32bit_readable_register(struct device *dev,
+                                           unsigned int reg)
+{
+       switch (reg) {
+       case MADERA_WSEQ_SEQUENCE_1 ... MADERA_WSEQ_SEQUENCE_508:
+       case CS47L85_OTP_HPDET_CAL_1 ... CS47L85_OTP_HPDET_CAL_2:
+       case MADERA_DSP1_CONFIG_1 ... MADERA_DSP1_SCRATCH_2:
+       case MADERA_DSP2_CONFIG_1 ... MADERA_DSP2_SCRATCH_2:
+       case MADERA_DSP3_CONFIG_1 ... MADERA_DSP3_SCRATCH_2:
+       case MADERA_DSP4_CONFIG_1 ... MADERA_DSP4_SCRATCH_2:
+       case MADERA_DSP5_CONFIG_1 ... MADERA_DSP5_SCRATCH_2:
+       case MADERA_DSP6_CONFIG_1 ... MADERA_DSP6_SCRATCH_2:
+       case MADERA_DSP7_CONFIG_1 ... MADERA_DSP7_SCRATCH_2:
+               return true;
+       default:
+               return cs47l85_is_adsp_memory(reg);
+       }
+}
+
+static bool cs47l85_32bit_volatile_register(struct device *dev,
+                                           unsigned int reg)
+{
+       switch (reg) {
+       case MADERA_WSEQ_SEQUENCE_1 ... MADERA_WSEQ_SEQUENCE_508:
+       case CS47L85_OTP_HPDET_CAL_1 ... CS47L85_OTP_HPDET_CAL_2:
+       case MADERA_DSP1_CONFIG_1 ... MADERA_DSP1_SCRATCH_2:
+       case MADERA_DSP2_CONFIG_1 ... MADERA_DSP2_SCRATCH_2:
+       case MADERA_DSP3_CONFIG_1 ... MADERA_DSP3_SCRATCH_2:
+       case MADERA_DSP4_CONFIG_1 ... MADERA_DSP4_SCRATCH_2:
+       case MADERA_DSP5_CONFIG_1 ... MADERA_DSP5_SCRATCH_2:
+       case MADERA_DSP6_CONFIG_1 ... MADERA_DSP6_SCRATCH_2:
+       case MADERA_DSP7_CONFIG_1 ... MADERA_DSP7_SCRATCH_2:
+               return true;
+       default:
+               return cs47l85_is_adsp_memory(reg);
+       }
+}
+
+const struct regmap_config cs47l85_16bit_spi_regmap = {
+       .name = "cs47l85_16bit",
+       .reg_bits = 32,
+       .pad_bits = 16,
+       .val_bits = 16,
+       .reg_format_endian = REGMAP_ENDIAN_BIG,
+       .val_format_endian = REGMAP_ENDIAN_BIG,
+
+       .max_register = 0x2fff,
+       .readable_reg = cs47l85_16bit_readable_register,
+       .volatile_reg = cs47l85_16bit_volatile_register,
+
+       .cache_type = REGCACHE_RBTREE,
+       .reg_defaults = cs47l85_reg_default,
+       .num_reg_defaults = ARRAY_SIZE(cs47l85_reg_default),
+};
+EXPORT_SYMBOL_GPL(cs47l85_16bit_spi_regmap);
+
+const struct regmap_config cs47l85_16bit_i2c_regmap = {
+       .name = "cs47l85_16bit",
+       .reg_bits = 32,
+       .val_bits = 16,
+       .reg_format_endian = REGMAP_ENDIAN_BIG,
+       .val_format_endian = REGMAP_ENDIAN_BIG,
+
+       .max_register = 0x2fff,
+       .readable_reg = cs47l85_16bit_readable_register,
+       .volatile_reg = cs47l85_16bit_volatile_register,
+
+       .cache_type = REGCACHE_RBTREE,
+       .reg_defaults = cs47l85_reg_default,
+       .num_reg_defaults = ARRAY_SIZE(cs47l85_reg_default),
+};
+EXPORT_SYMBOL_GPL(cs47l85_16bit_i2c_regmap);
+
+const struct regmap_config cs47l85_32bit_spi_regmap = {
+       .name = "cs47l85_32bit",
+       .reg_bits = 32,
+       .reg_stride = 2,
+       .pad_bits = 16,
+       .val_bits = 32,
+       .reg_format_endian = REGMAP_ENDIAN_BIG,
+       .val_format_endian = REGMAP_ENDIAN_BIG,
+
+       .max_register = MADERA_DSP7_SCRATCH_2,
+       .readable_reg = cs47l85_32bit_readable_register,
+       .volatile_reg = cs47l85_32bit_volatile_register,
+
+       .cache_type = REGCACHE_RBTREE,
+};
+EXPORT_SYMBOL_GPL(cs47l85_32bit_spi_regmap);
+
+const struct regmap_config cs47l85_32bit_i2c_regmap = {
+       .name = "cs47l85_32bit",
+       .reg_bits = 32,
+       .reg_stride = 2,
+       .val_bits = 32,
+       .reg_format_endian = REGMAP_ENDIAN_BIG,
+       .val_format_endian = REGMAP_ENDIAN_BIG,
+
+       .max_register = MADERA_DSP7_SCRATCH_2,
+       .readable_reg = cs47l85_32bit_readable_register,
+       .volatile_reg = cs47l85_32bit_volatile_register,
+
+       .cache_type = REGCACHE_RBTREE,
+};
+EXPORT_SYMBOL_GPL(cs47l85_32bit_i2c_regmap);
diff --git a/drivers/mfd/cs47l90-tables.c b/drivers/mfd/cs47l90-tables.c
new file mode 100644 (file)
index 0000000..77207d9
--- /dev/null
@@ -0,0 +1,2674 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Regmap tables for CS47L90 codec
+ *
+ * Copyright (C) 2015-2017 Cirrus Logic
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2.
+ */
+
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+
+#include <linux/mfd/madera/core.h>
+#include <linux/mfd/madera/registers.h>
+
+#include "madera.h"
+
+static const struct reg_sequence cs47l90_reva_16_patch[] = {
+       { 0x8A,   0x5555 },
+       { 0x8A,   0xAAAA },
+       { 0x4CF,  0x0700 },
+       { 0x171,  0x0003 },
+       { 0x101,  0x0444 },
+       { 0x159,  0x0002 },
+       { 0x120,  0x0444 },
+       { 0x1D1,  0x0004 },
+       { 0x1E0,  0xC084 },
+       { 0x159,  0x0000 },
+       { 0x120,  0x0404 },
+       { 0x101,  0x0404 },
+       { 0x171,  0x0002 },
+       { 0x17A,  0x2906 },
+       { 0x19A,  0x2906 },
+       { 0x441,  0xC750 },
+       { 0x340,  0x0001 },
+       { 0x112,  0x0405 },
+       { 0x124,  0x0C49 },
+       { 0x1300, 0x050E },
+       { 0x1302, 0x0101 },
+       { 0x1380, 0x0425 },
+       { 0x1381, 0xF6D8 },
+       { 0x1382, 0x0632 },
+       { 0x1383, 0xFEC8 },
+       { 0x1390, 0x042F },
+       { 0x1391, 0xF6CA },
+       { 0x1392, 0x0637 },
+       { 0x1393, 0xFEC8 },
+       { 0x281,  0x0000 },
+       { 0x282,  0x0000 },
+       { 0x4EA,  0x0100 },
+       { 0x8A,   0xCCCC },
+       { 0x8A,   0x3333 },
+};
+
+int cs47l90_patch(struct madera *madera)
+{
+       int ret;
+
+       ret = regmap_register_patch(madera->regmap,
+                                   cs47l90_reva_16_patch,
+                                   ARRAY_SIZE(cs47l90_reva_16_patch));
+       if (ret < 0) {
+               dev_err(madera->dev,
+                       "Error in applying 16-bit patch: %d\n", ret);
+               return ret;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(cs47l90_patch);
+
+static const struct reg_default cs47l90_reg_default[] = {
+       { 0x00000020, 0x0000 }, /* R32 (0x20) - Tone Generator 1 */
+       { 0x00000021, 0x1000 }, /* R33 (0x21) - Tone Generator 2 */
+       { 0x00000022, 0x0000 }, /* R34 (0x22) - Tone Generator 3 */
+       { 0x00000023, 0x1000 }, /* R35 (0x23) - Tone Generator 4 */
+       { 0x00000024, 0x0000 }, /* R36 (0x24) - Tone Generator 5 */
+       { 0x00000030, 0x0000 }, /* R48 (0x30) - PWM Drive 1 */
+       { 0x00000031, 0x0100 }, /* R49 (0x31) - PWM Drive 2 */
+       { 0x00000032, 0x0100 }, /* R50 (0x32) - PWM Drive 3 */
+       { 0x00000061, 0x01ff }, /* R97 (0x61) - Sample Rate Sequence Select 1 */
+       { 0x00000062, 0x01ff }, /* R98 (0x62) - Sample Rate Sequence Select 2 */
+       { 0x00000063, 0x01ff }, /* R99 (0x63) - Sample Rate Sequence Select 3 */
+       { 0x00000064, 0x01ff }, /* R100 (0x64) - Sample Rate Sequence Select 4 */
+       { 0x00000066, 0x01ff }, /* R102 (0x66) - Always On Triggers Sequence Select 1 */
+       { 0x00000067, 0x01ff }, /* R103 (0x67) - Always On Triggers Sequence Select 2 */
+       { 0x00000090, 0x0000 }, /* R144 (0x90) - Haptics Control 1 */
+       { 0x00000091, 0x7fff }, /* R145 (0x91) - Haptics Control 2 */
+       { 0x00000092, 0x0000 }, /* R146 (0x92) - Haptics phase 1 intensity */
+       { 0x00000093, 0x0000 }, /* R147 (0x93) - Haptics phase 1 duration */
+       { 0x00000094, 0x0000 }, /* R148 (0x94) - Haptics phase 2 intensity */
+       { 0x00000095, 0x0000 }, /* R149 (0x95) - Haptics phase 2 duration */
+       { 0x00000096, 0x0000 }, /* R150 (0x96) - Haptics phase 3 intensity */
+       { 0x00000097, 0x0000 }, /* R151 (0x97) - Haptics phase 3 duration */
+       { 0x000000a0, 0x0000 }, /* R160 (0xa0) - Comfort Noise Generator */
+       { 0x00000100, 0x0002 }, /* R256 (0x100) - Clock 32k 1 */
+       { 0x00000101, 0x0404 }, /* R257 (0x101) - System Clock 1 */
+       { 0x00000102, 0x0011 }, /* R258 (0x102) - Sample rate 1 */
+       { 0x00000103, 0x0011 }, /* R259 (0x103) - Sample rate 2 */
+       { 0x00000104, 0x0011 }, /* R260 (0x104) - Sample rate 3 */
+       { 0x00000112, 0x0405 }, /* R274 (0x112) - Async clock 1 */
+       { 0x00000113, 0x0011 }, /* R275 (0x113) - Async sample rate 1 */
+       { 0x00000114, 0x0011 }, /* R276 (0x114) - Async sample rate 2 */
+       { 0x00000120, 0x0404 }, /* R288 (0x120) - DSP Clock 1 */
+       { 0x00000122, 0x0000 }, /* R290 (0x122) - DSP Clock 2 */
+       { 0x00000149, 0x0000 }, /* R329 (0x149) - Output system clock */
+       { 0x0000014a, 0x0000 }, /* R330 (0x14a) - Output async clock */
+       { 0x00000152, 0x0000 }, /* R338 (0x152) - Rate Estimator 1 */
+       { 0x00000153, 0x0000 }, /* R339 (0x153) - Rate Estimator 2 */
+       { 0x00000154, 0x0000 }, /* R340 (0x154) - Rate Estimator 3 */
+       { 0x00000155, 0x0000 }, /* R341 (0x155) - Rate Estimator 4 */
+       { 0x00000156, 0x0000 }, /* R342 (0x156) - Rate Estimator 5 */
+       { 0x00000171, 0x0002 }, /* R369 (0x171) - FLL1 Control 1 */
+       { 0x00000172, 0x0008 }, /* R370 (0x172) - FLL1 Control 2 */
+       { 0x00000173, 0x0018 }, /* R371 (0x173) - FLL1 Control 3 */
+       { 0x00000174, 0x007d }, /* R372 (0x174) - FLL1 Control 4 */
+       { 0x00000175, 0x0000 }, /* R373 (0x175) - FLL1 Control 5 */
+       { 0x00000176, 0x0000 }, /* R374 (0x176) - FLL1 Control 6 */
+       { 0x00000177, 0x0281 }, /* R375 (0x177) - FLL1 Loop Filter Test 1 */
+       { 0x00000179, 0x0000 }, /* R377 (0x179) - FLL1 Control 7 */
+       { 0x0000017a, 0x2906 }, /* R377 (0x17a) - FLL1 Efs 2 */
+       { 0x00000181, 0x0000 }, /* R385 (0x181) - FLL1 Synchroniser 1 */
+       { 0x00000182, 0x0000 }, /* R386 (0x182) - FLL1 Synchroniser 2 */
+       { 0x00000183, 0x0000 }, /* R387 (0x183) - FLL1 Synchroniser 3 */
+       { 0x00000184, 0x0000 }, /* R388 (0x184) - FLL1 Synchroniser 4 */
+       { 0x00000185, 0x0000 }, /* R389 (0x185) - FLL1 Synchroniser 5 */
+       { 0x00000186, 0x0000 }, /* R390 (0x186) - FLL1 Synchroniser 6 */
+       { 0x00000187, 0x0001 }, /* R391 (0x187) - FLL1 Synchroniser 7 */
+       { 0x00000189, 0x0000 }, /* R393 (0x189) - FLL1 Spread Spectrum */
+       { 0x0000018a, 0x0004 }, /* R394 (0x18a) - FLL1 GPIO Clock */
+       { 0x00000191, 0x0002 }, /* R401 (0x191) - FLL2 Control 1 */
+       { 0x00000192, 0x0008 }, /* R402 (0x192) - FLL2 Control 2 */
+       { 0x00000193, 0x0018 }, /* R403 (0x193) - FLL2 Control 3 */
+       { 0x00000194, 0x007d }, /* R404 (0x194) - FLL2 Control 4 */
+       { 0x00000195, 0x0000 }, /* R405 (0x195) - FLL2 Control 5 */
+       { 0x00000196, 0x0000 }, /* R406 (0x196) - FLL2 Control 6 */
+       { 0x00000197, 0x0281 }, /* R407 (0x197) - FLL2 Loop Filter Test 1 */
+       { 0x00000199, 0x0000 }, /* R409 (0x199) - FLL2 Control 7 */
+       { 0x0000019a, 0x2906 }, /* R410 (0x19a) - FLL2 Efs 2 */
+       { 0x000001a1, 0x0000 }, /* R417 (0x1a1) - FLL2 Synchroniser 1 */
+       { 0x000001a2, 0x0000 }, /* R418 (0x1a2) - FLL2 Synchroniser 2 */
+       { 0x000001a3, 0x0000 }, /* R419 (0x1a3) - FLL2 Synchroniser 3 */
+       { 0x000001a4, 0x0000 }, /* R420 (0x1a4) - FLL2 Synchroniser 4 */
+       { 0x000001a5, 0x0000 }, /* R421 (0x1a5) - FLL2 Synchroniser 5 */
+       { 0x000001a6, 0x0000 }, /* R422 (0x1a6) - FLL2 Synchroniser 6 */
+       { 0x000001a7, 0x0001 }, /* R423 (0x1a7) - FLL2 Synchroniser 7 */
+       { 0x000001a9, 0x0000 }, /* R425 (0x1a9) - FLL2 Spread Spectrum */
+       { 0x000001aa, 0x0004 }, /* R426 (0x1aa) - FLL2 GPIO Clock */
+       { 0x000001d1, 0x0004 }, /* R465 (0x1d1) - FLLAO_CONTROL_1 */
+       { 0x000001d2, 0x0004 }, /* R466 (0x1d2) - FLLAO_CONTROL_2 */
+       { 0x000001d3, 0x0000 }, /* R467 (0x1d3) - FLLAO_CONTROL_3 */
+       { 0x000001d4, 0x0000 }, /* R468 (0x1d4) - FLLAO_CONTROL_4 */
+       { 0x000001d5, 0x0001 }, /* R469 (0x1d5) - FLLAO_CONTROL_5 */
+       { 0x000001d6, 0x8004 }, /* R470 (0x1d6) - FLLAO_CONTROL_6 */
+       { 0x000001d8, 0x0000 }, /* R472 (0x1d8) - FLLAO_CONTROL_7 */
+       { 0x000001da, 0x0070 }, /* R474 (0x1da) - FLLAO_CONTROL_8 */
+       { 0x000001db, 0x0000 }, /* R475 (0x1db) - FLLAO_CONTROL_9 */
+       { 0x000001dc, 0x06da }, /* R476 (0x1dc) - FLLAO_CONTROL_10 */
+       { 0x000001dd, 0x0011 }, /* R477 (0x1dd) - FLLAO_CONTROL_11 */
+       { 0x00000200, 0x0006 }, /* R512 (0x200) - Mic Charge Pump 1 */
+       { 0x00000213, 0x03e4 }, /* R531 (0x213) - LDO2 Control 1 */
+       { 0x00000218, 0x00e6 }, /* R536 (0x218) - Mic Bias Ctrl 1 */
+       { 0x00000219, 0x00e6 }, /* R537 (0x219) - Mic Bias Ctrl 2 */
+       { 0x0000021c, 0x2222 }, /* R540 (0x21c) - Mic Bias Ctrl 5 */
+       { 0x0000021e, 0x2222 }, /* R542 (0x21e) - Mic Bias Ctrl 6 */
+       { 0x0000027e, 0x0000 }, /* R638 (0x27e) - EDRE HP stereo control */
+       { 0x00000293, 0x0080 }, /* R659 (0x293) - Accessory Detect Mode 1 */
+       { 0x00000299, 0x0000 }, /* R665 (0x299) - Headphone Detect 0 */
+       { 0x0000029b, 0x0000 }, /* R667 (0x29b) - Headphone Detect 1 */
+       { 0x000002a2, 0x0010 }, /* R674 (0x2a2) - Mic Detect 1 Control 0 */
+       { 0x000002a3, 0x1102 }, /* R675 (0x2a3) - Mic Detect 1 Control 1 */
+       { 0x000002a4, 0x009f }, /* R676 (0x2a4) - Mic Detect 1 Control 2 */
+       { 0x000002a6, 0x3d3d }, /* R678 (0x2a6) - Mic Detect 1 Level 1 */
+       { 0x000002a7, 0x3d3d }, /* R679 (0x2a7) - Mic Detect 1 Level 2 */
+       { 0x000002a8, 0x333d }, /* R680 (0x2a8) - Mic Detect 1 Level 3 */
+       { 0x000002a9, 0x202d }, /* R681 (0x2a9) - Mic Detect 1 Level 4 */
+       { 0x000002b2, 0x0010 }, /* R690 (0x2b2) - Mic Detect 2 Control 0 */
+       { 0x000002b3, 0x1102 }, /* R691 (0x2b3) - Mic Detect 2 Control 1 */
+       { 0x000002b4, 0x009f }, /* R692 (0x2b4) - Mic Detect 2 Control 2 */
+       { 0x000002b6, 0x3d3d }, /* R694 (0x2b6) - Mic Detect 2 Level 1 */
+       { 0x000002b7, 0x3d3d }, /* R695 (0x2b7) - Mic Detect 2 Level 2 */
+       { 0x000002b8, 0x333d }, /* R696 (0x2b8) - Mic Detect 2 Level 3 */
+       { 0x000002b9, 0x202d }, /* R697 (0x2b9) - Mic Detect 2 Level 4 */
+       { 0x000002c6, 0x0010 }, /* R710 (0x2c6) - Mic Clamp control */
+       { 0x000002c8, 0x0000 }, /* R712 (0x2c8) - GP switch 1 */
+       { 0x000002d3, 0x0000 }, /* R723 (0x2d3) - Jack detect analogue */
+       { 0x00000300, 0x0000 }, /* R768 (0x300) - Input Enables */
+       { 0x00000308, 0x0400 }, /* R776 (0x308) - Input Rate */
+       { 0x00000309, 0x0022 }, /* R777 (0x309) - Input Volume Ramp */
+       { 0x0000030c, 0x0002 }, /* R780 (0x30C) - HPF Control */
+       { 0x00000310, 0x0080 }, /* R784 (0x310) - IN1L Control */
+       { 0x00000311, 0x0180 }, /* R785 (0x311) - ADC Digital Volume 1L */
+       { 0x00000312, 0x0500 }, /* R786 (0x312) - DMIC1L Control */
+       { 0x00000313, 0x0000 }, /* R787 (0x313) - IN1L Rate Control */
+       { 0x00000314, 0x0080 }, /* R788 (0x314) - IN1R Control */
+       { 0x00000315, 0x0180 }, /* R789 (0x315) - ADC Digital Volume 1R */
+       { 0x00000316, 0x0000 }, /* R790 (0x316) - DMIC1R Control */
+       { 0x00000317, 0x0000 }, /* R791 (0x317) - IN1R Rate Control */
+       { 0x00000318, 0x0080 }, /* R792 (0x318) - IN2L Control */
+       { 0x00000319, 0x0180 }, /* R793 (0x319) - ADC Digital Volume 2L */
+       { 0x0000031a, 0x0500 }, /* R794 (0x31a) - DMIC2L Control */
+       { 0x0000031b, 0x0000 }, /* R795 (0x31b) - IN2L Rate Control */
+       { 0x0000031c, 0x0080 }, /* R796 (0x31c) - IN2R Control */
+       { 0x0000031d, 0x0180 }, /* R797 (0x31d) - ADC Digital Volume 2R */
+       { 0x0000031e, 0x0000 }, /* R798 (0x31e) - DMIC2R Control */
+       { 0x0000031f, 0x0000 }, /* R799 (0x31f) - IN2R Rate Control */
+       { 0x00000320, 0x0000 }, /* R800 (0x320) - IN3L Control */
+       { 0x00000321, 0x0180 }, /* R801 (0x321) - ADC Digital Volume 3L */
+       { 0x00000322, 0x0500 }, /* R802 (0x322) - DMIC3L Control */
+       { 0x00000323, 0x0000 }, /* R803 (0x323) - IN3L Rate Control */
+       { 0x00000324, 0x0000 }, /* R804 (0x324) - IN3R Control */
+       { 0x00000325, 0x0180 }, /* R805 (0x325) - ADC Digital Volume 3R */
+       { 0x00000326, 0x0000 }, /* R806 (0x326) - DMIC3R Control */
+       { 0x00000327, 0x0000 }, /* R807 (0x327) - IN3R Rate Control */
+       { 0x00000328, 0x0000 }, /* R808 (0x328) - IN4 Control */
+       { 0x00000329, 0x0180 }, /* R809 (0x329) - ADC Digital Volume 4L */
+       { 0x0000032a, 0x0500 }, /* R810 (0x32a) - DMIC4L Control */
+       { 0x0000032b, 0x0000 }, /* R811 (0x32b) - IN4L Rate Control */
+       { 0x0000032c, 0x0000 }, /* R812 (0x32c) - IN4R Control */
+       { 0x0000032d, 0x0180 }, /* R813 (0x32d) - ADC Digital Volume 4R */
+       { 0x0000032e, 0x0000 }, /* R814 (0x32e) - DMIC4R Control */
+       { 0x0000032f, 0x0000 }, /* R815 (0x32f) - IN4R Rate Control */
+       { 0x00000330, 0x0000 }, /* R816 (0x330) - IN5L Control */
+       { 0x00000331, 0x0180 }, /* R817 (0x331) - ADC Digital Volume 5L */
+       { 0x00000332, 0x0500 }, /* R818 (0x332) - DMIC5L Control */
+       { 0x00000333, 0x0000 }, /* R819 (0x333) - IN5L Rate Control */
+       { 0x00000334, 0x0000 }, /* R820 (0x334) - IN5R Control */
+       { 0x00000335, 0x0180 }, /* R821 (0x335) - ADC Digital Volume 5R */
+       { 0x00000336, 0x0000 }, /* R822 (0x336) - DMIC5R Control */
+       { 0x00000337, 0x0000 }, /* R823 (0x337) - IN5R Rate Control */
+       { 0x00000400, 0x0000 }, /* R1024 (0x400) - Output Enables 1 */
+       { 0x00000408, 0x0000 }, /* R1032 (0x408) - Output Rate 1 */
+       { 0x00000409, 0x0022 }, /* R1033 (0x409) - Output Volume Ramp */
+       { 0x00000410, 0x0080 }, /* R1040 (0x410) - Output Path Config 1L */
+       { 0x00000411, 0x0180 }, /* R1041 (0x411) - DAC Digital Volume 1L */
+       { 0x00000412, 0x0000 }, /* R1042 (0x412) - Output Path Config 1 */
+       { 0x00000413, 0x0001 }, /* R1043 (0x413) - Noise Gate Select 1L */
+       { 0x00000414, 0x0080 }, /* R1044 (0x414) - Output Path Config 1R */
+       { 0x00000415, 0x0180 }, /* R1045 (0x415) - DAC Digital Volume 1R */
+       { 0x00000417, 0x0002 }, /* R1047 (0x417) - Noise Gate Select 1R */
+       { 0x00000418, 0x0080 }, /* R1048 (0x418) - Output Path Config 2L */
+       { 0x00000419, 0x0180 }, /* R1049 (0x419) - DAC Digital Volume 2L */
+       { 0x0000041a, 0x0002 }, /* R1050 (0x41a) - Output Path Config 2 */
+       { 0x0000041b, 0x0004 }, /* R1051 (0x41b) - Noise Gate Select 2L */
+       { 0x0000041c, 0x0080 }, /* R1052 (0x41c) - Output Path Config 2R */
+       { 0x0000041d, 0x0180 }, /* R1053 (0x41d) - DAC Digital Volume 2R */
+       { 0x0000041f, 0x0008 }, /* R1055 (0x41f) - Noise Gate Select 2R */
+       { 0x00000420, 0x0080 }, /* R1056 (0x420) - Output Path Config 3L */
+       { 0x00000421, 0x0180 }, /* R1057 (0x421) - DAC Digital Volume 3L */
+       { 0x00000423, 0x0010 }, /* R1059 (0x423) - Noise Gate Select 3L */
+       { 0x00000424, 0x0080 }, /* R1060 (0x424) - Output Path Config 3R */
+       { 0x00000425, 0x0180 }, /* R1061 (0x425) - DAC Digital Volume 3R */
+       { 0x00000427, 0x0020 }, /* R1063 (0x427) - Noise Gate Select 3R */
+       { 0x00000430, 0x0000 }, /* R1072 (0x430) - Output Path Config 5L */
+       { 0x00000431, 0x0180 }, /* R1073 (0x431) - DAC Digital Volume 5L */
+       { 0x00000433, 0x0100 }, /* R1075 (0x433) - Noise Gate Select 5L */
+       { 0x00000434, 0x0000 }, /* R1076 (0x434) - Output Path Config 5R */
+       { 0x00000435, 0x0180 }, /* R1077 (0x435) - DAC Digital Volume 5R */
+       { 0x00000437, 0x0200 }, /* R1079 (0x437) - Noise Gate Select 5R */
+       { 0x00000440, 0x003f }, /* R1088 (0x440) - DRE Enable */
+       { 0x00000448, 0x003f }, /* R1096 (0x448) - eDRE Enable */
+       { 0x00000450, 0x0000 }, /* R1104 (0x450) - DAC AEC Control 1 */
+       { 0x00000458, 0x0000 }, /* R1112 (0x458) - Noise Gate Control */
+       { 0x00000490, 0x0069 }, /* R1168 (0x490) - PDM SPK1 CTRL 1 */
+       { 0x00000491, 0x0000 }, /* R1169 (0x491) - PDM SPK1 CTRL 2 */
+       { 0x000004a0, 0x3080 }, /* R1184 (0x4a0) - HP1 Short Circuit Ctrl */
+       { 0x000004a1, 0x3000 }, /* R1185 (0x4a1) - HP2 Short Circuit Ctrl */
+       { 0x000004a2, 0x3000 }, /* R1186 (0x4a2) - HP3 Short Circuit Ctrl */
+       { 0x00000500, 0x000c }, /* R1280 (0x500) - AIF1 BCLK Ctrl */
+       { 0x00000501, 0x0000 }, /* R1281 (0x501) - AIF1 Tx Pin Ctrl */
+       { 0x00000502, 0x0000 }, /* R1282 (0x502) - AIF1 Rx Pin Ctrl */
+       { 0x00000503, 0x0000 }, /* R1283 (0x503) - AIF1 Rate Ctrl */
+       { 0x00000504, 0x0000 }, /* R1284 (0x504) - AIF1 Format */
+       { 0x00000506, 0x0040 }, /* R1286 (0x506) - AIF1 Rx BCLK Rate */
+       { 0x00000507, 0x1818 }, /* R1287 (0x507) - AIF1 Frame Ctrl 1 */
+       { 0x00000508, 0x1818 }, /* R1288 (0x508) - AIF1 Frame Ctrl 2 */
+       { 0x00000509, 0x0000 }, /* R1289 (0x509) - AIF1 Frame Ctrl 3 */
+       { 0x0000050a, 0x0001 }, /* R1290 (0x50a) - AIF1 Frame Ctrl 4 */
+       { 0x0000050b, 0x0002 }, /* R1291 (0x50b) - AIF1 Frame Ctrl 5 */
+       { 0x0000050c, 0x0003 }, /* R1292 (0x50c) - AIF1 Frame Ctrl 6 */
+       { 0x0000050d, 0x0004 }, /* R1293 (0x50d) - AIF1 Frame Ctrl 7 */
+       { 0x0000050e, 0x0005 }, /* R1294 (0x50e) - AIF1 Frame Ctrl 8 */
+       { 0x0000050f, 0x0006 }, /* R1295 (0x50f) - AIF1 Frame Ctrl 9 */
+       { 0x00000510, 0x0007 }, /* R1296 (0x510) - AIF1 Frame Ctrl 10 */
+       { 0x00000511, 0x0000 }, /* R1297 (0x511) - AIF1 Frame Ctrl 11 */
+       { 0x00000512, 0x0001 }, /* R1298 (0x512) - AIF1 Frame Ctrl 12 */
+       { 0x00000513, 0x0002 }, /* R1299 (0x513) - AIF1 Frame Ctrl 13 */
+       { 0x00000514, 0x0003 }, /* R1300 (0x514) - AIF1 Frame Ctrl 14 */
+       { 0x00000515, 0x0004 }, /* R1301 (0x515) - AIF1 Frame Ctrl 15 */
+       { 0x00000516, 0x0005 }, /* R1302 (0x516) - AIF1 Frame Ctrl 16 */
+       { 0x00000517, 0x0006 }, /* R1303 (0x517) - AIF1 Frame Ctrl 17 */
+       { 0x00000518, 0x0007 }, /* R1304 (0x518) - AIF1 Frame Ctrl 18 */
+       { 0x00000519, 0x0000 }, /* R1305 (0x519) - AIF1 Tx Enables */
+       { 0x0000051a, 0x0000 }, /* R1306 (0x51a) - AIF1 Rx Enables */
+       { 0x00000540, 0x000c }, /* R1344 (0x540) - AIF2 BCLK Ctrl */
+       { 0x00000541, 0x0000 }, /* R1345 (0x541) - AIF2 Tx Pin Ctrl */
+       { 0x00000542, 0x0000 }, /* R1346 (0x542) - AIF2 Rx Pin Ctrl */
+       { 0x00000543, 0x0000 }, /* R1347 (0x543) - AIF2 Rate Ctrl */
+       { 0x00000544, 0x0000 }, /* R1348 (0x544) - AIF2 Format */
+       { 0x00000546, 0x0040 }, /* R1350 (0x546) - AIF2 Rx BCLK Rate */
+       { 0x00000547, 0x1818 }, /* R1351 (0x547) - AIF2 Frame Ctrl 1 */
+       { 0x00000548, 0x1818 }, /* R1352 (0x548) - AIF2 Frame Ctrl 2 */
+       { 0x00000549, 0x0000 }, /* R1353 (0x549) - AIF2 Frame Ctrl 3 */
+       { 0x0000054a, 0x0001 }, /* R1354 (0x54a) - AIF2 Frame Ctrl 4 */
+       { 0x0000054b, 0x0002 }, /* R1355 (0x54b) - AIF2 Frame Ctrl 5 */
+       { 0x0000054c, 0x0003 }, /* R1356 (0x54c) - AIF2 Frame Ctrl 6 */
+       { 0x0000054d, 0x0004 }, /* R1357 (0x54d) - AIF2 Frame Ctrl 7 */
+       { 0x0000054e, 0x0005 }, /* R1358 (0x54e) - AIF2 Frame Ctrl 8 */
+       { 0x0000054f, 0x0006 }, /* R1359 (0x54f) - AIF2 Frame Ctrl 9 */
+       { 0x00000550, 0x0007 }, /* R1360 (0x550) - AIF2 Frame Ctrl 10 */
+       { 0x00000551, 0x0000 }, /* R1361 (0x551) - AIF2 Frame Ctrl 11 */
+       { 0x00000552, 0x0001 }, /* R1362 (0x552) - AIF2 Frame Ctrl 12 */
+       { 0x00000553, 0x0002 }, /* R1363 (0x553) - AIF2 Frame Ctrl 13 */
+       { 0x00000554, 0x0003 }, /* R1364 (0x554) - AIF2 Frame Ctrl 14 */
+       { 0x00000555, 0x0004 }, /* R1365 (0x555) - AIF2 Frame Ctrl 15 */
+       { 0x00000556, 0x0005 }, /* R1366 (0x556) - AIF2 Frame Ctrl 16 */
+       { 0x00000557, 0x0006 }, /* R1367 (0x557) - AIF2 Frame Ctrl 17 */
+       { 0x00000558, 0x0007 }, /* R1368 (0x558) - AIF2 Frame Ctrl 18 */
+       { 0x00000559, 0x0000 }, /* R1369 (0x559) - AIF2 Tx Enables */
+       { 0x0000055a, 0x0000 }, /* R1370 (0x55a) - AIF2 Rx Enables */
+       { 0x00000580, 0x000c }, /* R1408 (0x580) - AIF3 BCLK Ctrl */
+       { 0x00000581, 0x0000 }, /* R1409 (0x581) - AIF3 Tx Pin Ctrl */
+       { 0x00000582, 0x0000 }, /* R1410 (0x582) - AIF3 Rx Pin Ctrl */
+       { 0x00000583, 0x0000 }, /* R1411 (0x583) - AIF3 Rate Ctrl */
+       { 0x00000584, 0x0000 }, /* R1412 (0x584) - AIF3 Format */
+       { 0x00000586, 0x0040 }, /* R1414 (0x586) - AIF3 Rx BCLK Rate */
+       { 0x00000587, 0x1818 }, /* R1415 (0x587) - AIF3 Frame Ctrl 1 */
+       { 0x00000588, 0x1818 }, /* R1416 (0x588) - AIF3 Frame Ctrl 2 */
+       { 0x00000589, 0x0000 }, /* R1417 (0x589) - AIF3 Frame Ctrl 3 */
+       { 0x0000058a, 0x0001 }, /* R1418 (0x58a) - AIF3 Frame Ctrl 4 */
+       { 0x00000591, 0x0000 }, /* R1425 (0x591) - AIF3 Frame Ctrl 11 */
+       { 0x00000592, 0x0001 }, /* R1426 (0x592) - AIF3 Frame Ctrl 12 */
+       { 0x00000599, 0x0000 }, /* R1433 (0x599) - AIF3 Tx Enables */
+       { 0x0000059a, 0x0000 }, /* R1434 (0x59a) - AIF3 Rx Enables */
+       { 0x000005a0, 0x000c }, /* R1440 (0x5a0) - AIF4 BCLK Ctrl */
+       { 0x000005a1, 0x0000 }, /* R1441 (0x5a1) - AIF4 Tx Pin Ctrl */
+       { 0x000005a2, 0x0000 }, /* R1442 (0x5a2) - AIF4 Rx Pin Ctrl */
+       { 0x000005a3, 0x0000 }, /* R1443 (0x5a3) - AIF4 Rate Ctrl */
+       { 0x000005a4, 0x0000 }, /* R1444 (0x5a4) - AIF4 Format */
+       { 0x000005a6, 0x0040 }, /* R1446 (0x5a6) - AIF4 Rx BCLK Rate */
+       { 0x000005a7, 0x1818 }, /* R1447 (0x5a7) - AIF4 Frame Ctrl 1 */
+       { 0x000005a8, 0x1818 }, /* R1448 (0x5a8) - AIF4 Frame Ctrl 2 */
+       { 0x000005a9, 0x0000 }, /* R1449 (0x5a9) - AIF4 Frame Ctrl 3 */
+       { 0x000005aa, 0x0001 }, /* R1450 (0x5aa) - AIF4 Frame Ctrl 4 */
+       { 0x000005b1, 0x0000 }, /* R1457 (0x5b1) - AIF4 Frame Ctrl 11 */
+       { 0x000005b2, 0x0001 }, /* R1458 (0x5b2) - AIF4 Frame Ctrl 12 */
+       { 0x000005b9, 0x0000 }, /* R1465 (0x5b9) - AIF4 Tx Enables */
+       { 0x000005ba, 0x0000 }, /* R1466 (0x5ba) - AIF4 Rx Enables */
+       { 0x000005c2, 0x0000 }, /* R1474 (0x5c2) - SPD1 TX Control */
+       { 0x000005e3, 0x0000 }, /* R1507 (0x5e3) - SLIMbus Framer Ref Gear */
+       { 0x000005e5, 0x0000 }, /* R1509 (0x5e5) - SLIMbus Rates 1 */
+       { 0x000005e6, 0x0000 }, /* R1510 (0x5e6) - SLIMbus Rates 2 */
+       { 0x000005e7, 0x0000 }, /* R1511 (0x5e7) - SLIMbus Rates 3 */
+       { 0x000005e8, 0x0000 }, /* R1512 (0x5e8) - SLIMbus Rates 4 */
+       { 0x000005e9, 0x0000 }, /* R1513 (0x5e9) - SLIMbus Rates 5 */
+       { 0x000005ea, 0x0000 }, /* R1514 (0x5ea) - SLIMbus Rates 6 */
+       { 0x000005eb, 0x0000 }, /* R1515 (0x5eb) - SLIMbus Rates 7 */
+       { 0x000005ec, 0x0000 }, /* R1516 (0x5ec) - SLIMbus Rates 8 */
+       { 0x000005f5, 0x0000 }, /* R1525 (0x5f5) - SLIMbus RX Channel Enable */
+       { 0x000005f6, 0x0000 }, /* R1526 (0x5F6) - SLIMbus TX Channel Enable */
+       { 0x00000640, 0x0000 }, /* R1600 (0x640) - PWM1MIX Input 1 Source */
+       { 0x00000641, 0x0080 }, /* R1601 (0x641) - PWM1MIX Input 1 Volume */
+       { 0x00000642, 0x0000 }, /* R1602 (0x642) - PWM1MIX Input 2 Source */
+       { 0x00000643, 0x0080 }, /* R1603 (0x643) - PWM1MIX Input 2 Volume */
+       { 0x00000644, 0x0000 }, /* R1604 (0x644) - PWM1MIX Input 3 Source */
+       { 0x00000645, 0x0080 }, /* R1605 (0x645) - PWM1MIX Input 3 Volume */
+       { 0x00000646, 0x0000 }, /* R1606 (0x646) - PWM1MIX Input 4 Source */
+       { 0x00000647, 0x0080 }, /* R1607 (0x647) - PWM1MIX Input 4 Volume */
+       { 0x00000648, 0x0000 }, /* R1608 (0x648) - PWM2MIX Input 1 Source */
+       { 0x00000649, 0x0080 }, /* R1609 (0x649) - PWM2MIX Input 1 Volume */
+       { 0x0000064a, 0x0000 }, /* R1610 (0x64a) - PWM2MIX Input 2 Source */
+       { 0x0000064b, 0x0080 }, /* R1611 (0x64b) - PWM2MIX Input 2 Volume */
+       { 0x0000064c, 0x0000 }, /* R1612 (0x64c) - PWM2MIX Input 3 Source */
+       { 0x0000064d, 0x0080 }, /* R1613 (0x64d) - PWM2MIX Input 3 Volume */
+       { 0x0000064e, 0x0000 }, /* R1614 (0x64e) - PWM2MIX Input 4 Source */
+       { 0x0000064f, 0x0080 }, /* R1615 (0x64f) - PWM2MIX Input 4 Volume */
+       { 0x00000680, 0x0000 }, /* R1664 (0x680) - OUT1LMIX Input 1 Source */
+       { 0x00000681, 0x0080 }, /* R1665 (0x681) - OUT1LMIX Input 1 Volume */
+       { 0x00000682, 0x0000 }, /* R1666 (0x682) - OUT1LMIX Input 2 Source */
+       { 0x00000683, 0x0080 }, /* R1667 (0x683) - OUT1LMIX Input 2 Volume */
+       { 0x00000684, 0x0000 }, /* R1668 (0x684) - OUT1LMIX Input 3 Source */
+       { 0x00000685, 0x0080 }, /* R1669 (0x685) - OUT1LMIX Input 3 Volume */
+       { 0x00000686, 0x0000 }, /* R1670 (0x686) - OUT1LMIX Input 4 Source */
+       { 0x00000687, 0x0080 }, /* R1671 (0x687) - OUT1LMIX Input 4 Volume */
+       { 0x00000688, 0x0000 }, /* R1672 (0x688) - OUT1RMIX Input 1 Source */
+       { 0x00000689, 0x0080 }, /* R1673 (0x689) - OUT1RMIX Input 1 Volume */
+       { 0x0000068a, 0x0000 }, /* R1674 (0x68a) - OUT1RMIX Input 2 Source */
+       { 0x0000068b, 0x0080 }, /* R1675 (0x68b) - OUT1RMIX Input 2 Volume */
+       { 0x0000068c, 0x0000 }, /* R1672 (0x68c) - OUT1RMIX Input 3 Source */
+       { 0x0000068d, 0x0080 }, /* R1673 (0x68d) - OUT1RMIX Input 3 Volume */
+       { 0x0000068e, 0x0000 }, /* R1674 (0x68e) - OUT1RMIX Input 4 Source */
+       { 0x0000068f, 0x0080 }, /* R1675 (0x68f) - OUT1RMIX Input 4 Volume */
+       { 0x00000690, 0x0000 }, /* R1680 (0x690) - OUT2LMIX Input 1 Source */
+       { 0x00000691, 0x0080 }, /* R1681 (0x691) - OUT2LMIX Input 1 Volume */
+       { 0x00000692, 0x0000 }, /* R1682 (0x692) - OUT2LMIX Input 2 Source */
+       { 0x00000693, 0x0080 }, /* R1683 (0x693) - OUT2LMIX Input 2 Volume */
+       { 0x00000694, 0x0000 }, /* R1684 (0x694) - OUT2LMIX Input 3 Source */
+       { 0x00000695, 0x0080 }, /* R1685 (0x695) - OUT2LMIX Input 3 Volume */
+       { 0x00000696, 0x0000 }, /* R1686 (0x696) - OUT2LMIX Input 4 Source */
+       { 0x00000697, 0x0080 }, /* R1687 (0x697) - OUT2LMIX Input 4 Volume */
+       { 0x00000698, 0x0000 }, /* R1688 (0x698) - OUT2RMIX Input 1 Source */
+       { 0x00000699, 0x0080 }, /* R1689 (0x699) - OUT2RMIX Input 1 Volume */
+       { 0x0000069a, 0x0000 }, /* R1690 (0x69a) - OUT2RMIX Input 2 Source */
+       { 0x0000069b, 0x0080 }, /* R1691 (0x69b) - OUT2RMIX Input 2 Volume */
+       { 0x0000069c, 0x0000 }, /* R1692 (0x69c) - OUT2RMIX Input 3 Source */
+       { 0x0000069d, 0x0080 }, /* R1693 (0x69d) - OUT2RMIX Input 3 Volume */
+       { 0x0000069e, 0x0000 }, /* R1694 (0x69e) - OUT2RMIX Input 4 Source */
+       { 0x0000069f, 0x0080 }, /* R1695 (0x69f) - OUT2RMIX Input 4 Volume */
+       { 0x000006a0, 0x0000 }, /* R1696 (0x6a0) - OUT3LMIX Input 1 Source */
+       { 0x000006a1, 0x0080 }, /* R1697 (0x6a1) - OUT3LMIX Input 1 Volume */
+       { 0x000006a2, 0x0000 }, /* R1698 (0x6a2) - OUT3LMIX Input 2 Source */
+       { 0x000006a3, 0x0080 }, /* R1699 (0x6a3) - OUT3LMIX Input 2 Volume */
+       { 0x000006a4, 0x0000 }, /* R1700 (0x6a4) - OUT3LMIX Input 3 Source */
+       { 0x000006a5, 0x0080 }, /* R1701 (0x6a5) - OUT3LMIX Input 3 Volume */
+       { 0x000006a6, 0x0000 }, /* R1702 (0x6a6) - OUT3LMIX Input 4 Source */
+       { 0x000006a7, 0x0080 }, /* R1703 (0x6a7) - OUT3LMIX Input 4 Volume */
+       { 0x000006a8, 0x0000 }, /* R1704 (0x6a8) - OUT3RMIX Input 1 Source */
+       { 0x000006a9, 0x0080 }, /* R1705 (0x6a9) - OUT3RMIX Input 1 Volume */
+       { 0x000006aa, 0x0000 }, /* R1706 (0x6aa) - OUT3RMIX Input 2 Source */
+       { 0x000006ab, 0x0080 }, /* R1707 (0x6ab) - OUT3RMIX Input 2 Volume */
+       { 0x000006ac, 0x0000 }, /* R1708 (0x6ac) - OUT3RMIX Input 3 Source */
+       { 0x000006ad, 0x0080 }, /* R1709 (0x6ad) - OUT3RMIX Input 3 Volume */
+       { 0x000006ae, 0x0000 }, /* R1710 (0x6ae) - OUT3RMIX Input 4 Source */
+       { 0x000006af, 0x0080 }, /* R1711 (0x6af) - OUT3RMIX Input 4 Volume */
+       { 0x000006c0, 0x0000 }, /* R1728 (0x6c0) - OUT5LMIX Input 1 Source */
+       { 0x000006c1, 0x0080 }, /* R1729 (0x6c1) - OUT5LMIX Input 1 Volume */
+       { 0x000006c2, 0x0000 }, /* R1730 (0x6c2) - OUT5LMIX Input 2 Source */
+       { 0x000006c3, 0x0080 }, /* R1731 (0x6c3) - OUT5LMIX Input 2 Volume */
+       { 0x000006c4, 0x0000 }, /* R1732 (0x6c4) - OUT5LMIX Input 3 Source */
+       { 0x000006c5, 0x0080 }, /* R1733 (0x6c5) - OUT5LMIX Input 3 Volume */
+       { 0x000006c6, 0x0000 }, /* R1734 (0x6c6) - OUT5LMIX Input 4 Source */
+       { 0x000006c7, 0x0080 }, /* R1735 (0x6c7) - OUT5LMIX Input 4 Volume */
+       { 0x000006c8, 0x0000 }, /* R1736 (0x6c8) - OUT5RMIX Input 1 Source */
+       { 0x000006c9, 0x0080 }, /* R1737 (0x6c9) - OUT5RMIX Input 1 Volume */
+       { 0x000006ca, 0x0000 }, /* R1738 (0x6ca) - OUT5RMIX Input 2 Source */
+       { 0x000006cb, 0x0080 }, /* R1739 (0x6cb) - OUT5RMIX Input 2 Volume */
+       { 0x000006cc, 0x0000 }, /* R1740 (0x6cc) - OUT5RMIX Input 3 Source */
+       { 0x000006cd, 0x0080 }, /* R1741 (0x6cd) - OUT5RMIX Input 3 Volume */
+       { 0x000006ce, 0x0000 }, /* R1742 (0x6ce) - OUT5RMIX Input 4 Source */
+       { 0x000006cf, 0x0080 }, /* R1743 (0x6cf) - OUT5RMIX Input 4 Volume */
+       { 0x00000700, 0x0000 }, /* R1792 (0x700) - AIF1TX1MIX Input 1 Source */
+       { 0x00000701, 0x0080 }, /* R1793 (0x701) - AIF1TX1MIX Input 1 Volume */
+       { 0x00000702, 0x0000 }, /* R1794 (0x702) - AIF1TX1MIX Input 2 Source */
+       { 0x00000703, 0x0080 }, /* R1795 (0x703) - AIF1TX1MIX Input 2 Volume */
+       { 0x00000704, 0x0000 }, /* R1796 (0x704) - AIF1TX1MIX Input 3 Source */
+       { 0x00000705, 0x0080 }, /* R1797 (0x705) - AIF1TX1MIX Input 3 Volume */
+       { 0x00000706, 0x0000 }, /* R1798 (0x706) - AIF1TX1MIX Input 4 Source */
+       { 0x00000707, 0x0080 }, /* R1799 (0x707) - AIF1TX1MIX Input 4 Volume */
+       { 0x00000708, 0x0000 }, /* R1800 (0x708) - AIF1TX2MIX Input 1 Source */
+       { 0x00000709, 0x0080 }, /* R1801 (0x709) - AIF1TX2MIX Input 1 Volume */
+       { 0x0000070a, 0x0000 }, /* R1802 (0x70a) - AIF1TX2MIX Input 2 Source */
+       { 0x0000070b, 0x0080 }, /* R1803 (0x70b) - AIF1TX2MIX Input 2 Volume */
+       { 0x0000070c, 0x0000 }, /* R1804 (0x70c) - AIF1TX2MIX Input 3 Source */
+       { 0x0000070d, 0x0080 }, /* R1805 (0x70d) - AIF1TX2MIX Input 3 Volume */
+       { 0x0000070e, 0x0000 }, /* R1806 (0x70e) - AIF1TX2MIX Input 4 Source */
+       { 0x0000070f, 0x0080 }, /* R1807 (0x70f) - AIF1TX2MIX Input 4 Volume */
+       { 0x00000710, 0x0000 }, /* R1808 (0x710) - AIF1TX3MIX Input 1 Source */
+       { 0x00000711, 0x0080 }, /* R1809 (0x711) - AIF1TX3MIX Input 1 Volume */
+       { 0x00000712, 0x0000 }, /* R1810 (0x712) - AIF1TX3MIX Input 2 Source */
+       { 0x00000713, 0x0080 }, /* R1811 (0x713) - AIF1TX3MIX Input 2 Volume */
+       { 0x00000714, 0x0000 }, /* R1812 (0x714) - AIF1TX3MIX Input 3 Source */
+       { 0x00000715, 0x0080 }, /* R1813 (0x715) - AIF1TX3MIX Input 3 Volume */
+       { 0x00000716, 0x0000 }, /* R1814 (0x716) - AIF1TX3MIX Input 4 Source */
+       { 0x00000717, 0x0080 }, /* R1815 (0x717) - AIF1TX3MIX Input 4 Volume */
+       { 0x00000718, 0x0000 }, /* R1816 (0x718) - AIF1TX4MIX Input 1 Source */
+       { 0x00000719, 0x0080 }, /* R1817 (0x719) - AIF1TX4MIX Input 1 Volume */
+       { 0x0000071a, 0x0000 }, /* R1818 (0x71a) - AIF1TX4MIX Input 2 Source */
+       { 0x0000071b, 0x0080 }, /* R1819 (0x71b) - AIF1TX4MIX Input 2 Volume */
+       { 0x0000071c, 0x0000 }, /* R1820 (0x71c) - AIF1TX4MIX Input 3 Source */
+       { 0x0000071d, 0x0080 }, /* R1821 (0x71d) - AIF1TX4MIX Input 3 Volume */
+       { 0x0000071e, 0x0000 }, /* R1822 (0x71e) - AIF1TX4MIX Input 4 Source */
+       { 0x0000071f, 0x0080 }, /* R1823 (0x71f) - AIF1TX4MIX Input 4 Volume */
+       { 0x00000720, 0x0000 }, /* R1824 (0x720) - AIF1TX5MIX Input 1 Source */
+       { 0x00000721, 0x0080 }, /* R1825 (0x721) - AIF1TX5MIX Input 1 Volume */
+       { 0x00000722, 0x0000 }, /* R1826 (0x722) - AIF1TX5MIX Input 2 Source */
+       { 0x00000723, 0x0080 }, /* R1827 (0x723) - AIF1TX5MIX Input 2 Volume */
+       { 0x00000724, 0x0000 }, /* R1828 (0x724) - AIF1TX5MIX Input 3 Source */
+       { 0x00000725, 0x0080 }, /* R1829 (0x725) - AIF1TX5MIX Input 3 Volume */
+       { 0x00000726, 0x0000 }, /* R1830 (0x726) - AIF1TX5MIX Input 4 Source */
+       { 0x00000727, 0x0080 }, /* R1831 (0x727) - AIF1TX5MIX Input 4 Volume */
+       { 0x00000728, 0x0000 }, /* R1832 (0x728) - AIF1TX6MIX Input 1 Source */
+       { 0x00000729, 0x0080 }, /* R1833 (0x729) - AIF1TX6MIX Input 1 Volume */
+       { 0x0000072a, 0x0000 }, /* R1834 (0x72a) - AIF1TX6MIX Input 2 Source */
+       { 0x0000072b, 0x0080 }, /* R1835 (0x72b) - AIF1TX6MIX Input 2 Volume */
+       { 0x0000072c, 0x0000 }, /* R1836 (0x72c) - AIF1TX6MIX Input 3 Source */
+       { 0x0000072d, 0x0080 }, /* R1837 (0x72d) - AIF1TX6MIX Input 3 Volume */
+       { 0x0000072e, 0x0000 }, /* R1838 (0x72e) - AIF1TX6MIX Input 4 Source */
+       { 0x0000072f, 0x0080 }, /* R1839 (0x72f) - AIF1TX6MIX Input 4 Volume */
+       { 0x00000730, 0x0000 }, /* R1840 (0x730) - AIF1TX7MIX Input 1 Source */
+       { 0x00000731, 0x0080 }, /* R1841 (0x731) - AIF1TX7MIX Input 1 Volume */
+       { 0x00000732, 0x0000 }, /* R1842 (0x732) - AIF1TX7MIX Input 2 Source */
+       { 0x00000733, 0x0080 }, /* R1843 (0x733) - AIF1TX7MIX Input 2 Volume */
+       { 0x00000734, 0x0000 }, /* R1844 (0x734) - AIF1TX7MIX Input 3 Source */
+       { 0x00000735, 0x0080 }, /* R1845 (0x735) - AIF1TX7MIX Input 3 Volume */
+       { 0x00000736, 0x0000 }, /* R1846 (0x736) - AIF1TX7MIX Input 4 Source */
+       { 0x00000737, 0x0080 }, /* R1847 (0x737) - AIF1TX7MIX Input 4 Volume */
+       { 0x00000738, 0x0000 }, /* R1848 (0x738) - AIF1TX8MIX Input 1 Source */
+       { 0x00000739, 0x0080 }, /* R1849 (0x739) - AIF1TX8MIX Input 1 Volume */
+       { 0x0000073a, 0x0000 }, /* R1850 (0x73a) - AIF1TX8MIX Input 2 Source */
+       { 0x0000073b, 0x0080 }, /* R1851 (0x73b) - AIF1TX8MIX Input 2 Volume */
+       { 0x0000073c, 0x0000 }, /* R1852 (0x73c) - AIF1TX8MIX Input 3 Source */
+       { 0x0000073d, 0x0080 }, /* R1853 (0x73d) - AIF1TX8MIX Input 3 Volume */
+       { 0x0000073e, 0x0000 }, /* R1854 (0x73e) - AIF1TX8MIX Input 4 Source */
+       { 0x0000073f, 0x0080 }, /* R1855 (0x73f) - AIF1TX8MIX Input 4 Volume */
+       { 0x00000740, 0x0000 }, /* R1856 (0x740) - AIF2TX1MIX Input 1 Source */
+       { 0x00000741, 0x0080 }, /* R1857 (0x741) - AIF2TX1MIX Input 1 Volume */
+       { 0x00000742, 0x0000 }, /* R1858 (0x742) - AIF2TX1MIX Input 2 Source */
+       { 0x00000743, 0x0080 }, /* R1859 (0x743) - AIF2TX1MIX Input 2 Volume */
+       { 0x00000744, 0x0000 }, /* R1860 (0x744) - AIF2TX1MIX Input 3 Source */
+       { 0x00000745, 0x0080 }, /* R1861 (0x745) - AIF2TX1MIX Input 3 Volume */
+       { 0x00000746, 0x0000 }, /* R1862 (0x746) - AIF2TX1MIX Input 4 Source */
+       { 0x00000747, 0x0080 }, /* R1863 (0x747) - AIF2TX1MIX Input 4 Volume */
+       { 0x00000748, 0x0000 }, /* R1864 (0x748) - AIF2TX2MIX Input 1 Source */
+       { 0x00000749, 0x0080 }, /* R1865 (0x749) - AIF2TX2MIX Input 1 Volume */
+       { 0x0000074a, 0x0000 }, /* R1866 (0x74a) - AIF2TX2MIX Input 2 Source */
+       { 0x0000074b, 0x0080 }, /* R1867 (0x74b) - AIF2TX2MIX Input 2 Volume */
+       { 0x0000074c, 0x0000 }, /* R1868 (0x74c) - AIF2TX2MIX Input 3 Source */
+       { 0x0000074d, 0x0080 }, /* R1869 (0x74d) - AIF2TX2MIX Input 3 Volume */
+       { 0x0000074e, 0x0000 }, /* R1870 (0x74e) - AIF2TX2MIX Input 4 Source */
+       { 0x0000074f, 0x0080 }, /* R1871 (0x74f) - AIF2TX2MIX Input 4 Volume */
+       { 0x00000750, 0x0000 }, /* R1872 (0x750) - AIF2TX3MIX Input 1 Source */
+       { 0x00000751, 0x0080 }, /* R1873 (0x751) - AIF2TX3MIX Input 1 Volume */
+       { 0x00000752, 0x0000 }, /* R1874 (0x752) - AIF2TX3MIX Input 2 Source */
+       { 0x00000753, 0x0080 }, /* R1875 (0x753) - AIF2TX3MIX Input 2 Volume */
+       { 0x00000754, 0x0000 }, /* R1876 (0x754) - AIF2TX3MIX Input 3 Source */
+       { 0x00000755, 0x0080 }, /* R1877 (0x755) - AIF2TX3MIX Input 3 Volume */
+       { 0x00000756, 0x0000 }, /* R1878 (0x756) - AIF2TX3MIX Input 4 Source */
+       { 0x00000757, 0x0080 }, /* R1879 (0x757) - AIF2TX3MIX Input 4 Volume */
+       { 0x00000758, 0x0000 }, /* R1880 (0x758) - AIF2TX4MIX Input 1 Source */
+       { 0x00000759, 0x0080 }, /* R1881 (0x759) - AIF2TX4MIX Input 1 Volume */
+       { 0x0000075a, 0x0000 }, /* R1882 (0x75a) - AIF2TX4MIX Input 2 Source */
+       { 0x0000075b, 0x0080 }, /* R1883 (0x75b) - AIF2TX4MIX Input 2 Volume */
+       { 0x0000075c, 0x0000 }, /* R1884 (0x75c) - AIF2TX4MIX Input 3 Source */
+       { 0x0000075d, 0x0080 }, /* R1885 (0x75d) - AIF2TX4MIX Input 3 Volume */
+       { 0x0000075e, 0x0000 }, /* R1886 (0x75e) - AIF2TX4MIX Input 4 Source */
+       { 0x0000075f, 0x0080 }, /* R1887 (0x75f) - AIF2TX4MIX Input 4 Volume */
+       { 0x00000760, 0x0000 }, /* R1888 (0x760) - AIF2TX5MIX Input 1 Source */
+       { 0x00000761, 0x0080 }, /* R1889 (0x761) - AIF2TX5MIX Input 1 Volume */
+       { 0x00000762, 0x0000 }, /* R1890 (0x762) - AIF2TX5MIX Input 2 Source */
+       { 0x00000763, 0x0080 }, /* R1891 (0x763) - AIF2TX5MIX Input 2 Volume */
+       { 0x00000764, 0x0000 }, /* R1892 (0x764) - AIF2TX5MIX Input 3 Source */
+       { 0x00000765, 0x0080 }, /* R1893 (0x765) - AIF2TX5MIX Input 3 Volume */
+       { 0x00000766, 0x0000 }, /* R1894 (0x766) - AIF2TX5MIX Input 4 Source */
+       { 0x00000767, 0x0080 }, /* R1895 (0x767) - AIF2TX5MIX Input 4 Volume */
+       { 0x00000768, 0x0000 }, /* R1896 (0x768) - AIF2TX6MIX Input 1 Source */
+       { 0x00000769, 0x0080 }, /* R1897 (0x769) - AIF2TX6MIX Input 1 Volume */
+       { 0x0000076a, 0x0000 }, /* R1898 (0x76a) - AIF2TX6MIX Input 2 Source */
+       { 0x0000076b, 0x0080 }, /* R1899 (0x76b) - AIF2TX6MIX Input 2 Volume */
+       { 0x0000076c, 0x0000 }, /* R1900 (0x76c) - AIF2TX6MIX Input 3 Source */
+       { 0x0000076d, 0x0080 }, /* R1901 (0x76d) - AIF2TX6MIX Input 3 Volume */
+       { 0x0000076e, 0x0000 }, /* R1902 (0x76e) - AIF2TX6MIX Input 4 Source */
+       { 0x0000076f, 0x0080 }, /* R1903 (0x76f) - AIF2TX6MIX Input 4 Volume */
+       { 0x00000770, 0x0000 }, /* R1904 (0x770) - AIF2TX7MIX Input 1 Source */
+       { 0x00000771, 0x0080 }, /* R1905 (0x771) - AIF2TX7MIX Input 1 Volume */
+       { 0x00000772, 0x0000 }, /* R1906 (0x772) - AIF2TX7MIX Input 2 Source */
+       { 0x00000773, 0x0080 }, /* R1907 (0x773) - AIF2TX7MIX Input 2 Volume */
+       { 0x00000774, 0x0000 }, /* R1908 (0x774) - AIF2TX7MIX Input 3 Source */
+       { 0x00000775, 0x0080 }, /* R1909 (0x775) - AIF2TX7MIX Input 3 Volume */
+       { 0x00000776, 0x0000 }, /* R1910 (0x776) - AIF2TX7MIX Input 4 Source */
+       { 0x00000777, 0x0080 }, /* R1911 (0x777) - AIF2TX7MIX Input 4 Volume */
+       { 0x00000778, 0x0000 }, /* R1912 (0x778) - AIF2TX8MIX Input 1 Source */
+       { 0x00000779, 0x0080 }, /* R1913 (0x779) - AIF2TX8MIX Input 1 Volume */
+       { 0x0000077a, 0x0000 }, /* R1914 (0x77a) - AIF2TX8MIX Input 2 Source */
+       { 0x0000077b, 0x0080 }, /* R1915 (0x77b) - AIF2TX8MIX Input 2 Volume */
+       { 0x0000077c, 0x0000 }, /* R1916 (0x77c) - AIF2TX8MIX Input 3 Source */
+       { 0x0000077d, 0x0080 }, /* R1917 (0x77d) - AIF2TX8MIX Input 3 Volume */
+       { 0x0000077e, 0x0000 }, /* R1918 (0x77e) - AIF2TX8MIX Input 4 Source */
+       { 0x0000077f, 0x0080 }, /* R1919 (0x77f) - AIF2TX8MIX Input 4 Volume */
+       { 0x00000780, 0x0000 }, /* R1920 (0x780) - AIF3TX1MIX Input 1 Source */
+       { 0x00000781, 0x0080 }, /* R1921 (0x781) - AIF3TX1MIX Input 1 Volume */
+       { 0x00000782, 0x0000 }, /* R1922 (0x782) - AIF3TX1MIX Input 2 Source */
+       { 0x00000783, 0x0080 }, /* R1923 (0x783) - AIF3TX1MIX Input 2 Volume */
+       { 0x00000784, 0x0000 }, /* R1924 (0x784) - AIF3TX1MIX Input 3 Source */
+       { 0x00000785, 0x0080 }, /* R1925 (0x785) - AIF3TX1MIX Input 3 Volume */
+       { 0x00000786, 0x0000 }, /* R1926 (0x786) - AIF3TX1MIX Input 4 Source */
+       { 0x00000787, 0x0080 }, /* R1927 (0x787) - AIF3TX1MIX Input 4 Volume */
+       { 0x00000788, 0x0000 }, /* R1928 (0x788) - AIF3TX2MIX Input 1 Source */
+       { 0x00000789, 0x0080 }, /* R1929 (0x789) - AIF3TX2MIX Input 1 Volume */
+       { 0x0000078a, 0x0000 }, /* R1930 (0x78a) - AIF3TX2MIX Input 2 Source */
+       { 0x0000078b, 0x0080 }, /* R1931 (0x78b) - AIF3TX2MIX Input 2 Volume */
+       { 0x0000078c, 0x0000 }, /* R1932 (0x78c) - AIF3TX2MIX Input 3 Source */
+       { 0x0000078d, 0x0080 }, /* R1933 (0x78d) - AIF3TX2MIX Input 3 Volume */
+       { 0x0000078e, 0x0000 }, /* R1934 (0x78e) - AIF3TX2MIX Input 4 Source */
+       { 0x0000078f, 0x0080 }, /* R1935 (0x78f) - AIF3TX2MIX Input 4 Volume */
+       { 0x000007a0, 0x0000 }, /* R1952 (0x7a0) - AIF4TX1MIX Input 1 Source */
+       { 0x000007a1, 0x0080 }, /* R1953 (0x7a1) - AIF4TX1MIX Input 1 Volume */
+       { 0x000007a2, 0x0000 }, /* R1954 (0x7a2) - AIF4TX1MIX Input 2 Source */
+       { 0x000007a3, 0x0080 }, /* R1955 (0x7a3) - AIF4TX1MIX Input 2 Volume */
+       { 0x000007a4, 0x0000 }, /* R1956 (0x7a4) - AIF4TX1MIX Input 3 Source */
+       { 0x000007a5, 0x0080 }, /* R1957 (0x7a5) - AIF4TX1MIX Input 3 Volume */
+       { 0x000007a6, 0x0000 }, /* R1958 (0x7a6) - AIF4TX1MIX Input 4 Source */
+       { 0x000007a7, 0x0080 }, /* R1959 (0x7a7) - AIF4TX1MIX Input 4 Volume */
+       { 0x000007a8, 0x0000 }, /* R1960 (0x7a8) - AIF4TX2MIX Input 1 Source */
+       { 0x000007a9, 0x0080 }, /* R1961 (0x7a9) - AIF4TX2MIX Input 1 Volume */
+       { 0x000007aa, 0x0000 }, /* R1962 (0x7aa) - AIF4TX2MIX Input 2 Source */
+       { 0x000007ab, 0x0080 }, /* R1963 (0x7ab) - AIF4TX2MIX Input 2 Volume */
+       { 0x000007ac, 0x0000 }, /* R1964 (0x7ac) - AIF4TX2MIX Input 3 Source */
+       { 0x000007ad, 0x0080 }, /* R1965 (0x7ad) - AIF4TX2MIX Input 3 Volume */
+       { 0x000007ae, 0x0000 }, /* R1966 (0x7ae) - AIF4TX2MIX Input 4 Source */
+       { 0x000007af, 0x0080 }, /* R1967 (0x7af) - AIF4TX2MIX Input 4 Volume */
+       { 0x000007c0, 0x0000 }, /* R1984 (0x7c0) - SLIMTX1MIX Input 1 Source */
+       { 0x000007c1, 0x0080 }, /* R1985 (0x7c1) - SLIMTX1MIX Input 1 Volume */
+       { 0x000007c2, 0x0000 }, /* R1986 (0x7c2) - SLIMTX1MIX Input 2 Source */
+       { 0x000007c3, 0x0080 }, /* R1987 (0x7c3) - SLIMTX1MIX Input 2 Volume */
+       { 0x000007c4, 0x0000 }, /* R1988 (0x7c4) - SLIMTX1MIX Input 3 Source */
+       { 0x000007c5, 0x0080 }, /* R1989 (0x7c5) - SLIMTX1MIX Input 3 Volume */
+       { 0x000007c6, 0x0000 }, /* R1990 (0x7c6) - SLIMTX1MIX Input 4 Source */
+       { 0x000007c7, 0x0080 }, /* R1991 (0x7c7) - SLIMTX1MIX Input 4 Volume */
+       { 0x000007c8, 0x0000 }, /* R1992 (0x7c8) - SLIMTX2MIX Input 1 Source */
+       { 0x000007c9, 0x0080 }, /* R1993 (0x7c9) - SLIMTX2MIX Input 1 Volume */
+       { 0x000007ca, 0x0000 }, /* R1994 (0x7ca) - SLIMTX2MIX Input 2 Source */
+       { 0x000007cb, 0x0080 }, /* R1995 (0x7cb) - SLIMTX2MIX Input 2 Volume */
+       { 0x000007cc, 0x0000 }, /* R1996 (0x7cc) - SLIMTX2MIX Input 3 Source */
+       { 0x000007cd, 0x0080 }, /* R1997 (0x7cd) - SLIMTX2MIX Input 3 Volume */
+       { 0x000007ce, 0x0000 }, /* R1998 (0x7ce) - SLIMTX2MIX Input 4 Source */
+       { 0x000007cf, 0x0080 }, /* R1999 (0x7cf) - SLIMTX2MIX Input 4 Volume */
+       { 0x000007d0, 0x0000 }, /* R2000 (0x7d0) - SLIMTX3MIX Input 1 Source */
+       { 0x000007d1, 0x0080 }, /* R2001 (0x7d1) - SLIMTX3MIX Input 1 Volume */
+       { 0x000007d2, 0x0000 }, /* R2002 (0x7d2) - SLIMTX3MIX Input 2 Source */
+       { 0x000007d3, 0x0080 }, /* R2003 (0x7d3) - SLIMTX3MIX Input 2 Volume */
+       { 0x000007d4, 0x0000 }, /* R2004 (0x7d4) - SLIMTX3MIX Input 3 Source */
+       { 0x000007d5, 0x0080 }, /* R2005 (0x7d5) - SLIMTX3MIX Input 3 Volume */
+       { 0x000007d6, 0x0000 }, /* R2006 (0x7d6) - SLIMTX3MIX Input 4 Source */
+       { 0x000007d7, 0x0080 }, /* R2007 (0x7d7) - SLIMTX3MIX Input 4 Volume */
+       { 0x000007d8, 0x0000 }, /* R2008 (0x7d8) - SLIMTX4MIX Input 1 Source */
+       { 0x000007d9, 0x0080 }, /* R2009 (0x7d9) - SLIMTX4MIX Input 1 Volume */
+       { 0x000007da, 0x0000 }, /* R2010 (0x7da) - SLIMTX4MIX Input 2 Source */
+       { 0x000007db, 0x0080 }, /* R2011 (0x7db) - SLIMTX4MIX Input 2 Volume */
+       { 0x000007dc, 0x0000 }, /* R2012 (0x7dc) - SLIMTX4MIX Input 3 Source */
+       { 0x000007dd, 0x0080 }, /* R2013 (0x7dd) - SLIMTX4MIX Input 3 Volume */
+       { 0x000007de, 0x0000 }, /* R2014 (0x7de) - SLIMTX4MIX Input 4 Source */
+       { 0x000007df, 0x0080 }, /* R2015 (0x7df) - SLIMTX4MIX Input 4 Volume */
+       { 0x000007e0, 0x0000 }, /* R2016 (0x7e0) - SLIMTX5MIX Input 1 Source */
+       { 0x000007e1, 0x0080 }, /* R2017 (0x7e1) - SLIMTX5MIX Input 1 Volume */
+       { 0x000007e2, 0x0000 }, /* R2018 (0x7e2) - SLIMTX5MIX Input 2 Source */
+       { 0x000007e3, 0x0080 }, /* R2019 (0x7e3) - SLIMTX5MIX Input 2 Volume */
+       { 0x000007e4, 0x0000 }, /* R2020 (0x7e4) - SLIMTX5MIX Input 3 Source */
+       { 0x000007e5, 0x0080 }, /* R2021 (0x7e5) - SLIMTX5MIX Input 3 Volume */
+       { 0x000007e6, 0x0000 }, /* R2022 (0x7e6) - SLIMTX5MIX Input 4 Source */
+       { 0x000007e7, 0x0080 }, /* R2023 (0x7e7) - SLIMTX5MIX Input 4 Volume */
+       { 0x000007e8, 0x0000 }, /* R2024 (0x7e8) - SLIMTX6MIX Input 1 Source */
+       { 0x000007e9, 0x0080 }, /* R2025 (0x7e9) - SLIMTX6MIX Input 1 Volume */
+       { 0x000007ea, 0x0000 }, /* R2026 (0x7ea) - SLIMTX6MIX Input 2 Source */
+       { 0x000007eb, 0x0080 }, /* R2027 (0x7eb) - SLIMTX6MIX Input 2 Volume */
+       { 0x000007ec, 0x0000 }, /* R2028 (0x7ec) - SLIMTX6MIX Input 3 Source */
+       { 0x000007ed, 0x0080 }, /* R2029 (0x7ed) - SLIMTX6MIX Input 3 Volume */
+       { 0x000007ee, 0x0000 }, /* R2030 (0x7ee) - SLIMTX6MIX Input 4 Source */
+       { 0x000007ef, 0x0080 }, /* R2031 (0x7ef) - SLIMTX6MIX Input 4 Volume */
+       { 0x000007f0, 0x0000 }, /* R2032 (0x7f0) - SLIMTX7MIX Input 1 Source */
+       { 0x000007f1, 0x0080 }, /* R2033 (0x7f1) - SLIMTX7MIX Input 1 Volume */
+       { 0x000007f2, 0x0000 }, /* R2034 (0x7f2) - SLIMTX7MIX Input 2 Source */
+       { 0x000007f3, 0x0080 }, /* R2035 (0x7f3) - SLIMTX7MIX Input 2 Volume */
+       { 0x000007f4, 0x0000 }, /* R2036 (0x7f4) - SLIMTX7MIX Input 3 Source */
+       { 0x000007f5, 0x0080 }, /* R2037 (0x7f5) - SLIMTX7MIX Input 3 Volume */
+       { 0x000007f6, 0x0000 }, /* R2038 (0x7f6) - SLIMTX7MIX Input 4 Source */
+       { 0x000007f7, 0x0080 }, /* R2039 (0x7f7) - SLIMTX7MIX Input 4 Volume */
+       { 0x000007f8, 0x0000 }, /* R2040 (0x7f8) - SLIMTX8MIX Input 1 Source */
+       { 0x000007f9, 0x0080 }, /* R2041 (0x7f9) - SLIMTX8MIX Input 1 Volume */
+       { 0x000007fa, 0x0000 }, /* R2042 (0x7fa) - SLIMTX8MIX Input 2 Source */
+       { 0x000007fb, 0x0080 }, /* R2043 (0x7fb) - SLIMTX8MIX Input 2 Volume */
+       { 0x000007fc, 0x0000 }, /* R2044 (0x7fc) - SLIMTX8MIX Input 3 Source */
+       { 0x000007fd, 0x0080 }, /* R2045 (0x7fd) - SLIMTX8MIX Input 3 Volume */
+       { 0x000007fe, 0x0000 }, /* R2046 (0x7fe) - SLIMTX8MIX Input 4 Source */
+       { 0x000007ff, 0x0080 }, /* R2047 (0x7ff) - SLIMTX8MIX Input 4 Volume */
+       { 0x00000800, 0x0000 }, /* R2048 (0x800) - SPDIF1TX1MIX Input 1 Source */
+       { 0x00000801, 0x0080 }, /* R2049 (0x801) - SPDIF1TX1MIX Input 1 Volume */
+       { 0x00000808, 0x0000 }, /* R2056 (0x808) - SPDIF1TX2MIX Input 1 Source */
+       { 0x00000809, 0x0080 }, /* R2057 (0x809) - SPDIF1TX2MIX Input 1 Volume */
+       { 0x00000880, 0x0000 }, /* R2176 (0x880) - EQ1MIX Input 1 Source */
+       { 0x00000881, 0x0080 }, /* R2177 (0x881) - EQ1MIX Input 1 Volume */
+       { 0x00000882, 0x0000 }, /* R2178 (0x882) - EQ1MIX Input 2 Source */
+       { 0x00000883, 0x0080 }, /* R2179 (0x883) - EQ1MIX Input 2 Volume */
+       { 0x00000884, 0x0000 }, /* R2180 (0x884) - EQ1MIX Input 3 Source */
+       { 0x00000885, 0x0080 }, /* R2181 (0x885) - EQ1MIX Input 3 Volume */
+       { 0x00000886, 0x0000 }, /* R2182 (0x886) - EQ1MIX Input 4 Source */
+       { 0x00000887, 0x0080 }, /* R2183 (0x887) - EQ1MIX Input 4 Volume */
+       { 0x00000888, 0x0000 }, /* R2184 (0x888) - EQ2MIX Input 1 Source */
+       { 0x00000889, 0x0080 }, /* R2185 (0x889) - EQ2MIX Input 1 Volume */
+       { 0x0000088a, 0x0000 }, /* R2186 (0x88a) - EQ2MIX Input 2 Source */
+       { 0x0000088b, 0x0080 }, /* R2187 (0x88b) - EQ2MIX Input 2 Volume */
+       { 0x0000088c, 0x0000 }, /* R2188 (0x88c) - EQ2MIX Input 3 Source */
+       { 0x0000088d, 0x0080 }, /* R2189 (0x88d) - EQ2MIX Input 3 Volume */
+       { 0x0000088e, 0x0000 }, /* R2190 (0x88e) - EQ2MIX Input 4 Source */
+       { 0x0000088f, 0x0080 }, /* R2191 (0x88f) - EQ2MIX Input 4 Volume */
+       { 0x00000890, 0x0000 }, /* R2192 (0x890) - EQ3MIX Input 1 Source */
+       { 0x00000891, 0x0080 }, /* R2193 (0x891) - EQ3MIX Input 1 Volume */
+       { 0x00000892, 0x0000 }, /* R2194 (0x892) - EQ3MIX Input 2 Source */
+       { 0x00000893, 0x0080 }, /* R2195 (0x893) - EQ3MIX Input 2 Volume */
+       { 0x00000894, 0x0000 }, /* R2196 (0x894) - EQ3MIX Input 3 Source */
+       { 0x00000895, 0x0080 }, /* R2197 (0x895) - EQ3MIX Input 3 Volume */
+       { 0x00000896, 0x0000 }, /* R2198 (0x896) - EQ3MIX Input 4 Source */
+       { 0x00000897, 0x0080 }, /* R2199 (0x897) - EQ3MIX Input 4 Volume */
+       { 0x00000898, 0x0000 }, /* R2200 (0x898) - EQ4MIX Input 1 Source */
+       { 0x00000899, 0x0080 }, /* R2201 (0x899) - EQ4MIX Input 1 Volume */
+       { 0x0000089a, 0x0000 }, /* R2202 (0x89a) - EQ4MIX Input 2 Source */
+       { 0x0000089b, 0x0080 }, /* R2203 (0x89b) - EQ4MIX Input 2 Volume */
+       { 0x0000089c, 0x0000 }, /* R2204 (0x89c) - EQ4MIX Input 3 Source */
+       { 0x0000089d, 0x0080 }, /* R2205 (0x89d) - EQ4MIX Input 3 Volume */
+       { 0x0000089e, 0x0000 }, /* R2206 (0x89e) - EQ4MIX Input 4 Source */
+       { 0x0000089f, 0x0080 }, /* R2207 (0x89f) - EQ4MIX Input 4 Volume */
+       { 0x000008c0, 0x0000 }, /* R2240 (0x8c0) - DRC1LMIX Input 1 Source */
+       { 0x000008c1, 0x0080 }, /* R2241 (0x8c1) - DRC1LMIX Input 1 Volume */
+       { 0x000008c2, 0x0000 }, /* R2242 (0x8c2) - DRC1LMIX Input 2 Source */
+       { 0x000008c3, 0x0080 }, /* R2243 (0x8c3) - DRC1LMIX Input 2 Volume */
+       { 0x000008c4, 0x0000 }, /* R2244 (0x8c4) - DRC1LMIX Input 3 Source */
+       { 0x000008c5, 0x0080 }, /* R2245 (0x8c5) - DRC1LMIX Input 3 Volume */
+       { 0x000008c6, 0x0000 }, /* R2246 (0x8c6) - DRC1LMIX Input 4 Source */
+       { 0x000008c7, 0x0080 }, /* R2247 (0x8c7) - DRC1LMIX Input 4 Volume */
+       { 0x000008c8, 0x0000 }, /* R2248 (0x8c8) - DRC1RMIX Input 1 Source */
+       { 0x000008c9, 0x0080 }, /* R2249 (0x8c9) - DRC1RMIX Input 1 Volume */
+       { 0x000008ca, 0x0000 }, /* R2250 (0x8ca) - DRC1RMIX Input 2 Source */
+       { 0x000008cb, 0x0080 }, /* R2251 (0x8cb) - DRC1RMIX Input 2 Volume */
+       { 0x000008cc, 0x0000 }, /* R2252 (0x8cc) - DRC1RMIX Input 3 Source */
+       { 0x000008cd, 0x0080 }, /* R2253 (0x8cd) - DRC1RMIX Input 3 Volume */
+       { 0x000008ce, 0x0000 }, /* R2254 (0x8ce) - DRC1RMIX Input 4 Source */
+       { 0x000008cf, 0x0080 }, /* R2255 (0x8cf) - DRC1RMIX Input 4 Volume */
+       { 0x000008d0, 0x0000 }, /* R2256 (0x8d0) - DRC2LMIX Input 1 Source */
+       { 0x000008d1, 0x0080 }, /* R2257 (0x8d1) - DRC2LMIX Input 1 Volume */
+       { 0x000008d2, 0x0000 }, /* R2258 (0x8d2) - DRC2LMIX Input 2 Source */
+       { 0x000008d3, 0x0080 }, /* R2259 (0x8d3) - DRC2LMIX Input 2 Volume */
+       { 0x000008d4, 0x0000 }, /* R2260 (0x8d4) - DRC2LMIX Input 3 Source */
+       { 0x000008d5, 0x0080 }, /* R2261 (0x8d5) - DRC2LMIX Input 3 Volume */
+       { 0x000008d6, 0x0000 }, /* R2262 (0x8d6) - DRC2LMIX Input 4 Source */
+       { 0x000008d7, 0x0080 }, /* R2263 (0x8d7) - DRC2LMIX Input 4 Volume */
+       { 0x000008d8, 0x0000 }, /* R2264 (0x8d8) - DRC2RMIX Input 1 Source */
+       { 0x000008d9, 0x0080 }, /* R2265 (0x8d9) - DRC2RMIX Input 1 Volume */
+       { 0x000008da, 0x0000 }, /* R2266 (0x8da) - DRC2RMIX Input 2 Source */
+       { 0x000008db, 0x0080 }, /* R2267 (0x8db) - DRC2RMIX Input 2 Volume */
+       { 0x000008dc, 0x0000 }, /* R2268 (0x8dc) - DRC2RMIX Input 3 Source */
+       { 0x000008dd, 0x0080 }, /* R2269 (0x8dd) - DRC2RMIX Input 3 Volume */
+       { 0x000008de, 0x0000 }, /* R2270 (0x8de) - DRC2RMIX Input 4 Source */
+       { 0x000008df, 0x0080 }, /* R2271 (0x8df) - DRC2RMIX Input 4 Volume */
+       { 0x00000900, 0x0000 }, /* R2304 (0x900) - HPLP1MIX Input 1 Source */
+       { 0x00000901, 0x0080 }, /* R2305 (0x901) - HPLP1MIX Input 1 Volume */
+       { 0x00000902, 0x0000 }, /* R2306 (0x902) - HPLP1MIX Input 2 Source */
+       { 0x00000903, 0x0080 }, /* R2307 (0x903) - HPLP1MIX Input 2 Volume */
+       { 0x00000904, 0x0000 }, /* R2308 (0x904) - HPLP1MIX Input 3 Source */
+       { 0x00000905, 0x0080 }, /* R2309 (0x905) - HPLP1MIX Input 3 Volume */
+       { 0x00000906, 0x0000 }, /* R2310 (0x906) - HPLP1MIX Input 4 Source */
+       { 0x00000907, 0x0080 }, /* R2311 (0x907) - HPLP1MIX Input 4 Volume */
+       { 0x00000908, 0x0000 }, /* R2312 (0x908) - HPLP2MIX Input 1 Source */
+       { 0x00000909, 0x0080 }, /* R2313 (0x909) - HPLP2MIX Input 1 Volume */
+       { 0x0000090a, 0x0000 }, /* R2314 (0x90a) - HPLP2MIX Input 2 Source */
+       { 0x0000090b, 0x0080 }, /* R2315 (0x90b) - HPLP2MIX Input 2 Volume */
+       { 0x0000090c, 0x0000 }, /* R2316 (0x90c) - HPLP2MIX Input 3 Source */
+       { 0x0000090d, 0x0080 }, /* R2317 (0x90d) - HPLP2MIX Input 3 Volume */
+       { 0x0000090e, 0x0000 }, /* R2318 (0x90e) - HPLP2MIX Input 4 Source */
+       { 0x0000090f, 0x0080 }, /* R2319 (0x90f) - HPLP2MIX Input 4 Volume */
+       { 0x00000910, 0x0000 }, /* R2320 (0x910) - HPLP3MIX Input 1 Source */
+       { 0x00000911, 0x0080 }, /* R2321 (0x911) - HPLP3MIX Input 1 Volume */
+       { 0x00000912, 0x0000 }, /* R2322 (0x912) - HPLP3MIX Input 2 Source */
+       { 0x00000913, 0x0080 }, /* R2323 (0x913) - HPLP3MIX Input 2 Volume */
+       { 0x00000914, 0x0000 }, /* R2324 (0x914) - HPLP3MIX Input 3 Source */
+       { 0x00000915, 0x0080 }, /* R2325 (0x915) - HPLP3MIX Input 3 Volume */
+       { 0x00000916, 0x0000 }, /* R2326 (0x916) - HPLP3MIX Input 4 Source */
+       { 0x00000917, 0x0080 }, /* R2327 (0x917) - HPLP3MIX Input 4 Volume */
+       { 0x00000918, 0x0000 }, /* R2328 (0x918) - HPLP4MIX Input 1 Source */
+       { 0x00000919, 0x0080 }, /* R2329 (0x919) - HPLP4MIX Input 1 Volume */
+       { 0x0000091a, 0x0000 }, /* R2330 (0x91a) - HPLP4MIX Input 2 Source */
+       { 0x0000091b, 0x0080 }, /* R2331 (0x91b) - HPLP4MIX Input 2 Volume */
+       { 0x0000091c, 0x0000 }, /* R2332 (0x91c) - HPLP4MIX Input 3 Source */
+       { 0x0000091d, 0x0080 }, /* R2333 (0x91d) - HPLP4MIX Input 3 Volume */
+       { 0x0000091e, 0x0000 }, /* R2334 (0x91e) - HPLP4MIX Input 4 Source */
+       { 0x0000091f, 0x0080 }, /* R2335 (0x91f) - HPLP4MIX Input 4 Volume */
+       { 0x00000940, 0x0000 }, /* R2368 (0x940) - DSP1LMIX Input 1 Source */
+       { 0x00000941, 0x0080 }, /* R2369 (0x941) - DSP1LMIX Input 1 Volume */
+       { 0x00000942, 0x0000 }, /* R2370 (0x942) - DSP1LMIX Input 2 Source */
+       { 0x00000943, 0x0080 }, /* R2371 (0x943) - DSP1LMIX Input 2 Volume */
+       { 0x00000944, 0x0000 }, /* R2372 (0x944) - DSP1LMIX Input 3 Source */
+       { 0x00000945, 0x0080 }, /* R2373 (0x945) - DSP1LMIX Input 3 Volume */
+       { 0x00000946, 0x0000 }, /* R2374 (0x946) - DSP1LMIX Input 4 Source */
+       { 0x00000947, 0x0080 }, /* R2375 (0x947) - DSP1LMIX Input 4 Volume */
+       { 0x00000948, 0x0000 }, /* R2376 (0x948) - DSP1RMIX Input 1 Source */
+       { 0x00000949, 0x0080 }, /* R2377 (0x949) - DSP1RMIX Input 1 Volume */
+       { 0x0000094a, 0x0000 }, /* R2378 (0x94a) - DSP1RMIX Input 2 Source */
+       { 0x0000094b, 0x0080 }, /* R2379 (0x94b) - DSP1RMIX Input 2 Volume */
+       { 0x0000094c, 0x0000 }, /* R2380 (0x94c) - DSP1RMIX Input 3 Source */
+       { 0x0000094d, 0x0080 }, /* R2381 (0x94d) - DSP1RMIX Input 3 Volume */
+       { 0x0000094e, 0x0000 }, /* R2382 (0x94e) - DSP1RMIX Input 4 Source */
+       { 0x0000094f, 0x0080 }, /* R2383 (0x94f) - DSP1RMIX Input 4 Volume */
+       { 0x00000950, 0x0000 }, /* R2384 (0x950) - DSP1AUX1MIX Input 1 Source */
+       { 0x00000958, 0x0000 }, /* R2392 (0x958) - DSP1AUX2MIX Input 1 Source */
+       { 0x00000960, 0x0000 }, /* R2400 (0x960) - DSP1AUX3MIX Input 1 Source */
+       { 0x00000968, 0x0000 }, /* R2408 (0x968) - DSP1AUX4MIX Input 1 Source */
+       { 0x00000970, 0x0000 }, /* R2416 (0x970) - DSP1AUX5MIX Input 1 Source */
+       { 0x00000978, 0x0000 }, /* R2424 (0x978) - DSP1AUX6MIX Input 1 Source */
+       { 0x00000980, 0x0000 }, /* R2432 (0x980) - DSP2LMIX Input 1 Source */
+       { 0x00000981, 0x0080 }, /* R2433 (0x981) - DSP2LMIX Input 1 Volume */
+       { 0x00000982, 0x0000 }, /* R2434 (0x982) - DSP2LMIX Input 2 Source */
+       { 0x00000983, 0x0080 }, /* R2435 (0x983) - DSP2LMIX Input 2 Volume */
+       { 0x00000984, 0x0000 }, /* R2436 (0x984) - DSP2LMIX Input 3 Source */
+       { 0x00000985, 0x0080 }, /* R2437 (0x985) - DSP2LMIX Input 3 Volume */
+       { 0x00000986, 0x0000 }, /* R2438 (0x986) - DSP2LMIX Input 4 Source */
+       { 0x00000987, 0x0080 }, /* R2439 (0x987) - DSP2LMIX Input 4 Volume */
+       { 0x00000988, 0x0000 }, /* R2440 (0x988) - DSP2RMIX Input 1 Source */
+       { 0x00000989, 0x0080 }, /* R2441 (0x989) - DSP2RMIX Input 1 Volume */
+       { 0x0000098a, 0x0000 }, /* R2442 (0x98a) - DSP2RMIX Input 2 Source */
+       { 0x0000098b, 0x0080 }, /* R2443 (0x98b) - DSP2RMIX Input 2 Volume */
+       { 0x0000098c, 0x0000 }, /* R2444 (0x98c) - DSP2RMIX Input 3 Source */
+       { 0x0000098d, 0x0080 }, /* R2445 (0x98d) - DSP2RMIX Input 3 Volume */
+       { 0x0000098e, 0x0000 }, /* R2446 (0x98e) - DSP2RMIX Input 4 Source */
+       { 0x0000098f, 0x0080 }, /* R2447 (0x98f) - DSP2RMIX Input 4 Volume */
+       { 0x00000990, 0x0000 }, /* R2448 (0x990) - DSP2AUX1MIX Input 1 Source */
+       { 0x00000998, 0x0000 }, /* R2456 (0x998) - DSP2AUX2MIX Input 1 Source */
+       { 0x000009a0, 0x0000 }, /* R2464 (0x9a0) - DSP2AUX3MIX Input 1 Source */
+       { 0x000009a8, 0x0000 }, /* R2472 (0x9a8) - DSP2AUX4MIX Input 1 Source */
+       { 0x000009b0, 0x0000 }, /* R2480 (0x9b0) - DSP2AUX5MIX Input 1 Source */
+       { 0x000009b8, 0x0000 }, /* R2488 (0x9b8) - DSP2AUX6MIX Input 1 Source */
+       { 0x000009c0, 0x0000 }, /* R2496 (0x9c0) - DSP3LMIX Input 1 Source */
+       { 0x000009c1, 0x0080 }, /* R2497 (0x9c1) - DSP3LMIX Input 1 Volume */
+       { 0x000009c2, 0x0000 }, /* R2498 (0x9c2) - DSP3LMIX Input 2 Source */
+       { 0x000009c3, 0x0080 }, /* R2499 (0x9c3) - DSP3LMIX Input 2 Volume */
+       { 0x000009c4, 0x0000 }, /* R2500 (0x9c4) - DSP3LMIX Input 3 Source */
+       { 0x000009c5, 0x0080 }, /* R2501 (0x9c5) - DSP3LMIX Input 3 Volume */
+       { 0x000009c6, 0x0000 }, /* R2502 (0x9c6) - DSP3LMIX Input 4 Source */
+       { 0x000009c7, 0x0080 }, /* R2503 (0x9c7) - DSP3LMIX Input 4 Volume */
+       { 0x000009c8, 0x0000 }, /* R2504 (0x9c8) - DSP3RMIX Input 1 Source */
+       { 0x000009c9, 0x0080 }, /* R2505 (0x9c9) - DSP3RMIX Input 1 Volume */
+       { 0x000009ca, 0x0000 }, /* R2506 (0x9ca) - DSP3RMIX Input 2 Source */
+       { 0x000009cb, 0x0080 }, /* R2507 (0x9cb) - DSP3RMIX Input 2 Volume */
+       { 0x000009cc, 0x0000 }, /* R2508 (0x9cc) - DSP3RMIX Input 3 Source */
+       { 0x000009cd, 0x0080 }, /* R2509 (0x9cd) - DSP3RMIX Input 3 Volume */
+       { 0x000009ce, 0x0000 }, /* R2510 (0x9ce) - DSP3RMIX Input 4 Source */
+       { 0x000009cf, 0x0080 }, /* R2511 (0x9cf) - DSP3RMIX Input 4 Volume */
+       { 0x000009d0, 0x0000 }, /* R2512 (0x9d0) - DSP3AUX1MIX Input 1 Source */
+       { 0x000009d8, 0x0000 }, /* R2520 (0x9d8) - DSP3AUX2MIX Input 1 Source */
+       { 0x000009e0, 0x0000 }, /* R2528 (0x9e0) - DSP3AUX3MIX Input 1 Source */
+       { 0x000009e8, 0x0000 }, /* R2536 (0x9e8) - DSP3AUX4MIX Input 1 Source */
+       { 0x000009f0, 0x0000 }, /* R2544 (0x9f0) - DSP3AUX5MIX Input 1 Source */
+       { 0x000009f8, 0x0000 }, /* R2552 (0x9f8) - DSP3AUX6MIX Input 1 Source */
+       { 0x00000a00, 0x0000 }, /* R2560 (0xa00) - DSP4LMIX Input 1 Source */
+       { 0x00000a01, 0x0080 }, /* R2561 (0xa01) - DSP4LMIX Input 1 Volume */
+       { 0x00000a02, 0x0000 }, /* R2562 (0xa02) - DSP4LMIX Input 2 Source */
+       { 0x00000a03, 0x0080 }, /* R2563 (0xa03) - DSP4LMIX Input 2 Volume */
+       { 0x00000a04, 0x0000 }, /* R2564 (0xa04) - DSP4LMIX Input 3 Source */
+       { 0x00000a05, 0x0080 }, /* R2565 (0xa05) - DSP4LMIX Input 3 Volume */
+       { 0x00000a06, 0x0000 }, /* R2566 (0xa06) - DSP4LMIX Input 4 Source */
+       { 0x00000a07, 0x0080 }, /* R2567 (0xa07) - DSP4LMIX Input 4 Volume */
+       { 0x00000a08, 0x0000 }, /* R2568 (0xa08) - DSP4RMIX Input 1 Source */
+       { 0x00000a09, 0x0080 }, /* R2569 (0xa09) - DSP4RMIX Input 1 Volume */
+       { 0x00000a0a, 0x0000 }, /* R2570 (0xa0a) - DSP4RMIX Input 2 Source */
+       { 0x00000a0b, 0x0080 }, /* R2571 (0xa0b) - DSP4RMIX Input 2 Volume */
+       { 0x00000a0c, 0x0000 }, /* R2572 (0xa0c) - DSP4RMIX Input 3 Source */
+       { 0x00000a0d, 0x0080 }, /* R2573 (0xa0d) - DSP4RMIX Input 3 Volume */
+       { 0x00000a0e, 0x0000 }, /* R2574 (0xa0e) - DSP4RMIX Input 4 Source */
+       { 0x00000a0f, 0x0080 }, /* R2575 (0xa0f) - DSP4RMIX Input 4 Volume */
+       { 0x00000a10, 0x0000 }, /* R2576 (0xa10) - DSP4AUX1MIX Input 1 Source */
+       { 0x00000a18, 0x0000 }, /* R2584 (0xa18) - DSP4AUX2MIX Input 1 Source */
+       { 0x00000a20, 0x0000 }, /* R2592 (0xa20) - DSP4AUX3MIX Input 1 Source */
+       { 0x00000a28, 0x0000 }, /* R2600 (0xa28) - DSP4AUX4MIX Input 1 Source */
+       { 0x00000a30, 0x0000 }, /* R2608 (0xa30) - DSP4AUX5MIX Input 1 Source */
+       { 0x00000a38, 0x0000 }, /* R2616 (0xa38) - DSP4AUX6MIX Input 1 Source */
+       { 0x00000a40, 0x0000 }, /* R2624 (0xa40) - DSP5LMIX Input 1 Source */
+       { 0x00000a41, 0x0080 }, /* R2625 (0xa41) - DSP5LMIX Input 1 Volume */
+       { 0x00000a42, 0x0000 }, /* R2626 (0xa42) - DSP5LMIX Input 2 Source */
+       { 0x00000a43, 0x0080 }, /* R2627 (0xa43) - DSP5LMIX Input 2 Volume */
+       { 0x00000a44, 0x0000 }, /* R2628 (0xa44) - DSP5LMIX Input 3 Source */
+       { 0x00000a45, 0x0080 }, /* R2629 (0xa45) - DSP5LMIX Input 3 Volume */
+       { 0x00000a46, 0x0000 }, /* R2630 (0xa46) - DSP5LMIX Input 4 Source */
+       { 0x00000a47, 0x0080 }, /* R2631 (0xa47) - DSP5LMIX Input 4 Volume */
+       { 0x00000a48, 0x0000 }, /* R2632 (0xa48) - DSP5RMIX Input 1 Source */
+       { 0x00000a49, 0x0080 }, /* R2633 (0xa49) - DSP5RMIX Input 1 Volume */
+       { 0x00000a4a, 0x0000 }, /* R2634 (0xa4a) - DSP5RMIX Input 2 Source */
+       { 0x00000a4b, 0x0080 }, /* R2635 (0xa4b) - DSP5RMIX Input 2 Volume */
+       { 0x00000a4c, 0x0000 }, /* R2636 (0xa4c) - DSP5RMIX Input 3 Source */
+       { 0x00000a4d, 0x0080 }, /* R2637 (0xa4d) - DSP5RMIX Input 3 Volume */
+       { 0x00000a4e, 0x0000 }, /* R2638 (0xa4e) - DSP5RMIX Input 4 Source */
+       { 0x00000a4f, 0x0080 }, /* R2639 (0xa4f) - DSP5RMIX Input 4 Volume */
+       { 0x00000a50, 0x0000 }, /* R2640 (0xa50) - DSP5AUX1MIX Input 1 Source */
+       { 0x00000a58, 0x0000 }, /* R2658 (0xa58) - DSP5AUX2MIX Input 1 Source */
+       { 0x00000a60, 0x0000 }, /* R2656 (0xa60) - DSP5AUX3MIX Input 1 Source */
+       { 0x00000a68, 0x0000 }, /* R2664 (0xa68) - DSP5AUX4MIX Input 1 Source */
+       { 0x00000a70, 0x0000 }, /* R2672 (0xa70) - DSP5AUX5MIX Input 1 Source */
+       { 0x00000a78, 0x0000 }, /* R2680 (0xa78) - DSP5AUX6MIX Input 1 Source */
+       { 0x00000a80, 0x0000 }, /* R2688 (0xa80) - ASRC1_1LMIX Input 1 Source */
+       { 0x00000a88, 0x0000 }, /* R2696 (0xa88) - ASRC1_1RMIX Input 1 Source */
+       { 0x00000a90, 0x0000 }, /* R2704 (0xa90) - ASRC1_2LMIX Input 1 Source */
+       { 0x00000a98, 0x0000 }, /* R2712 (0xa98) - ASRC1_2RMIX Input 1 Source */
+       { 0x00000aa0, 0x0000 }, /* R2720 (0xaa0) - ASRC2_1LMIX Input 1 Source */
+       { 0x00000aa8, 0x0000 }, /* R2728 (0xaa8) - ASRC2_1RMIX Input 1 Source */
+       { 0x00000ab0, 0x0000 }, /* R2736 (0xab0) - ASRC2_2LMIX Input 1 Source */
+       { 0x00000ab8, 0x0000 }, /* R2744 (0xab8) - ASRC2_2RMIX Input 1 Source */
+       { 0x00000b00, 0x0000 }, /* R2816 (0xb00) - ISRC1DEC1MIX Input 1 Source*/
+       { 0x00000b08, 0x0000 }, /* R2824 (0xb08) - ISRC1DEC2MIX Input 1 Source*/
+       { 0x00000b10, 0x0000 }, /* R2832 (0xb10) - ISRC1DEC3MIX Input 1 Source*/
+       { 0x00000b18, 0x0000 }, /* R2840 (0xb18) - ISRC1DEC4MIX Input 1 Source*/
+       { 0x00000b20, 0x0000 }, /* R2848 (0xb20) - ISRC1INT1MIX Input 1 Source*/
+       { 0x00000b28, 0x0000 }, /* R2856 (0xb28) - ISRC1INT2MIX Input 1 Source*/
+       { 0x00000b30, 0x0000 }, /* R2864 (0xb30) - ISRC1INT3MIX Input 1 Source*/
+       { 0x00000b38, 0x0000 }, /* R2872 (0xb38) - ISRC1INT4MIX Input 1 Source*/
+       { 0x00000b40, 0x0000 }, /* R2880 (0xb40) - ISRC2DEC1MIX Input 1 Source*/
+       { 0x00000b48, 0x0000 }, /* R2888 (0xb48) - ISRC2DEC2MIX Input 1 Source*/
+       { 0x00000b50, 0x0000 }, /* R2896 (0xb50) - ISRC2DEC3MIX Input 1 Source*/
+       { 0x00000b58, 0x0000 }, /* R2904 (0xb58) - ISRC2DEC4MIX Input 1 Source*/
+       { 0x00000b60, 0x0000 }, /* R2912 (0xb60) - ISRC2INT1MIX Input 1 Source*/
+       { 0x00000b68, 0x0000 }, /* R2920 (0xb68) - ISRC2INT2MIX Input 1 Source*/
+       { 0x00000b70, 0x0000 }, /* R2928 (0xb70) - ISRC2INT3MIX Input 1 Source*/
+       { 0x00000b78, 0x0000 }, /* R2936 (0xb78) - ISRC2INT4MIX Input 1 Source*/
+       { 0x00000b80, 0x0000 }, /* R2944 (0xb80) - ISRC3DEC1MIX Input 1 Source*/
+       { 0x00000b88, 0x0000 }, /* R2952 (0xb88) - ISRC3DEC2MIX Input 1 Source*/
+       { 0x00000ba0, 0x0000 }, /* R2976 (0xb80) - ISRC3INT1MIX Input 1 Source*/
+       { 0x00000ba8, 0x0000 }, /* R2984 (0xb88) - ISRC3INT2MIX Input 1 Source*/
+       { 0x00000bc0, 0x0000 }, /* R3008 (0xbc0) - ISRC4DEC1MIX Input 1 Source */
+       { 0x00000bc8, 0x0000 }, /* R3016 (0xbc8) - ISRC4DEC2MIX Input 1 Source */
+       { 0x00000be0, 0x0000 }, /* R3040 (0xbe0) - ISRC4INT1MIX Input 1 Source */
+       { 0x00000be8, 0x0000 }, /* R3048 (0xbe8) - ISRC4INT2MIX Input 1 Source */
+       { 0x00000c00, 0x0000 }, /* R3072 (0xc00) - DSP6LMIX Input 1 Source */
+       { 0x00000c01, 0x0080 }, /* R3073 (0xc01) - DSP6LMIX Input 1 Volume */
+       { 0x00000c02, 0x0000 }, /* R3074 (0xc02) - DSP6LMIX Input 2 Source */
+       { 0x00000c03, 0x0080 }, /* R3075 (0xc03) - DSP6LMIX Input 2 Volume */
+       { 0x00000c04, 0x0000 }, /* R3076 (0xc04) - DSP6LMIX Input 3 Source */
+       { 0x00000c05, 0x0080 }, /* R3077 (0xc05) - DSP6LMIX Input 3 Volume */
+       { 0x00000c06, 0x0000 }, /* R3078 (0xc06) - DSP6LMIX Input 4 Source */
+       { 0x00000c07, 0x0080 }, /* R3079 (0xc07) - DSP6LMIX Input 4 Volume */
+       { 0x00000c08, 0x0000 }, /* R3080 (0xc08) - DSP6RMIX Input 1 Source */
+       { 0x00000c09, 0x0080 }, /* R3081 (0xc09) - DSP6RMIX Input 1 Volume */
+       { 0x00000c0a, 0x0000 }, /* R3082 (0xc0a) - DSP6RMIX Input 2 Source */
+       { 0x00000c0b, 0x0080 }, /* R3083 (0xc0b) - DSP6RMIX Input 2 Volume */
+       { 0x00000c0c, 0x0000 }, /* R3084 (0xc0c) - DSP6RMIX Input 3 Source */
+       { 0x00000c0d, 0x0080 }, /* R3085 (0xc0d) - DSP6RMIX Input 3 Volume */
+       { 0x00000c0e, 0x0000 }, /* R3086 (0xc0e) - DSP6RMIX Input 4 Source */
+       { 0x00000c0f, 0x0080 }, /* R3087 (0xc0f) - DSP6RMIX Input 4 Volume */
+       { 0x00000c10, 0x0000 }, /* R3088 (0xc10) - DSP6AUX1MIX Input 1 Source */
+       { 0x00000c18, 0x0000 }, /* R3088 (0xc18) - DSP6AUX2MIX Input 1 Source */
+       { 0x00000c20, 0x0000 }, /* R3088 (0xc20) - DSP6AUX3MIX Input 1 Source */
+       { 0x00000c28, 0x0000 }, /* R3088 (0xc28) - DSP6AUX4MIX Input 1 Source */
+       { 0x00000c30, 0x0000 }, /* R3088 (0xc30) - DSP6AUX5MIX Input 1 Source */
+       { 0x00000c38, 0x0000 }, /* R3088 (0xc38) - DSP6AUX6MIX Input 1 Source */
+       { 0x00000c40, 0x0000 }, /* R3136 (0xc40) - DSP7LMIX Input 1 Source */
+       { 0x00000c41, 0x0080 }, /* R3137 (0xc41) - DSP7LMIX Input 1 Volume */
+       { 0x00000c42, 0x0000 }, /* R3138 (0xc42) - DSP7LMIX Input 2 Source */
+       { 0x00000c43, 0x0080 }, /* R3139 (0xc43) - DSP7LMIX Input 2 Volume */
+       { 0x00000c44, 0x0000 }, /* R3140 (0xc44) - DSP7LMIX Input 3 Source */
+       { 0x00000c45, 0x0080 }, /* R3141 (0xc45) - DSP7lMIX Input 3 Volume */
+       { 0x00000c46, 0x0000 }, /* R3142 (0xc46) - DSP7lMIX Input 4 Source */
+       { 0x00000c47, 0x0080 }, /* R3143 (0xc47) - DSP7LMIX Input 4 Volume */
+       { 0x00000c48, 0x0000 }, /* R3144 (0xc48) - DSP7RMIX Input 1 Source */
+       { 0x00000c49, 0x0080 }, /* R3145 (0xc49) - DSP7RMIX Input 1 Volume */
+       { 0x00000c4a, 0x0000 }, /* R3146 (0xc4a) - DSP7RMIX Input 2 Source */
+       { 0x00000c4b, 0x0080 }, /* R3147 (0xc4b) - DSP7RMIX Input 2 Volume */
+       { 0x00000c4c, 0x0000 }, /* R3148 (0xc4c) - DSP7RMIX Input 3 Source */
+       { 0x00000c4d, 0x0080 }, /* R3159 (0xc4d) - DSP7RMIX Input 3 Volume */
+       { 0x00000c4e, 0x0000 }, /* R3150 (0xc4e) - DSP7RMIX Input 4 Source */
+       { 0x00000c4f, 0x0080 }, /* R3151 (0xc4f) - DSP7RMIX Input 4 Volume */
+       { 0x00000c50, 0x0000 }, /* R3152 (0xc50) - DSP7AUX1MIX Input 1 Source */
+       { 0x00000c58, 0x0000 }, /* R3160 (0xc58) - DSP7AUX2MIX Input 1 Source */
+       { 0x00000c60, 0x0000 }, /* R3168 (0xc60) - DSP7AUX3MIX Input 1 Source */
+       { 0x00000c68, 0x0000 }, /* R3176 (0xc68) - DSP7AUX4MIX Input 1 Source */
+       { 0x00000c70, 0x0000 }, /* R3184 (0xc70) - DSP7AUX5MIX Input 1 Source */
+       { 0x00000c78, 0x0000 }, /* R3192 (0xc78) - DSP7AUX6MIX Input 1 Source */
+       { 0x00000dc0, 0x0000 }, /* R3520 (0xdc0) - DFC1MIX Input 1 Source */
+       { 0x00000dc8, 0x0000 }, /* R3528 (0xdc8) - DFC2MIX Input 1 Source */
+       { 0x00000dd0, 0x0000 }, /* R3536 (0xdd0) - DFC3MIX Input 1 Source */
+       { 0x00000dd8, 0x0000 }, /* R3544 (0xdd8) - DFC4MIX Input 1 Source */
+       { 0x00000de0, 0x0000 }, /* R3552 (0xde0) - DFC5MIX Input 1 Source */
+       { 0x00000de8, 0x0000 }, /* R3560 (0xde8) - DFC6MIX Input 1 Source */
+       { 0x00000df0, 0x0000 }, /* R3568 (0xdf0) - DFC7MIX Input 1 Source */
+       { 0x00000df8, 0x0000 }, /* R3576 (0xdf8) - DFC8MIX Input 1 Source */
+       { 0x00000e00, 0x0000 }, /* R3584 (0xe00) - FX_Ctrl1 */
+       { 0x00000e10, 0x6318 }, /* R3600 (0xe10) - EQ1_1 */
+       { 0x00000e11, 0x6300 }, /* R3601 (0xe11) - EQ1_2 */
+       { 0x00000e12, 0x0fc8 }, /* R3602 (0xe12) - EQ1_3 */
+       { 0x00000e13, 0x03fe }, /* R3603 (0xe13) - EQ1_4 */
+       { 0x00000e14, 0x00e0 }, /* R3604 (0xe14) - EQ1_5 */
+       { 0x00000e15, 0x1ec4 }, /* R3605 (0xe15) - EQ1_6 */
+       { 0x00000e16, 0xf136 }, /* R3606 (0xe16) - EQ1_7 */
+       { 0x00000e17, 0x0409 }, /* R3607 (0xe17) - EQ1_8 */
+       { 0x00000e18, 0x04cc }, /* R3608 (0xe18) - EQ1_9 */
+       { 0x00000e19, 0x1c9b }, /* R3609 (0xe19) - EQ1_10 */
+       { 0x00000e1a, 0xf337 }, /* R3610 (0xe1a) - EQ1_11 */
+       { 0x00000e1b, 0x040b }, /* R3611 (0xe1b) - EQ1_12 */
+       { 0x00000e1c, 0x0cbb }, /* R3612 (0xe1c) - EQ1_13 */
+       { 0x00000e1d, 0x16f8 }, /* R3613 (0xe1d) - EQ1_14 */
+       { 0x00000e1e, 0xf7d9 }, /* R3614 (0xe1e) - EQ1_15 */
+       { 0x00000e1f, 0x040a }, /* R3615 (0xe1f) - EQ1_16 */
+       { 0x00000e20, 0x1f14 }, /* R3616 (0xe20) - EQ1_17 */
+       { 0x00000e21, 0x058c }, /* R3617 (0xe21) - EQ1_18 */
+       { 0x00000e22, 0x0563 }, /* R3618 (0xe22) - EQ1_19 */
+       { 0x00000e23, 0x4000 }, /* R3619 (0xe23) - EQ1_20 */
+       { 0x00000e24, 0x0b75 }, /* R3620 (0xe24) - EQ1_21 */
+       { 0x00000e26, 0x6318 }, /* R3622 (0xe26) - EQ2_1 */
+       { 0x00000e27, 0x6300 }, /* R3623 (0xe27) - EQ2_2 */
+       { 0x00000e28, 0x0fc8 }, /* R3624 (0xe28) - EQ2_3 */
+       { 0x00000e29, 0x03fe }, /* R3625 (0xe29) - EQ2_4 */
+       { 0x00000e2a, 0x00e0 }, /* R3626 (0xe2a) - EQ2_5 */
+       { 0x00000e2b, 0x1ec4 }, /* R3627 (0xe2b) - EQ2_6 */
+       { 0x00000e2c, 0xf136 }, /* R3628 (0xe2c) - EQ2_7 */
+       { 0x00000e2d, 0x0409 }, /* R3629 (0xe2d) - EQ2_8 */
+       { 0x00000e2e, 0x04cc }, /* R3630 (0xe2e) - EQ2_9 */
+       { 0x00000e2f, 0x1c9b }, /* R3631 (0xe2f) - EQ2_10 */
+       { 0x00000e30, 0xf337 }, /* R3632 (0xe30) - EQ2_11 */
+       { 0x00000e31, 0x040b }, /* R3633 (0xe31) - EQ2_12 */
+       { 0x00000e32, 0x0cbb }, /* R3634 (0xe32) - EQ2_13 */
+       { 0x00000e33, 0x16f8 }, /* R3635 (0xe33) - EQ2_14 */
+       { 0x00000e34, 0xf7d9 }, /* R3636 (0xe34) - EQ2_15 */
+       { 0x00000e35, 0x040a }, /* R3637 (0xe35) - EQ2_16 */
+       { 0x00000e36, 0x1f14 }, /* R3638 (0xe36) - EQ2_17 */
+       { 0x00000e37, 0x058c }, /* R3639 (0xe37) - EQ2_18 */
+       { 0x00000e38, 0x0563 }, /* R3640 (0xe38) - EQ2_19 */
+       { 0x00000e39, 0x4000 }, /* R3641 (0xe39) - EQ2_20 */
+       { 0x00000e3a, 0x0b75 }, /* R3642 (0xe3a) - EQ2_21 */
+       { 0x00000e3c, 0x6318 }, /* R3644 (0xe3c) - EQ3_1 */
+       { 0x00000e3d, 0x6300 }, /* R3645 (0xe3d) - EQ3_2 */
+       { 0x00000e3e, 0x0fc8 }, /* R3646 (0xe3e) - EQ3_3 */
+       { 0x00000e3f, 0x03fe }, /* R3647 (0xe3f) - EQ3_4 */
+       { 0x00000e40, 0x00e0 }, /* R3648 (0xe40) - EQ3_5 */
+       { 0x00000e41, 0x1ec4 }, /* R3649 (0xe41) - EQ3_6 */
+       { 0x00000e42, 0xf136 }, /* R3650 (0xe42) - EQ3_7 */
+       { 0x00000e43, 0x0409 }, /* R3651 (0xe43) - EQ3_8 */
+       { 0x00000e44, 0x04cc }, /* R3652 (0xe44) - EQ3_9 */
+       { 0x00000e45, 0x1c9b }, /* R3653 (0xe45) - EQ3_10 */
+       { 0x00000e46, 0xf337 }, /* R3654 (0xe46) - EQ3_11 */
+       { 0x00000e47, 0x040b }, /* R3655 (0xe47) - EQ3_12 */
+       { 0x00000e48, 0x0cbb }, /* R3656 (0xe48) - EQ3_13 */
+       { 0x00000e49, 0x16f8 }, /* R3657 (0xe49) - EQ3_14 */
+       { 0x00000e4a, 0xf7d9 }, /* R3658 (0xe4a) - EQ3_15 */
+       { 0x00000e4b, 0x040a }, /* R3659 (0xe4b) - EQ3_16 */
+       { 0x00000e4c, 0x1f14 }, /* R3660 (0xe4c) - EQ3_17 */
+       { 0x00000e4d, 0x058c }, /* R3661 (0xe4d) - EQ3_18 */
+       { 0x00000e4e, 0x0563 }, /* R3662 (0xe4e) - EQ3_19 */
+       { 0x00000e4f, 0x4000 }, /* R3663 (0xe4f) - EQ3_20 */
+       { 0x00000e50, 0x0b75 }, /* R3664 (0xe50) - EQ3_21 */
+       { 0x00000e52, 0x6318 }, /* R3666 (0xe52) - EQ4_1 */
+       { 0x00000e53, 0x6300 }, /* R3667 (0xe53) - EQ4_2 */
+       { 0x00000e54, 0x0fc8 }, /* R3668 (0xe54) - EQ4_3 */
+       { 0x00000e55, 0x03fe }, /* R3669 (0xe55) - EQ4_4 */
+       { 0x00000e56, 0x00e0 }, /* R3670 (0xe56) - EQ4_5 */
+       { 0x00000e57, 0x1ec4 }, /* R3671 (0xe57) - EQ4_6 */
+       { 0x00000e58, 0xf136 }, /* R3672 (0xe58) - EQ4_7 */
+       { 0x00000e59, 0x0409 }, /* R3673 (0xe59) - EQ4_8 */
+       { 0x00000e5a, 0x04cc }, /* R3674 (0xe5a) - EQ4_9 */
+       { 0x00000e5b, 0x1c9b }, /* R3675 (0xe5b) - EQ4_10 */
+       { 0x00000e5c, 0xf337 }, /* R3676 (0xe5c) - EQ4_11 */
+       { 0x00000e5d, 0x040b }, /* R3677 (0xe5d) - EQ4_12 */
+       { 0x00000e5e, 0x0cbb }, /* R3678 (0xe5e) - EQ4_13 */
+       { 0x00000e5f, 0x16f8 }, /* R3679 (0xe5f) - EQ4_14 */
+       { 0x00000e60, 0xf7d9 }, /* R3680 (0xe60) - EQ4_15 */
+       { 0x00000e61, 0x040a }, /* R3681 (0xe61) - EQ4_16 */
+       { 0x00000e62, 0x1f14 }, /* R3682 (0xe62) - EQ4_17 */
+       { 0x00000e63, 0x058c }, /* R3683 (0xe63) - EQ4_18 */
+       { 0x00000e64, 0x0563 }, /* R3684 (0xe64) - EQ4_19 */
+       { 0x00000e65, 0x4000 }, /* R3685 (0xe65) - EQ4_20 */
+       { 0x00000e66, 0x0b75 }, /* R3686 (0xe66) - EQ4_21 */
+       { 0x00000e80, 0x0018 }, /* R3712 (0xe80) - DRC1 ctrl1 */
+       { 0x00000e81, 0x0933 }, /* R3713 (0xe81) - DRC1 ctrl2 */
+       { 0x00000e82, 0x0018 }, /* R3714 (0xe82) - DRC1 ctrl3 */
+       { 0x00000e83, 0x0000 }, /* R3715 (0xe83) - DRC1 ctrl4 */
+       { 0x00000e84, 0x0000 }, /* R3716 (0xe84) - DRC1 ctrl5 */
+       { 0x00000e88, 0x0018 }, /* R3720 (0xe88) - DRC2 ctrl1 */
+       { 0x00000e89, 0x0933 }, /* R3721 (0xe89) - DRC2 ctrl2 */
+       { 0x00000e8a, 0x0018 }, /* R3722 (0xe8a) - DRC2 ctrl3 */
+       { 0x00000e8b, 0x0000 }, /* R3723 (0xe8b) - DRC2 ctrl4 */
+       { 0x00000e8c, 0x0000 }, /* R3724 (0xe8c) - DRC2 ctrl5 */
+       { 0x00000ec0, 0x0000 }, /* R3776 (0xec0) - HPLPF1_1 */
+       { 0x00000ec1, 0x0000 }, /* R3777 (0xec1) - HPLPF1_2 */
+       { 0x00000ec4, 0x0000 }, /* R3780 (0xec4) - HPLPF2_1 */
+       { 0x00000ec5, 0x0000 }, /* R3781 (0xec5) - HPLPF2_2 */
+       { 0x00000ec8, 0x0000 }, /* R3784 (0xec8) - HPLPF3_1 */
+       { 0x00000ec9, 0x0000 }, /* R3785 (0xec9) - HPLPF3_2 */
+       { 0x00000ecc, 0x0000 }, /* R3788 (0xecc) - HPLPF4_1 */
+       { 0x00000ecd, 0x0000 }, /* R3789 (0xecd) - HPLPF4_2 */
+       { 0x00000ed0, 0x0000 }, /* R3792 (0xed0) - ASRC2_ENABLE */
+       { 0x00000ed2, 0x0000 }, /* R3794 (0xed2) - ASRC2_RATE1 */
+       { 0x00000ed3, 0x4000 }, /* R3795 (0xed3) - ASRC2_RATE2 */
+       { 0x00000ee0, 0x0000 }, /* R3808 (0xee0) - ASRC1_ENABLE */
+       { 0x00000ee2, 0x0000 }, /* R3810 (0xee2) - ASRC1_RATE1 */
+       { 0x00000ee3, 0x4000 }, /* R3811 (0xee3) - ASRC1_RATE2 */
+       { 0x00000ef0, 0x0000 }, /* R3824 (0xef0) - ISRC 1 CTRL 1 */
+       { 0x00000ef1, 0x0001 }, /* R3825 (0xef1) - ISRC 1 CTRL 2 */
+       { 0x00000ef2, 0x0000 }, /* R3826 (0xef2) - ISRC 1 CTRL 3 */
+       { 0x00000ef3, 0x0000 }, /* R3827 (0xef3) - ISRC 2 CTRL 1 */
+       { 0x00000ef4, 0x0001 }, /* R3828 (0xef4) - ISRC 2 CTRL 2 */
+       { 0x00000ef5, 0x0000 }, /* R3829 (0xef5) - ISRC 2 CTRL 3 */
+       { 0x00000ef6, 0x0000 }, /* R3830 (0xef6) - ISRC 3 CTRL 1 */
+       { 0x00000ef7, 0x0001 }, /* R3831 (0xef7) - ISRC 3 CTRL 2 */
+       { 0x00000ef8, 0x0000 }, /* R3832 (0xef8) - ISRC 3 CTRL 3 */
+       { 0x00000ef9, 0x0000 }, /* R3833 (0xef9) - ISRC 4 CTRL 1 */
+       { 0x00000efa, 0x0001 }, /* R3834 (0xefa) - ISRC 4 CTRL 2 */
+       { 0x00000efb, 0x0000 }, /* R3835 (0xefb) - ISRC 4 CTRL 3 */
+       { 0x00000f01, 0x0000 }, /* R3841 (0xf01) - ANC_SRC */
+       { 0x00000f02, 0x0000 }, /* R3842 (0xf02) - DSP Status */
+       { 0x00000f08, 0x001c }, /* R3848 (0xf08) - ANC Coefficient */
+       { 0x00000f09, 0x0000 }, /* R3849 (0xf09) - ANC Coefficient */
+       { 0x00000f0a, 0x0000 }, /* R3850 (0xf0a) - ANC Coefficient */
+       { 0x00000f0b, 0x0000 }, /* R3851 (0xf0b) - ANC Coefficient */
+       { 0x00000f0c, 0x0000 }, /* R3852 (0xf0c) - ANC Coefficient */
+       { 0x00000f0d, 0x0000 }, /* R3853 (0xf0d) - ANC Coefficient */
+       { 0x00000f0e, 0x0000 }, /* R3854 (0xf0e) - ANC Coefficient */
+       { 0x00000f0f, 0x0000 }, /* R3855 (0xf0f) - ANC Coefficient */
+       { 0x00000f10, 0x0000 }, /* R3856 (0xf10) - ANC Coefficient */
+       { 0x00000f11, 0x0000 }, /* R3857 (0xf11) - ANC Coefficient */
+       { 0x00000f12, 0x0000 }, /* R3858 (0xf12) - ANC Coefficient */
+       { 0x00000f15, 0x0000 }, /* R3861 (0xf15) - FCL Filter Control */
+       { 0x00000f17, 0x0004 }, /* R3863 (0xf17) - FCL ADC Reformatter Control */
+       { 0x00000f18, 0x0004 }, /* R3864 (0xf18) - ANC Coefficient */
+       { 0x00000f19, 0x0002 }, /* R3865 (0xf19) - ANC Coefficient */
+       { 0x00000f1a, 0x0000 }, /* R3866 (0xf1a) - ANC Coefficient */
+       { 0x00000f1b, 0x0010 }, /* R3867 (0xf1b) - ANC Coefficient */
+       { 0x00000f1c, 0x0000 }, /* R3868 (0xf1c) - ANC Coefficient */
+       { 0x00000f1d, 0x0000 }, /* R3869 (0xf1d) - ANC Coefficient */
+       { 0x00000f1e, 0x0000 }, /* R3870 (0xf1e) - ANC Coefficient */
+       { 0x00000f1f, 0x0000 }, /* R3871 (0xf1f) - ANC Coefficient */
+       { 0x00000f20, 0x0000 }, /* R3872 (0xf20) - ANC Coefficient */
+       { 0x00000f21, 0x0000 }, /* R3873 (0xf21) - ANC Coefficient */
+       { 0x00000f22, 0x0000 }, /* R3874 (0xf22) - ANC Coefficient */
+       { 0x00000f23, 0x0000 }, /* R3875 (0xf23) - ANC Coefficient */
+       { 0x00000f24, 0x0000 }, /* R3876 (0xf24) - ANC Coefficient */
+       { 0x00000f25, 0x0000 }, /* R3877 (0xf25) - ANC Coefficient */
+       { 0x00000f26, 0x0000 }, /* R3878 (0xf26) - ANC Coefficient */
+       { 0x00000f27, 0x0000 }, /* R3879 (0xf27) - ANC Coefficient */
+       { 0x00000f28, 0x0000 }, /* R3880 (0xf28) - ANC Coefficient */
+       { 0x00000f29, 0x0000 }, /* R3881 (0xf29) - ANC Coefficient */
+       { 0x00000f2a, 0x0000 }, /* R3882 (0xf2a) - ANC Coefficient */
+       { 0x00000f2b, 0x0000 }, /* R3883 (0xf2b) - ANC Coefficient */
+       { 0x00000f2c, 0x0000 }, /* R3884 (0xf2c) - ANC Coefficient */
+       { 0x00000f2d, 0x0000 }, /* R3885 (0xf2d) - ANC Coefficient */
+       { 0x00000f2e, 0x0000 }, /* R3886 (0xf2e) - ANC Coefficient */
+       { 0x00000f2f, 0x0000 }, /* R3887 (0xf2f) - ANC Coefficient */
+       { 0x00000f30, 0x0000 }, /* R3888 (0xf30) - ANC Coefficient */
+       { 0x00000f31, 0x0000 }, /* R3889 (0xf31) - ANC Coefficient */
+       { 0x00000f32, 0x0000 }, /* R3890 (0xf32) - ANC Coefficient */
+       { 0x00000f33, 0x0000 }, /* R3891 (0xf33) - ANC Coefficient */
+       { 0x00000f34, 0x0000 }, /* R3892 (0xf34) - ANC Coefficient */
+       { 0x00000f35, 0x0000 }, /* R3893 (0xf35) - ANC Coefficient */
+       { 0x00000f36, 0x0000 }, /* R3894 (0xf36) - ANC Coefficient */
+       { 0x00000f37, 0x0000 }, /* R3895 (0xf37) - ANC Coefficient */
+       { 0x00000f38, 0x0000 }, /* R3896 (0xf38) - ANC Coefficient */
+       { 0x00000f39, 0x0000 }, /* R3897 (0xf39) - ANC Coefficient */
+       { 0x00000f3a, 0x0000 }, /* R3898 (0xf3a) - ANC Coefficient */
+       { 0x00000f3b, 0x0000 }, /* R3899 (0xf3b) - ANC Coefficient */
+       { 0x00000f3c, 0x0000 }, /* R3900 (0xf3c) - ANC Coefficient */
+       { 0x00000f3d, 0x0000 }, /* R3901 (0xf3d) - ANC Coefficient */
+       { 0x00000f3e, 0x0000 }, /* R3902 (0xf3e) - ANC Coefficient */
+       { 0x00000f3f, 0x0000 }, /* R3903 (0xf3f) - ANC Coefficient */
+       { 0x00000f40, 0x0000 }, /* R3904 (0xf40) - ANC Coefficient */
+       { 0x00000f41, 0x0000 }, /* R3905 (0xf41) - ANC Coefficient */
+       { 0x00000f42, 0x0000 }, /* R3906 (0xf42) - ANC Coefficient */
+       { 0x00000f43, 0x0000 }, /* R3907 (0xf43) - ANC Coefficient */
+       { 0x00000f44, 0x0000 }, /* R3908 (0xf44) - ANC Coefficient */
+       { 0x00000f45, 0x0000 }, /* R3909 (0xf45) - ANC Coefficient */
+       { 0x00000f46, 0x0000 }, /* R3910 (0xf46) - ANC Coefficient */
+       { 0x00000f47, 0x0000 }, /* R3911 (0xf47) - ANC Coefficient */
+       { 0x00000f48, 0x0000 }, /* R3912 (0xf48) - ANC Coefficient */
+       { 0x00000f49, 0x0000 }, /* R3913 (0xf49) - ANC Coefficient */
+       { 0x00000f4a, 0x0000 }, /* R3914 (0xf4a) - ANC Coefficient */
+       { 0x00000f4b, 0x0000 }, /* R3915 (0xf4b) - ANC Coefficient */
+       { 0x00000f4c, 0x0000 }, /* R3916 (0xf4c) - ANC Coefficient */
+       { 0x00000f4d, 0x0000 }, /* R3917 (0xf4d) - ANC Coefficient */
+       { 0x00000f4e, 0x0000 }, /* R3918 (0xf4e) - ANC Coefficient */
+       { 0x00000f4f, 0x0000 }, /* R3919 (0xf4f) - ANC Coefficient */
+       { 0x00000f50, 0x0000 }, /* R3920 (0xf50) - ANC Coefficient */
+       { 0x00000f51, 0x0000 }, /* R3921 (0xf51) - ANC Coefficient */
+       { 0x00000f52, 0x0000 }, /* R3922 (0xf52) - ANC Coefficient */
+       { 0x00000f53, 0x0000 }, /* R3923 (0xf53) - ANC Coefficient */
+       { 0x00000f54, 0x0000 }, /* R3924 (0xf54) - ANC Coefficient */
+       { 0x00000f55, 0x0000 }, /* R3925 (0xf55) - ANC Coefficient */
+       { 0x00000f56, 0x0000 }, /* R3926 (0xf56) - ANC Coefficient */
+       { 0x00000f57, 0x0000 }, /* R3927 (0xf57) - ANC Coefficient */
+       { 0x00000f58, 0x0000 }, /* R3928 (0xf58) - ANC Coefficient */
+       { 0x00000f59, 0x0000 }, /* R3929 (0xf59) - ANC Coefficient */
+       { 0x00000f5a, 0x0000 }, /* R3930 (0xf5a) - ANC Coefficient */
+       { 0x00000f5b, 0x0000 }, /* R3931 (0xf5b) - ANC Coefficient */
+       { 0x00000f5c, 0x0000 }, /* R3932 (0xf5c) - ANC Coefficient */
+       { 0x00000f5d, 0x0000 }, /* R3933 (0xf5d) - ANC Coefficient */
+       { 0x00000f5e, 0x0000 }, /* R3934 (0xf5e) - ANC Coefficient */
+       { 0x00000f5f, 0x0000 }, /* R3935 (0xf5f) - ANC Coefficient */
+       { 0x00000f60, 0x0000 }, /* R3936 (0xf60) - ANC Coefficient */
+       { 0x00000f61, 0x0000 }, /* R3937 (0xf61) - ANC Coefficient */
+       { 0x00000f62, 0x0000 }, /* R3938 (0xf62) - ANC Coefficient */
+       { 0x00000f63, 0x0000 }, /* R3939 (0xf63) - ANC Coefficient */
+       { 0x00000f64, 0x0000 }, /* R3940 (0xf64) - ANC Coefficient */
+       { 0x00000f65, 0x0000 }, /* R3941 (0xf65) - ANC Coefficient */
+       { 0x00000f66, 0x0000 }, /* R3942 (0xf66) - ANC Coefficient */
+       { 0x00000f67, 0x0000 }, /* R3943 (0xf67) - ANC Coefficient */
+       { 0x00000f68, 0x0000 }, /* R3944 (0xf68) - ANC Coefficient */
+       { 0x00000f69, 0x0000 }, /* R3945 (0xf69) - ANC Coefficient */
+       { 0x00000f71, 0x0000 }, /* R3953 (0xf71) - FCR Filter Control */
+       { 0x00000f73, 0x0004 }, /* R3955 (0xf73) - FCR ADC Reformatter Control */
+       { 0x00000f74, 0x0004 }, /* R3956 (0xf74) - ANC Coefficient */
+       { 0x00000f75, 0x0002 }, /* R3957 (0xf75) - ANC Coefficient */
+       { 0x00000f76, 0x0000 }, /* R3958 (0xf76) - ANC Coefficient */
+       { 0x00000f77, 0x0010 }, /* R3959 (0xf77) - ANC Coefficient */
+       { 0x00000f78, 0x0000 }, /* R3960 (0xf78) - ANC Coefficient */
+       { 0x00000f79, 0x0000 }, /* R3961 (0xf79) - ANC Coefficient */
+       { 0x00000f7a, 0x0000 }, /* R3962 (0xf7a) - ANC Coefficient */
+       { 0x00000f7b, 0x0000 }, /* R3963 (0xf7b) - ANC Coefficient */
+       { 0x00000f7c, 0x0000 }, /* R3964 (0xf7c) - ANC Coefficient */
+       { 0x00000f7d, 0x0000 }, /* R3965 (0xf7d) - ANC Coefficient */
+       { 0x00000f7e, 0x0000 }, /* R3966 (0xf7e) - ANC Coefficient */
+       { 0x00000f7f, 0x0000 }, /* R3967 (0xf7f) - ANC Coefficient */
+       { 0x00000f80, 0x0000 }, /* R3968 (0xf80) - ANC Coefficient */
+       { 0x00000f81, 0x0000 }, /* R3969 (0xf81) - ANC Coefficient */
+       { 0x00000f82, 0x0000 }, /* R3970 (0xf82) - ANC Coefficient */
+       { 0x00000f83, 0x0000 }, /* R3971 (0xf83) - ANC Coefficient */
+       { 0x00000f84, 0x0000 }, /* R3972 (0xf84) - ANC Coefficient */
+       { 0x00000f85, 0x0000 }, /* R3973 (0xf85) - ANC Coefficient */
+       { 0x00000f86, 0x0000 }, /* R3974 (0xf86) - ANC Coefficient */
+       { 0x00000f87, 0x0000 }, /* R3975 (0xf87) - ANC Coefficient */
+       { 0x00000f88, 0x0000 }, /* R3976 (0xf88) - ANC Coefficient */
+       { 0x00000f89, 0x0000 }, /* R3977 (0xf89) - ANC Coefficient */
+       { 0x00000f8a, 0x0000 }, /* R3978 (0xf8a) - ANC Coefficient */
+       { 0x00000f8b, 0x0000 }, /* R3979 (0xf8b) - ANC Coefficient */
+       { 0x00000f8c, 0x0000 }, /* R3980 (0xf8c) - ANC Coefficient */
+       { 0x00000f8d, 0x0000 }, /* R3981 (0xf8d) - ANC Coefficient */
+       { 0x00000f8e, 0x0000 }, /* R3982 (0xf8e) - ANC Coefficient */
+       { 0x00000f8f, 0x0000 }, /* R3983 (0xf8f) - ANC Coefficient */
+       { 0x00000f90, 0x0000 }, /* R3984 (0xf90) - ANC Coefficient */
+       { 0x00000f91, 0x0000 }, /* R3985 (0xf91) - ANC Coefficient */
+       { 0x00000f92, 0x0000 }, /* R3986 (0xf92) - ANC Coefficient */
+       { 0x00000f93, 0x0000 }, /* R3987 (0xf93) - ANC Coefficient */
+       { 0x00000f94, 0x0000 }, /* R3988 (0xf94) - ANC Coefficient */
+       { 0x00000f95, 0x0000 }, /* R3989 (0xf95) - ANC Coefficient */
+       { 0x00000f96, 0x0000 }, /* R3990 (0xf96) - ANC Coefficient */
+       { 0x00000f97, 0x0000 }, /* R3991 (0xf97) - ANC Coefficient */
+       { 0x00000f98, 0x0000 }, /* R3992 (0xf98) - ANC Coefficient */
+       { 0x00000f99, 0x0000 }, /* R3993 (0xf99) - ANC Coefficient */
+       { 0x00000f9a, 0x0000 }, /* R3994 (0xf9a) - ANC Coefficient */
+       { 0x00000f9b, 0x0000 }, /* R3995 (0xf9b) - ANC Coefficient */
+       { 0x00000f9c, 0x0000 }, /* R3996 (0xf9c) - ANC Coefficient */
+       { 0x00000f9d, 0x0000 }, /* R3997 (0xf9d) - ANC Coefficient */
+       { 0x00000f9e, 0x0000 }, /* R3998 (0xf9e) - ANC Coefficient */
+       { 0x00000f9f, 0x0000 }, /* R3999 (0xf9f) - ANC Coefficient */
+       { 0x00000fa0, 0x0000 }, /* R4000 (0xfa0) - ANC Coefficient */
+       { 0x00000fa1, 0x0000 }, /* R4001 (0xfa1) - ANC Coefficient */
+       { 0x00000fa2, 0x0000 }, /* R4002 (0xfa2) - ANC Coefficient */
+       { 0x00000fa3, 0x0000 }, /* R4003 (0xfa3) - ANC Coefficient */
+       { 0x00000fa4, 0x0000 }, /* R4004 (0xfa4) - ANC Coefficient */
+       { 0x00000fa5, 0x0000 }, /* R4005 (0xfa5) - ANC Coefficient */
+       { 0x00000fa6, 0x0000 }, /* R4006 (0xfa6) - ANC Coefficient */
+       { 0x00000fa7, 0x0000 }, /* R4007 (0xfa7) - ANC Coefficient */
+       { 0x00000fa8, 0x0000 }, /* R4008 (0xfa8) - ANC Coefficient */
+       { 0x00000fa9, 0x0000 }, /* R4009 (0xfa9) - ANC Coefficient */
+       { 0x00000faa, 0x0000 }, /* R4010 (0xfaa) - ANC Coefficient */
+       { 0x00000fab, 0x0000 }, /* R4011 (0xfab) - ANC Coefficient */
+       { 0x00000fac, 0x0000 }, /* R4012 (0xfac) - ANC Coefficient */
+       { 0x00000fad, 0x0000 }, /* R4013 (0xfad) - ANC Coefficient */
+       { 0x00000fae, 0x0000 }, /* R4014 (0xfae) - ANC Coefficient */
+       { 0x00000faf, 0x0000 }, /* R4015 (0xfaf) - ANC Coefficient */
+       { 0x00000fb0, 0x0000 }, /* R4016 (0xfb0) - ANC Coefficient */
+       { 0x00000fb1, 0x0000 }, /* R4017 (0xfb1) - ANC Coefficient */
+       { 0x00000fb2, 0x0000 }, /* R4018 (0xfb2) - ANC Coefficient */
+       { 0x00000fb3, 0x0000 }, /* R4019 (0xfb3) - ANC Coefficient */
+       { 0x00000fb4, 0x0000 }, /* R4020 (0xfb4) - ANC Coefficient */
+       { 0x00000fb5, 0x0000 }, /* R4021 (0xfb5) - ANC Coefficient */
+       { 0x00000fb6, 0x0000 }, /* R4022 (0xfb6) - ANC Coefficient */
+       { 0x00000fb7, 0x0000 }, /* R4023 (0xfb7) - ANC Coefficient */
+       { 0x00000fb8, 0x0000 }, /* R4024 (0xfb8) - ANC Coefficient */
+       { 0x00000fb9, 0x0000 }, /* R4025 (0xfb9) - ANC Coefficient */
+       { 0x00000fba, 0x0000 }, /* R4026 (0xfba) - ANC Coefficient */
+       { 0x00000fbb, 0x0000 }, /* R4027 (0xfbb) - ANC Coefficient */
+       { 0x00000fbc, 0x0000 }, /* R4028 (0xfbc) - ANC Coefficient */
+       { 0x00000fbd, 0x0000 }, /* R4029 (0xfbd) - ANC Coefficient */
+       { 0x00000fbe, 0x0000 }, /* R4030 (0xfbe) - ANC Coefficient */
+       { 0x00000fbf, 0x0000 }, /* R4031 (0xfbf) - ANC Coefficient */
+       { 0x00000fc0, 0x0000 }, /* R4032 (0xfc0) - ANC Coefficient */
+       { 0x00000fc1, 0x0000 }, /* R4033 (0xfc1) - ANC Coefficient */
+       { 0x00000fc2, 0x0000 }, /* R4034 (0xfc2) - ANC Coefficient */
+       { 0x00000fc3, 0x0000 }, /* R4035 (0xfc3) - ANC Coefficient */
+       { 0x00000fc4, 0x0000 }, /* R4036 (0xfc4) - ANC Coefficient */
+       { 0x00000fc5, 0x0000 }, /* R4037 (0xfc5) - ANC Coefficient */
+       { 0x00001300, 0x050E }, /* R4864 (0x1300) - DAC Comp 1 */
+       { 0x00001302, 0x0101 }, /* R4866 (0x1302) - DAC Comp 2 */
+       { 0x00001380, 0x0425 }, /* R4992 (0x1380) - FRF Coefficient 1L 1 */
+       { 0x00001381, 0xF6D8 }, /* R4993 (0x1381) - FRF Coefficient 1L 2 */
+       { 0x00001382, 0x0632 }, /* R4994 (0x1382) - FRF Coefficient 1L 3 */
+       { 0x00001383, 0xFEC8 }, /* R4995 (0x1383) - FRF Coefficient 1L 4 */
+       { 0x00001390, 0x042F }, /* R5008 (0x1390) - FRF Coefficient 1R 1 */
+       { 0x00001391, 0xF6CA }, /* R5009 (0x1391) - FRF Coefficient 1R 2 */
+       { 0x00001392, 0x0637 }, /* R5010 (0x1392) - FRF Coefficient 1R 3 */
+       { 0x00001393, 0xFEC8 }, /* R5011 (0x1393) - FRF Coefficient 1R 4 */
+       { 0x000013a0, 0x0000 }, /* R5024 (0x13a0) - FRF Coefficient 2L 1 */
+       { 0x000013a1, 0x0000 }, /* R5025 (0x13a1) - FRF Coefficient 2L 2 */
+       { 0x000013a2, 0x0000 }, /* R5026 (0x13a2) - FRF Coefficient 2L 3 */
+       { 0x000013a3, 0x0000 }, /* R5027 (0x13a3) - FRF Coefficient 2L 4 */
+       { 0x000013b0, 0x0000 }, /* R5040 (0x13b0) - FRF Coefficient 2R 1 */
+       { 0x000013b1, 0x0000 }, /* R5041 (0x13b1) - FRF Coefficient 2R 2 */
+       { 0x000013b2, 0x0000 }, /* R5042 (0x13b2) - FRF Coefficient 2R 3 */
+       { 0x000013b3, 0x0000 }, /* R5043 (0x13b3) - FRF Coefficient 2R 4 */
+       { 0x000013c0, 0x0000 }, /* R5040 (0x13c0) - FRF Coefficient 3L 1 */
+       { 0x000013c1, 0x0000 }, /* R5041 (0x13c1) - FRF Coefficient 3L 2 */
+       { 0x000013c2, 0x0000 }, /* R5042 (0x13c2) - FRF Coefficient 3L 3 */
+       { 0x000013c3, 0x0000 }, /* R5043 (0x13c3) - FRF Coefficient 3L 4 */
+       { 0x000013d0, 0x0000 }, /* R5072 (0x13d0) - FRF Coefficient 3R 1 */
+       { 0x000013d1, 0x0000 }, /* R5073 (0x13d1) - FRF Coefficient 3R 2 */
+       { 0x000013d2, 0x0000 }, /* R5074 (0x13d2) - FRF Coefficient 3R 3 */
+       { 0x000013d3, 0x0000 }, /* R5075 (0x13d3) - FRF Coefficient 3R 4 */
+       { 0x00001400, 0x0000 }, /* R5120 (0x1400) - FRF Coefficient 5L 1 */
+       { 0x00001401, 0x0000 }, /* R5121 (0x1401) - FRF Coefficient 5L 2 */
+       { 0x00001402, 0x0000 }, /* R5122 (0x1402) - FRF Coefficient 5L 3 */
+       { 0x00001403, 0x0000 }, /* R5123 (0x1403) - FRF Coefficient 5L 4 */
+       { 0x00001410, 0x0000 }, /* R5136 (0x1410) - FRF Coefficient 5R 1 */
+       { 0x00001411, 0x0000 }, /* R5137 (0x1411) - FRF Coefficient 5R 2 */
+       { 0x00001412, 0x0000 }, /* R5138 (0x1412) - FRF Coefficient 5R 3 */
+       { 0x00001413, 0x0000 }, /* R5139 (0x1413) - FRF Coefficient 5R 4 */
+       { 0x00001480, 0x0000 }, /* R5248 (0x1480) - DFC1_CTRL */
+       { 0x00001482, 0x1f00 }, /* R5250 (0x1482) - DFC1_RX */
+       { 0x00001484, 0x1f00 }, /* R5252 (0x1486) - DFC1_TX */
+       { 0x00001486, 0x0000 }, /* R5254 (0x1486) - DFC2_CTRL */
+       { 0x00001488, 0x1f00 }, /* R5256 (0x1488) - DFC2_RX */
+       { 0x0000148a, 0x1f00 }, /* R5258 (0x148a) - DFC2_TX */
+       { 0x0000148c, 0x0000 }, /* R5260 (0x148c) - DFC3_CTRL */
+       { 0x0000148e, 0x1f00 }, /* R5262 (0x148e) - DFC3_RX */
+       { 0x00001490, 0x1f00 }, /* R5264 (0x1490) - DFC3_TX */
+       { 0x00001492, 0x0000 }, /* R5266 (0x1492) - DFC4_CTRL */
+       { 0x00001494, 0x1f00 }, /* R5268 (0x1494) - DFC4_RX */
+       { 0x00001496, 0x1f00 }, /* R5270 (0x1496) - DFC4_TX */
+       { 0x00001498, 0x0000 }, /* R5272 (0x1498) - DFC5_CTRL */
+       { 0x0000149a, 0x1f00 }, /* R5274 (0x149a) - DFC5_RX */
+       { 0x0000149c, 0x1f00 }, /* R5276 (0x149c) - DFC5_TX */
+       { 0x0000149e, 0x0000 }, /* R5278 (0x149e) - DFC6_CTRL */
+       { 0x000014a0, 0x1f00 }, /* R5280 (0x14a0) - DFC6_RX */
+       { 0x000014a2, 0x1f00 }, /* R5282 (0x14a2) - DFC6_TX */
+       { 0x000014a4, 0x0000 }, /* R5284 (0x14a4) - DFC7_CTRL */
+       { 0x000014a6, 0x1f00 }, /* R5286 (0x14a6) - DFC7_RX */
+       { 0x000014a8, 0x1f00 }, /* R5288 (0x14a8) - DFC7_TX */
+       { 0x000014aa, 0x0000 }, /* R5290 (0x14aa) - DFC8_CTRL */
+       { 0x000014ac, 0x1f00 }, /* R5292 (0x14ac) - DFC8_RX */
+       { 0x000014ae, 0x1f00 }, /* R5294 (0x14ae) - DFC8_TX */
+       { 0x00001700, 0x2001 }, /* R5888 (0x1700) - GPIO1 Control 1 */
+       { 0x00001701, 0xf000 }, /* R5889 (0x1701) - GPIO1 Control 2 */
+       { 0x00001702, 0x2001 }, /* R5890 (0x1702) - GPIO2 Control 1 */
+       { 0x00001703, 0xf000 }, /* R5891 (0x1702) - GPIO2 Control 2 */
+       { 0x00001704, 0x2001 }, /* R5892 (0x1704) - GPIO3 Control 1 */
+       { 0x00001705, 0xf000 }, /* R5893 (0x1705) - GPIO3 Control 2 */
+       { 0x00001706, 0x2001 }, /* R5894 (0x1706) - GPIO4 Control 1 */
+       { 0x00001707, 0xf000 }, /* R5895 (0x1707) - GPIO4 Control 2 */
+       { 0x00001708, 0x2001 }, /* R5896 (0x1708) - GPIO5 Control 1 */
+       { 0x00001709, 0xf000 }, /* R5897 (0x1709) - GPIO5 Control 2 */
+       { 0x0000170a, 0x2001 }, /* R5898 (0x170a) - GPIO6 Control 1 */
+       { 0x0000170b, 0xf000 }, /* R5899 (0x170b) - GPIO6 Control 2 */
+       { 0x0000170c, 0x2001 }, /* R5900 (0x170c) - GPIO7 Control 1 */
+       { 0x0000170d, 0xf000 }, /* R5901 (0x170d) - GPIO7 Control 2 */
+       { 0x0000170e, 0x2001 }, /* R5902 (0x170e) - GPIO8 Control 1 */
+       { 0x0000170f, 0xf000 }, /* R5903 (0x170f) - GPIO8 Control 2 */
+       { 0x00001710, 0x2001 }, /* R5904 (0x1710) - GPIO9 Control 1 */
+       { 0x00001711, 0xf000 }, /* R5905 (0x1711) - GPIO9 Control 2 */
+       { 0x00001712, 0x2001 }, /* R5906 (0x1712) - GPIO10 Control 1 */
+       { 0x00001713, 0xf000 }, /* R5907 (0x1713) - GPIO10 Control 2 */
+       { 0x00001714, 0x2001 }, /* R5908 (0x1714) - GPIO11 Control 1 */
+       { 0x00001715, 0xf000 }, /* R5909 (0x1715) - GPIO11 Control 2 */
+       { 0x00001716, 0x2001 }, /* R5910 (0x1716) - GPIO12 Control 1 */
+       { 0x00001717, 0xf000 }, /* R5911 (0x1717) - GPIO12 Control 2 */
+       { 0x00001718, 0x2001 }, /* R5912 (0x1718) - GPIO13 Control 1 */
+       { 0x00001719, 0xf000 }, /* R5913 (0x1719) - GPIO13 Control 2 */
+       { 0x0000171a, 0x2001 }, /* R5914 (0x171a) - GPIO14 Control 1 */
+       { 0x0000171b, 0xf000 }, /* R5915 (0x171b) - GPIO14 Control 2 */
+       { 0x0000171c, 0x2001 }, /* R5916 (0x171c) - GPIO15 Control 1 */
+       { 0x0000171d, 0xf000 }, /* R5917 (0x171d) - GPIO15 Control 2 */
+       { 0x0000171e, 0x2001 }, /* R5918 (0x171e) - GPIO16 Control 1 */
+       { 0x0000171f, 0xf000 }, /* R5919 (0x171f) - GPIO16 Control 2 */
+       { 0x00001720, 0x2001 }, /* R5920 (0x1720) - GPIO17 Control 1 */
+       { 0x00001721, 0xf000 }, /* R5921 (0x1721) - GPIO17 Control 2 */
+       { 0x00001722, 0x2001 }, /* R5922 (0x1722) - GPIO18 Control 1 */
+       { 0x00001723, 0xf000 }, /* R5923 (0x1723) - GPIO18 Control 2 */
+       { 0x00001724, 0x2001 }, /* R5924 (0x1724) - GPIO19 Control 1 */
+       { 0x00001725, 0xf000 }, /* R5925 (0x1725) - GPIO19 Control 2 */
+       { 0x00001726, 0x2001 }, /* R5926 (0x1726) - GPIO20 Control 1 */
+       { 0x00001727, 0xf000 }, /* R5927 (0x1727) - GPIO20 Control 2 */
+       { 0x00001728, 0x2001 }, /* R5928 (0x1728) - GPIO21 Control 1 */
+       { 0x00001729, 0xf000 }, /* R5929 (0x1729) - GPIO21 Control 2 */
+       { 0x0000172a, 0x2001 }, /* R5930 (0x172a) - GPIO22 Control 1 */
+       { 0x0000172b, 0xf000 }, /* R5931 (0x172b) - GPIO22 Control 2 */
+       { 0x0000172c, 0x2001 }, /* R5932 (0x172c) - GPIO23 Control 1 */
+       { 0x0000172d, 0xf000 }, /* R5933 (0x172d) - GPIO23 Control 2 */
+       { 0x0000172e, 0x2001 }, /* R5934 (0x172e) - GPIO24 Control 1 */
+       { 0x0000172f, 0xf000 }, /* R5935 (0x172f) - GPIO24 Control 2 */
+       { 0x00001730, 0x2001 }, /* R5936 (0x1730) - GPIO25 Control 1 */
+       { 0x00001731, 0xf000 }, /* R5937 (0x1731) - GPIO25 Control 2 */
+       { 0x00001732, 0x2001 }, /* R5938 (0x1732) - GPIO26 Control 1 */
+       { 0x00001733, 0xf000 }, /* R5939 (0x1733) - GPIO26 Control 2 */
+       { 0x00001734, 0x2001 }, /* R5940 (0x1734) - GPIO27 Control 1 */
+       { 0x00001735, 0xf000 }, /* R5941 (0x1735) - GPIO27 Control 2 */
+       { 0x00001736, 0x2001 }, /* R5942 (0x1736) - GPIO28 Control 1 */
+       { 0x00001737, 0xf000 }, /* R5943 (0x1737) - GPIO28 Control 2 */
+       { 0x00001738, 0x2001 }, /* R5944 (0x1738) - GPIO29 Control 1 */
+       { 0x00001739, 0xf000 }, /* R5945 (0x1739) - GPIO29 Control 2 */
+       { 0x0000173a, 0x2001 }, /* R5946 (0x173a) - GPIO30 Control 1 */
+       { 0x0000173b, 0xf000 }, /* R5947 (0x173b) - GPIO30 Control 2 */
+       { 0x0000173c, 0x2001 }, /* R5948 (0x173c) - GPIO31 Control 1 */
+       { 0x0000173d, 0xf000 }, /* R5949 (0x173d) - GPIO31 Control 2 */
+       { 0x0000173e, 0x2001 }, /* R5950 (0x173e) - GPIO32 Control 1 */
+       { 0x0000173f, 0xf000 }, /* R5951 (0x173f) - GPIO32 Control 2 */
+       { 0x00001740, 0x2001 }, /* R5952 (0x1740) - GPIO33 Control 1 */
+       { 0x00001741, 0xf000 }, /* R5953 (0x1741) - GPIO33 Control 2 */
+       { 0x00001742, 0x2001 }, /* R5954 (0x1742) - GPIO34 Control 1 */
+       { 0x00001743, 0xf000 }, /* R5955 (0x1743) - GPIO34 Control 2 */
+       { 0x00001744, 0x2001 }, /* R5956 (0x1744) - GPIO35 Control 1 */
+       { 0x00001745, 0xf000 }, /* R5957 (0x1745) - GPIO35 Control 2 */
+       { 0x00001746, 0x2001 }, /* R5958 (0x1746) - GPIO36 Control 1 */
+       { 0x00001747, 0xf000 }, /* R5959 (0x1747) - GPIO36 Control 2 */
+       { 0x00001748, 0x2001 }, /* R5960 (0x1748) - GPIO37 Control 1 */
+       { 0x00001749, 0xf000 }, /* R5961 (0x1749) - GPIO37 Control 2 */
+       { 0x0000174a, 0x2001 }, /* R5962 (0x174a) - GPIO38 Control 1 */
+       { 0x0000174b, 0xf000 }, /* R5963 (0x174b) - GPIO38 Control 2 */
+       { 0x00001840, 0xffff }, /* R6208 (0x1840) - IRQ1 Mask 1 */
+       { 0x00001841, 0xffff }, /* R6209 (0x1841) - IRQ1 Mask 2 */
+       { 0x00001842, 0xffff }, /* R6210 (0x1842) - IRQ1 Mask 3 */
+       { 0x00001843, 0xffff }, /* R6211 (0x1843) - IRQ1 Mask 4 */
+       { 0x00001844, 0xffff }, /* R6212 (0x1844) - IRQ1 Mask 5 */
+       { 0x00001845, 0xffff }, /* R6213 (0x1845) - IRQ1 Mask 6 */
+       { 0x00001846, 0xffff }, /* R6214 (0x1846) - IRQ1 Mask 7 */
+       { 0x00001847, 0xffff }, /* R6215 (0x1847) - IRQ1 Mask 8 */
+       { 0x00001848, 0xffff }, /* R6216 (0x1848) - IRQ1 Mask 9 */
+       { 0x00001849, 0xffff }, /* R6217 (0x1849) - IRQ1 Mask 10 */
+       { 0x0000184a, 0xffff }, /* R6218 (0x184a) - IRQ1 Mask 11 */
+       { 0x0000184b, 0xffff }, /* R6219 (0x184b) - IRQ1 Mask 12 */
+       { 0x0000184c, 0xffff }, /* R6220 (0x184c) - IRQ1 Mask 13 */
+       { 0x0000184d, 0xffff }, /* R6221 (0x184d) - IRQ1 Mask 14 */
+       { 0x0000184e, 0xffff }, /* R6222 (0x184e) - IRQ1 Mask 15 */
+       { 0x0000184f, 0xffff }, /* R6223 (0x184f) - IRQ1 Mask 16 */
+       { 0x00001850, 0xffff }, /* R6224 (0x1850) - IRQ1 Mask 17 */
+       { 0x00001851, 0xffff }, /* R6225 (0x1851) - IRQ1 Mask 18 */
+       { 0x00001852, 0xffff }, /* R6226 (0x1852) - IRQ1 Mask 19 */
+       { 0x00001853, 0xffff }, /* R6227 (0x1853) - IRQ1 Mask 20 */
+       { 0x00001854, 0xffff }, /* R6228 (0x1854) - IRQ1 Mask 21 */
+       { 0x00001855, 0xffff }, /* R6229 (0x1855) - IRQ1 Mask 22 */
+       { 0x00001856, 0xffff }, /* R6230 (0x1856) - IRQ1 Mask 23 */
+       { 0x00001857, 0xffff }, /* R6231 (0x1857) - IRQ1 Mask 24 */
+       { 0x00001858, 0xffff }, /* R6232 (0x1858) - IRQ1 Mask 25 */
+       { 0x00001859, 0xffff }, /* R6233 (0x1859) - IRQ1 Mask 26 */
+       { 0x0000185a, 0xffff }, /* R6234 (0x185a) - IRQ1 Mask 27 */
+       { 0x0000185b, 0xffff }, /* R6235 (0x185b) - IRQ1 Mask 28 */
+       { 0x0000185c, 0xffff }, /* R6236 (0x185c) - IRQ1 Mask 29 */
+       { 0x0000185d, 0xffff }, /* R6237 (0x185d) - IRQ1 Mask 30 */
+       { 0x0000185e, 0xffff }, /* R6238 (0x185e) - IRQ1 Mask 31 */
+       { 0x0000185f, 0xffff }, /* R6239 (0x185f) - IRQ1 Mask 32 */
+       { 0x00001860, 0xffff }, /* R6240 (0x1860) - IRQ1 Mask 33 */
+       { 0x00001a06, 0x0000 }, /* R6662 (0x1a06) - Interrupt Debounce 7 */
+       { 0x00001a80, 0x4400 }, /* R6784 (0x1a80) - IRQ1 CTRL */
+};
+
+static bool cs47l90_is_adsp_memory(unsigned int reg)
+{
+       switch (reg) {
+       case 0x080000 ... 0x088ffe:
+       case 0x0a0000 ... 0x0a9ffe:
+       case 0x0c0000 ... 0x0c3ffe:
+       case 0x0e0000 ... 0x0e1ffe:
+       case 0x100000 ... 0x10effe:
+       case 0x120000 ... 0x12bffe:
+       case 0x136000 ... 0x137ffe:
+       case 0x140000 ... 0x14bffe:
+       case 0x160000 ... 0x161ffe:
+       case 0x180000 ... 0x18effe:
+       case 0x1a0000 ... 0x1b1ffe:
+       case 0x1b6000 ... 0x1b7ffe:
+       case 0x1c0000 ... 0x1cbffe:
+       case 0x1e0000 ... 0x1e1ffe:
+       case 0x200000 ... 0x208ffe:
+       case 0x220000 ... 0x229ffe:
+       case 0x240000 ... 0x243ffe:
+       case 0x260000 ... 0x261ffe:
+       case 0x280000 ... 0x288ffe:
+       case 0x2a0000 ... 0x2a9ffe:
+       case 0x2c0000 ... 0x2c3ffe:
+       case 0x2e0000 ... 0x2e1ffe:
+       case 0x300000 ... 0x308ffe:
+       case 0x320000 ... 0x333ffe:
+       case 0x340000 ... 0x353ffe:
+       case 0x360000 ... 0x361ffe:
+       case 0x380000 ... 0x388ffe:
+       case 0x3a0000 ... 0x3b3ffe:
+       case 0x3c0000 ... 0x3d3ffe:
+       case 0x3e0000 ... 0x3e1ffe:
+               return true;
+       default:
+               return false;
+       }
+}
+
+static bool cs47l90_16bit_readable_register(struct device *dev,
+                                           unsigned int reg)
+{
+       switch (reg) {
+       case MADERA_SOFTWARE_RESET:
+       case MADERA_HARDWARE_REVISION:
+       case MADERA_WRITE_SEQUENCER_CTRL_0:
+       case MADERA_WRITE_SEQUENCER_CTRL_1:
+       case MADERA_WRITE_SEQUENCER_CTRL_2:
+       case MADERA_TONE_GENERATOR_1:
+       case MADERA_TONE_GENERATOR_2:
+       case MADERA_TONE_GENERATOR_3:
+       case MADERA_TONE_GENERATOR_4:
+       case MADERA_TONE_GENERATOR_5:
+       case MADERA_PWM_DRIVE_1:
+       case MADERA_PWM_DRIVE_2:
+       case MADERA_PWM_DRIVE_3:
+       case MADERA_SAMPLE_RATE_SEQUENCE_SELECT_1:
+       case MADERA_SAMPLE_RATE_SEQUENCE_SELECT_2:
+       case MADERA_SAMPLE_RATE_SEQUENCE_SELECT_3:
+       case MADERA_SAMPLE_RATE_SEQUENCE_SELECT_4:
+       case MADERA_ALWAYS_ON_TRIGGERS_SEQUENCE_SELECT_1:
+       case MADERA_ALWAYS_ON_TRIGGERS_SEQUENCE_SELECT_2:
+       case MADERA_HAPTICS_CONTROL_1:
+       case MADERA_HAPTICS_CONTROL_2:
+       case MADERA_HAPTICS_PHASE_1_INTENSITY:
+       case MADERA_HAPTICS_PHASE_1_DURATION:
+       case MADERA_HAPTICS_PHASE_2_INTENSITY:
+       case MADERA_HAPTICS_PHASE_2_DURATION:
+       case MADERA_HAPTICS_PHASE_3_INTENSITY:
+       case MADERA_HAPTICS_PHASE_3_DURATION:
+       case MADERA_HAPTICS_STATUS:
+       case MADERA_COMFORT_NOISE_GENERATOR:
+       case MADERA_CLOCK_32K_1:
+       case MADERA_SYSTEM_CLOCK_1:
+       case MADERA_SAMPLE_RATE_1:
+       case MADERA_SAMPLE_RATE_2:
+       case MADERA_SAMPLE_RATE_3:
+       case MADERA_SAMPLE_RATE_1_STATUS:
+       case MADERA_SAMPLE_RATE_2_STATUS:
+       case MADERA_SAMPLE_RATE_3_STATUS:
+       case MADERA_ASYNC_CLOCK_1:
+       case MADERA_ASYNC_SAMPLE_RATE_1:
+       case MADERA_ASYNC_SAMPLE_RATE_1_STATUS:
+       case MADERA_ASYNC_SAMPLE_RATE_2:
+       case MADERA_ASYNC_SAMPLE_RATE_2_STATUS:
+       case MADERA_DSP_CLOCK_1:
+       case MADERA_DSP_CLOCK_2:
+       case MADERA_OUTPUT_SYSTEM_CLOCK:
+       case MADERA_OUTPUT_ASYNC_CLOCK:
+       case MADERA_RATE_ESTIMATOR_1:
+       case MADERA_RATE_ESTIMATOR_2:
+       case MADERA_RATE_ESTIMATOR_3:
+       case MADERA_RATE_ESTIMATOR_4:
+       case MADERA_RATE_ESTIMATOR_5:
+       case MADERA_FLL1_CONTROL_1:
+       case MADERA_FLL1_CONTROL_2:
+       case MADERA_FLL1_CONTROL_3:
+       case MADERA_FLL1_CONTROL_4:
+       case MADERA_FLL1_CONTROL_5:
+       case MADERA_FLL1_CONTROL_6:
+       case MADERA_FLL1_CONTROL_7:
+       case MADERA_FLL1_EFS_2:
+       case MADERA_FLL1_LOOP_FILTER_TEST_1:
+       case MADERA_FLL1_SYNCHRONISER_1:
+       case MADERA_FLL1_SYNCHRONISER_2:
+       case MADERA_FLL1_SYNCHRONISER_3:
+       case MADERA_FLL1_SYNCHRONISER_4:
+       case MADERA_FLL1_SYNCHRONISER_5:
+       case MADERA_FLL1_SYNCHRONISER_6:
+       case MADERA_FLL1_SYNCHRONISER_7:
+       case MADERA_FLL1_SPREAD_SPECTRUM:
+       case MADERA_FLL1_GPIO_CLOCK:
+       case MADERA_FLL2_CONTROL_1:
+       case MADERA_FLL2_CONTROL_2:
+       case MADERA_FLL2_CONTROL_3:
+       case MADERA_FLL2_CONTROL_4:
+       case MADERA_FLL2_CONTROL_5:
+       case MADERA_FLL2_CONTROL_6:
+       case MADERA_FLL2_CONTROL_7:
+       case MADERA_FLL2_EFS_2:
+       case MADERA_FLL2_LOOP_FILTER_TEST_1:
+       case MADERA_FLL2_SYNCHRONISER_1:
+       case MADERA_FLL2_SYNCHRONISER_2:
+       case MADERA_FLL2_SYNCHRONISER_3:
+       case MADERA_FLL2_SYNCHRONISER_4:
+       case MADERA_FLL2_SYNCHRONISER_5:
+       case MADERA_FLL2_SYNCHRONISER_6:
+       case MADERA_FLL2_SYNCHRONISER_7:
+       case MADERA_FLL2_SPREAD_SPECTRUM:
+       case MADERA_FLL2_GPIO_CLOCK:
+       case MADERA_FLLAO_CONTROL_1:
+       case MADERA_FLLAO_CONTROL_2:
+       case MADERA_FLLAO_CONTROL_3:
+       case MADERA_FLLAO_CONTROL_4:
+       case MADERA_FLLAO_CONTROL_5:
+       case MADERA_FLLAO_CONTROL_6:
+       case MADERA_FLLAO_CONTROL_7:
+       case MADERA_FLLAO_CONTROL_8:
+       case MADERA_FLLAO_CONTROL_9:
+       case MADERA_FLLAO_CONTROL_10:
+       case MADERA_FLLAO_CONTROL_11:
+       case MADERA_MIC_CHARGE_PUMP_1:
+       case MADERA_LDO2_CONTROL_1:
+       case MADERA_MIC_BIAS_CTRL_1:
+       case MADERA_MIC_BIAS_CTRL_2:
+       case MADERA_MIC_BIAS_CTRL_5:
+       case MADERA_MIC_BIAS_CTRL_6:
+       case MADERA_HP_CTRL_1L:
+       case MADERA_HP_CTRL_1R:
+       case MADERA_HP_CTRL_2L:
+       case MADERA_HP_CTRL_2R:
+       case MADERA_HP_CTRL_3L:
+       case MADERA_HP_CTRL_3R:
+       case MADERA_EDRE_HP_STEREO_CONTROL:
+       case MADERA_ACCESSORY_DETECT_MODE_1:
+       case MADERA_HEADPHONE_DETECT_0:
+       case MADERA_HEADPHONE_DETECT_1:
+       case MADERA_HEADPHONE_DETECT_2:
+       case MADERA_HEADPHONE_DETECT_3:
+       case MADERA_HEADPHONE_DETECT_5:
+       case MADERA_MICD_CLAMP_CONTROL:
+       case MADERA_MIC_DETECT_1_CONTROL_0:
+       case MADERA_MIC_DETECT_1_CONTROL_1:
+       case MADERA_MIC_DETECT_1_CONTROL_2:
+       case MADERA_MIC_DETECT_1_CONTROL_3:
+       case MADERA_MIC_DETECT_1_LEVEL_1:
+       case MADERA_MIC_DETECT_1_LEVEL_2:
+       case MADERA_MIC_DETECT_1_LEVEL_3:
+       case MADERA_MIC_DETECT_1_LEVEL_4:
+       case MADERA_MIC_DETECT_1_CONTROL_4:
+       case MADERA_MIC_DETECT_2_CONTROL_0:
+       case MADERA_MIC_DETECT_2_CONTROL_1:
+       case MADERA_MIC_DETECT_2_CONTROL_2:
+       case MADERA_MIC_DETECT_2_CONTROL_3:
+       case MADERA_MIC_DETECT_2_LEVEL_1:
+       case MADERA_MIC_DETECT_2_LEVEL_2:
+       case MADERA_MIC_DETECT_2_LEVEL_3:
+       case MADERA_MIC_DETECT_2_LEVEL_4:
+       case MADERA_MIC_DETECT_2_CONTROL_4:
+       case MADERA_GP_SWITCH_1:
+       case MADERA_JACK_DETECT_ANALOGUE:
+       case MADERA_INPUT_ENABLES:
+       case MADERA_INPUT_ENABLES_STATUS:
+       case MADERA_INPUT_RATE:
+       case MADERA_INPUT_VOLUME_RAMP:
+       case MADERA_HPF_CONTROL:
+       case MADERA_IN1L_CONTROL:
+       case MADERA_ADC_DIGITAL_VOLUME_1L:
+       case MADERA_DMIC1L_CONTROL:
+       case MADERA_IN1L_RATE_CONTROL:
+       case MADERA_IN1R_CONTROL:
+       case MADERA_ADC_DIGITAL_VOLUME_1R:
+       case MADERA_DMIC1R_CONTROL:
+       case MADERA_IN1R_RATE_CONTROL:
+       case MADERA_IN2L_CONTROL:
+       case MADERA_ADC_DIGITAL_VOLUME_2L:
+       case MADERA_DMIC2L_CONTROL:
+       case MADERA_IN2L_RATE_CONTROL:
+       case MADERA_IN2R_CONTROL:
+       case MADERA_ADC_DIGITAL_VOLUME_2R:
+       case MADERA_DMIC2R_CONTROL:
+       case MADERA_IN2R_RATE_CONTROL:
+       case MADERA_IN3L_CONTROL:
+       case MADERA_ADC_DIGITAL_VOLUME_3L:
+       case MADERA_DMIC3L_CONTROL:
+       case MADERA_IN3L_RATE_CONTROL:
+       case MADERA_IN3R_CONTROL:
+       case MADERA_ADC_DIGITAL_VOLUME_3R:
+       case MADERA_DMIC3R_CONTROL:
+       case MADERA_IN3R_RATE_CONTROL:
+       case MADERA_IN4L_CONTROL:
+       case MADERA_ADC_DIGITAL_VOLUME_4L:
+       case MADERA_DMIC4L_CONTROL:
+       case MADERA_IN4L_RATE_CONTROL:
+       case MADERA_IN4R_CONTROL:
+       case MADERA_ADC_DIGITAL_VOLUME_4R:
+       case MADERA_DMIC4R_CONTROL:
+       case MADERA_IN4R_RATE_CONTROL:
+       case MADERA_IN5L_CONTROL:
+       case MADERA_ADC_DIGITAL_VOLUME_5L:
+       case MADERA_DMIC5L_CONTROL:
+       case MADERA_IN5L_RATE_CONTROL:
+       case MADERA_IN5R_CONTROL:
+       case MADERA_ADC_DIGITAL_VOLUME_5R:
+       case MADERA_DMIC5R_CONTROL:
+       case MADERA_IN5R_RATE_CONTROL:
+       case MADERA_OUTPUT_ENABLES_1:
+       case MADERA_OUTPUT_STATUS_1:
+       case MADERA_RAW_OUTPUT_STATUS_1:
+       case MADERA_OUTPUT_RATE_1:
+       case MADERA_OUTPUT_VOLUME_RAMP:
+       case MADERA_OUTPUT_PATH_CONFIG_1L:
+       case MADERA_DAC_DIGITAL_VOLUME_1L:
+       case MADERA_OUTPUT_PATH_CONFIG_1:
+       case MADERA_NOISE_GATE_SELECT_1L:
+       case MADERA_OUTPUT_PATH_CONFIG_1R:
+       case MADERA_DAC_DIGITAL_VOLUME_1R:
+       case MADERA_NOISE_GATE_SELECT_1R:
+       case MADERA_OUTPUT_PATH_CONFIG_2L:
+       case MADERA_DAC_DIGITAL_VOLUME_2L:
+       case MADERA_OUTPUT_PATH_CONFIG_2:
+       case MADERA_NOISE_GATE_SELECT_2L:
+       case MADERA_OUTPUT_PATH_CONFIG_2R:
+       case MADERA_DAC_DIGITAL_VOLUME_2R:
+       case MADERA_NOISE_GATE_SELECT_2R:
+       case MADERA_OUTPUT_PATH_CONFIG_3L:
+       case MADERA_DAC_DIGITAL_VOLUME_3L:
+       case MADERA_NOISE_GATE_SELECT_3L:
+       case MADERA_OUTPUT_PATH_CONFIG_3R:
+       case MADERA_DAC_DIGITAL_VOLUME_3R:
+       case MADERA_NOISE_GATE_SELECT_3R:
+       case MADERA_OUTPUT_PATH_CONFIG_5L:
+       case MADERA_DAC_DIGITAL_VOLUME_5L:
+       case MADERA_NOISE_GATE_SELECT_5L:
+       case MADERA_OUTPUT_PATH_CONFIG_5R:
+       case MADERA_DAC_DIGITAL_VOLUME_5R:
+       case MADERA_NOISE_GATE_SELECT_5R:
+       case MADERA_DRE_ENABLE:
+       case MADERA_EDRE_ENABLE:
+       case MADERA_DAC_AEC_CONTROL_1:
+       case MADERA_NOISE_GATE_CONTROL:
+       case MADERA_PDM_SPK1_CTRL_1:
+       case MADERA_PDM_SPK1_CTRL_2:
+       case MADERA_HP1_SHORT_CIRCUIT_CTRL:
+       case MADERA_HP2_SHORT_CIRCUIT_CTRL:
+       case MADERA_HP3_SHORT_CIRCUIT_CTRL:
+       case MADERA_AIF1_BCLK_CTRL:
+       case MADERA_AIF1_TX_PIN_CTRL:
+       case MADERA_AIF1_RX_PIN_CTRL:
+       case MADERA_AIF1_RATE_CTRL:
+       case MADERA_AIF1_FORMAT:
+       case MADERA_AIF1_RX_BCLK_RATE:
+       case MADERA_AIF1_FRAME_CTRL_1:
+       case MADERA_AIF1_FRAME_CTRL_2:
+       case MADERA_AIF1_FRAME_CTRL_3:
+       case MADERA_AIF1_FRAME_CTRL_4:
+       case MADERA_AIF1_FRAME_CTRL_5:
+       case MADERA_AIF1_FRAME_CTRL_6:
+       case MADERA_AIF1_FRAME_CTRL_7:
+       case MADERA_AIF1_FRAME_CTRL_8:
+       case MADERA_AIF1_FRAME_CTRL_9:
+       case MADERA_AIF1_FRAME_CTRL_10:
+       case MADERA_AIF1_FRAME_CTRL_11:
+       case MADERA_AIF1_FRAME_CTRL_12:
+       case MADERA_AIF1_FRAME_CTRL_13:
+       case MADERA_AIF1_FRAME_CTRL_14:
+       case MADERA_AIF1_FRAME_CTRL_15:
+       case MADERA_AIF1_FRAME_CTRL_16:
+       case MADERA_AIF1_FRAME_CTRL_17:
+       case MADERA_AIF1_FRAME_CTRL_18:
+       case MADERA_AIF1_TX_ENABLES:
+       case MADERA_AIF1_RX_ENABLES:
+       case MADERA_AIF2_BCLK_CTRL:
+       case MADERA_AIF2_TX_PIN_CTRL:
+       case MADERA_AIF2_RX_PIN_CTRL:
+       case MADERA_AIF2_RATE_CTRL:
+       case MADERA_AIF2_FORMAT:
+       case MADERA_AIF2_RX_BCLK_RATE:
+       case MADERA_AIF2_FRAME_CTRL_1:
+       case MADERA_AIF2_FRAME_CTRL_2:
+       case MADERA_AIF2_FRAME_CTRL_3:
+       case MADERA_AIF2_FRAME_CTRL_4:
+       case MADERA_AIF2_FRAME_CTRL_5:
+       case MADERA_AIF2_FRAME_CTRL_6:
+       case MADERA_AIF2_FRAME_CTRL_7:
+       case MADERA_AIF2_FRAME_CTRL_8:
+       case MADERA_AIF2_FRAME_CTRL_9:
+       case MADERA_AIF2_FRAME_CTRL_10:
+       case MADERA_AIF2_FRAME_CTRL_11:
+       case MADERA_AIF2_FRAME_CTRL_12:
+       case MADERA_AIF2_FRAME_CTRL_13:
+       case MADERA_AIF2_FRAME_CTRL_14:
+       case MADERA_AIF2_FRAME_CTRL_15:
+       case MADERA_AIF2_FRAME_CTRL_16:
+       case MADERA_AIF2_FRAME_CTRL_17:
+       case MADERA_AIF2_FRAME_CTRL_18:
+       case MADERA_AIF2_TX_ENABLES:
+       case MADERA_AIF2_RX_ENABLES:
+       case MADERA_AIF3_BCLK_CTRL:
+       case MADERA_AIF3_TX_PIN_CTRL:
+       case MADERA_AIF3_RX_PIN_CTRL:
+       case MADERA_AIF3_RATE_CTRL:
+       case MADERA_AIF3_FORMAT:
+       case MADERA_AIF3_RX_BCLK_RATE:
+       case MADERA_AIF3_FRAME_CTRL_1:
+       case MADERA_AIF3_FRAME_CTRL_2:
+       case MADERA_AIF3_FRAME_CTRL_3:
+       case MADERA_AIF3_FRAME_CTRL_4:
+       case MADERA_AIF3_FRAME_CTRL_11:
+       case MADERA_AIF3_FRAME_CTRL_12:
+       case MADERA_AIF3_TX_ENABLES:
+       case MADERA_AIF3_RX_ENABLES:
+       case MADERA_AIF4_BCLK_CTRL:
+       case MADERA_AIF4_TX_PIN_CTRL:
+       case MADERA_AIF4_RX_PIN_CTRL:
+       case MADERA_AIF4_RATE_CTRL:
+       case MADERA_AIF4_FORMAT:
+       case MADERA_AIF4_RX_BCLK_RATE:
+       case MADERA_AIF4_FRAME_CTRL_1:
+       case MADERA_AIF4_FRAME_CTRL_2:
+       case MADERA_AIF4_FRAME_CTRL_3:
+       case MADERA_AIF4_FRAME_CTRL_4:
+       case MADERA_AIF4_FRAME_CTRL_11:
+       case MADERA_AIF4_FRAME_CTRL_12:
+       case MADERA_AIF4_TX_ENABLES:
+       case MADERA_AIF4_RX_ENABLES:
+       case MADERA_SPD1_TX_CONTROL:
+       case MADERA_SPD1_TX_CHANNEL_STATUS_1:
+       case MADERA_SPD1_TX_CHANNEL_STATUS_2:
+       case MADERA_SPD1_TX_CHANNEL_STATUS_3:
+       case MADERA_SLIMBUS_FRAMER_REF_GEAR:
+       case MADERA_SLIMBUS_RATES_1:
+       case MADERA_SLIMBUS_RATES_2:
+       case MADERA_SLIMBUS_RATES_3:
+       case MADERA_SLIMBUS_RATES_4:
+       case MADERA_SLIMBUS_RATES_5:
+       case MADERA_SLIMBUS_RATES_6:
+       case MADERA_SLIMBUS_RATES_7:
+       case MADERA_SLIMBUS_RATES_8:
+       case MADERA_SLIMBUS_RX_CHANNEL_ENABLE:
+       case MADERA_SLIMBUS_TX_CHANNEL_ENABLE:
+       case MADERA_SLIMBUS_RX_PORT_STATUS:
+       case MADERA_SLIMBUS_TX_PORT_STATUS:
+       case MADERA_PWM1MIX_INPUT_1_SOURCE:
+       case MADERA_PWM1MIX_INPUT_1_VOLUME:
+       case MADERA_PWM1MIX_INPUT_2_SOURCE:
+       case MADERA_PWM1MIX_INPUT_2_VOLUME:
+       case MADERA_PWM1MIX_INPUT_3_SOURCE:
+       case MADERA_PWM1MIX_INPUT_3_VOLUME:
+       case MADERA_PWM1MIX_INPUT_4_SOURCE:
+       case MADERA_PWM1MIX_INPUT_4_VOLUME:
+       case MADERA_PWM2MIX_INPUT_1_SOURCE:
+       case MADERA_PWM2MIX_INPUT_1_VOLUME:
+       case MADERA_PWM2MIX_INPUT_2_SOURCE:
+       case MADERA_PWM2MIX_INPUT_2_VOLUME:
+       case MADERA_PWM2MIX_INPUT_3_SOURCE:
+       case MADERA_PWM2MIX_INPUT_3_VOLUME:
+       case MADERA_PWM2MIX_INPUT_4_SOURCE:
+       case MADERA_PWM2MIX_INPUT_4_VOLUME:
+       case MADERA_OUT1LMIX_INPUT_1_SOURCE:
+       case MADERA_OUT1LMIX_INPUT_1_VOLUME:
+       case MADERA_OUT1LMIX_INPUT_2_SOURCE:
+       case MADERA_OUT1LMIX_INPUT_2_VOLUME:
+       case MADERA_OUT1LMIX_INPUT_3_SOURCE:
+       case MADERA_OUT1LMIX_INPUT_3_VOLUME:
+       case MADERA_OUT1LMIX_INPUT_4_SOURCE:
+       case MADERA_OUT1LMIX_INPUT_4_VOLUME:
+       case MADERA_OUT1RMIX_INPUT_1_SOURCE:
+       case MADERA_OUT1RMIX_INPUT_1_VOLUME:
+       case MADERA_OUT1RMIX_INPUT_2_SOURCE:
+       case MADERA_OUT1RMIX_INPUT_2_VOLUME:
+       case MADERA_OUT1RMIX_INPUT_3_SOURCE:
+       case MADERA_OUT1RMIX_INPUT_3_VOLUME:
+       case MADERA_OUT1RMIX_INPUT_4_SOURCE:
+       case MADERA_OUT1RMIX_INPUT_4_VOLUME:
+       case MADERA_OUT2LMIX_INPUT_1_SOURCE:
+       case MADERA_OUT2LMIX_INPUT_1_VOLUME:
+       case MADERA_OUT2LMIX_INPUT_2_SOURCE:
+       case MADERA_OUT2LMIX_INPUT_2_VOLUME:
+       case MADERA_OUT2LMIX_INPUT_3_SOURCE:
+       case MADERA_OUT2LMIX_INPUT_3_VOLUME:
+       case MADERA_OUT2LMIX_INPUT_4_SOURCE:
+       case MADERA_OUT2LMIX_INPUT_4_VOLUME:
+       case MADERA_OUT2RMIX_INPUT_1_SOURCE:
+       case MADERA_OUT2RMIX_INPUT_1_VOLUME:
+       case MADERA_OUT2RMIX_INPUT_2_SOURCE:
+       case MADERA_OUT2RMIX_INPUT_2_VOLUME:
+       case MADERA_OUT2RMIX_INPUT_3_SOURCE:
+       case MADERA_OUT2RMIX_INPUT_3_VOLUME:
+       case MADERA_OUT2RMIX_INPUT_4_SOURCE:
+       case MADERA_OUT2RMIX_INPUT_4_VOLUME:
+       case MADERA_OUT3LMIX_INPUT_1_SOURCE:
+       case MADERA_OUT3LMIX_INPUT_1_VOLUME:
+       case MADERA_OUT3LMIX_INPUT_2_SOURCE:
+       case MADERA_OUT3LMIX_INPUT_2_VOLUME:
+       case MADERA_OUT3LMIX_INPUT_3_SOURCE:
+       case MADERA_OUT3LMIX_INPUT_3_VOLUME:
+       case MADERA_OUT3LMIX_INPUT_4_SOURCE:
+       case MADERA_OUT3LMIX_INPUT_4_VOLUME:
+       case MADERA_OUT3RMIX_INPUT_1_SOURCE:
+       case MADERA_OUT3RMIX_INPUT_1_VOLUME:
+       case MADERA_OUT3RMIX_INPUT_2_SOURCE:
+       case MADERA_OUT3RMIX_INPUT_2_VOLUME:
+       case MADERA_OUT3RMIX_INPUT_3_SOURCE:
+       case MADERA_OUT3RMIX_INPUT_3_VOLUME:
+       case MADERA_OUT3RMIX_INPUT_4_SOURCE:
+       case MADERA_OUT3RMIX_INPUT_4_VOLUME:
+       case MADERA_OUT5LMIX_INPUT_1_SOURCE:
+       case MADERA_OUT5LMIX_INPUT_1_VOLUME:
+       case MADERA_OUT5LMIX_INPUT_2_SOURCE:
+       case MADERA_OUT5LMIX_INPUT_2_VOLUME:
+       case MADERA_OUT5LMIX_INPUT_3_SOURCE:
+       case MADERA_OUT5LMIX_INPUT_3_VOLUME:
+       case MADERA_OUT5LMIX_INPUT_4_SOURCE:
+       case MADERA_OUT5LMIX_INPUT_4_VOLUME:
+       case MADERA_OUT5RMIX_INPUT_1_SOURCE:
+       case MADERA_OUT5RMIX_INPUT_1_VOLUME:
+       case MADERA_OUT5RMIX_INPUT_2_SOURCE:
+       case MADERA_OUT5RMIX_INPUT_2_VOLUME:
+       case MADERA_OUT5RMIX_INPUT_3_SOURCE:
+       case MADERA_OUT5RMIX_INPUT_3_VOLUME:
+       case MADERA_OUT5RMIX_INPUT_4_SOURCE:
+       case MADERA_OUT5RMIX_INPUT_4_VOLUME:
+       case MADERA_AIF1TX1MIX_INPUT_1_SOURCE:
+       case MADERA_AIF1TX1MIX_INPUT_1_VOLUME:
+       case MADERA_AIF1TX1MIX_INPUT_2_SOURCE:
+       case MADERA_AIF1TX1MIX_INPUT_2_VOLUME:
+       case MADERA_AIF1TX1MIX_INPUT_3_SOURCE:
+       case MADERA_AIF1TX1MIX_INPUT_3_VOLUME:
+       case MADERA_AIF1TX1MIX_INPUT_4_SOURCE:
+       case MADERA_AIF1TX1MIX_INPUT_4_VOLUME:
+       case MADERA_AIF1TX2MIX_INPUT_1_SOURCE:
+       case MADERA_AIF1TX2MIX_INPUT_1_VOLUME:
+       case MADERA_AIF1TX2MIX_INPUT_2_SOURCE:
+       case MADERA_AIF1TX2MIX_INPUT_2_VOLUME:
+       case MADERA_AIF1TX2MIX_INPUT_3_SOURCE:
+       case MADERA_AIF1TX2MIX_INPUT_3_VOLUME:
+       case MADERA_AIF1TX2MIX_INPUT_4_SOURCE:
+       case MADERA_AIF1TX2MIX_INPUT_4_VOLUME:
+       case MADERA_AIF1TX3MIX_INPUT_1_SOURCE:
+       case MADERA_AIF1TX3MIX_INPUT_1_VOLUME:
+       case MADERA_AIF1TX3MIX_INPUT_2_SOURCE:
+       case MADERA_AIF1TX3MIX_INPUT_2_VOLUME:
+       case MADERA_AIF1TX3MIX_INPUT_3_SOURCE:
+       case MADERA_AIF1TX3MIX_INPUT_3_VOLUME:
+       case MADERA_AIF1TX3MIX_INPUT_4_SOURCE:
+       case MADERA_AIF1TX3MIX_INPUT_4_VOLUME:
+       case MADERA_AIF1TX4MIX_INPUT_1_SOURCE:
+       case MADERA_AIF1TX4MIX_INPUT_1_VOLUME:
+       case MADERA_AIF1TX4MIX_INPUT_2_SOURCE:
+       case MADERA_AIF1TX4MIX_INPUT_2_VOLUME:
+       case MADERA_AIF1TX4MIX_INPUT_3_SOURCE:
+       case MADERA_AIF1TX4MIX_INPUT_3_VOLUME:
+       case MADERA_AIF1TX4MIX_INPUT_4_SOURCE:
+       case MADERA_AIF1TX4MIX_INPUT_4_VOLUME:
+       case MADERA_AIF1TX5MIX_INPUT_1_SOURCE:
+       case MADERA_AIF1TX5MIX_INPUT_1_VOLUME:
+       case MADERA_AIF1TX5MIX_INPUT_2_SOURCE:
+       case MADERA_AIF1TX5MIX_INPUT_2_VOLUME:
+       case MADERA_AIF1TX5MIX_INPUT_3_SOURCE:
+       case MADERA_AIF1TX5MIX_INPUT_3_VOLUME:
+       case MADERA_AIF1TX5MIX_INPUT_4_SOURCE:
+       case MADERA_AIF1TX5MIX_INPUT_4_VOLUME:
+       case MADERA_AIF1TX6MIX_INPUT_1_SOURCE:
+       case MADERA_AIF1TX6MIX_INPUT_1_VOLUME:
+       case MADERA_AIF1TX6MIX_INPUT_2_SOURCE:
+       case MADERA_AIF1TX6MIX_INPUT_2_VOLUME:
+       case MADERA_AIF1TX6MIX_INPUT_3_SOURCE:
+       case MADERA_AIF1TX6MIX_INPUT_3_VOLUME:
+       case MADERA_AIF1TX6MIX_INPUT_4_SOURCE:
+       case MADERA_AIF1TX6MIX_INPUT_4_VOLUME:
+       case MADERA_AIF1TX7MIX_INPUT_1_SOURCE:
+       case MADERA_AIF1TX7MIX_INPUT_1_VOLUME:
+       case MADERA_AIF1TX7MIX_INPUT_2_SOURCE:
+       case MADERA_AIF1TX7MIX_INPUT_2_VOLUME:
+       case MADERA_AIF1TX7MIX_INPUT_3_SOURCE:
+       case MADERA_AIF1TX7MIX_INPUT_3_VOLUME:
+       case MADERA_AIF1TX7MIX_INPUT_4_SOURCE:
+       case MADERA_AIF1TX7MIX_INPUT_4_VOLUME:
+       case MADERA_AIF1TX8MIX_INPUT_1_SOURCE:
+       case MADERA_AIF1TX8MIX_INPUT_1_VOLUME:
+       case MADERA_AIF1TX8MIX_INPUT_2_SOURCE:
+       case MADERA_AIF1TX8MIX_INPUT_2_VOLUME:
+       case MADERA_AIF1TX8MIX_INPUT_3_SOURCE:
+       case MADERA_AIF1TX8MIX_INPUT_3_VOLUME:
+       case MADERA_AIF1TX8MIX_INPUT_4_SOURCE:
+       case MADERA_AIF1TX8MIX_INPUT_4_VOLUME:
+       case MADERA_AIF2TX1MIX_INPUT_1_SOURCE:
+       case MADERA_AIF2TX1MIX_INPUT_1_VOLUME:
+       case MADERA_AIF2TX1MIX_INPUT_2_SOURCE:
+       case MADERA_AIF2TX1MIX_INPUT_2_VOLUME:
+       case MADERA_AIF2TX1MIX_INPUT_3_SOURCE:
+       case MADERA_AIF2TX1MIX_INPUT_3_VOLUME:
+       case MADERA_AIF2TX1MIX_INPUT_4_SOURCE:
+       case MADERA_AIF2TX1MIX_INPUT_4_VOLUME:
+       case MADERA_AIF2TX2MIX_INPUT_1_SOURCE:
+       case MADERA_AIF2TX2MIX_INPUT_1_VOLUME:
+       case MADERA_AIF2TX2MIX_INPUT_2_SOURCE:
+       case MADERA_AIF2TX2MIX_INPUT_2_VOLUME:
+       case MADERA_AIF2TX2MIX_INPUT_3_SOURCE:
+       case MADERA_AIF2TX2MIX_INPUT_3_VOLUME:
+       case MADERA_AIF2TX2MIX_INPUT_4_SOURCE:
+       case MADERA_AIF2TX2MIX_INPUT_4_VOLUME:
+       case MADERA_AIF2TX3MIX_INPUT_1_SOURCE:
+       case MADERA_AIF2TX3MIX_INPUT_1_VOLUME:
+       case MADERA_AIF2TX3MIX_INPUT_2_SOURCE:
+       case MADERA_AIF2TX3MIX_INPUT_2_VOLUME:
+       case MADERA_AIF2TX3MIX_INPUT_3_SOURCE:
+       case MADERA_AIF2TX3MIX_INPUT_3_VOLUME:
+       case MADERA_AIF2TX3MIX_INPUT_4_SOURCE:
+       case MADERA_AIF2TX3MIX_INPUT_4_VOLUME:
+       case MADERA_AIF2TX4MIX_INPUT_1_SOURCE:
+       case MADERA_AIF2TX4MIX_INPUT_1_VOLUME:
+       case MADERA_AIF2TX4MIX_INPUT_2_SOURCE:
+       case MADERA_AIF2TX4MIX_INPUT_2_VOLUME:
+       case MADERA_AIF2TX4MIX_INPUT_3_SOURCE:
+       case MADERA_AIF2TX4MIX_INPUT_3_VOLUME:
+       case MADERA_AIF2TX4MIX_INPUT_4_SOURCE:
+       case MADERA_AIF2TX4MIX_INPUT_4_VOLUME:
+       case MADERA_AIF2TX5MIX_INPUT_1_SOURCE:
+       case MADERA_AIF2TX5MIX_INPUT_1_VOLUME:
+       case MADERA_AIF2TX5MIX_INPUT_2_SOURCE:
+       case MADERA_AIF2TX5MIX_INPUT_2_VOLUME:
+       case MADERA_AIF2TX5MIX_INPUT_3_SOURCE:
+       case MADERA_AIF2TX5MIX_INPUT_3_VOLUME:
+       case MADERA_AIF2TX5MIX_INPUT_4_SOURCE:
+       case MADERA_AIF2TX5MIX_INPUT_4_VOLUME:
+       case MADERA_AIF2TX6MIX_INPUT_1_SOURCE:
+       case MADERA_AIF2TX6MIX_INPUT_1_VOLUME:
+       case MADERA_AIF2TX6MIX_INPUT_2_SOURCE:
+       case MADERA_AIF2TX6MIX_INPUT_2_VOLUME:
+       case MADERA_AIF2TX6MIX_INPUT_3_SOURCE:
+       case MADERA_AIF2TX6MIX_INPUT_3_VOLUME:
+       case MADERA_AIF2TX6MIX_INPUT_4_SOURCE:
+       case MADERA_AIF2TX6MIX_INPUT_4_VOLUME:
+       case MADERA_AIF2TX7MIX_INPUT_1_SOURCE:
+       case MADERA_AIF2TX7MIX_INPUT_1_VOLUME:
+       case MADERA_AIF2TX7MIX_INPUT_2_SOURCE:
+       case MADERA_AIF2TX7MIX_INPUT_2_VOLUME:
+       case MADERA_AIF2TX7MIX_INPUT_3_SOURCE:
+       case MADERA_AIF2TX7MIX_INPUT_3_VOLUME:
+       case MADERA_AIF2TX7MIX_INPUT_4_SOURCE:
+       case MADERA_AIF2TX7MIX_INPUT_4_VOLUME:
+       case MADERA_AIF2TX8MIX_INPUT_1_SOURCE:
+       case MADERA_AIF2TX8MIX_INPUT_1_VOLUME:
+       case MADERA_AIF2TX8MIX_INPUT_2_SOURCE:
+       case MADERA_AIF2TX8MIX_INPUT_2_VOLUME:
+       case MADERA_AIF2TX8MIX_INPUT_3_SOURCE:
+       case MADERA_AIF2TX8MIX_INPUT_3_VOLUME:
+       case MADERA_AIF2TX8MIX_INPUT_4_SOURCE:
+       case MADERA_AIF2TX8MIX_INPUT_4_VOLUME:
+       case MADERA_AIF3TX1MIX_INPUT_1_SOURCE:
+       case MADERA_AIF3TX1MIX_INPUT_1_VOLUME:
+       case MADERA_AIF3TX1MIX_INPUT_2_SOURCE:
+       case MADERA_AIF3TX1MIX_INPUT_2_VOLUME:
+       case MADERA_AIF3TX1MIX_INPUT_3_SOURCE:
+       case MADERA_AIF3TX1MIX_INPUT_3_VOLUME:
+       case MADERA_AIF3TX1MIX_INPUT_4_SOURCE:
+       case MADERA_AIF3TX1MIX_INPUT_4_VOLUME:
+       case MADERA_AIF3TX2MIX_INPUT_1_SOURCE:
+       case MADERA_AIF3TX2MIX_INPUT_1_VOLUME:
+       case MADERA_AIF3TX2MIX_INPUT_2_SOURCE:
+       case MADERA_AIF3TX2MIX_INPUT_2_VOLUME:
+       case MADERA_AIF3TX2MIX_INPUT_3_SOURCE:
+       case MADERA_AIF3TX2MIX_INPUT_3_VOLUME:
+       case MADERA_AIF3TX2MIX_INPUT_4_SOURCE:
+       case MADERA_AIF3TX2MIX_INPUT_4_VOLUME:
+       case MADERA_AIF4TX1MIX_INPUT_1_SOURCE:
+       case MADERA_AIF4TX1MIX_INPUT_1_VOLUME:
+       case MADERA_AIF4TX1MIX_INPUT_2_SOURCE:
+       case MADERA_AIF4TX1MIX_INPUT_2_VOLUME:
+       case MADERA_AIF4TX1MIX_INPUT_3_SOURCE:
+       case MADERA_AIF4TX1MIX_INPUT_3_VOLUME:
+       case MADERA_AIF4TX1MIX_INPUT_4_SOURCE:
+       case MADERA_AIF4TX1MIX_INPUT_4_VOLUME:
+       case MADERA_AIF4TX2MIX_INPUT_1_SOURCE:
+       case MADERA_AIF4TX2MIX_INPUT_1_VOLUME:
+       case MADERA_AIF4TX2MIX_INPUT_2_SOURCE:
+       case MADERA_AIF4TX2MIX_INPUT_2_VOLUME:
+       case MADERA_AIF4TX2MIX_INPUT_3_SOURCE:
+       case MADERA_AIF4TX2MIX_INPUT_3_VOLUME:
+       case MADERA_AIF4TX2MIX_INPUT_4_SOURCE:
+       case MADERA_AIF4TX2MIX_INPUT_4_VOLUME:
+       case MADERA_SLIMTX1MIX_INPUT_1_SOURCE:
+       case MADERA_SLIMTX1MIX_INPUT_1_VOLUME:
+       case MADERA_SLIMTX1MIX_INPUT_2_SOURCE:
+       case MADERA_SLIMTX1MIX_INPUT_2_VOLUME:
+       case MADERA_SLIMTX1MIX_INPUT_3_SOURCE:
+       case MADERA_SLIMTX1MIX_INPUT_3_VOLUME:
+       case MADERA_SLIMTX1MIX_INPUT_4_SOURCE:
+       case MADERA_SLIMTX1MIX_INPUT_4_VOLUME:
+       case MADERA_SLIMTX2MIX_INPUT_1_SOURCE:
+       case MADERA_SLIMTX2MIX_INPUT_1_VOLUME:
+       case MADERA_SLIMTX2MIX_INPUT_2_SOURCE:
+       case MADERA_SLIMTX2MIX_INPUT_2_VOLUME:
+       case MADERA_SLIMTX2MIX_INPUT_3_SOURCE:
+       case MADERA_SLIMTX2MIX_INPUT_3_VOLUME:
+       case MADERA_SLIMTX2MIX_INPUT_4_SOURCE:
+       case MADERA_SLIMTX2MIX_INPUT_4_VOLUME:
+       case MADERA_SLIMTX3MIX_INPUT_1_SOURCE:
+       case MADERA_SLIMTX3MIX_INPUT_1_VOLUME:
+       case MADERA_SLIMTX3MIX_INPUT_2_SOURCE:
+       case MADERA_SLIMTX3MIX_INPUT_2_VOLUME:
+       case MADERA_SLIMTX3MIX_INPUT_3_SOURCE:
+       case MADERA_SLIMTX3MIX_INPUT_3_VOLUME:
+       case MADERA_SLIMTX3MIX_INPUT_4_SOURCE:
+       case MADERA_SLIMTX3MIX_INPUT_4_VOLUME:
+       case MADERA_SLIMTX4MIX_INPUT_1_SOURCE:
+       case MADERA_SLIMTX4MIX_INPUT_1_VOLUME:
+       case MADERA_SLIMTX4MIX_INPUT_2_SOURCE:
+       case MADERA_SLIMTX4MIX_INPUT_2_VOLUME:
+       case MADERA_SLIMTX4MIX_INPUT_3_SOURCE:
+       case MADERA_SLIMTX4MIX_INPUT_3_VOLUME:
+       case MADERA_SLIMTX4MIX_INPUT_4_SOURCE:
+       case MADERA_SLIMTX4MIX_INPUT_4_VOLUME:
+       case MADERA_SLIMTX5MIX_INPUT_1_SOURCE:
+       case MADERA_SLIMTX5MIX_INPUT_1_VOLUME:
+       case MADERA_SLIMTX5MIX_INPUT_2_SOURCE:
+       case MADERA_SLIMTX5MIX_INPUT_2_VOLUME:
+       case MADERA_SLIMTX5MIX_INPUT_3_SOURCE:
+       case MADERA_SLIMTX5MIX_INPUT_3_VOLUME:
+       case MADERA_SLIMTX5MIX_INPUT_4_SOURCE:
+       case MADERA_SLIMTX5MIX_INPUT_4_VOLUME:
+       case MADERA_SLIMTX6MIX_INPUT_1_SOURCE:
+       case MADERA_SLIMTX6MIX_INPUT_1_VOLUME:
+       case MADERA_SLIMTX6MIX_INPUT_2_SOURCE:
+       case MADERA_SLIMTX6MIX_INPUT_2_VOLUME:
+       case MADERA_SLIMTX6MIX_INPUT_3_SOURCE:
+       case MADERA_SLIMTX6MIX_INPUT_3_VOLUME:
+       case MADERA_SLIMTX6MIX_INPUT_4_SOURCE:
+       case MADERA_SLIMTX6MIX_INPUT_4_VOLUME:
+       case MADERA_SLIMTX7MIX_INPUT_1_SOURCE:
+       case MADERA_SLIMTX7MIX_INPUT_1_VOLUME:
+       case MADERA_SLIMTX7MIX_INPUT_2_SOURCE:
+       case MADERA_SLIMTX7MIX_INPUT_2_VOLUME:
+       case MADERA_SLIMTX7MIX_INPUT_3_SOURCE:
+       case MADERA_SLIMTX7MIX_INPUT_3_VOLUME:
+       case MADERA_SLIMTX7MIX_INPUT_4_SOURCE:
+       case MADERA_SLIMTX7MIX_INPUT_4_VOLUME:
+       case MADERA_SLIMTX8MIX_INPUT_1_SOURCE:
+       case MADERA_SLIMTX8MIX_INPUT_1_VOLUME:
+       case MADERA_SLIMTX8MIX_INPUT_2_SOURCE:
+       case MADERA_SLIMTX8MIX_INPUT_2_VOLUME:
+       case MADERA_SLIMTX8MIX_INPUT_3_SOURCE:
+       case MADERA_SLIMTX8MIX_INPUT_3_VOLUME:
+       case MADERA_SLIMTX8MIX_INPUT_4_SOURCE:
+       case MADERA_SLIMTX8MIX_INPUT_4_VOLUME:
+       case MADERA_SPDIF1TX1MIX_INPUT_1_SOURCE:
+       case MADERA_SPDIF1TX1MIX_INPUT_1_VOLUME:
+       case MADERA_SPDIF1TX2MIX_INPUT_1_SOURCE:
+       case MADERA_SPDIF1TX2MIX_INPUT_1_VOLUME:
+       case MADERA_EQ1MIX_INPUT_1_SOURCE:
+       case MADERA_EQ1MIX_INPUT_1_VOLUME:
+       case MADERA_EQ1MIX_INPUT_2_SOURCE:
+       case MADERA_EQ1MIX_INPUT_2_VOLUME:
+       case MADERA_EQ1MIX_INPUT_3_SOURCE:
+       case MADERA_EQ1MIX_INPUT_3_VOLUME:
+       case MADERA_EQ1MIX_INPUT_4_SOURCE:
+       case MADERA_EQ1MIX_INPUT_4_VOLUME:
+       case MADERA_EQ2MIX_INPUT_1_SOURCE:
+       case MADERA_EQ2MIX_INPUT_1_VOLUME:
+       case MADERA_EQ2MIX_INPUT_2_SOURCE:
+       case MADERA_EQ2MIX_INPUT_2_VOLUME:
+       case MADERA_EQ2MIX_INPUT_3_SOURCE:
+       case MADERA_EQ2MIX_INPUT_3_VOLUME:
+       case MADERA_EQ2MIX_INPUT_4_SOURCE:
+       case MADERA_EQ2MIX_INPUT_4_VOLUME:
+       case MADERA_EQ3MIX_INPUT_1_SOURCE:
+       case MADERA_EQ3MIX_INPUT_1_VOLUME:
+       case MADERA_EQ3MIX_INPUT_2_SOURCE:
+       case MADERA_EQ3MIX_INPUT_2_VOLUME:
+       case MADERA_EQ3MIX_INPUT_3_SOURCE:
+       case MADERA_EQ3MIX_INPUT_3_VOLUME:
+       case MADERA_EQ3MIX_INPUT_4_SOURCE:
+       case MADERA_EQ3MIX_INPUT_4_VOLUME:
+       case MADERA_EQ4MIX_INPUT_1_SOURCE:
+       case MADERA_EQ4MIX_INPUT_1_VOLUME:
+       case MADERA_EQ4MIX_INPUT_2_SOURCE:
+       case MADERA_EQ4MIX_INPUT_2_VOLUME:
+       case MADERA_EQ4MIX_INPUT_3_SOURCE:
+       case MADERA_EQ4MIX_INPUT_3_VOLUME:
+       case MADERA_EQ4MIX_INPUT_4_SOURCE:
+       case MADERA_EQ4MIX_INPUT_4_VOLUME:
+       case MADERA_DRC1LMIX_INPUT_1_SOURCE:
+       case MADERA_DRC1LMIX_INPUT_1_VOLUME:
+       case MADERA_DRC1LMIX_INPUT_2_SOURCE:
+       case MADERA_DRC1LMIX_INPUT_2_VOLUME:
+       case MADERA_DRC1LMIX_INPUT_3_SOURCE:
+       case MADERA_DRC1LMIX_INPUT_3_VOLUME:
+       case MADERA_DRC1LMIX_INPUT_4_SOURCE:
+       case MADERA_DRC1LMIX_INPUT_4_VOLUME:
+       case MADERA_DRC1RMIX_INPUT_1_SOURCE:
+       case MADERA_DRC1RMIX_INPUT_1_VOLUME:
+       case MADERA_DRC1RMIX_INPUT_2_SOURCE:
+       case MADERA_DRC1RMIX_INPUT_2_VOLUME:
+       case MADERA_DRC1RMIX_INPUT_3_SOURCE:
+       case MADERA_DRC1RMIX_INPUT_3_VOLUME:
+       case MADERA_DRC1RMIX_INPUT_4_SOURCE:
+       case MADERA_DRC1RMIX_INPUT_4_VOLUME:
+       case MADERA_DRC2LMIX_INPUT_1_SOURCE:
+       case MADERA_DRC2LMIX_INPUT_1_VOLUME:
+       case MADERA_DRC2LMIX_INPUT_2_SOURCE:
+       case MADERA_DRC2LMIX_INPUT_2_VOLUME:
+       case MADERA_DRC2LMIX_INPUT_3_SOURCE:
+       case MADERA_DRC2LMIX_INPUT_3_VOLUME:
+       case MADERA_DRC2LMIX_INPUT_4_SOURCE:
+       case MADERA_DRC2LMIX_INPUT_4_VOLUME:
+       case MADERA_DRC2RMIX_INPUT_1_SOURCE:
+       case MADERA_DRC2RMIX_INPUT_1_VOLUME:
+       case MADERA_DRC2RMIX_INPUT_2_SOURCE:
+       case MADERA_DRC2RMIX_INPUT_2_VOLUME:
+       case MADERA_DRC2RMIX_INPUT_3_SOURCE:
+       case MADERA_DRC2RMIX_INPUT_3_VOLUME:
+       case MADERA_DRC2RMIX_INPUT_4_SOURCE:
+       case MADERA_DRC2RMIX_INPUT_4_VOLUME:
+       case MADERA_HPLP1MIX_INPUT_1_SOURCE:
+       case MADERA_HPLP1MIX_INPUT_1_VOLUME:
+       case MADERA_HPLP1MIX_INPUT_2_SOURCE:
+       case MADERA_HPLP1MIX_INPUT_2_VOLUME:
+       case MADERA_HPLP1MIX_INPUT_3_SOURCE:
+       case MADERA_HPLP1MIX_INPUT_3_VOLUME:
+       case MADERA_HPLP1MIX_INPUT_4_SOURCE:
+       case MADERA_HPLP1MIX_INPUT_4_VOLUME:
+       case MADERA_HPLP2MIX_INPUT_1_SOURCE:
+       case MADERA_HPLP2MIX_INPUT_1_VOLUME:
+       case MADERA_HPLP2MIX_INPUT_2_SOURCE:
+       case MADERA_HPLP2MIX_INPUT_2_VOLUME:
+       case MADERA_HPLP2MIX_INPUT_3_SOURCE:
+       case MADERA_HPLP2MIX_INPUT_3_VOLUME:
+       case MADERA_HPLP2MIX_INPUT_4_SOURCE:
+       case MADERA_HPLP2MIX_INPUT_4_VOLUME:
+       case MADERA_HPLP3MIX_INPUT_1_SOURCE:
+       case MADERA_HPLP3MIX_INPUT_1_VOLUME:
+       case MADERA_HPLP3MIX_INPUT_2_SOURCE:
+       case MADERA_HPLP3MIX_INPUT_2_VOLUME:
+       case MADERA_HPLP3MIX_INPUT_3_SOURCE:
+       case MADERA_HPLP3MIX_INPUT_3_VOLUME:
+       case MADERA_HPLP3MIX_INPUT_4_SOURCE:
+       case MADERA_HPLP3MIX_INPUT_4_VOLUME:
+       case MADERA_HPLP4MIX_INPUT_1_SOURCE:
+       case MADERA_HPLP4MIX_INPUT_1_VOLUME:
+       case MADERA_HPLP4MIX_INPUT_2_SOURCE:
+       case MADERA_HPLP4MIX_INPUT_2_VOLUME:
+       case MADERA_HPLP4MIX_INPUT_3_SOURCE:
+       case MADERA_HPLP4MIX_INPUT_3_VOLUME:
+       case MADERA_HPLP4MIX_INPUT_4_SOURCE:
+       case MADERA_HPLP4MIX_INPUT_4_VOLUME:
+       case MADERA_DSP1LMIX_INPUT_1_SOURCE:
+       case MADERA_DSP1LMIX_INPUT_1_VOLUME:
+       case MADERA_DSP1LMIX_INPUT_2_SOURCE:
+       case MADERA_DSP1LMIX_INPUT_2_VOLUME:
+       case MADERA_DSP1LMIX_INPUT_3_SOURCE:
+       case MADERA_DSP1LMIX_INPUT_3_VOLUME:
+       case MADERA_DSP1LMIX_INPUT_4_SOURCE:
+       case MADERA_DSP1LMIX_INPUT_4_VOLUME:
+       case MADERA_DSP1RMIX_INPUT_1_SOURCE:
+       case MADERA_DSP1RMIX_INPUT_1_VOLUME:
+       case MADERA_DSP1RMIX_INPUT_2_SOURCE:
+       case MADERA_DSP1RMIX_INPUT_2_VOLUME:
+       case MADERA_DSP1RMIX_INPUT_3_SOURCE:
+       case MADERA_DSP1RMIX_INPUT_3_VOLUME:
+       case MADERA_DSP1RMIX_INPUT_4_SOURCE:
+       case MADERA_DSP1RMIX_INPUT_4_VOLUME:
+       case MADERA_DSP1AUX1MIX_INPUT_1_SOURCE:
+       case MADERA_DSP1AUX2MIX_INPUT_1_SOURCE:
+       case MADERA_DSP1AUX3MIX_INPUT_1_SOURCE:
+       case MADERA_DSP1AUX4MIX_INPUT_1_SOURCE:
+       case MADERA_DSP1AUX5MIX_INPUT_1_SOURCE:
+       case MADERA_DSP1AUX6MIX_INPUT_1_SOURCE:
+       case MADERA_DSP2LMIX_INPUT_1_SOURCE:
+       case MADERA_DSP2LMIX_INPUT_1_VOLUME:
+       case MADERA_DSP2LMIX_INPUT_2_SOURCE:
+       case MADERA_DSP2LMIX_INPUT_2_VOLUME:
+       case MADERA_DSP2LMIX_INPUT_3_SOURCE:
+       case MADERA_DSP2LMIX_INPUT_3_VOLUME:
+       case MADERA_DSP2LMIX_INPUT_4_SOURCE:
+       case MADERA_DSP2LMIX_INPUT_4_VOLUME:
+       case MADERA_DSP2RMIX_INPUT_1_SOURCE:
+       case MADERA_DSP2RMIX_INPUT_1_VOLUME:
+       case MADERA_DSP2RMIX_INPUT_2_SOURCE:
+       case MADERA_DSP2RMIX_INPUT_2_VOLUME:
+       case MADERA_DSP2RMIX_INPUT_3_SOURCE:
+       case MADERA_DSP2RMIX_INPUT_3_VOLUME:
+       case MADERA_DSP2RMIX_INPUT_4_SOURCE:
+       case MADERA_DSP2RMIX_INPUT_4_VOLUME:
+       case MADERA_DSP2AUX1MIX_INPUT_1_SOURCE:
+       case MADERA_DSP2AUX2MIX_INPUT_1_SOURCE:
+       case MADERA_DSP2AUX3MIX_INPUT_1_SOURCE:
+       case MADERA_DSP2AUX4MIX_INPUT_1_SOURCE:
+       case MADERA_DSP2AUX5MIX_INPUT_1_SOURCE:
+       case MADERA_DSP2AUX6MIX_INPUT_1_SOURCE:
+       case MADERA_DSP3LMIX_INPUT_1_SOURCE:
+       case MADERA_DSP3LMIX_INPUT_1_VOLUME:
+       case MADERA_DSP3LMIX_INPUT_2_SOURCE:
+       case MADERA_DSP3LMIX_INPUT_2_VOLUME:
+       case MADERA_DSP3LMIX_INPUT_3_SOURCE:
+       case MADERA_DSP3LMIX_INPUT_3_VOLUME:
+       case MADERA_DSP3LMIX_INPUT_4_SOURCE:
+       case MADERA_DSP3LMIX_INPUT_4_VOLUME:
+       case MADERA_DSP3RMIX_INPUT_1_SOURCE:
+       case MADERA_DSP3RMIX_INPUT_1_VOLUME:
+       case MADERA_DSP3RMIX_INPUT_2_SOURCE:
+       case MADERA_DSP3RMIX_INPUT_2_VOLUME:
+       case MADERA_DSP3RMIX_INPUT_3_SOURCE:
+       case MADERA_DSP3RMIX_INPUT_3_VOLUME:
+       case MADERA_DSP3RMIX_INPUT_4_SOURCE:
+       case MADERA_DSP3RMIX_INPUT_4_VOLUME:
+       case MADERA_DSP3AUX1MIX_INPUT_1_SOURCE:
+       case MADERA_DSP3AUX2MIX_INPUT_1_SOURCE:
+       case MADERA_DSP3AUX3MIX_INPUT_1_SOURCE:
+       case MADERA_DSP3AUX4MIX_INPUT_1_SOURCE:
+       case MADERA_DSP3AUX5MIX_INPUT_1_SOURCE:
+       case MADERA_DSP3AUX6MIX_INPUT_1_SOURCE:
+       case MADERA_DSP4LMIX_INPUT_1_SOURCE:
+       case MADERA_DSP4LMIX_INPUT_1_VOLUME:
+       case MADERA_DSP4LMIX_INPUT_2_SOURCE:
+       case MADERA_DSP4LMIX_INPUT_2_VOLUME:
+       case MADERA_DSP4LMIX_INPUT_3_SOURCE:
+       case MADERA_DSP4LMIX_INPUT_3_VOLUME:
+       case MADERA_DSP4LMIX_INPUT_4_SOURCE:
+       case MADERA_DSP4LMIX_INPUT_4_VOLUME:
+       case MADERA_DSP4RMIX_INPUT_1_SOURCE:
+       case MADERA_DSP4RMIX_INPUT_1_VOLUME:
+       case MADERA_DSP4RMIX_INPUT_2_SOURCE:
+       case MADERA_DSP4RMIX_INPUT_2_VOLUME:
+       case MADERA_DSP4RMIX_INPUT_3_SOURCE:
+       case MADERA_DSP4RMIX_INPUT_3_VOLUME:
+       case MADERA_DSP4RMIX_INPUT_4_SOURCE:
+       case MADERA_DSP4RMIX_INPUT_4_VOLUME:
+       case MADERA_DSP4AUX1MIX_INPUT_1_SOURCE:
+       case MADERA_DSP4AUX2MIX_INPUT_1_SOURCE:
+       case MADERA_DSP4AUX3MIX_INPUT_1_SOURCE:
+       case MADERA_DSP4AUX4MIX_INPUT_1_SOURCE:
+       case MADERA_DSP4AUX5MIX_INPUT_1_SOURCE:
+       case MADERA_DSP4AUX6MIX_INPUT_1_SOURCE:
+       case MADERA_DSP5LMIX_INPUT_1_SOURCE:
+       case MADERA_DSP5LMIX_INPUT_1_VOLUME:
+       case MADERA_DSP5LMIX_INPUT_2_SOURCE:
+       case MADERA_DSP5LMIX_INPUT_2_VOLUME:
+       case MADERA_DSP5LMIX_INPUT_3_SOURCE:
+       case MADERA_DSP5LMIX_INPUT_3_VOLUME:
+       case MADERA_DSP5LMIX_INPUT_4_SOURCE:
+       case MADERA_DSP5LMIX_INPUT_4_VOLUME:
+       case MADERA_DSP5RMIX_INPUT_1_SOURCE:
+       case MADERA_DSP5RMIX_INPUT_1_VOLUME:
+       case MADERA_DSP5RMIX_INPUT_2_SOURCE:
+       case MADERA_DSP5RMIX_INPUT_2_VOLUME:
+       case MADERA_DSP5RMIX_INPUT_3_SOURCE:
+       case MADERA_DSP5RMIX_INPUT_3_VOLUME:
+       case MADERA_DSP5RMIX_INPUT_4_SOURCE:
+       case MADERA_DSP5RMIX_INPUT_4_VOLUME:
+       case MADERA_DSP5AUX1MIX_INPUT_1_SOURCE:
+       case MADERA_DSP5AUX2MIX_INPUT_1_SOURCE:
+       case MADERA_DSP5AUX3MIX_INPUT_1_SOURCE:
+       case MADERA_DSP5AUX4MIX_INPUT_1_SOURCE:
+       case MADERA_DSP5AUX5MIX_INPUT_1_SOURCE:
+       case MADERA_DSP5AUX6MIX_INPUT_1_SOURCE:
+       case MADERA_ASRC1_1LMIX_INPUT_1_SOURCE:
+       case MADERA_ASRC1_1RMIX_INPUT_1_SOURCE:
+       case MADERA_ASRC1_2LMIX_INPUT_1_SOURCE:
+       case MADERA_ASRC1_2RMIX_INPUT_1_SOURCE:
+       case MADERA_ASRC2_1LMIX_INPUT_1_SOURCE:
+       case MADERA_ASRC2_1RMIX_INPUT_1_SOURCE:
+       case MADERA_ASRC2_2LMIX_INPUT_1_SOURCE:
+       case MADERA_ASRC2_2RMIX_INPUT_1_SOURCE:
+       case MADERA_ISRC1DEC1MIX_INPUT_1_SOURCE:
+       case MADERA_ISRC1DEC2MIX_INPUT_1_SOURCE:
+       case MADERA_ISRC1DEC3MIX_INPUT_1_SOURCE:
+       case MADERA_ISRC1DEC4MIX_INPUT_1_SOURCE:
+       case MADERA_ISRC1INT1MIX_INPUT_1_SOURCE:
+       case MADERA_ISRC1INT2MIX_INPUT_1_SOURCE:
+       case MADERA_ISRC1INT3MIX_INPUT_1_SOURCE:
+       case MADERA_ISRC1INT4MIX_INPUT_1_SOURCE:
+       case MADERA_ISRC2DEC1MIX_INPUT_1_SOURCE:
+       case MADERA_ISRC2DEC2MIX_INPUT_1_SOURCE:
+       case MADERA_ISRC2DEC3MIX_INPUT_1_SOURCE:
+       case MADERA_ISRC2DEC4MIX_INPUT_1_SOURCE:
+       case MADERA_ISRC2INT1MIX_INPUT_1_SOURCE:
+       case MADERA_ISRC2INT2MIX_INPUT_1_SOURCE:
+       case MADERA_ISRC2INT3MIX_INPUT_1_SOURCE:
+       case MADERA_ISRC2INT4MIX_INPUT_1_SOURCE:
+       case MADERA_ISRC3DEC1MIX_INPUT_1_SOURCE:
+       case MADERA_ISRC3DEC2MIX_INPUT_1_SOURCE:
+       case MADERA_ISRC3INT1MIX_INPUT_1_SOURCE:
+       case MADERA_ISRC3INT2MIX_INPUT_1_SOURCE:
+       case MADERA_ISRC4DEC1MIX_INPUT_1_SOURCE:
+       case MADERA_ISRC4DEC2MIX_INPUT_1_SOURCE:
+       case MADERA_ISRC4INT1MIX_INPUT_1_SOURCE:
+       case MADERA_ISRC4INT2MIX_INPUT_1_SOURCE:
+       case MADERA_DSP6LMIX_INPUT_1_SOURCE:
+       case MADERA_DSP6LMIX_INPUT_1_VOLUME:
+       case MADERA_DSP6LMIX_INPUT_2_SOURCE:
+       case MADERA_DSP6LMIX_INPUT_2_VOLUME:
+       case MADERA_DSP6LMIX_INPUT_3_SOURCE:
+       case MADERA_DSP6LMIX_INPUT_3_VOLUME:
+       case MADERA_DSP6LMIX_INPUT_4_SOURCE:
+       case MADERA_DSP6LMIX_INPUT_4_VOLUME:
+       case MADERA_DSP6RMIX_INPUT_1_SOURCE:
+       case MADERA_DSP6RMIX_INPUT_1_VOLUME:
+       case MADERA_DSP6RMIX_INPUT_2_SOURCE:
+       case MADERA_DSP6RMIX_INPUT_2_VOLUME:
+       case MADERA_DSP6RMIX_INPUT_3_SOURCE:
+       case MADERA_DSP6RMIX_INPUT_3_VOLUME:
+       case MADERA_DSP6RMIX_INPUT_4_SOURCE:
+       case MADERA_DSP6RMIX_INPUT_4_VOLUME:
+       case MADERA_DSP6AUX1MIX_INPUT_1_SOURCE:
+       case MADERA_DSP6AUX2MIX_INPUT_1_SOURCE:
+       case MADERA_DSP6AUX3MIX_INPUT_1_SOURCE:
+       case MADERA_DSP6AUX4MIX_INPUT_1_SOURCE:
+       case MADERA_DSP6AUX5MIX_INPUT_1_SOURCE:
+       case MADERA_DSP6AUX6MIX_INPUT_1_SOURCE:
+       case MADERA_DSP7LMIX_INPUT_1_SOURCE:
+       case MADERA_DSP7LMIX_INPUT_1_VOLUME:
+       case MADERA_DSP7LMIX_INPUT_2_SOURCE:
+       case MADERA_DSP7LMIX_INPUT_2_VOLUME:
+       case MADERA_DSP7LMIX_INPUT_3_SOURCE:
+       case MADERA_DSP7LMIX_INPUT_3_VOLUME:
+       case MADERA_DSP7LMIX_INPUT_4_SOURCE:
+       case MADERA_DSP7LMIX_INPUT_4_VOLUME:
+       case MADERA_DSP7RMIX_INPUT_1_SOURCE:
+       case MADERA_DSP7RMIX_INPUT_1_VOLUME:
+       case MADERA_DSP7RMIX_INPUT_2_SOURCE:
+       case MADERA_DSP7RMIX_INPUT_2_VOLUME:
+       case MADERA_DSP7RMIX_INPUT_3_SOURCE:
+       case MADERA_DSP7RMIX_INPUT_3_VOLUME:
+       case MADERA_DSP7RMIX_INPUT_4_SOURCE:
+       case MADERA_DSP7RMIX_INPUT_4_VOLUME:
+       case MADERA_DSP7AUX1MIX_INPUT_1_SOURCE:
+       case MADERA_DSP7AUX2MIX_INPUT_1_SOURCE:
+       case MADERA_DSP7AUX3MIX_INPUT_1_SOURCE:
+       case MADERA_DSP7AUX4MIX_INPUT_1_SOURCE:
+       case MADERA_DSP7AUX5MIX_INPUT_1_SOURCE:
+       case MADERA_DSP7AUX6MIX_INPUT_1_SOURCE:
+       case MADERA_DFC1MIX_INPUT_1_SOURCE:
+       case MADERA_DFC2MIX_INPUT_1_SOURCE:
+       case MADERA_DFC3MIX_INPUT_1_SOURCE:
+       case MADERA_DFC4MIX_INPUT_1_SOURCE:
+       case MADERA_DFC5MIX_INPUT_1_SOURCE:
+       case MADERA_DFC6MIX_INPUT_1_SOURCE:
+       case MADERA_DFC7MIX_INPUT_1_SOURCE:
+       case MADERA_DFC8MIX_INPUT_1_SOURCE:
+       case MADERA_FX_CTRL1:
+       case MADERA_FX_CTRL2:
+       case MADERA_EQ1_1 ... MADERA_EQ1_21:
+       case MADERA_EQ2_1 ... MADERA_EQ2_21:
+       case MADERA_EQ3_1 ... MADERA_EQ3_21:
+       case MADERA_EQ4_1 ... MADERA_EQ4_21:
+       case MADERA_DRC1_CTRL1:
+       case MADERA_DRC1_CTRL2:
+       case MADERA_DRC1_CTRL3:
+       case MADERA_DRC1_CTRL4:
+       case MADERA_DRC1_CTRL5:
+       case MADERA_DRC2_CTRL1:
+       case MADERA_DRC2_CTRL2:
+       case MADERA_DRC2_CTRL3:
+       case MADERA_DRC2_CTRL4:
+       case MADERA_DRC2_CTRL5:
+       case MADERA_HPLPF1_1:
+       case MADERA_HPLPF1_2:
+       case MADERA_HPLPF2_1:
+       case MADERA_HPLPF2_2:
+       case MADERA_HPLPF3_1:
+       case MADERA_HPLPF3_2:
+       case MADERA_HPLPF4_1:
+       case MADERA_HPLPF4_2:
+       case MADERA_ASRC1_ENABLE:
+       case MADERA_ASRC1_STATUS:
+       case MADERA_ASRC1_RATE1:
+       case MADERA_ASRC1_RATE2:
+       case MADERA_ASRC2_ENABLE:
+       case MADERA_ASRC2_STATUS:
+       case MADERA_ASRC2_RATE1:
+       case MADERA_ASRC2_RATE2:
+       case MADERA_ISRC_1_CTRL_1:
+       case MADERA_ISRC_1_CTRL_2:
+       case MADERA_ISRC_1_CTRL_3:
+       case MADERA_ISRC_2_CTRL_1:
+       case MADERA_ISRC_2_CTRL_2:
+       case MADERA_ISRC_2_CTRL_3:
+       case MADERA_ISRC_3_CTRL_1:
+       case MADERA_ISRC_3_CTRL_2:
+       case MADERA_ISRC_3_CTRL_3:
+       case MADERA_ISRC_4_CTRL_1:
+       case MADERA_ISRC_4_CTRL_2:
+       case MADERA_ISRC_4_CTRL_3:
+       case MADERA_CLOCK_CONTROL:
+       case MADERA_ANC_SRC:
+       case MADERA_DSP_STATUS:
+       case MADERA_ANC_COEFF_START ... MADERA_ANC_COEFF_END:
+       case MADERA_FCL_FILTER_CONTROL:
+       case MADERA_FCL_ADC_REFORMATTER_CONTROL:
+       case MADERA_FCL_COEFF_START ... MADERA_FCL_COEFF_END:
+       case MADERA_FCR_FILTER_CONTROL:
+       case MADERA_FCR_ADC_REFORMATTER_CONTROL:
+       case MADERA_FCR_COEFF_START ... MADERA_FCR_COEFF_END:
+       case MADERA_DAC_COMP_1:
+       case MADERA_DAC_COMP_2:
+       case MADERA_FRF_COEFFICIENT_1L_1:
+       case MADERA_FRF_COEFFICIENT_1L_2:
+       case MADERA_FRF_COEFFICIENT_1L_3:
+       case MADERA_FRF_COEFFICIENT_1L_4:
+       case MADERA_FRF_COEFFICIENT_1R_1:
+       case MADERA_FRF_COEFFICIENT_1R_2:
+       case MADERA_FRF_COEFFICIENT_1R_3:
+       case MADERA_FRF_COEFFICIENT_1R_4:
+       case MADERA_FRF_COEFFICIENT_2L_1:
+       case MADERA_FRF_COEFFICIENT_2L_2:
+       case MADERA_FRF_COEFFICIENT_2L_3:
+       case MADERA_FRF_COEFFICIENT_2L_4:
+       case MADERA_FRF_COEFFICIENT_2R_1:
+       case MADERA_FRF_COEFFICIENT_2R_2:
+       case MADERA_FRF_COEFFICIENT_2R_3:
+       case MADERA_FRF_COEFFICIENT_2R_4:
+       case MADERA_FRF_COEFFICIENT_3L_1:
+       case MADERA_FRF_COEFFICIENT_3L_2:
+       case MADERA_FRF_COEFFICIENT_3L_3:
+       case MADERA_FRF_COEFFICIENT_3L_4:
+       case MADERA_FRF_COEFFICIENT_3R_1:
+       case MADERA_FRF_COEFFICIENT_3R_2:
+       case MADERA_FRF_COEFFICIENT_3R_3:
+       case MADERA_FRF_COEFFICIENT_3R_4:
+       case MADERA_FRF_COEFFICIENT_5L_1:
+       case MADERA_FRF_COEFFICIENT_5L_2:
+       case MADERA_FRF_COEFFICIENT_5L_3:
+       case MADERA_FRF_COEFFICIENT_5L_4:
+       case MADERA_FRF_COEFFICIENT_5R_1:
+       case MADERA_FRF_COEFFICIENT_5R_2:
+       case MADERA_FRF_COEFFICIENT_5R_3:
+       case MADERA_FRF_COEFFICIENT_5R_4:
+       case MADERA_DFC1_CTRL:
+       case MADERA_DFC1_RX:
+       case MADERA_DFC1_TX:
+       case MADERA_DFC2_CTRL:
+       case MADERA_DFC2_RX:
+       case MADERA_DFC2_TX:
+       case MADERA_DFC3_CTRL:
+       case MADERA_DFC3_RX:
+       case MADERA_DFC3_TX:
+       case MADERA_DFC4_CTRL:
+       case MADERA_DFC4_RX:
+       case MADERA_DFC4_TX:
+       case MADERA_DFC5_CTRL:
+       case MADERA_DFC5_RX:
+       case MADERA_DFC5_TX:
+       case MADERA_DFC6_CTRL:
+       case MADERA_DFC6_RX:
+       case MADERA_DFC6_TX:
+       case MADERA_DFC7_CTRL:
+       case MADERA_DFC7_RX:
+       case MADERA_DFC7_TX:
+       case MADERA_DFC8_CTRL:
+       case MADERA_DFC8_RX:
+       case MADERA_DFC8_TX:
+       case MADERA_DFC_STATUS:
+       case MADERA_GPIO1_CTRL_1 ... MADERA_GPIO38_CTRL_2:
+       case MADERA_IRQ1_STATUS_1 ... MADERA_IRQ1_STATUS_33:
+       case MADERA_IRQ1_MASK_1 ... MADERA_IRQ1_MASK_33:
+       case MADERA_IRQ1_RAW_STATUS_1 ... MADERA_IRQ1_RAW_STATUS_33:
+       case MADERA_INTERRUPT_DEBOUNCE_7:
+       case MADERA_IRQ1_CTRL:
+               return true;
+       default:
+               return false;
+       }
+}
+
+static bool cs47l90_16bit_volatile_register(struct device *dev,
+                                           unsigned int reg)
+{
+       switch (reg) {
+       case MADERA_SOFTWARE_RESET:
+       case MADERA_HARDWARE_REVISION:
+       case MADERA_WRITE_SEQUENCER_CTRL_0:
+       case MADERA_WRITE_SEQUENCER_CTRL_1:
+       case MADERA_WRITE_SEQUENCER_CTRL_2:
+       case MADERA_HAPTICS_STATUS:
+       case MADERA_SAMPLE_RATE_1_STATUS:
+       case MADERA_SAMPLE_RATE_2_STATUS:
+       case MADERA_SAMPLE_RATE_3_STATUS:
+       case MADERA_ASYNC_SAMPLE_RATE_1_STATUS:
+       case MADERA_ASYNC_SAMPLE_RATE_2_STATUS:
+       case MADERA_HP_CTRL_1L:
+       case MADERA_HP_CTRL_1R:
+       case MADERA_HP_CTRL_2L:
+       case MADERA_HP_CTRL_2R:
+       case MADERA_HP_CTRL_3L:
+       case MADERA_HP_CTRL_3R:
+       case MADERA_MIC_DETECT_1_CONTROL_3:
+       case MADERA_MIC_DETECT_1_CONTROL_4:
+       case MADERA_MIC_DETECT_2_CONTROL_3:
+       case MADERA_MIC_DETECT_2_CONTROL_4:
+       case MADERA_HEADPHONE_DETECT_2:
+       case MADERA_HEADPHONE_DETECT_3:
+       case MADERA_HEADPHONE_DETECT_5:
+       case MADERA_INPUT_ENABLES_STATUS:
+       case MADERA_OUTPUT_STATUS_1:
+       case MADERA_RAW_OUTPUT_STATUS_1:
+       case MADERA_SPD1_TX_CHANNEL_STATUS_1:
+       case MADERA_SPD1_TX_CHANNEL_STATUS_2:
+       case MADERA_SPD1_TX_CHANNEL_STATUS_3:
+       case MADERA_SLIMBUS_RX_PORT_STATUS:
+       case MADERA_SLIMBUS_TX_PORT_STATUS:
+       case MADERA_FX_CTRL2:
+       case MADERA_ASRC2_STATUS:
+       case MADERA_ASRC1_STATUS:
+       case MADERA_CLOCK_CONTROL:
+       case MADERA_DFC_STATUS:
+       case MADERA_IRQ1_STATUS_1 ... MADERA_IRQ1_STATUS_33:
+       case MADERA_IRQ1_RAW_STATUS_1 ... MADERA_IRQ1_RAW_STATUS_33:
+               return true;
+       default:
+               return false;
+       }
+}
+
+static bool cs47l90_32bit_readable_register(struct device *dev,
+                                           unsigned int reg)
+{
+       switch (reg) {
+       case MADERA_WSEQ_SEQUENCE_1 ... MADERA_WSEQ_SEQUENCE_508:
+       case MADERA_OTP_HPDET_CAL_1 ... MADERA_OTP_HPDET_CAL_2:
+       case MADERA_DSP1_CONFIG_1 ... MADERA_DSP1_PMEM_ERR_ADDR___XMEM_ERR_ADDR:
+       case MADERA_DSP2_CONFIG_1 ... MADERA_DSP2_PMEM_ERR_ADDR___XMEM_ERR_ADDR:
+       case MADERA_DSP3_CONFIG_1 ... MADERA_DSP3_PMEM_ERR_ADDR___XMEM_ERR_ADDR:
+       case MADERA_DSP4_CONFIG_1 ... MADERA_DSP4_PMEM_ERR_ADDR___XMEM_ERR_ADDR:
+       case MADERA_DSP5_CONFIG_1 ... MADERA_DSP5_PMEM_ERR_ADDR___XMEM_ERR_ADDR:
+       case MADERA_DSP6_CONFIG_1 ... MADERA_DSP6_PMEM_ERR_ADDR___XMEM_ERR_ADDR:
+       case MADERA_DSP7_CONFIG_1 ... MADERA_DSP7_PMEM_ERR_ADDR___XMEM_ERR_ADDR:
+               return true;
+       default:
+               return cs47l90_is_adsp_memory(reg);
+       }
+}
+
+static bool cs47l90_32bit_volatile_register(struct device *dev,
+                                           unsigned int reg)
+{
+       switch (reg) {
+       case MADERA_WSEQ_SEQUENCE_1 ... MADERA_WSEQ_SEQUENCE_508:
+       case MADERA_OTP_HPDET_CAL_1 ... MADERA_OTP_HPDET_CAL_2:
+       case MADERA_DSP1_CONFIG_1 ... MADERA_DSP1_PMEM_ERR_ADDR___XMEM_ERR_ADDR:
+       case MADERA_DSP2_CONFIG_1 ... MADERA_DSP2_PMEM_ERR_ADDR___XMEM_ERR_ADDR:
+       case MADERA_DSP3_CONFIG_1 ... MADERA_DSP3_PMEM_ERR_ADDR___XMEM_ERR_ADDR:
+       case MADERA_DSP4_CONFIG_1 ... MADERA_DSP4_PMEM_ERR_ADDR___XMEM_ERR_ADDR:
+       case MADERA_DSP5_CONFIG_1 ... MADERA_DSP5_PMEM_ERR_ADDR___XMEM_ERR_ADDR:
+       case MADERA_DSP6_CONFIG_1 ... MADERA_DSP6_PMEM_ERR_ADDR___XMEM_ERR_ADDR:
+       case MADERA_DSP7_CONFIG_1 ... MADERA_DSP7_PMEM_ERR_ADDR___XMEM_ERR_ADDR:
+               return true;
+       default:
+               return cs47l90_is_adsp_memory(reg);
+       }
+}
+
+const struct regmap_config cs47l90_16bit_spi_regmap = {
+       .name = "cs47l90_16bit",
+       .reg_bits = 32,
+       .pad_bits = 16,
+       .val_bits = 16,
+       .reg_format_endian = REGMAP_ENDIAN_BIG,
+       .val_format_endian = REGMAP_ENDIAN_BIG,
+
+       .max_register = MADERA_INTERRUPT_RAW_STATUS_1,
+       .readable_reg = cs47l90_16bit_readable_register,
+       .volatile_reg = cs47l90_16bit_volatile_register,
+
+       .cache_type = REGCACHE_RBTREE,
+       .reg_defaults = cs47l90_reg_default,
+       .num_reg_defaults = ARRAY_SIZE(cs47l90_reg_default),
+};
+EXPORT_SYMBOL_GPL(cs47l90_16bit_spi_regmap);
+
+const struct regmap_config cs47l90_16bit_i2c_regmap = {
+       .name = "cs47l90_16bit",
+       .reg_bits = 32,
+       .val_bits = 16,
+       .reg_format_endian = REGMAP_ENDIAN_BIG,
+       .val_format_endian = REGMAP_ENDIAN_BIG,
+
+       .max_register = MADERA_INTERRUPT_RAW_STATUS_1,
+       .readable_reg = cs47l90_16bit_readable_register,
+       .volatile_reg = cs47l90_16bit_volatile_register,
+
+       .cache_type = REGCACHE_RBTREE,
+       .reg_defaults = cs47l90_reg_default,
+       .num_reg_defaults = ARRAY_SIZE(cs47l90_reg_default),
+};
+EXPORT_SYMBOL_GPL(cs47l90_16bit_i2c_regmap);
+
+const struct regmap_config cs47l90_32bit_spi_regmap = {
+       .name = "cs47l90_32bit",
+       .reg_bits = 32,
+       .reg_stride = 2,
+       .pad_bits = 16,
+       .val_bits = 32,
+       .reg_format_endian = REGMAP_ENDIAN_BIG,
+       .val_format_endian = REGMAP_ENDIAN_BIG,
+
+       .max_register = MADERA_DSP7_PMEM_ERR_ADDR___XMEM_ERR_ADDR,
+       .readable_reg = cs47l90_32bit_readable_register,
+       .volatile_reg = cs47l90_32bit_volatile_register,
+
+       .cache_type = REGCACHE_RBTREE,
+};
+EXPORT_SYMBOL_GPL(cs47l90_32bit_spi_regmap);
+
+const struct regmap_config cs47l90_32bit_i2c_regmap = {
+       .name = "cs47l90_32bit",
+       .reg_bits = 32,
+       .reg_stride = 2,
+       .val_bits = 32,
+       .reg_format_endian = REGMAP_ENDIAN_BIG,
+       .val_format_endian = REGMAP_ENDIAN_BIG,
+
+       .max_register = MADERA_DSP7_PMEM_ERR_ADDR___XMEM_ERR_ADDR,
+       .readable_reg = cs47l90_32bit_readable_register,
+       .volatile_reg = cs47l90_32bit_volatile_register,
+
+       .cache_type = REGCACHE_RBTREE,
+};
+EXPORT_SYMBOL_GPL(cs47l90_32bit_i2c_regmap);
index 6c2870d..6e4ce49 100644 (file)
@@ -76,7 +76,7 @@ static struct resource da9063_hwmon_resources[] = {
 };
 
 
-static const struct mfd_cell da9063_devs[] = {
+static const struct mfd_cell da9063_common_devs[] = {
        {
                .name           = DA9063_DRVNAME_REGULATORS,
                .num_resources  = ARRAY_SIZE(da9063_regulators_resources),
@@ -101,14 +101,18 @@ static const struct mfd_cell da9063_devs[] = {
                .of_compatible = "dlg,da9063-onkey",
        },
        {
+               .name           = DA9063_DRVNAME_VIBRATION,
+       },
+};
+
+/* Only present on DA9063 , not on DA9063L */
+static const struct mfd_cell da9063_devs[] = {
+       {
                .name           = DA9063_DRVNAME_RTC,
                .num_resources  = ARRAY_SIZE(da9063_rtc_resources),
                .resources      = da9063_rtc_resources,
                .of_compatible  = "dlg,da9063-rtc",
        },
-       {
-               .name           = DA9063_DRVNAME_VIBRATION,
-       },
 };
 
 static int da9063_clear_fault_log(struct da9063 *da9063)
@@ -192,7 +196,7 @@ int da9063_device_init(struct da9063 *da9063, unsigned int irq)
                dev_err(da9063->dev, "Cannot read chip model id.\n");
                return -EIO;
        }
-       if (model != PMIC_DA9063) {
+       if (model != PMIC_CHIP_ID_DA9063) {
                dev_err(da9063->dev, "Invalid chip model id: 0x%02x\n", model);
                return -ENODEV;
        }
@@ -215,7 +219,6 @@ int da9063_device_init(struct da9063 *da9063, unsigned int irq)
                return -ENODEV;
        }
 
-       da9063->model = model;
        da9063->variant_code = variant_code;
 
        ret = da9063_irq_init(da9063);
@@ -226,19 +229,26 @@ int da9063_device_init(struct da9063 *da9063, unsigned int irq)
 
        da9063->irq_base = regmap_irq_chip_get_base(da9063->regmap_irq);
 
-       ret = mfd_add_devices(da9063->dev, -1, da9063_devs,
-                             ARRAY_SIZE(da9063_devs), NULL, da9063->irq_base,
-                             NULL);
-       if (ret)
-               dev_err(da9063->dev, "Cannot add MFD cells\n");
+       ret = devm_mfd_add_devices(da9063->dev, PLATFORM_DEVID_NONE,
+                                  da9063_common_devs,
+                                  ARRAY_SIZE(da9063_common_devs),
+                                  NULL, da9063->irq_base, NULL);
+       if (ret) {
+               dev_err(da9063->dev, "Failed to add child devices\n");
+               return ret;
+       }
 
-       return ret;
-}
+       if (da9063->type == PMIC_TYPE_DA9063) {
+               ret = devm_mfd_add_devices(da9063->dev, PLATFORM_DEVID_NONE,
+                                          da9063_devs, ARRAY_SIZE(da9063_devs),
+                                          NULL, da9063->irq_base, NULL);
+               if (ret) {
+                       dev_err(da9063->dev, "Failed to add child devices\n");
+                       return ret;
+               }
+       }
 
-void da9063_device_exit(struct da9063 *da9063)
-{
-       mfd_remove_devices(da9063->dev);
-       da9063_irq_exit(da9063);
+       return ret;
 }
 
 MODULE_DESCRIPTION("PMIC driver for Dialog DA9063");
index 981805a..50a24b1 100644 (file)
 #include <linux/regulator/of_regulator.h>
 
 static const struct regmap_range da9063_ad_readable_ranges[] = {
-       {
-               .range_min = DA9063_REG_PAGE_CON,
-               .range_max = DA9063_AD_REG_SECOND_D,
-       }, {
-               .range_min = DA9063_REG_SEQ,
-               .range_max = DA9063_REG_ID_32_31,
-       }, {
-               .range_min = DA9063_REG_SEQ_A,
-               .range_max = DA9063_REG_AUTO3_LOW,
-       }, {
-               .range_min = DA9063_REG_T_OFFSET,
-               .range_max = DA9063_AD_REG_GP_ID_19,
-       }, {
-               .range_min = DA9063_REG_CHIP_ID,
-               .range_max = DA9063_REG_CHIP_VARIANT,
-       },
+       regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_AD_REG_SECOND_D),
+       regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_ID_32_31),
+       regmap_reg_range(DA9063_REG_SEQ_A, DA9063_REG_AUTO3_LOW),
+       regmap_reg_range(DA9063_REG_T_OFFSET, DA9063_AD_REG_GP_ID_19),
+       regmap_reg_range(DA9063_REG_CHIP_ID, DA9063_REG_CHIP_VARIANT),
 };
 
 static const struct regmap_range da9063_ad_writeable_ranges[] = {
-       {
-               .range_min = DA9063_REG_PAGE_CON,
-               .range_max = DA9063_REG_PAGE_CON,
-       }, {
-               .range_min = DA9063_REG_FAULT_LOG,
-               .range_max = DA9063_REG_VSYS_MON,
-       }, {
-               .range_min = DA9063_REG_COUNT_S,
-               .range_max = DA9063_AD_REG_ALARM_Y,
-       }, {
-               .range_min = DA9063_REG_SEQ,
-               .range_max = DA9063_REG_ID_32_31,
-       }, {
-               .range_min = DA9063_REG_SEQ_A,
-               .range_max = DA9063_REG_AUTO3_LOW,
-       }, {
-               .range_min = DA9063_REG_CONFIG_I,
-               .range_max = DA9063_AD_REG_MON_REG_4,
-       }, {
-               .range_min = DA9063_AD_REG_GP_ID_0,
-               .range_max = DA9063_AD_REG_GP_ID_19,
-       },
+       regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_REG_PAGE_CON),
+       regmap_reg_range(DA9063_REG_FAULT_LOG, DA9063_REG_VSYS_MON),
+       regmap_reg_range(DA9063_REG_COUNT_S, DA9063_AD_REG_ALARM_Y),
+       regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_ID_32_31),
+       regmap_reg_range(DA9063_REG_SEQ_A, DA9063_REG_AUTO3_LOW),
+       regmap_reg_range(DA9063_REG_CONFIG_I, DA9063_AD_REG_MON_REG_4),
+       regmap_reg_range(DA9063_AD_REG_GP_ID_0, DA9063_AD_REG_GP_ID_19),
 };
 
 static const struct regmap_range da9063_ad_volatile_ranges[] = {
-       {
-               .range_min = DA9063_REG_PAGE_CON,
-               .range_max = DA9063_REG_EVENT_D,
-       }, {
-               .range_min = DA9063_REG_CONTROL_A,
-               .range_max = DA9063_REG_CONTROL_B,
-       }, {
-               .range_min = DA9063_REG_CONTROL_E,
-               .range_max = DA9063_REG_CONTROL_F,
-       }, {
-               .range_min = DA9063_REG_BCORE2_CONT,
-               .range_max = DA9063_REG_LDO11_CONT,
-       }, {
-               .range_min = DA9063_REG_DVC_1,
-               .range_max = DA9063_REG_ADC_MAN,
-       }, {
-               .range_min = DA9063_REG_ADC_RES_L,
-               .range_max = DA9063_AD_REG_SECOND_D,
-       }, {
-               .range_min = DA9063_REG_SEQ,
-               .range_max = DA9063_REG_SEQ,
-       }, {
-               .range_min = DA9063_REG_EN_32K,
-               .range_max = DA9063_REG_EN_32K,
-       }, {
-               .range_min = DA9063_AD_REG_MON_REG_5,
-               .range_max = DA9063_AD_REG_MON_REG_6,
-       },
+       regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_REG_EVENT_D),
+       regmap_reg_range(DA9063_REG_CONTROL_A, DA9063_REG_CONTROL_B),
+       regmap_reg_range(DA9063_REG_CONTROL_E, DA9063_REG_CONTROL_F),
+       regmap_reg_range(DA9063_REG_BCORE2_CONT, DA9063_REG_LDO11_CONT),
+       regmap_reg_range(DA9063_REG_DVC_1, DA9063_REG_ADC_MAN),
+       regmap_reg_range(DA9063_REG_ADC_RES_L, DA9063_AD_REG_SECOND_D),
+       regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_SEQ),
+       regmap_reg_range(DA9063_REG_EN_32K, DA9063_REG_EN_32K),
+       regmap_reg_range(DA9063_AD_REG_MON_REG_5, DA9063_AD_REG_MON_REG_6),
 };
 
 static const struct regmap_access_table da9063_ad_readable_table = {
@@ -119,78 +74,33 @@ static const struct regmap_access_table da9063_ad_volatile_table = {
 };
 
 static const struct regmap_range da9063_bb_readable_ranges[] = {
-       {
-               .range_min = DA9063_REG_PAGE_CON,
-               .range_max = DA9063_BB_REG_SECOND_D,
-       }, {
-               .range_min = DA9063_REG_SEQ,
-               .range_max = DA9063_REG_ID_32_31,
-       }, {
-               .range_min = DA9063_REG_SEQ_A,
-               .range_max = DA9063_REG_AUTO3_LOW,
-       }, {
-               .range_min = DA9063_REG_T_OFFSET,
-               .range_max = DA9063_BB_REG_GP_ID_19,
-       }, {
-               .range_min = DA9063_REG_CHIP_ID,
-               .range_max = DA9063_REG_CHIP_VARIANT,
-       },
+       regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_BB_REG_SECOND_D),
+       regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_ID_32_31),
+       regmap_reg_range(DA9063_REG_SEQ_A, DA9063_REG_AUTO3_LOW),
+       regmap_reg_range(DA9063_REG_T_OFFSET, DA9063_BB_REG_GP_ID_19),
+       regmap_reg_range(DA9063_REG_CHIP_ID, DA9063_REG_CHIP_VARIANT),
 };
 
 static const struct regmap_range da9063_bb_writeable_ranges[] = {
-       {
-               .range_min = DA9063_REG_PAGE_CON,
-               .range_max = DA9063_REG_PAGE_CON,
-       }, {
-               .range_min = DA9063_REG_FAULT_LOG,
-               .range_max = DA9063_REG_VSYS_MON,
-       }, {
-               .range_min = DA9063_REG_COUNT_S,
-               .range_max = DA9063_BB_REG_ALARM_Y,
-       }, {
-               .range_min = DA9063_REG_SEQ,
-               .range_max = DA9063_REG_ID_32_31,
-       }, {
-               .range_min = DA9063_REG_SEQ_A,
-               .range_max = DA9063_REG_AUTO3_LOW,
-       }, {
-               .range_min = DA9063_REG_CONFIG_I,
-               .range_max = DA9063_BB_REG_MON_REG_4,
-       }, {
-               .range_min = DA9063_BB_REG_GP_ID_0,
-               .range_max = DA9063_BB_REG_GP_ID_19,
-       },
+       regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_REG_PAGE_CON),
+       regmap_reg_range(DA9063_REG_FAULT_LOG, DA9063_REG_VSYS_MON),
+       regmap_reg_range(DA9063_REG_COUNT_S, DA9063_BB_REG_ALARM_Y),
+       regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_ID_32_31),
+       regmap_reg_range(DA9063_REG_SEQ_A, DA9063_REG_AUTO3_LOW),
+       regmap_reg_range(DA9063_REG_CONFIG_I, DA9063_BB_REG_MON_REG_4),
+       regmap_reg_range(DA9063_BB_REG_GP_ID_0, DA9063_BB_REG_GP_ID_19),
 };
 
 static const struct regmap_range da9063_bb_volatile_ranges[] = {
-       {
-               .range_min = DA9063_REG_PAGE_CON,
-               .range_max = DA9063_REG_EVENT_D,
-       }, {
-               .range_min = DA9063_REG_CONTROL_A,
-               .range_max = DA9063_REG_CONTROL_B,
-       }, {
-               .range_min = DA9063_REG_CONTROL_E,
-               .range_max = DA9063_REG_CONTROL_F,
-       }, {
-               .range_min = DA9063_REG_BCORE2_CONT,
-               .range_max = DA9063_REG_LDO11_CONT,
-       }, {
-               .range_min = DA9063_REG_DVC_1,
-               .range_max = DA9063_REG_ADC_MAN,
-       }, {
-               .range_min = DA9063_REG_ADC_RES_L,
-               .range_max = DA9063_BB_REG_SECOND_D,
-       }, {
-               .range_min = DA9063_REG_SEQ,
-               .range_max = DA9063_REG_SEQ,
-       }, {
-               .range_min = DA9063_REG_EN_32K,
-               .range_max = DA9063_REG_EN_32K,
-       }, {
-               .range_min = DA9063_BB_REG_MON_REG_5,
-               .range_max = DA9063_BB_REG_MON_REG_6,
-       },
+       regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_REG_EVENT_D),
+       regmap_reg_range(DA9063_REG_CONTROL_A, DA9063_REG_CONTROL_B),
+       regmap_reg_range(DA9063_REG_CONTROL_E, DA9063_REG_CONTROL_F),
+       regmap_reg_range(DA9063_REG_BCORE2_CONT, DA9063_REG_LDO11_CONT),
+       regmap_reg_range(DA9063_REG_DVC_1, DA9063_REG_ADC_MAN),
+       regmap_reg_range(DA9063_REG_ADC_RES_L, DA9063_BB_REG_SECOND_D),
+       regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_SEQ),
+       regmap_reg_range(DA9063_REG_EN_32K, DA9063_REG_EN_32K),
+       regmap_reg_range(DA9063_BB_REG_MON_REG_5, DA9063_BB_REG_MON_REG_6),
 };
 
 static const struct regmap_access_table da9063_bb_readable_table = {
@@ -208,6 +118,50 @@ static const struct regmap_access_table da9063_bb_volatile_table = {
        .n_yes_ranges = ARRAY_SIZE(da9063_bb_volatile_ranges),
 };
 
+static const struct regmap_range da9063l_bb_readable_ranges[] = {
+       regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_REG_MON_A10_RES),
+       regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_ID_32_31),
+       regmap_reg_range(DA9063_REG_SEQ_A, DA9063_REG_AUTO3_LOW),
+       regmap_reg_range(DA9063_REG_T_OFFSET, DA9063_BB_REG_GP_ID_19),
+       regmap_reg_range(DA9063_REG_CHIP_ID, DA9063_REG_CHIP_VARIANT),
+};
+
+static const struct regmap_range da9063l_bb_writeable_ranges[] = {
+       regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_REG_PAGE_CON),
+       regmap_reg_range(DA9063_REG_FAULT_LOG, DA9063_REG_VSYS_MON),
+       regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_ID_32_31),
+       regmap_reg_range(DA9063_REG_SEQ_A, DA9063_REG_AUTO3_LOW),
+       regmap_reg_range(DA9063_REG_CONFIG_I, DA9063_BB_REG_MON_REG_4),
+       regmap_reg_range(DA9063_BB_REG_GP_ID_0, DA9063_BB_REG_GP_ID_19),
+};
+
+static const struct regmap_range da9063l_bb_volatile_ranges[] = {
+       regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_REG_EVENT_D),
+       regmap_reg_range(DA9063_REG_CONTROL_A, DA9063_REG_CONTROL_B),
+       regmap_reg_range(DA9063_REG_CONTROL_E, DA9063_REG_CONTROL_F),
+       regmap_reg_range(DA9063_REG_BCORE2_CONT, DA9063_REG_LDO11_CONT),
+       regmap_reg_range(DA9063_REG_DVC_1, DA9063_REG_ADC_MAN),
+       regmap_reg_range(DA9063_REG_ADC_RES_L, DA9063_REG_MON_A10_RES),
+       regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_SEQ),
+       regmap_reg_range(DA9063_REG_EN_32K, DA9063_REG_EN_32K),
+       regmap_reg_range(DA9063_BB_REG_MON_REG_5, DA9063_BB_REG_MON_REG_6),
+};
+
+static const struct regmap_access_table da9063l_bb_readable_table = {
+       .yes_ranges = da9063l_bb_readable_ranges,
+       .n_yes_ranges = ARRAY_SIZE(da9063l_bb_readable_ranges),
+};
+
+static const struct regmap_access_table da9063l_bb_writeable_table = {
+       .yes_ranges = da9063l_bb_writeable_ranges,
+       .n_yes_ranges = ARRAY_SIZE(da9063l_bb_writeable_ranges),
+};
+
+static const struct regmap_access_table da9063l_bb_volatile_table = {
+       .yes_ranges = da9063l_bb_volatile_ranges,
+       .n_yes_ranges = ARRAY_SIZE(da9063l_bb_volatile_ranges),
+};
+
 static const struct regmap_range_cfg da9063_range_cfg[] = {
        {
                .range_min = DA9063_REG_PAGE_CON,
@@ -232,11 +186,12 @@ static struct regmap_config da9063_regmap_config = {
 
 static const struct of_device_id da9063_dt_ids[] = {
        { .compatible = "dlg,da9063", },
+       { .compatible = "dlg,da9063l", },
        { }
 };
 MODULE_DEVICE_TABLE(of, da9063_dt_ids);
 static int da9063_i2c_probe(struct i2c_client *i2c,
-       const struct i2c_device_id *id)
+                           const struct i2c_device_id *id)
 {
        struct da9063 *da9063;
        int ret;
@@ -248,11 +203,16 @@ static int da9063_i2c_probe(struct i2c_client *i2c,
        i2c_set_clientdata(i2c, da9063);
        da9063->dev = &i2c->dev;
        da9063->chip_irq = i2c->irq;
+       da9063->type = id->driver_data;
 
        if (da9063->variant_code == PMIC_DA9063_AD) {
                da9063_regmap_config.rd_table = &da9063_ad_readable_table;
                da9063_regmap_config.wr_table = &da9063_ad_writeable_table;
                da9063_regmap_config.volatile_table = &da9063_ad_volatile_table;
+       } else if (da9063->type == PMIC_TYPE_DA9063L) {
+               da9063_regmap_config.rd_table = &da9063l_bb_readable_table;
+               da9063_regmap_config.wr_table = &da9063l_bb_writeable_table;
+               da9063_regmap_config.volatile_table = &da9063l_bb_volatile_table;
        } else {
                da9063_regmap_config.rd_table = &da9063_bb_readable_table;
                da9063_regmap_config.wr_table = &da9063_bb_writeable_table;
@@ -270,17 +230,9 @@ static int da9063_i2c_probe(struct i2c_client *i2c,
        return da9063_device_init(da9063, i2c->irq);
 }
 
-static int da9063_i2c_remove(struct i2c_client *i2c)
-{
-       struct da9063 *da9063 = i2c_get_clientdata(i2c);
-
-       da9063_device_exit(da9063);
-
-       return 0;
-}
-
 static const struct i2c_device_id da9063_i2c_id[] = {
-       {"da9063", PMIC_DA9063},
+       { "da9063", PMIC_TYPE_DA9063 },
+       { "da9063l", PMIC_TYPE_DA9063L },
        {},
 };
 MODULE_DEVICE_TABLE(i2c, da9063_i2c_id);
@@ -291,7 +243,6 @@ static struct i2c_driver da9063_i2c_driver = {
                .of_match_table = of_match_ptr(da9063_dt_ids),
        },
        .probe    = da9063_i2c_probe,
-       .remove   = da9063_i2c_remove,
        .id_table = da9063_i2c_id,
 };
 
index 207bbfe..ecc0c8c 100644 (file)
 
 static const struct regmap_irq da9063_irqs[] = {
        /* DA9063 event A register */
-       [DA9063_IRQ_ONKEY] = {
-               .reg_offset = DA9063_REG_EVENT_A_OFFSET,
-               .mask = DA9063_M_ONKEY,
-       },
-       [DA9063_IRQ_ALARM] = {
-               .reg_offset = DA9063_REG_EVENT_A_OFFSET,
-               .mask = DA9063_M_ALARM,
-       },
-       [DA9063_IRQ_TICK] = {
-               .reg_offset = DA9063_REG_EVENT_A_OFFSET,
-               .mask = DA9063_M_TICK,
-       },
-       [DA9063_IRQ_ADC_RDY] = {
-               .reg_offset = DA9063_REG_EVENT_A_OFFSET,
-               .mask = DA9063_M_ADC_RDY,
-       },
-       [DA9063_IRQ_SEQ_RDY] = {
-               .reg_offset = DA9063_REG_EVENT_A_OFFSET,
-               .mask = DA9063_M_SEQ_RDY,
-       },
+       REGMAP_IRQ_REG(DA9063_IRQ_ONKEY,
+                      DA9063_REG_EVENT_A_OFFSET, DA9063_M_ONKEY),
+       REGMAP_IRQ_REG(DA9063_IRQ_ALARM,
+                      DA9063_REG_EVENT_A_OFFSET, DA9063_M_ALARM),
+       REGMAP_IRQ_REG(DA9063_IRQ_TICK,
+                      DA9063_REG_EVENT_A_OFFSET, DA9063_M_TICK),
+       REGMAP_IRQ_REG(DA9063_IRQ_ADC_RDY,
+                      DA9063_REG_EVENT_A_OFFSET, DA9063_M_ADC_RDY),
+       REGMAP_IRQ_REG(DA9063_IRQ_SEQ_RDY,
+                      DA9063_REG_EVENT_A_OFFSET, DA9063_M_SEQ_RDY),
        /* DA9063 event B register */
-       [DA9063_IRQ_WAKE] = {
-               .reg_offset = DA9063_REG_EVENT_B_OFFSET,
-               .mask = DA9063_M_WAKE,
-       },
-       [DA9063_IRQ_TEMP] = {
-               .reg_offset = DA9063_REG_EVENT_B_OFFSET,
-               .mask = DA9063_M_TEMP,
-       },
-       [DA9063_IRQ_COMP_1V2] = {
-               .reg_offset = DA9063_REG_EVENT_B_OFFSET,
-               .mask = DA9063_M_COMP_1V2,
-       },
-       [DA9063_IRQ_LDO_LIM] = {
-               .reg_offset = DA9063_REG_EVENT_B_OFFSET,
-               .mask = DA9063_M_LDO_LIM,
-       },
-       [DA9063_IRQ_REG_UVOV] = {
-               .reg_offset = DA9063_REG_EVENT_B_OFFSET,
-               .mask = DA9063_M_UVOV,
-       },
-       [DA9063_IRQ_DVC_RDY] = {
-               .reg_offset = DA9063_REG_EVENT_B_OFFSET,
-               .mask = DA9063_M_DVC_RDY,
-       },
-       [DA9063_IRQ_VDD_MON] = {
-               .reg_offset = DA9063_REG_EVENT_B_OFFSET,
-               .mask = DA9063_M_VDD_MON,
-       },
-       [DA9063_IRQ_WARN] = {
-               .reg_offset = DA9063_REG_EVENT_B_OFFSET,
-               .mask = DA9063_M_VDD_WARN,
-       },
+       REGMAP_IRQ_REG(DA9063_IRQ_WAKE,
+                      DA9063_REG_EVENT_B_OFFSET, DA9063_M_WAKE),
+       REGMAP_IRQ_REG(DA9063_IRQ_TEMP,
+                      DA9063_REG_EVENT_B_OFFSET, DA9063_M_TEMP),
+       REGMAP_IRQ_REG(DA9063_IRQ_COMP_1V2,
+                      DA9063_REG_EVENT_B_OFFSET, DA9063_M_COMP_1V2),
+       REGMAP_IRQ_REG(DA9063_IRQ_LDO_LIM,
+                      DA9063_REG_EVENT_B_OFFSET, DA9063_M_LDO_LIM),
+       REGMAP_IRQ_REG(DA9063_IRQ_REG_UVOV,
+                      DA9063_REG_EVENT_B_OFFSET, DA9063_M_UVOV),
+       REGMAP_IRQ_REG(DA9063_IRQ_DVC_RDY,
+                      DA9063_REG_EVENT_B_OFFSET, DA9063_M_DVC_RDY),
+       REGMAP_IRQ_REG(DA9063_IRQ_VDD_MON,
+                      DA9063_REG_EVENT_B_OFFSET, DA9063_M_VDD_MON),
+       REGMAP_IRQ_REG(DA9063_IRQ_WARN,
+                      DA9063_REG_EVENT_B_OFFSET, DA9063_M_VDD_WARN),
        /* DA9063 event C register */
-       [DA9063_IRQ_GPI0] = {
-               .reg_offset = DA9063_REG_EVENT_C_OFFSET,
-               .mask = DA9063_M_GPI0,
-       },
-       [DA9063_IRQ_GPI1] = {
-               .reg_offset = DA9063_REG_EVENT_C_OFFSET,
-               .mask = DA9063_M_GPI1,
-       },
-       [DA9063_IRQ_GPI2] = {
-               .reg_offset = DA9063_REG_EVENT_C_OFFSET,
-               .mask = DA9063_M_GPI2,
-       },
-       [DA9063_IRQ_GPI3] = {
-               .reg_offset = DA9063_REG_EVENT_C_OFFSET,
-               .mask = DA9063_M_GPI3,
-       },
-       [DA9063_IRQ_GPI4] = {
-               .reg_offset = DA9063_REG_EVENT_C_OFFSET,
-               .mask = DA9063_M_GPI4,
-       },
-       [DA9063_IRQ_GPI5] = {
-               .reg_offset = DA9063_REG_EVENT_C_OFFSET,
-               .mask = DA9063_M_GPI5,
-       },
-       [DA9063_IRQ_GPI6] = {
-               .reg_offset = DA9063_REG_EVENT_C_OFFSET,
-               .mask = DA9063_M_GPI6,
-       },
-       [DA9063_IRQ_GPI7] = {
-               .reg_offset = DA9063_REG_EVENT_C_OFFSET,
-               .mask = DA9063_M_GPI7,
-       },
+       REGMAP_IRQ_REG(DA9063_IRQ_GPI0,
+                      DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI0),
+       REGMAP_IRQ_REG(DA9063_IRQ_GPI1,
+                      DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI1),
+       REGMAP_IRQ_REG(DA9063_IRQ_GPI2,
+                      DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI2),
+       REGMAP_IRQ_REG(DA9063_IRQ_GPI3,
+                      DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI3),
+       REGMAP_IRQ_REG(DA9063_IRQ_GPI4,
+                      DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI4),
+       REGMAP_IRQ_REG(DA9063_IRQ_GPI5,
+                      DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI5),
+       REGMAP_IRQ_REG(DA9063_IRQ_GPI6,
+                      DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI6),
+       REGMAP_IRQ_REG(DA9063_IRQ_GPI7,
+                      DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI7),
        /* DA9063 event D register */
-       [DA9063_IRQ_GPI8] = {
-               .reg_offset = DA9063_REG_EVENT_D_OFFSET,
-               .mask = DA9063_M_GPI8,
-       },
-       [DA9063_IRQ_GPI9] = {
-               .reg_offset = DA9063_REG_EVENT_D_OFFSET,
-               .mask = DA9063_M_GPI9,
-       },
-       [DA9063_IRQ_GPI10] = {
-               .reg_offset = DA9063_REG_EVENT_D_OFFSET,
-               .mask = DA9063_M_GPI10,
-       },
-       [DA9063_IRQ_GPI11] = {
-               .reg_offset = DA9063_REG_EVENT_D_OFFSET,
-               .mask = DA9063_M_GPI11,
-       },
-       [DA9063_IRQ_GPI12] = {
-               .reg_offset = DA9063_REG_EVENT_D_OFFSET,
-               .mask = DA9063_M_GPI12,
-       },
-       [DA9063_IRQ_GPI13] = {
-               .reg_offset = DA9063_REG_EVENT_D_OFFSET,
-               .mask = DA9063_M_GPI13,
-       },
-       [DA9063_IRQ_GPI14] = {
-               .reg_offset = DA9063_REG_EVENT_D_OFFSET,
-               .mask = DA9063_M_GPI14,
-       },
-       [DA9063_IRQ_GPI15] = {
-               .reg_offset = DA9063_REG_EVENT_D_OFFSET,
-               .mask = DA9063_M_GPI15,
-       },
+       REGMAP_IRQ_REG(DA9063_IRQ_GPI8,
+                      DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI8),
+       REGMAP_IRQ_REG(DA9063_IRQ_GPI9,
+                      DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI9),
+       REGMAP_IRQ_REG(DA9063_IRQ_GPI10,
+                      DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI10),
+       REGMAP_IRQ_REG(DA9063_IRQ_GPI11,
+                      DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI11),
+       REGMAP_IRQ_REG(DA9063_IRQ_GPI12,
+                      DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI12),
+       REGMAP_IRQ_REG(DA9063_IRQ_GPI13,
+                      DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI13),
+       REGMAP_IRQ_REG(DA9063_IRQ_GPI14,
+                      DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI14),
+       REGMAP_IRQ_REG(DA9063_IRQ_GPI15,
+                      DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI15),
 };
 
 static const struct regmap_irq_chip da9063_irq_chip = {
        .name = "da9063-irq",
        .irqs = da9063_irqs,
-       .num_irqs = DA9063_NUM_IRQ,
+       .num_irqs = ARRAY_SIZE(da9063_irqs),
+       .num_regs = 4,
+       .status_base = DA9063_REG_EVENT_A,
+       .mask_base = DA9063_REG_IRQ_MASK_A,
+       .ack_base = DA9063_REG_EVENT_A,
+       .init_ack_masked = true,
+};
+
+static const struct regmap_irq da9063l_irqs[] = {
+       /* DA9063 event A register */
+       REGMAP_IRQ_REG(DA9063_IRQ_ONKEY,
+                      DA9063_REG_EVENT_A_OFFSET, DA9063_M_ONKEY),
+       REGMAP_IRQ_REG(DA9063_IRQ_ADC_RDY,
+                      DA9063_REG_EVENT_A_OFFSET, DA9063_M_ADC_RDY),
+       REGMAP_IRQ_REG(DA9063_IRQ_SEQ_RDY,
+                      DA9063_REG_EVENT_A_OFFSET, DA9063_M_SEQ_RDY),
+       /* DA9063 event B register */
+       REGMAP_IRQ_REG(DA9063_IRQ_WAKE,
+                      DA9063_REG_EVENT_B_OFFSET, DA9063_M_WAKE),
+       REGMAP_IRQ_REG(DA9063_IRQ_TEMP,
+                      DA9063_REG_EVENT_B_OFFSET, DA9063_M_TEMP),
+       REGMAP_IRQ_REG(DA9063_IRQ_COMP_1V2,
+                      DA9063_REG_EVENT_B_OFFSET, DA9063_M_COMP_1V2),
+       REGMAP_IRQ_REG(DA9063_IRQ_LDO_LIM,
+                      DA9063_REG_EVENT_B_OFFSET, DA9063_M_LDO_LIM),
+       REGMAP_IRQ_REG(DA9063_IRQ_REG_UVOV,
+                      DA9063_REG_EVENT_B_OFFSET, DA9063_M_UVOV),
+       REGMAP_IRQ_REG(DA9063_IRQ_DVC_RDY,
+                      DA9063_REG_EVENT_B_OFFSET, DA9063_M_DVC_RDY),
+       REGMAP_IRQ_REG(DA9063_IRQ_VDD_MON,
+                      DA9063_REG_EVENT_B_OFFSET, DA9063_M_VDD_MON),
+       REGMAP_IRQ_REG(DA9063_IRQ_WARN,
+                      DA9063_REG_EVENT_B_OFFSET, DA9063_M_VDD_WARN),
+       /* DA9063 event C register */
+       REGMAP_IRQ_REG(DA9063_IRQ_GPI0,
+                      DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI0),
+       REGMAP_IRQ_REG(DA9063_IRQ_GPI1,
+                      DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI1),
+       REGMAP_IRQ_REG(DA9063_IRQ_GPI2,
+                      DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI2),
+       REGMAP_IRQ_REG(DA9063_IRQ_GPI3,
+                      DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI3),
+       REGMAP_IRQ_REG(DA9063_IRQ_GPI4,
+                      DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI4),
+       REGMAP_IRQ_REG(DA9063_IRQ_GPI5,
+                      DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI5),
+       REGMAP_IRQ_REG(DA9063_IRQ_GPI6,
+                      DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI6),
+       REGMAP_IRQ_REG(DA9063_IRQ_GPI7,
+                      DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI7),
+       /* DA9063 event D register */
+       REGMAP_IRQ_REG(DA9063_IRQ_GPI8,
+                      DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI8),
+       REGMAP_IRQ_REG(DA9063_IRQ_GPI9,
+                      DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI9),
+       REGMAP_IRQ_REG(DA9063_IRQ_GPI10,
+                      DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI10),
+       REGMAP_IRQ_REG(DA9063_IRQ_GPI11,
+                      DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI11),
+       REGMAP_IRQ_REG(DA9063_IRQ_GPI12,
+                      DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI12),
+       REGMAP_IRQ_REG(DA9063_IRQ_GPI13,
+                      DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI13),
+       REGMAP_IRQ_REG(DA9063_IRQ_GPI14,
+                      DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI14),
+       REGMAP_IRQ_REG(DA9063_IRQ_GPI15,
+                      DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI15),
+};
 
+static const struct regmap_irq_chip da9063l_irq_chip = {
+       .name = "da9063l-irq",
+       .irqs = da9063l_irqs,
+       .num_irqs = ARRAY_SIZE(da9063l_irqs),
        .num_regs = 4,
        .status_base = DA9063_REG_EVENT_A,
        .mask_base = DA9063_REG_IRQ_MASK_A,
@@ -163,6 +176,7 @@ static const struct regmap_irq_chip da9063_irq_chip = {
 
 int da9063_irq_init(struct da9063 *da9063)
 {
+       const struct regmap_irq_chip *irq_chip;
        int ret;
 
        if (!da9063->chip_irq) {
@@ -170,10 +184,15 @@ int da9063_irq_init(struct da9063 *da9063)
                return -EINVAL;
        }
 
-       ret = regmap_add_irq_chip(da9063->regmap, da9063->chip_irq,
+       if (da9063->type == PMIC_TYPE_DA9063)
+               irq_chip = &da9063_irq_chip;
+       else
+               irq_chip = &da9063l_irq_chip;
+
+       ret = devm_regmap_add_irq_chip(da9063->dev, da9063->regmap,
+                       da9063->chip_irq,
                        IRQF_TRIGGER_LOW | IRQF_ONESHOT | IRQF_SHARED,
-                       da9063->irq_base, &da9063_irq_chip,
-                       &da9063->regmap_irq);
+                       da9063->irq_base, irq_chip, &da9063->regmap_irq);
        if (ret) {
                dev_err(da9063->dev, "Failed to reguest IRQ %d: %d\n",
                                da9063->chip_irq, ret);
@@ -182,8 +201,3 @@ int da9063_irq_init(struct da9063 *da9063)
 
        return 0;
 }
-
-void da9063_irq_exit(struct da9063 *da9063)
-{
-       regmap_del_irq_chip(da9063->chip_irq, da9063->regmap_irq);
-}
index 704e189..90e7899 100644 (file)
@@ -194,6 +194,7 @@ static bool dln2_transfer_complete(struct dln2_dev *dln2, struct urb *urb,
        struct device *dev = &dln2->interface->dev;
        struct dln2_mod_rx_slots *rxs = &dln2->mod_rx_slots[handle];
        struct dln2_rx_context *rxc;
+       unsigned long flags;
        bool valid_slot = false;
 
        if (rx_slot >= DLN2_MAX_RX_SLOTS)
@@ -201,18 +202,13 @@ static bool dln2_transfer_complete(struct dln2_dev *dln2, struct urb *urb,
 
        rxc = &rxs->slots[rx_slot];
 
-       /*
-        * No need to disable interrupts as this lock is not taken in interrupt
-        * context elsewhere in this driver. This function (or its callers) are
-        * also not exported to other modules.
-        */
-       spin_lock(&rxs->lock);
+       spin_lock_irqsave(&rxs->lock, flags);
        if (rxc->in_use && !rxc->urb) {
                rxc->urb = urb;
                complete(&rxc->done);
                valid_slot = true;
        }
-       spin_unlock(&rxs->lock);
+       spin_unlock_irqrestore(&rxs->lock, flags);
 
 out:
        if (!valid_slot)
index c37ccbf..96c07fa 100644 (file)
@@ -49,7 +49,7 @@ static struct regmap_config hi655x_regmap_config = {
        .reg_bits = 32,
        .reg_stride = HI655X_STRIDE,
        .val_bits = 8,
-       .max_register = HI655X_BUS_ADDR(0xFFF),
+       .max_register = HI655X_BUS_ADDR(0x400) - HI655X_STRIDE,
 };
 
 static struct resource pwrkey_resources[] = {
index d9ae983..0e5282f 100644 (file)
@@ -178,6 +178,19 @@ static const struct pci_device_id intel_lpss_pci_ids[] = {
        { PCI_VDEVICE(INTEL, 0x31c2), (kernel_ulong_t)&bxt_info },
        { PCI_VDEVICE(INTEL, 0x31c4), (kernel_ulong_t)&bxt_info },
        { PCI_VDEVICE(INTEL, 0x31c6), (kernel_ulong_t)&bxt_info },
+       /* ICL-LP */
+       { PCI_VDEVICE(INTEL, 0x34a8), (kernel_ulong_t)&spt_uart_info },
+       { PCI_VDEVICE(INTEL, 0x34a9), (kernel_ulong_t)&spt_uart_info },
+       { PCI_VDEVICE(INTEL, 0x34aa), (kernel_ulong_t)&spt_info },
+       { PCI_VDEVICE(INTEL, 0x34ab), (kernel_ulong_t)&spt_info },
+       { PCI_VDEVICE(INTEL, 0x34c5), (kernel_ulong_t)&bxt_i2c_info },
+       { PCI_VDEVICE(INTEL, 0x34c6), (kernel_ulong_t)&bxt_i2c_info },
+       { PCI_VDEVICE(INTEL, 0x34c7), (kernel_ulong_t)&spt_uart_info },
+       { PCI_VDEVICE(INTEL, 0x34e8), (kernel_ulong_t)&bxt_i2c_info },
+       { PCI_VDEVICE(INTEL, 0x34e9), (kernel_ulong_t)&bxt_i2c_info },
+       { PCI_VDEVICE(INTEL, 0x34ea), (kernel_ulong_t)&bxt_i2c_info },
+       { PCI_VDEVICE(INTEL, 0x34eb), (kernel_ulong_t)&bxt_i2c_info },
+       { PCI_VDEVICE(INTEL, 0x34fb), (kernel_ulong_t)&spt_info },
        /* APL */
        { PCI_VDEVICE(INTEL, 0x5aac), (kernel_ulong_t)&apl_i2c_info },
        { PCI_VDEVICE(INTEL, 0x5aae), (kernel_ulong_t)&apl_i2c_info },
index 390b27c..fb5a10b 100644 (file)
@@ -143,7 +143,7 @@ static struct platform_device *kempld_pdev;
 
 static int kempld_create_platform_device(const struct dmi_system_id *id)
 {
-       struct kempld_platform_data *pdata = id->driver_data;
+       const struct kempld_platform_data *pdata = id->driver_data;
        int ret;
 
        kempld_pdev = platform_device_alloc("kempld", -1);
@@ -259,7 +259,7 @@ EXPORT_SYMBOL_GPL(kempld_write32);
  */
 void kempld_get_mutex(struct kempld_device_data *pld)
 {
-       struct kempld_platform_data *pdata = dev_get_platdata(pld->dev);
+       const struct kempld_platform_data *pdata = dev_get_platdata(pld->dev);
 
        mutex_lock(&pld->lock);
        pdata->get_hardware_mutex(pld);
@@ -272,7 +272,7 @@ EXPORT_SYMBOL_GPL(kempld_get_mutex);
  */
 void kempld_release_mutex(struct kempld_device_data *pld)
 {
-       struct kempld_platform_data *pdata = dev_get_platdata(pld->dev);
+       const struct kempld_platform_data *pdata = dev_get_platdata(pld->dev);
 
        pdata->release_hardware_mutex(pld);
        mutex_unlock(&pld->lock);
@@ -290,7 +290,7 @@ EXPORT_SYMBOL_GPL(kempld_release_mutex);
 static int kempld_get_info(struct kempld_device_data *pld)
 {
        int ret;
-       struct kempld_platform_data *pdata = dev_get_platdata(pld->dev);
+       const struct kempld_platform_data *pdata = dev_get_platdata(pld->dev);
        char major, minor;
 
        ret = pdata->get_info(pld);
@@ -332,7 +332,7 @@ static int kempld_get_info(struct kempld_device_data *pld)
  */
 static int kempld_register_cells(struct kempld_device_data *pld)
 {
-       struct kempld_platform_data *pdata = dev_get_platdata(pld->dev);
+       const struct kempld_platform_data *pdata = dev_get_platdata(pld->dev);
 
        return pdata->register_cells(pld);
 }
@@ -444,7 +444,8 @@ static int kempld_detect_device(struct kempld_device_data *pld)
 
 static int kempld_probe(struct platform_device *pdev)
 {
-       struct kempld_platform_data *pdata = dev_get_platdata(&pdev->dev);
+       const struct kempld_platform_data *pdata =
+               dev_get_platdata(&pdev->dev);
        struct device *dev = &pdev->dev;
        struct kempld_device_data *pld;
        struct resource *ioport;
@@ -476,7 +477,7 @@ static int kempld_probe(struct platform_device *pdev)
 static int kempld_remove(struct platform_device *pdev)
 {
        struct kempld_device_data *pld = platform_get_drvdata(pdev);
-       struct kempld_platform_data *pdata = dev_get_platdata(pld->dev);
+       const struct kempld_platform_data *pdata = dev_get_platdata(pld->dev);
 
        sysfs_remove_group(&pld->dev->kobj, &pld_attr_group);
 
diff --git a/drivers/mfd/madera-core.c b/drivers/mfd/madera-core.c
new file mode 100644 (file)
index 0000000..8cfea96
--- /dev/null
@@ -0,0 +1,609 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Core MFD support for Cirrus Logic Madera codecs
+ *
+ * Copyright (C) 2015-2018 Cirrus Logic
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2.
+ */
+
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/mfd/core.h>
+#include <linux/module.h>
+#include <linux/notifier.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/of_regulator.h>
+
+#include <linux/mfd/madera/core.h>
+#include <linux/mfd/madera/registers.h>
+
+#include "madera.h"
+
+#define CS47L35_SILICON_ID     0x6360
+#define CS47L85_SILICON_ID     0x6338
+#define CS47L90_SILICON_ID     0x6364
+
+#define MADERA_32KZ_MCLK2      1
+
+static const char * const madera_core_supplies[] = {
+       "AVDD",
+       "DBVDD1",
+};
+
+static const struct mfd_cell madera_ldo1_devs[] = {
+       { .name = "madera-ldo1" },
+};
+
+static const char * const cs47l35_supplies[] = {
+       "MICVDD",
+       "DBVDD2",
+       "CPVDD1",
+       "CPVDD2",
+       "SPKVDD",
+};
+
+static const struct mfd_cell cs47l35_devs[] = {
+       { .name = "madera-pinctrl", },
+       { .name = "madera-irq", },
+       { .name = "madera-micsupp", },
+       { .name = "madera-gpio", },
+       { .name = "madera-extcon", },
+       {
+               .name = "cs47l35-codec",
+               .parent_supplies = cs47l35_supplies,
+               .num_parent_supplies = ARRAY_SIZE(cs47l35_supplies),
+       },
+};
+
+static const char * const cs47l85_supplies[] = {
+       "MICVDD",
+       "DBVDD2",
+       "DBVDD3",
+       "DBVDD4",
+       "CPVDD1",
+       "CPVDD2",
+       "SPKVDDL",
+       "SPKVDDR",
+};
+
+static const struct mfd_cell cs47l85_devs[] = {
+       { .name = "madera-pinctrl", },
+       { .name = "madera-irq", },
+       { .name = "madera-micsupp" },
+       { .name = "madera-gpio", },
+       { .name = "madera-extcon", },
+       {
+               .name = "cs47l85-codec",
+               .parent_supplies = cs47l85_supplies,
+               .num_parent_supplies = ARRAY_SIZE(cs47l85_supplies),
+       },
+};
+
+static const char * const cs47l90_supplies[] = {
+       "MICVDD",
+       "DBVDD2",
+       "DBVDD3",
+       "DBVDD4",
+       "CPVDD1",
+       "CPVDD2",
+};
+
+static const struct mfd_cell cs47l90_devs[] = {
+       { .name = "madera-pinctrl", },
+       { .name = "madera-irq", },
+       { .name = "madera-micsupp", },
+       { .name = "madera-gpio", },
+       { .name = "madera-extcon", },
+       {
+               .name = "cs47l90-codec",
+               .parent_supplies = cs47l90_supplies,
+               .num_parent_supplies = ARRAY_SIZE(cs47l90_supplies),
+       },
+};
+
+/* Used by madera-i2c and madera-spi drivers */
+const char *madera_name_from_type(enum madera_type type)
+{
+       switch (type) {
+       case CS47L35:
+               return "CS47L35";
+       case CS47L85:
+               return "CS47L85";
+       case CS47L90:
+               return "CS47L90";
+       case CS47L91:
+               return "CS47L91";
+       case WM1840:
+               return "WM1840";
+       default:
+               return "Unknown";
+       }
+}
+EXPORT_SYMBOL_GPL(madera_name_from_type);
+
+#define MADERA_BOOT_POLL_MAX_INTERVAL_US  5000
+#define MADERA_BOOT_POLL_TIMEOUT_US     25000
+
+static int madera_wait_for_boot(struct madera *madera)
+{
+       unsigned int val;
+       int ret;
+
+       /*
+        * We can't use an interrupt as we need to runtime resume to do so,
+        * so we poll the status bit. This won't race with the interrupt
+        * handler because it will be blocked on runtime resume.
+        */
+       ret = regmap_read_poll_timeout(madera->regmap,
+                                      MADERA_IRQ1_RAW_STATUS_1,
+                                      val,
+                                      (val & MADERA_BOOT_DONE_STS1),
+                                      MADERA_BOOT_POLL_MAX_INTERVAL_US,
+                                      MADERA_BOOT_POLL_TIMEOUT_US);
+
+       if (ret)
+               dev_err(madera->dev, "Polling BOOT_DONE_STS failed: %d\n", ret);
+
+       /*
+        * BOOT_DONE defaults to unmasked on boot so we must ack it.
+        * Do this unconditionally to avoid interrupt storms.
+        */
+       regmap_write(madera->regmap, MADERA_IRQ1_STATUS_1,
+                    MADERA_BOOT_DONE_EINT1);
+
+       pm_runtime_mark_last_busy(madera->dev);
+
+       return ret;
+}
+
+static int madera_soft_reset(struct madera *madera)
+{
+       int ret;
+
+       ret = regmap_write(madera->regmap, MADERA_SOFTWARE_RESET, 0);
+       if (ret != 0) {
+               dev_err(madera->dev, "Failed to soft reset device: %d\n", ret);
+               return ret;
+       }
+
+       /* Allow time for internal clocks to startup after reset */
+       usleep_range(1000, 2000);
+
+       return 0;
+}
+
+static void madera_enable_hard_reset(struct madera *madera)
+{
+       if (!madera->pdata.reset)
+               return;
+
+       /*
+        * There are many existing out-of-tree users of these codecs that we
+        * can't break so preserve the expected behaviour of setting the line
+        * low to assert reset.
+        */
+       gpiod_set_raw_value_cansleep(madera->pdata.reset, 0);
+}
+
+static void madera_disable_hard_reset(struct madera *madera)
+{
+       if (!madera->pdata.reset)
+               return;
+
+       gpiod_set_raw_value_cansleep(madera->pdata.reset, 1);
+       usleep_range(1000, 2000);
+}
+
+static int __maybe_unused madera_runtime_resume(struct device *dev)
+{
+       struct madera *madera = dev_get_drvdata(dev);
+       int ret;
+
+       dev_dbg(dev, "Leaving sleep mode\n");
+
+       ret = regulator_enable(madera->dcvdd);
+       if (ret) {
+               dev_err(dev, "Failed to enable DCVDD: %d\n", ret);
+               return ret;
+       }
+
+       regcache_cache_only(madera->regmap, false);
+       regcache_cache_only(madera->regmap_32bit, false);
+
+       ret = madera_wait_for_boot(madera);
+       if (ret)
+               goto err;
+
+       ret = regcache_sync(madera->regmap);
+       if (ret) {
+               dev_err(dev, "Failed to restore 16-bit register cache\n");
+               goto err;
+       }
+
+       ret = regcache_sync(madera->regmap_32bit);
+       if (ret) {
+               dev_err(dev, "Failed to restore 32-bit register cache\n");
+               goto err;
+       }
+
+       return 0;
+
+err:
+       regcache_cache_only(madera->regmap_32bit, true);
+       regcache_cache_only(madera->regmap, true);
+       regulator_disable(madera->dcvdd);
+
+       return ret;
+}
+
+static int __maybe_unused madera_runtime_suspend(struct device *dev)
+{
+       struct madera *madera = dev_get_drvdata(dev);
+
+       dev_dbg(madera->dev, "Entering sleep mode\n");
+
+       regcache_cache_only(madera->regmap, true);
+       regcache_mark_dirty(madera->regmap);
+       regcache_cache_only(madera->regmap_32bit, true);
+       regcache_mark_dirty(madera->regmap_32bit);
+
+       regulator_disable(madera->dcvdd);
+
+       return 0;
+}
+
+const struct dev_pm_ops madera_pm_ops = {
+       SET_RUNTIME_PM_OPS(madera_runtime_suspend,
+                          madera_runtime_resume,
+                          NULL)
+};
+EXPORT_SYMBOL_GPL(madera_pm_ops);
+
+const struct of_device_id madera_of_match[] = {
+       { .compatible = "cirrus,cs47l35", .data = (void *)CS47L35 },
+       { .compatible = "cirrus,cs47l85", .data = (void *)CS47L85 },
+       { .compatible = "cirrus,cs47l90", .data = (void *)CS47L90 },
+       { .compatible = "cirrus,cs47l91", .data = (void *)CS47L91 },
+       { .compatible = "cirrus,wm1840", .data = (void *)WM1840 },
+       {}
+};
+EXPORT_SYMBOL_GPL(madera_of_match);
+
+static int madera_get_reset_gpio(struct madera *madera)
+{
+       struct gpio_desc *reset;
+       int ret;
+
+       if (madera->pdata.reset)
+               return 0;
+
+       reset = devm_gpiod_get_optional(madera->dev, "reset", GPIOD_OUT_LOW);
+       if (IS_ERR(reset)) {
+               ret = PTR_ERR(reset);
+               if (ret != -EPROBE_DEFER)
+                       dev_err(madera->dev, "Failed to request /RESET: %d\n",
+                               ret);
+               return ret;
+       }
+
+       /*
+        * A hard reset is needed for full reset of the chip. We allow running
+        * without hard reset only because it can be useful for early
+        * prototyping and some debugging, but we need to warn it's not ideal.
+        */
+       if (!reset)
+               dev_warn(madera->dev,
+                        "Running without reset GPIO is not recommended\n");
+
+       madera->pdata.reset = reset;
+
+       return 0;
+}
+
+static void madera_set_micbias_info(struct madera *madera)
+{
+       /*
+        * num_childbias is an array because future codecs can have different
+        * childbiases for each micbias. Unspecified values default to 0.
+        */
+       switch (madera->type) {
+       case CS47L35:
+               madera->num_micbias = 2;
+               madera->num_childbias[0] = 2;
+               madera->num_childbias[1] = 2;
+               return;
+       case CS47L85:
+       case WM1840:
+               madera->num_micbias = 4;
+               /* no child biases */
+               return;
+       case CS47L90:
+       case CS47L91:
+               madera->num_micbias = 2;
+               madera->num_childbias[0] = 4;
+               madera->num_childbias[1] = 4;
+               return;
+       default:
+               return;
+       }
+}
+
+int madera_dev_init(struct madera *madera)
+{
+       struct device *dev = madera->dev;
+       unsigned int hwid;
+       int (*patch_fn)(struct madera *) = NULL;
+       const struct mfd_cell *mfd_devs;
+       int n_devs = 0;
+       int i, ret;
+
+       dev_set_drvdata(madera->dev, madera);
+       BLOCKING_INIT_NOTIFIER_HEAD(&madera->notifier);
+       madera_set_micbias_info(madera);
+
+       /*
+        * We need writable hw config info that all children can share.
+        * Simplest to take one shared copy of pdata struct.
+        */
+       if (dev_get_platdata(madera->dev)) {
+               memcpy(&madera->pdata, dev_get_platdata(madera->dev),
+                      sizeof(madera->pdata));
+       }
+
+       ret = madera_get_reset_gpio(madera);
+       if (ret)
+               return ret;
+
+       regcache_cache_only(madera->regmap, true);
+       regcache_cache_only(madera->regmap_32bit, true);
+
+       for (i = 0; i < ARRAY_SIZE(madera_core_supplies); i++)
+               madera->core_supplies[i].supply = madera_core_supplies[i];
+
+       madera->num_core_supplies = ARRAY_SIZE(madera_core_supplies);
+
+       /*
+        * On some codecs DCVDD could be supplied by the internal LDO1.
+        * For those we must add the LDO1 driver before requesting DCVDD
+        * No devm_ because we need to control shutdown order of children.
+        */
+       switch (madera->type) {
+       case CS47L35:
+       case CS47L90:
+       case CS47L91:
+               break;
+       case CS47L85:
+       case WM1840:
+               ret = mfd_add_devices(madera->dev, PLATFORM_DEVID_NONE,
+                                     madera_ldo1_devs,
+                                     ARRAY_SIZE(madera_ldo1_devs),
+                                     NULL, 0, NULL);
+               if (ret) {
+                       dev_err(dev, "Failed to add LDO1 child: %d\n", ret);
+                       return ret;
+               }
+               break;
+       default:
+               /* No point continuing if the type is unknown */
+               dev_err(madera->dev, "Unknown device type %d\n", madera->type);
+               return -ENODEV;
+       }
+
+       ret = devm_regulator_bulk_get(dev, madera->num_core_supplies,
+                                     madera->core_supplies);
+       if (ret) {
+               dev_err(dev, "Failed to request core supplies: %d\n", ret);
+               goto err_devs;
+       }
+
+       /*
+        * Don't use devres here. If the regulator is one of our children it
+        * will already have been removed before devres cleanup on this mfd
+        * driver tries to call put() on it. We need control of shutdown order.
+        */
+       madera->dcvdd = regulator_get(madera->dev, "DCVDD");
+       if (IS_ERR(madera->dcvdd)) {
+               ret = PTR_ERR(madera->dcvdd);
+               dev_err(dev, "Failed to request DCVDD: %d\n", ret);
+               goto err_devs;
+       }
+
+       ret = regulator_bulk_enable(madera->num_core_supplies,
+                                   madera->core_supplies);
+       if (ret) {
+               dev_err(dev, "Failed to enable core supplies: %d\n", ret);
+               goto err_dcvdd;
+       }
+
+       ret = regulator_enable(madera->dcvdd);
+       if (ret) {
+               dev_err(dev, "Failed to enable DCVDD: %d\n", ret);
+               goto err_enable;
+       }
+
+       madera_disable_hard_reset(madera);
+
+       regcache_cache_only(madera->regmap, false);
+       regcache_cache_only(madera->regmap_32bit, false);
+
+       /*
+        * Now we can power up and verify that this is a chip we know about
+        * before we start doing any writes to its registers.
+        */
+       ret = regmap_read(madera->regmap, MADERA_SOFTWARE_RESET, &hwid);
+       if (ret) {
+               dev_err(dev, "Failed to read ID register: %d\n", ret);
+               goto err_reset;
+       }
+
+       switch (hwid) {
+       case CS47L35_SILICON_ID:
+               if (IS_ENABLED(CONFIG_MFD_CS47L35)) {
+                       switch (madera->type) {
+                       case CS47L35:
+                               patch_fn = cs47l35_patch;
+                               mfd_devs = cs47l35_devs;
+                               n_devs = ARRAY_SIZE(cs47l35_devs);
+                               break;
+                       default:
+                               break;
+                       }
+               }
+               break;
+       case CS47L85_SILICON_ID:
+               if (IS_ENABLED(CONFIG_MFD_CS47L85)) {
+                       switch (madera->type) {
+                       case CS47L85:
+                       case WM1840:
+                               patch_fn = cs47l85_patch;
+                               mfd_devs = cs47l85_devs;
+                               n_devs = ARRAY_SIZE(cs47l85_devs);
+                               break;
+                       default:
+                               break;
+                       }
+               }
+               break;
+       case CS47L90_SILICON_ID:
+               if (IS_ENABLED(CONFIG_MFD_CS47L90)) {
+                       switch (madera->type) {
+                       case CS47L90:
+                       case CS47L91:
+                               patch_fn = cs47l90_patch;
+                               mfd_devs = cs47l90_devs;
+                               n_devs = ARRAY_SIZE(cs47l90_devs);
+                               break;
+                       default:
+                               break;
+                       }
+               }
+               break;
+       default:
+               dev_err(madera->dev, "Unknown device ID: %x\n", hwid);
+               ret = -EINVAL;
+               goto err_reset;
+       }
+
+       if (!n_devs) {
+               dev_err(madera->dev, "Device ID 0x%x not a %s\n", hwid,
+                       madera->type_name);
+               ret = -ENODEV;
+               goto err_reset;
+       }
+
+       /*
+        * It looks like a device we support. If we don't have a hard reset
+        * we can now attempt a soft reset.
+        */
+       if (!madera->pdata.reset) {
+               ret = madera_soft_reset(madera);
+               if (ret)
+                       goto err_reset;
+       }
+
+       ret = madera_wait_for_boot(madera);
+       if (ret) {
+               dev_err(madera->dev, "Device failed initial boot: %d\n", ret);
+               goto err_reset;
+       }
+
+       ret = regmap_read(madera->regmap, MADERA_HARDWARE_REVISION,
+                         &madera->rev);
+       if (ret) {
+               dev_err(dev, "Failed to read revision register: %d\n", ret);
+               goto err_reset;
+       }
+       madera->rev &= MADERA_HW_REVISION_MASK;
+
+       dev_info(dev, "%s silicon revision %d\n", madera->type_name,
+                madera->rev);
+
+       /* Apply hardware patch */
+       if (patch_fn) {
+               ret = patch_fn(madera);
+               if (ret) {
+                       dev_err(madera->dev, "Failed to apply patch %d\n", ret);
+                       goto err_reset;
+               }
+       }
+
+       /* Init 32k clock sourced from MCLK2 */
+       ret = regmap_update_bits(madera->regmap,
+                       MADERA_CLOCK_32K_1,
+                       MADERA_CLK_32K_ENA_MASK | MADERA_CLK_32K_SRC_MASK,
+                       MADERA_CLK_32K_ENA | MADERA_32KZ_MCLK2);
+       if (ret) {
+               dev_err(madera->dev, "Failed to init 32k clock: %d\n", ret);
+               goto err_reset;
+       }
+
+       pm_runtime_set_active(madera->dev);
+       pm_runtime_enable(madera->dev);
+       pm_runtime_set_autosuspend_delay(madera->dev, 100);
+       pm_runtime_use_autosuspend(madera->dev);
+
+       /* No devm_ because we need to control shutdown order of children */
+       ret = mfd_add_devices(madera->dev, PLATFORM_DEVID_NONE,
+                             mfd_devs, n_devs,
+                             NULL, 0, NULL);
+       if (ret) {
+               dev_err(madera->dev, "Failed to add subdevices: %d\n", ret);
+               goto err_pm_runtime;
+       }
+
+       return 0;
+
+err_pm_runtime:
+       pm_runtime_disable(madera->dev);
+err_reset:
+       madera_enable_hard_reset(madera);
+       regulator_disable(madera->dcvdd);
+err_enable:
+       regulator_bulk_disable(madera->num_core_supplies,
+                              madera->core_supplies);
+err_dcvdd:
+       regulator_put(madera->dcvdd);
+err_devs:
+       mfd_remove_devices(dev);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(madera_dev_init);
+
+int madera_dev_exit(struct madera *madera)
+{
+       /* Prevent any IRQs being serviced while we clean up */
+       disable_irq(madera->irq);
+
+       /*
+        * DCVDD could be supplied by a child node, we must disable it before
+        * removing the children, and prevent PM runtime from turning it back on
+        */
+       pm_runtime_disable(madera->dev);
+
+       regulator_disable(madera->dcvdd);
+       regulator_put(madera->dcvdd);
+
+       mfd_remove_devices(madera->dev);
+       madera_enable_hard_reset(madera);
+
+       regulator_bulk_disable(madera->num_core_supplies,
+                              madera->core_supplies);
+       return 0;
+}
+EXPORT_SYMBOL_GPL(madera_dev_exit);
+
+MODULE_DESCRIPTION("Madera core MFD driver");
+MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/mfd/madera-i2c.c b/drivers/mfd/madera-i2c.c
new file mode 100644 (file)
index 0000000..05ae94b
--- /dev/null
@@ -0,0 +1,140 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * I2C bus interface to Cirrus Logic Madera codecs
+ *
+ * Copyright (C) 2015-2018 Cirrus Logic
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2.
+ */
+
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/regmap.h>
+
+#include <linux/mfd/madera/core.h>
+
+#include "madera.h"
+
+static int madera_i2c_probe(struct i2c_client *i2c,
+                           const struct i2c_device_id *id)
+{
+       struct madera *madera;
+       const struct regmap_config *regmap_16bit_config = NULL;
+       const struct regmap_config *regmap_32bit_config = NULL;
+       const void *of_data;
+       unsigned long type;
+       const char *name;
+       int ret;
+
+       of_data = of_device_get_match_data(&i2c->dev);
+       if (of_data)
+               type = (unsigned long)of_data;
+       else
+               type = id->driver_data;
+
+       switch (type) {
+       case CS47L35:
+               if (IS_ENABLED(CONFIG_MFD_CS47L35)) {
+                       regmap_16bit_config = &cs47l35_16bit_i2c_regmap;
+                       regmap_32bit_config = &cs47l35_32bit_i2c_regmap;
+               }
+               break;
+       case CS47L85:
+       case WM1840:
+               if (IS_ENABLED(CONFIG_MFD_CS47L85)) {
+                       regmap_16bit_config = &cs47l85_16bit_i2c_regmap;
+                       regmap_32bit_config = &cs47l85_32bit_i2c_regmap;
+               }
+               break;
+       case CS47L90:
+       case CS47L91:
+               if (IS_ENABLED(CONFIG_MFD_CS47L90)) {
+                       regmap_16bit_config = &cs47l90_16bit_i2c_regmap;
+                       regmap_32bit_config = &cs47l90_32bit_i2c_regmap;
+               }
+               break;
+       default:
+               dev_err(&i2c->dev,
+                       "Unknown Madera I2C device type %ld\n", type);
+               return -EINVAL;
+       }
+
+       name = madera_name_from_type(type);
+
+       if (!regmap_16bit_config) {
+               /* it's polite to say which codec isn't built into the kernel */
+               dev_err(&i2c->dev,
+                       "Kernel does not include support for %s\n", name);
+               return -EINVAL;
+       }
+
+       madera = devm_kzalloc(&i2c->dev, sizeof(*madera), GFP_KERNEL);
+       if (!madera)
+               return -ENOMEM;
+
+
+       madera->regmap = devm_regmap_init_i2c(i2c, regmap_16bit_config);
+       if (IS_ERR(madera->regmap)) {
+               ret = PTR_ERR(madera->regmap);
+               dev_err(&i2c->dev,
+                       "Failed to allocate 16-bit register map: %d\n", ret);
+               return ret;
+       }
+
+       madera->regmap_32bit = devm_regmap_init_i2c(i2c, regmap_32bit_config);
+       if (IS_ERR(madera->regmap_32bit)) {
+               ret = PTR_ERR(madera->regmap_32bit);
+               dev_err(&i2c->dev,
+                       "Failed to allocate 32-bit register map: %d\n", ret);
+               return ret;
+       }
+
+       madera->type = type;
+       madera->type_name = name;
+       madera->dev = &i2c->dev;
+       madera->irq = i2c->irq;
+
+       return madera_dev_init(madera);
+}
+
+static int madera_i2c_remove(struct i2c_client *i2c)
+{
+       struct madera *madera = dev_get_drvdata(&i2c->dev);
+
+       madera_dev_exit(madera);
+
+       return 0;
+}
+
+static const struct i2c_device_id madera_i2c_id[] = {
+       { "cs47l35", CS47L35 },
+       { "cs47l85", CS47L85 },
+       { "cs47l90", CS47L90 },
+       { "cs47l91", CS47L91 },
+       { "wm1840", WM1840 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, madera_i2c_id);
+
+static struct i2c_driver madera_i2c_driver = {
+       .driver = {
+               .name   = "madera",
+               .pm     = &madera_pm_ops,
+               .of_match_table = of_match_ptr(madera_of_match),
+       },
+       .probe          = madera_i2c_probe,
+       .remove         = madera_i2c_remove,
+       .id_table       = madera_i2c_id,
+};
+
+module_i2c_driver(madera_i2c_driver);
+
+MODULE_DESCRIPTION("Madera I2C bus interface");
+MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/mfd/madera-spi.c b/drivers/mfd/madera-spi.c
new file mode 100644 (file)
index 0000000..4c398b2
--- /dev/null
@@ -0,0 +1,139 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * SPI bus interface to Cirrus Logic Madera codecs
+ *
+ * Copyright (C) 2015-2018 Cirrus Logic
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2.
+ */
+
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/regmap.h>
+#include <linux/spi/spi.h>
+
+#include <linux/mfd/madera/core.h>
+
+#include "madera.h"
+
+static int madera_spi_probe(struct spi_device *spi)
+{
+       const struct spi_device_id *id = spi_get_device_id(spi);
+       struct madera *madera;
+       const struct regmap_config *regmap_16bit_config = NULL;
+       const struct regmap_config *regmap_32bit_config = NULL;
+       const void *of_data;
+       unsigned long type;
+       const char *name;
+       int ret;
+
+       of_data = of_device_get_match_data(&spi->dev);
+       if (of_data)
+               type = (unsigned long)of_data;
+       else
+               type = id->driver_data;
+
+       switch (type) {
+       case CS47L35:
+               if (IS_ENABLED(CONFIG_MFD_CS47L35)) {
+                       regmap_16bit_config = &cs47l35_16bit_spi_regmap;
+                       regmap_32bit_config = &cs47l35_32bit_spi_regmap;
+               }
+               break;
+       case CS47L85:
+       case WM1840:
+               if (IS_ENABLED(CONFIG_MFD_CS47L85)) {
+                       regmap_16bit_config = &cs47l85_16bit_spi_regmap;
+                       regmap_32bit_config = &cs47l85_32bit_spi_regmap;
+               }
+               break;
+       case CS47L90:
+       case CS47L91:
+               if (IS_ENABLED(CONFIG_MFD_CS47L90)) {
+                       regmap_16bit_config = &cs47l90_16bit_spi_regmap;
+                       regmap_32bit_config = &cs47l90_32bit_spi_regmap;
+               }
+               break;
+       default:
+               dev_err(&spi->dev,
+                       "Unknown Madera SPI device type %ld\n", type);
+               return -EINVAL;
+       }
+
+       name = madera_name_from_type(type);
+
+       if (!regmap_16bit_config) {
+               /* it's polite to say which codec isn't built into the kernel */
+               dev_err(&spi->dev,
+                       "Kernel does not include support for %s\n", name);
+               return -EINVAL;
+       }
+
+       madera = devm_kzalloc(&spi->dev, sizeof(*madera), GFP_KERNEL);
+       if (!madera)
+               return -ENOMEM;
+
+       madera->regmap = devm_regmap_init_spi(spi, regmap_16bit_config);
+       if (IS_ERR(madera->regmap)) {
+               ret = PTR_ERR(madera->regmap);
+               dev_err(&spi->dev,
+                       "Failed to allocate 16-bit register map: %d\n", ret);
+               return ret;
+       }
+
+       madera->regmap_32bit = devm_regmap_init_spi(spi, regmap_32bit_config);
+       if (IS_ERR(madera->regmap_32bit)) {
+               ret = PTR_ERR(madera->regmap_32bit);
+               dev_err(&spi->dev,
+                       "Failed to allocate 32-bit register map: %d\n", ret);
+               return ret;
+       }
+
+       madera->type = type;
+       madera->type_name = name;
+       madera->dev = &spi->dev;
+       madera->irq = spi->irq;
+
+       return madera_dev_init(madera);
+}
+
+static int madera_spi_remove(struct spi_device *spi)
+{
+       struct madera *madera = spi_get_drvdata(spi);
+
+       madera_dev_exit(madera);
+
+       return 0;
+}
+
+static const struct spi_device_id madera_spi_ids[] = {
+       { "cs47l35", CS47L35 },
+       { "cs47l85", CS47L85 },
+       { "cs47l90", CS47L90 },
+       { "cs47l91", CS47L91 },
+       { "wm1840", WM1840 },
+       { }
+};
+MODULE_DEVICE_TABLE(spi, madera_spi_ids);
+
+static struct spi_driver madera_spi_driver = {
+       .driver = {
+               .name   = "madera",
+               .pm     = &madera_pm_ops,
+               .of_match_table = of_match_ptr(madera_of_match),
+       },
+       .probe          = madera_spi_probe,
+       .remove         = madera_spi_remove,
+       .id_table       = madera_spi_ids,
+};
+
+module_spi_driver(madera_spi_driver);
+
+MODULE_DESCRIPTION("Madera SPI bus interface");
+MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/mfd/madera.h b/drivers/mfd/madera.h
new file mode 100644 (file)
index 0000000..891b84e
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * MFD internals for Cirrus Logic Madera codecs
+ *
+ * Copyright 2015-2018 Cirrus Logic
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef MADERA_MFD_H
+#define MADERA_MFD_H
+
+#include <linux/of.h>
+#include <linux/pm.h>
+
+struct madera;
+
+extern const struct dev_pm_ops madera_pm_ops;
+extern const struct of_device_id madera_of_match[];
+
+int madera_dev_init(struct madera *madera);
+int madera_dev_exit(struct madera *madera);
+
+const char *madera_name_from_type(enum madera_type type);
+
+extern const struct regmap_config cs47l35_16bit_spi_regmap;
+extern const struct regmap_config cs47l35_32bit_spi_regmap;
+extern const struct regmap_config cs47l35_16bit_i2c_regmap;
+extern const struct regmap_config cs47l35_32bit_i2c_regmap;
+int cs47l35_patch(struct madera *madera);
+
+extern const struct regmap_config cs47l85_16bit_spi_regmap;
+extern const struct regmap_config cs47l85_32bit_spi_regmap;
+extern const struct regmap_config cs47l85_16bit_i2c_regmap;
+extern const struct regmap_config cs47l85_32bit_i2c_regmap;
+int cs47l85_patch(struct madera *madera);
+
+extern const struct regmap_config cs47l90_16bit_spi_regmap;
+extern const struct regmap_config cs47l90_32bit_spi_regmap;
+extern const struct regmap_config cs47l90_16bit_i2c_regmap;
+extern const struct regmap_config cs47l90_32bit_i2c_regmap;
+int cs47l90_patch(struct madera *madera);
+#endif
index 36dcd98..2a83696 100644 (file)
 #define RAVE_SP_TX_BUFFER_SIZE                         \
        (RAVE_SP_STX_ETX_SIZE + 2 * RAVE_SP_RX_BUFFER_SIZE)
 
-#define RAVE_SP_BOOT_SOURCE_GET                0
-#define RAVE_SP_BOOT_SOURCE_SET                1
-
-#define RAVE_SP_RDU2_BOARD_TYPE_RMB    0
-#define RAVE_SP_RDU2_BOARD_TYPE_DEB    1
-
-#define RAVE_SP_BOOT_SOURCE_SD         0
-#define RAVE_SP_BOOT_SOURCE_EMMC       1
-#define RAVE_SP_BOOT_SOURCE_NOR                2
-
 /**
  * enum rave_sp_deframer_state - Possible state for de-framer
  *
@@ -127,14 +117,44 @@ struct rave_sp_checksum {
        void (*subroutine)(const u8 *, size_t, u8 *);
 };
 
+struct rave_sp_version {
+       u8     hardware;
+       __le16 major;
+       u8     minor;
+       u8     letter[2];
+} __packed;
+
+struct rave_sp_status {
+       struct rave_sp_version bootloader_version;
+       struct rave_sp_version firmware_version;
+       u16 rdu_eeprom_flag;
+       u16 dds_eeprom_flag;
+       u8  pic_flag;
+       u8  orientation;
+       u32 etc;
+       s16 temp[2];
+       u8  backlight_current[3];
+       u8  dip_switch;
+       u8  host_interrupt;
+       u16 voltage_28;
+       u8  i2c_device_status;
+       u8  power_status;
+       u8  general_status;
+       u8  deprecated1;
+       u8  power_led_status;
+       u8  deprecated2;
+       u8  periph_power_shutoff;
+} __packed;
+
 /**
  * struct rave_sp_variant_cmds - Variant specific command routines
  *
  * @translate: Generic to variant specific command mapping routine
- *
+ * @get_status: Variant specific implementation of CMD_GET_STATUS
  */
 struct rave_sp_variant_cmds {
        int (*translate)(enum rave_sp_command);
+       int (*get_status)(struct rave_sp *sp, struct rave_sp_status *);
 };
 
 /**
@@ -180,35 +200,6 @@ struct rave_sp {
        const char *part_number_bootloader;
 };
 
-struct rave_sp_version {
-       u8     hardware;
-       __le16 major;
-       u8     minor;
-       u8     letter[2];
-} __packed;
-
-struct rave_sp_status {
-       struct rave_sp_version bootloader_version;
-       struct rave_sp_version firmware_version;
-       u16 rdu_eeprom_flag;
-       u16 dds_eeprom_flag;
-       u8  pic_flag;
-       u8  orientation;
-       u32 etc;
-       s16 temp[2];
-       u8  backlight_current[3];
-       u8  dip_switch;
-       u8  host_interrupt;
-       u16 voltage_28;
-       u8  i2c_device_status;
-       u8  power_status;
-       u8  general_status;
-       u8  deprecated1;
-       u8  power_led_status;
-       u8  deprecated2;
-       u8  periph_power_shutoff;
-} __packed;
-
 static bool rave_sp_id_is_event(u8 code)
 {
        return (code & 0xF0) == RAVE_SP_EVNT_BASE;
@@ -641,10 +632,14 @@ static int rave_sp_default_cmd_translate(enum rave_sp_command command)
                return 0x14;
        case RAVE_SP_CMD_SW_WDT:
                return 0x1C;
+       case RAVE_SP_CMD_PET_WDT:
+               return 0x1D;
        case RAVE_SP_CMD_RESET:
                return 0x1E;
        case RAVE_SP_CMD_RESET_REASON:
                return 0x1F;
+       case RAVE_SP_CMD_RMB_EEPROM:
+               return 0x20;
        default:
                return -EINVAL;
        }
@@ -666,18 +661,44 @@ static const char *devm_rave_sp_version(struct device *dev,
                              version->letter[1]);
 }
 
-static int rave_sp_get_status(struct rave_sp *sp)
+static int rave_sp_rdu1_get_status(struct rave_sp *sp,
+                                  struct rave_sp_status *status)
 {
-       struct device *dev = &sp->serdev->dev;
        u8 cmd[] = {
                [0] = RAVE_SP_CMD_STATUS,
                [1] = 0
        };
+
+       return rave_sp_exec(sp, cmd, sizeof(cmd), status, sizeof(*status));
+}
+
+static int rave_sp_emulated_get_status(struct rave_sp *sp,
+                                      struct rave_sp_status *status)
+{
+       u8 cmd[] = {
+               [0] = RAVE_SP_CMD_GET_FIRMWARE_VERSION,
+               [1] = 0,
+       };
+       int ret;
+
+       ret = rave_sp_exec(sp, cmd, sizeof(cmd), &status->firmware_version,
+                          sizeof(status->firmware_version));
+       if (ret)
+               return ret;
+
+       cmd[0] = RAVE_SP_CMD_GET_BOOTLOADER_VERSION;
+       return rave_sp_exec(sp, cmd, sizeof(cmd), &status->bootloader_version,
+                           sizeof(status->bootloader_version));
+}
+
+static int rave_sp_get_status(struct rave_sp *sp)
+{
+       struct device *dev = &sp->serdev->dev;
        struct rave_sp_status status;
        const char *version;
        int ret;
 
-       ret = rave_sp_exec(sp, cmd, sizeof(cmd), &status, sizeof(status));
+       ret = sp->variant->cmd.get_status(sp, &status);
        if (ret)
                return ret;
 
@@ -707,9 +728,10 @@ static const struct rave_sp_checksum rave_sp_checksum_ccitt = {
 };
 
 static const struct rave_sp_variant rave_sp_legacy = {
-       .checksum = &rave_sp_checksum_8b2c,
+       .checksum = &rave_sp_checksum_ccitt,
        .cmd = {
                .translate = rave_sp_default_cmd_translate,
+               .get_status = rave_sp_emulated_get_status,
        },
 };
 
@@ -717,6 +739,7 @@ static const struct rave_sp_variant rave_sp_rdu1 = {
        .checksum = &rave_sp_checksum_8b2c,
        .cmd = {
                .translate = rave_sp_rdu1_cmd_translate,
+               .get_status = rave_sp_rdu1_get_status,
        },
 };
 
@@ -724,6 +747,7 @@ static const struct rave_sp_variant rave_sp_rdu2 = {
        .checksum = &rave_sp_checksum_ccitt,
        .cmd = {
                .translate = rave_sp_rdu2_cmd_translate,
+               .get_status = rave_sp_emulated_get_status,
        },
 };
 
@@ -776,6 +800,13 @@ static int rave_sp_probe(struct serdev_device *serdev)
                return ret;
 
        serdev_device_set_baudrate(serdev, baud);
+       serdev_device_set_flow_control(serdev, false);
+
+       ret = serdev_device_set_parity(serdev, SERDEV_PARITY_NONE);
+       if (ret) {
+               dev_err(dev, "Failed to set parity\n");
+               return ret;
+       }
 
        ret = rave_sp_get_status(sp);
        if (ret) {
diff --git a/drivers/mfd/rohm-bd718x7.c b/drivers/mfd/rohm-bd718x7.c
new file mode 100644 (file)
index 0000000..75c8ec6
--- /dev/null
@@ -0,0 +1,211 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+//
+// Copyright (C) 2018 ROHM Semiconductors
+//
+// ROHM BD71837MWV PMIC driver
+//
+// Datasheet available from
+// https://www.rohm.com/datasheet/BD71837MWV/bd71837mwv-e
+
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/mfd/rohm-bd718x7.h>
+#include <linux/mfd/core.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+
+/*
+ * gpio_keys.h requires definiton of bool. It is brought in
+ * by above includes. Keep this as last until gpio_keys.h gets fixed.
+ */
+#include <linux/gpio_keys.h>
+
+static const u8 supported_revisions[] = { 0xA2 /* BD71837 */ };
+
+static struct gpio_keys_button button = {
+       .code = KEY_POWER,
+       .gpio = -1,
+       .type = EV_KEY,
+};
+
+static struct gpio_keys_platform_data bd718xx_powerkey_data = {
+       .buttons = &button,
+       .nbuttons = 1,
+       .name = "bd718xx-pwrkey",
+};
+
+static struct mfd_cell bd71837_mfd_cells[] = {
+       {
+               .name = "gpio-keys",
+               .platform_data = &bd718xx_powerkey_data,
+               .pdata_size = sizeof(bd718xx_powerkey_data),
+       },
+       { .name = "bd71837-clk", },
+       { .name = "bd71837-pmic", },
+};
+
+static const struct regmap_irq bd71837_irqs[] = {
+       REGMAP_IRQ_REG(BD71837_INT_SWRST, 0, BD71837_INT_SWRST_MASK),
+       REGMAP_IRQ_REG(BD71837_INT_PWRBTN_S, 0, BD71837_INT_PWRBTN_S_MASK),
+       REGMAP_IRQ_REG(BD71837_INT_PWRBTN_L, 0, BD71837_INT_PWRBTN_L_MASK),
+       REGMAP_IRQ_REG(BD71837_INT_PWRBTN, 0, BD71837_INT_PWRBTN_MASK),
+       REGMAP_IRQ_REG(BD71837_INT_WDOG, 0, BD71837_INT_WDOG_MASK),
+       REGMAP_IRQ_REG(BD71837_INT_ON_REQ, 0, BD71837_INT_ON_REQ_MASK),
+       REGMAP_IRQ_REG(BD71837_INT_STBY_REQ, 0, BD71837_INT_STBY_REQ_MASK),
+};
+
+static struct regmap_irq_chip bd71837_irq_chip = {
+       .name = "bd71837-irq",
+       .irqs = bd71837_irqs,
+       .num_irqs = ARRAY_SIZE(bd71837_irqs),
+       .num_regs = 1,
+       .irq_reg_stride = 1,
+       .status_base = BD71837_REG_IRQ,
+       .mask_base = BD71837_REG_MIRQ,
+       .ack_base = BD71837_REG_IRQ,
+       .init_ack_masked = true,
+       .mask_invert = false,
+};
+
+static const struct regmap_range pmic_status_range = {
+       .range_min = BD71837_REG_IRQ,
+       .range_max = BD71837_REG_POW_STATE,
+};
+
+static const struct regmap_access_table volatile_regs = {
+       .yes_ranges = &pmic_status_range,
+       .n_yes_ranges = 1,
+};
+
+static const struct regmap_config bd71837_regmap_config = {
+       .reg_bits = 8,
+       .val_bits = 8,
+       .volatile_table = &volatile_regs,
+       .max_register = BD71837_MAX_REGISTER - 1,
+       .cache_type = REGCACHE_RBTREE,
+};
+
+static int bd71837_i2c_probe(struct i2c_client *i2c,
+                           const struct i2c_device_id *id)
+{
+       struct bd71837 *bd71837;
+       int ret, i;
+       unsigned int val;
+
+       bd71837 = devm_kzalloc(&i2c->dev, sizeof(struct bd71837), GFP_KERNEL);
+
+       if (!bd71837)
+               return -ENOMEM;
+
+       bd71837->chip_irq = i2c->irq;
+
+       if (!bd71837->chip_irq) {
+               dev_err(&i2c->dev, "No IRQ configured\n");
+               return -EINVAL;
+       }
+
+       bd71837->dev = &i2c->dev;
+       dev_set_drvdata(&i2c->dev, bd71837);
+
+       bd71837->regmap = devm_regmap_init_i2c(i2c, &bd71837_regmap_config);
+       if (IS_ERR(bd71837->regmap)) {
+               dev_err(&i2c->dev, "regmap initialization failed\n");
+               return PTR_ERR(bd71837->regmap);
+       }
+
+       ret = regmap_read(bd71837->regmap, BD71837_REG_REV, &val);
+       if (ret) {
+               dev_err(&i2c->dev, "Read BD71837_REG_DEVICE failed\n");
+               return ret;
+       }
+       for (i = 0; i < ARRAY_SIZE(supported_revisions); i++)
+               if (supported_revisions[i] == val)
+                       break;
+
+       if (i == ARRAY_SIZE(supported_revisions)) {
+               dev_err(&i2c->dev, "Unsupported chip revision\n");
+               return -ENODEV;
+       }
+
+       ret = devm_regmap_add_irq_chip(&i2c->dev, bd71837->regmap,
+                                      bd71837->chip_irq, IRQF_ONESHOT, 0,
+                                      &bd71837_irq_chip, &bd71837->irq_data);
+       if (ret) {
+               dev_err(&i2c->dev, "Failed to add irq_chip\n");
+               return ret;
+       }
+
+       /* Configure short press to 10 milliseconds */
+       ret = regmap_update_bits(bd71837->regmap,
+                                BD71837_REG_PWRONCONFIG0,
+                                BD718XX_PWRBTN_PRESS_DURATION_MASK,
+                                BD718XX_PWRBTN_SHORT_PRESS_10MS);
+       if (ret) {
+               dev_err(&i2c->dev,
+                       "Failed to configure button short press timeout\n");
+               return ret;
+       }
+
+       /* Configure long press to 10 seconds */
+       ret = regmap_update_bits(bd71837->regmap,
+                                BD71837_REG_PWRONCONFIG1,
+                                BD718XX_PWRBTN_PRESS_DURATION_MASK,
+                                BD718XX_PWRBTN_LONG_PRESS_10S);
+
+       if (ret) {
+               dev_err(&i2c->dev,
+                       "Failed to configure button long press timeout\n");
+               return ret;
+       }
+
+       ret = regmap_irq_get_virq(bd71837->irq_data, BD71837_INT_PWRBTN_S);
+
+       if (ret < 0) {
+               dev_err(&i2c->dev, "Failed to get the IRQ\n");
+               return ret;
+       }
+
+       button.irq = ret;
+
+       ret = devm_mfd_add_devices(bd71837->dev, PLATFORM_DEVID_AUTO,
+                                  bd71837_mfd_cells,
+                                  ARRAY_SIZE(bd71837_mfd_cells), NULL, 0,
+                                  regmap_irq_get_domain(bd71837->irq_data));
+       if (ret)
+               dev_err(&i2c->dev, "Failed to create subdevices\n");
+
+       return ret;
+}
+
+static const struct of_device_id bd71837_of_match[] = {
+       { .compatible = "rohm,bd71837", },
+       { }
+};
+MODULE_DEVICE_TABLE(of, bd71837_of_match);
+
+static struct i2c_driver bd71837_i2c_driver = {
+       .driver = {
+               .name = "rohm-bd718x7",
+               .of_match_table = bd71837_of_match,
+       },
+       .probe = bd71837_i2c_probe,
+};
+
+static int __init bd71837_i2c_init(void)
+{
+       return i2c_add_driver(&bd71837_i2c_driver);
+}
+
+/* Initialise early so consumer devices can complete system boot */
+subsys_initcall(bd71837_i2c_init);
+
+static void __exit bd71837_i2c_exit(void)
+{
+       i2c_del_driver(&bd71837_i2c_driver);
+}
+module_exit(bd71837_i2c_exit);
+
+MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>");
+MODULE_DESCRIPTION("ROHM BD71837 Power Management IC driver");
+MODULE_LICENSE("GPL");
index ca6b80d..9613b42 100644 (file)
@@ -146,6 +146,7 @@ static const struct of_device_id sec_dt_match[] = {
                /* Sentinel */
        },
 };
+MODULE_DEVICE_TABLE(of, sec_dt_match);
 #endif
 
 static bool s2mpa01_volatile(struct device *dev, unsigned int reg)
index 2a87b0d..a530972 100644 (file)
@@ -715,6 +715,7 @@ sm501_create_subdev(struct sm501_devdata *sm, char *name,
        smdev->pdev.name = name;
        smdev->pdev.id = sm->pdev_id;
        smdev->pdev.dev.parent = sm->dev;
+       smdev->pdev.dev.coherent_dma_mask = 0xffffffff;
 
        if (res_count) {
                smdev->pdev.resource = (struct resource *)(smdev+1);
index 47012c0..7a30546 100644 (file)
@@ -209,14 +209,13 @@ static    int ti_tscadc_probe(struct platform_device *pdev)
         * The TSC_ADC_SS controller design assumes the OCP clock is
         * at least 6x faster than the ADC clock.
         */
-       clk = clk_get(&pdev->dev, "adc_tsc_fck");
+       clk = devm_clk_get(&pdev->dev, "adc_tsc_fck");
        if (IS_ERR(clk)) {
                dev_err(&pdev->dev, "failed to get TSC fck\n");
                err = PTR_ERR(clk);
                goto err_disable_clk;
        }
        clock_rate = clk_get_rate(clk);
-       clk_put(clk);
        tscadc->clk_div = clock_rate / ADC_CLK;
 
        /* TSCADC_CLKDIV needs to be configured to the value minus 1 */
index 5d5888e..22bd652 100644 (file)
@@ -302,6 +302,10 @@ static int wm8994_set_pdata_from_of(struct wm8994 *wm8994)
        if (of_find_property(np, "wlf,ldoena-always-driven", NULL))
                pdata->lineout2fb = true;
 
+       pdata->spkmode_pu = of_property_read_bool(np, "wlf,spkmode-pu");
+
+       pdata->csnaddr_pd = of_property_read_bool(np, "wlf,csnaddr-pd");
+
        pdata->ldo[0].enable = of_get_named_gpio(np, "wlf,ldo1ena", 0);
        if (pdata->ldo[0].enable < 0)
                pdata->ldo[0].enable = 0;
@@ -513,14 +517,15 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq)
                break;
        default:
                dev_err(wm8994->dev, "Unknown device type %d\n", wm8994->type);
-               return -EINVAL;
+               ret = -EINVAL;
+               goto err_enable;
        }
 
        ret = regmap_reinit_cache(wm8994->regmap, regmap_config);
        if (ret != 0) {
                dev_err(wm8994->dev, "Failed to reinit register cache: %d\n",
                        ret);
-               return ret;
+               goto err_enable;
        }
 
        /* Explicitly put the device into reset in case regulators
@@ -531,7 +536,7 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq)
                               wm8994_reg_read(wm8994, WM8994_SOFTWARE_RESET));
        if (ret != 0) {
                dev_err(wm8994->dev, "Failed to reset device: %d\n", ret);
-               return ret;
+               goto err_enable;
        }
 
        if (regmap_patch) {
@@ -540,7 +545,7 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq)
                if (ret != 0) {
                        dev_err(wm8994->dev, "Failed to register patch: %d\n",
                                ret);
-                       goto err;
+                       goto err_enable;
                }
        }
 
@@ -559,6 +564,8 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq)
 
        if (pdata->spkmode_pu)
                pulls |= WM8994_SPKMODE_PU;
+       if (pdata->csnaddr_pd)
+               pulls |= WM8994_CSNADDR_PD;
 
        /* Disable unneeded pulls */
        wm8994_set_bits(wm8994, WM8994_PULL_CONTROL_2,
index 4d4acf7..2c43fd0 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/gfp.h>
 
 static DEFINE_IDA(cb710_ida);
-static DEFINE_SPINLOCK(cb710_ida_lock);
 
 void cb710_pci_update_config_reg(struct pci_dev *pdev,
        int reg, uint32_t mask, uint32_t xor)
@@ -205,7 +204,6 @@ static int cb710_probe(struct pci_dev *pdev,
        const struct pci_device_id *ent)
 {
        struct cb710_chip *chip;
-       unsigned long flags;
        u32 val;
        int err;
        int n = 0;
@@ -256,18 +254,10 @@ static int cb710_probe(struct pci_dev *pdev,
        if (err)
                return err;
 
-       do {
-               if (!ida_pre_get(&cb710_ida, GFP_KERNEL))
-                       return -ENOMEM;
-
-               spin_lock_irqsave(&cb710_ida_lock, flags);
-               err = ida_get_new(&cb710_ida, &chip->platform_id);
-               spin_unlock_irqrestore(&cb710_ida_lock, flags);
-
-               if (err && err != -EAGAIN)
-                       return err;
-       } while (err);
-
+       err = ida_alloc(&cb710_ida, GFP_KERNEL);
+       if (err < 0)
+               return err;
+       chip->platform_id = err;
 
        dev_info(&pdev->dev, "id %d, IO 0x%p, IRQ %d\n",
                chip->platform_id, chip->iobase, pdev->irq);
@@ -308,7 +298,6 @@ unreg_mmc:
 static void cb710_remove_one(struct pci_dev *pdev)
 {
        struct cb710_chip *chip = pci_get_drvdata(pdev);
-       unsigned long flags;
 
        cb710_unregister_slot(chip, CB710_SLOT_SM);
        cb710_unregister_slot(chip, CB710_SLOT_MS);
@@ -317,9 +306,7 @@ static void cb710_remove_one(struct pci_dev *pdev)
        BUG_ON(atomic_read(&chip->slot_refs_count) != 0);
 #endif
 
-       spin_lock_irqsave(&cb710_ida_lock, flags);
-       ida_remove(&cb710_ida, chip->platform_id);
-       spin_unlock_irqrestore(&cb710_ida_lock, flags);
+       ida_free(&cb710_ida, chip->platform_id);
 }
 
 static const struct pci_device_id cb710_pci_tbl[] = {
index f5cc517..7e50e1d 100644 (file)
@@ -478,6 +478,23 @@ static void at24_properties_to_pdata(struct device *dev,
        if (device_property_present(dev, "no-read-rollover"))
                chip->flags |= AT24_FLAG_NO_RDROL;
 
+       err = device_property_read_u32(dev, "address-width", &val);
+       if (!err) {
+               switch (val) {
+               case 8:
+                       if (chip->flags & AT24_FLAG_ADDR16)
+                               dev_warn(dev, "Override address width to be 8, while default is 16\n");
+                       chip->flags &= ~AT24_FLAG_ADDR16;
+                       break;
+               case 16:
+                       chip->flags |= AT24_FLAG_ADDR16;
+                       break;
+               default:
+                       dev_warn(dev, "Bad \"address-width\" property: %u\n",
+                                val);
+               }
+       }
+
        err = device_property_read_u32(dev, "size", &val);
        if (!err)
                chip->byte_len = val;
index 63d6246..6369aea 100644 (file)
@@ -200,15 +200,18 @@ static void scif_mmu_notifier_release(struct mmu_notifier *mn,
        schedule_work(&scif_info.misc_work);
 }
 
-static void scif_mmu_notifier_invalidate_range_start(struct mmu_notifier *mn,
+static int scif_mmu_notifier_invalidate_range_start(struct mmu_notifier *mn,
                                                     struct mm_struct *mm,
                                                     unsigned long start,
-                                                    unsigned long end)
+                                                    unsigned long end,
+                                                    bool blockable)
 {
        struct scif_mmu_notif   *mmn;
 
        mmn = container_of(mn, struct scif_mmu_notif, ep_mmu_notifier);
        scif_rma_destroy_tcw(mmn, start, end - start);
+
+       return 0;
 }
 
 static void scif_mmu_notifier_invalidate_range_end(struct mmu_notifier *mn,
index a3454eb..be28f05 100644 (file)
@@ -219,9 +219,10 @@ void gru_flush_all_tlb(struct gru_state *gru)
 /*
  * MMUOPS notifier callout functions
  */
-static void gru_invalidate_range_start(struct mmu_notifier *mn,
+static int gru_invalidate_range_start(struct mmu_notifier *mn,
                                       struct mm_struct *mm,
-                                      unsigned long start, unsigned long end)
+                                      unsigned long start, unsigned long end,
+                                      bool blockable)
 {
        struct gru_mm_struct *gms = container_of(mn, struct gru_mm_struct,
                                                 ms_notifier);
@@ -231,6 +232,8 @@ static void gru_invalidate_range_start(struct mmu_notifier *mn,
        gru_dbg(grudev, "gms %p, start 0x%lx, end 0x%lx, act %d\n", gms,
                start, end, atomic_read(&gms->ms_range_active));
        gru_flush_tlb_range(gms, start, end - start);
+
+       return 0;
 }
 
 static void gru_invalidate_range_end(struct mmu_notifier *mn,
index 45c3296..22547d7 100644 (file)
@@ -367,6 +367,10 @@ static ssize_t vol_cdev_write(struct file *file, const char __user *buf,
                        return count;
                }
 
+               /*
+                * We voluntarily do not take into account the skip_check flag
+                * as we want to make sure what we wrote was correctly written.
+                */
                err = ubi_check_volume(ubi, vol->vol_id);
                if (err < 0)
                        return err;
@@ -622,6 +626,13 @@ static int verify_mkvol_req(const struct ubi_device *ubi,
            req->vol_type != UBI_STATIC_VOLUME)
                goto bad;
 
+       if (req->flags & ~UBI_VOL_VALID_FLGS)
+               goto bad;
+
+       if (req->flags & UBI_VOL_SKIP_CRC_CHECK_FLG &&
+           req->vol_type != UBI_STATIC_VOLUME)
+               goto bad;
+
        if (req->alignment > ubi->leb_size)
                goto bad;
 
index d4b2e87..e9e9ecb 100644 (file)
@@ -202,7 +202,7 @@ struct ubi_volume_desc *ubi_open_volume(int ubi_num, int vol_id, int mode)
        desc->mode = mode;
 
        mutex_lock(&ubi->ckvol_mutex);
-       if (!vol->checked) {
+       if (!vol->checked && !vol->skip_check) {
                /* This is the first open - check the volume */
                err = ubi_check_volume(ubi, vol_id);
                if (err < 0) {
index 195ff8c..b5fe8f8 100644 (file)
@@ -45,6 +45,11 @@ enum {
  * Volume flags used in the volume table record.
  *
  * @UBI_VTBL_AUTORESIZE_FLG: auto-resize this volume
+ * @UBI_VTBL_SKIP_CRC_CHECK_FLG: skip the CRC check done on a static volume at
+ *                              open time. Should only be set on volumes that
+ *                              are used by upper layers doing this kind of
+ *                              check. Main use-case for this flag is
+ *                              boot-time reduction
  *
  * %UBI_VTBL_AUTORESIZE_FLG flag can be set only for one volume in the volume
  * table. UBI automatically re-sizes the volume which has this flag and makes
@@ -76,6 +81,7 @@ enum {
  */
 enum {
        UBI_VTBL_AUTORESIZE_FLG = 0x01,
+       UBI_VTBL_SKIP_CRC_CHECK_FLG = 0x02,
 };
 
 /*
index f5ba97c..d47b9e4 100644 (file)
@@ -327,6 +327,9 @@ struct ubi_eba_leb_desc {
  *           atomic LEB change
  *
  * @eba_tbl: EBA table of this volume (LEB->PEB mapping)
+ * @skip_check: %1 if CRC check of this static volume should be skipped.
+ *             Directly reflects the presence of the
+ *             %UBI_VTBL_SKIP_CRC_CHECK_FLG flag in the vtbl entry
  * @checked: %1 if this static volume was checked
  * @corrupted: %1 if the volume is corrupted (static volumes only)
  * @upd_marker: %1 if the update marker is set for this volume
@@ -374,6 +377,7 @@ struct ubi_volume {
        void *upd_buf;
 
        struct ubi_eba_table *eba_tbl;
+       unsigned int skip_check:1;
        unsigned int checked:1;
        unsigned int corrupted:1;
        unsigned int upd_marker:1;
index 0be5167..729588b 100644 (file)
@@ -174,6 +174,9 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req)
        vol->dev.class = &ubi_class;
        vol->dev.groups = volume_dev_groups;
 
+       if (req->flags & UBI_VOL_SKIP_CRC_CHECK_FLG)
+               vol->skip_check = 1;
+
        spin_lock(&ubi->volumes_lock);
        if (vol_id == UBI_VOL_NUM_AUTO) {
                /* Find unused volume ID */
@@ -299,6 +302,10 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req)
                vtbl_rec.vol_type = UBI_VID_DYNAMIC;
        else
                vtbl_rec.vol_type = UBI_VID_STATIC;
+
+       if (vol->skip_check)
+               vtbl_rec.flags |= UBI_VTBL_SKIP_CRC_CHECK_FLG;
+
        memcpy(vtbl_rec.name, vol->name, vol->name_len);
 
        err = ubi_change_vtbl_record(ubi, vol_id, &vtbl_rec);
@@ -733,6 +740,11 @@ static int self_check_volume(struct ubi_device *ubi, int vol_id)
                        ubi_err(ubi, "bad used_bytes");
                        goto fail;
                }
+
+               if (vol->skip_check) {
+                       ubi_err(ubi, "bad skip_check");
+                       goto fail;
+               }
        } else {
                if (vol->used_ebs < 0 || vol->used_ebs > vol->reserved_pebs) {
                        ubi_err(ubi, "bad used_ebs");
index 94d7a86..1bc8215 100644 (file)
@@ -560,6 +560,9 @@ static int init_volumes(struct ubi_device *ubi,
                vol->name[vol->name_len] = '\0';
                vol->vol_id = i;
 
+               if (vtbl[i].flags & UBI_VTBL_SKIP_CRC_CHECK_FLG)
+                       vol->skip_check = 1;
+
                if (vtbl[i].flags & UBI_VTBL_AUTORESIZE_FLG) {
                        /* Auto re-size flag may be set only for one volume */
                        if (ubi->autoresize_vol_id != -1) {
@@ -579,6 +582,16 @@ static int init_volumes(struct ubi_device *ubi,
                reserved_pebs += vol->reserved_pebs;
 
                /*
+                * We use ubi->peb_count and not vol->reserved_pebs because
+                * we want to keep the code simple. Otherwise we'd have to
+                * resize/check the bitmap upon volume resize too.
+                * Allocating a few bytes more does not hurt.
+                */
+               err = ubi_fastmap_init_checkmap(vol, ubi->peb_count);
+               if (err)
+                       return err;
+
+               /*
                 * In case of dynamic volume UBI knows nothing about how many
                 * data is stored there. So assume the whole volume is used.
                 */
@@ -620,16 +633,6 @@ static int init_volumes(struct ubi_device *ubi,
                        (long long)(vol->used_ebs - 1) * vol->usable_leb_size;
                vol->used_bytes += av->last_data_size;
                vol->last_eb_bytes = av->last_data_size;
-
-               /*
-                * We use ubi->peb_count and not vol->reserved_pebs because
-                * we want to keep the code simple. Otherwise we'd have to
-                * resize/check the bitmap upon volume resize too.
-                * Allocating a few bytes more does not hurt.
-                */
-               err = ubi_fastmap_init_checkmap(vol, ubi->peb_count);
-               if (err)
-                       return err;
        }
 
        /* And add the layout volume */
index 0515744..b1b53f6 100644 (file)
@@ -74,7 +74,6 @@ static const char version[] =
 #include <linux/skbuff.h>
 
 #include <linux/dmaengine.h>
-#include <linux/dma/pxa-dma.h>
 
 #include <asm/io.h>
 
@@ -1795,7 +1794,6 @@ static int smc911x_probe(struct net_device *dev)
 #ifdef SMC_USE_DMA
        struct dma_slave_config config;
        dma_cap_mask_t mask;
-       struct pxad_param param;
 #endif
 
        DBG(SMC_DEBUG_FUNC, dev, "--> %s\n", __func__);
@@ -1971,15 +1969,8 @@ static int smc911x_probe(struct net_device *dev)
 
        dma_cap_zero(mask);
        dma_cap_set(DMA_SLAVE, mask);
-       param.prio = PXAD_PRIO_LOWEST;
-       param.drcmr = -1UL;
-
-       lp->rxdma =
-               dma_request_slave_channel_compat(mask, pxad_filter_fn,
-                                                &param, &dev->dev, "rx");
-       lp->txdma =
-               dma_request_slave_channel_compat(mask, pxad_filter_fn,
-                                                &param, &dev->dev, "tx");
+       lp->rxdma = dma_request_channel(mask, NULL, NULL);
+       lp->txdma = dma_request_channel(mask, NULL, NULL);
        lp->rxdma_active = 0;
        lp->txdma_active = 0;
 
index 0804287..b944828 100644 (file)
@@ -2019,17 +2019,10 @@ static int smc_probe(struct net_device *dev, void __iomem *ioaddr,
 #  endif
        if (lp->cfg.flags & SMC91X_USE_DMA) {
                dma_cap_mask_t mask;
-               struct pxad_param param;
 
                dma_cap_zero(mask);
                dma_cap_set(DMA_SLAVE, mask);
-               param.prio = PXAD_PRIO_LOWEST;
-               param.drcmr = -1UL;
-
-               lp->dma_chan =
-                       dma_request_slave_channel_compat(mask, pxad_filter_fn,
-                                                        &param, &dev->dev,
-                                                        "data");
+               lp->dma_chan = dma_request_channel(mask, NULL, NULL);
        }
 #endif
 
index b337ee9..a273522 100644 (file)
@@ -301,7 +301,6 @@ struct smc_local {
  * as RX which can overrun memory and lose packets.
  */
 #include <linux/dma-mapping.h>
-#include <linux/dma/pxa-dma.h>
 
 #ifdef SMC_insl
 #undef SMC_insl
index 2bbefe8..ebd07ad 100644 (file)
@@ -3217,7 +3217,7 @@ static int tun_chr_fasync(int fd, struct file *file, int on)
                goto out;
 
        if (on) {
-               __f_setown(file, task_pid(current), PIDTYPE_PID, 0);
+               __f_setown(file, task_pid(current), PIDTYPE_TGID, 0);
                tfile->flags |= TUN_FASYNC;
        } else
                tfile->flags &= ~TUN_FASYNC;
index 27902a8..8aae6dc 100644 (file)
@@ -812,9 +812,9 @@ u32 nd_cmd_out_size(struct nvdimm *nvdimm, int cmd,
                 * overshoots the remainder by 4 bytes, assume it was
                 * including 'status'.
                 */
-               if (out_field[1] - 8 == remainder)
+               if (out_field[1] - 4 == remainder)
                        return remainder;
-               return out_field[1] - 4;
+               return out_field[1] - 8;
        } else if (cmd == ND_CMD_CALL) {
                struct nd_cmd_pkg *pkg = (struct nd_cmd_pkg *) in_field;
 
index 2339078..6c8fb75 100644 (file)
@@ -34,6 +34,9 @@ static int nvdimm_probe(struct device *dev)
                return rc;
        }
 
+       /* reset locked, to be validated below... */
+       nvdimm_clear_locked(dev);
+
        ndd = kzalloc(sizeof(*ndd), GFP_KERNEL);
        if (!ndd)
                return -ENOMEM;
@@ -48,12 +51,30 @@ static int nvdimm_probe(struct device *dev)
        get_device(dev);
        kref_init(&ndd->kref);
 
+       /*
+        * EACCES failures reading the namespace label-area-properties
+        * are interpreted as the DIMM capacity being locked but the
+        * namespace labels themselves being accessible.
+        */
        rc = nvdimm_init_nsarea(ndd);
-       if (rc == -EACCES)
+       if (rc == -EACCES) {
+               /*
+                * See nvdimm_namespace_common_probe() where we fail to
+                * allow namespaces to probe while the DIMM is locked,
+                * but we do allow for namespace enumeration.
+                */
                nvdimm_set_locked(dev);
+               rc = 0;
+       }
        if (rc)
                goto err;
 
+       /*
+        * EACCES failures reading the namespace label-data are
+        * interpreted as the label area being locked in addition to the
+        * DIMM capacity. We fail the dimm probe to prevent regions from
+        * attempting to parse the label area.
+        */
        rc = nvdimm_init_config_data(ndd);
        if (rc == -EACCES)
                nvdimm_set_locked(dev);
@@ -72,7 +93,6 @@ static int nvdimm_probe(struct device *dev)
                if (rc == 0)
                        nvdimm_set_aliasing(dev);
        }
-       nvdimm_clear_locked(dev);
        nvdimm_bus_unlock(dev);
 
        if (rc)
index 8d348b2..863cabc 100644 (file)
@@ -537,6 +537,37 @@ resource_size_t nd_blk_available_dpa(struct nd_region *nd_region)
 }
 
 /**
+ * nd_pmem_max_contiguous_dpa - For the given dimm+region, return the max
+ *                        contiguous unallocated dpa range.
+ * @nd_region: constrain available space check to this reference region
+ * @nd_mapping: container of dpa-resource-root + labels
+ */
+resource_size_t nd_pmem_max_contiguous_dpa(struct nd_region *nd_region,
+                                          struct nd_mapping *nd_mapping)
+{
+       struct nvdimm_drvdata *ndd = to_ndd(nd_mapping);
+       struct nvdimm_bus *nvdimm_bus;
+       resource_size_t max = 0;
+       struct resource *res;
+
+       /* if a dimm is disabled the available capacity is zero */
+       if (!ndd)
+               return 0;
+
+       nvdimm_bus = walk_to_nvdimm_bus(ndd->dev);
+       if (__reserve_free_pmem(&nd_region->dev, nd_mapping->nvdimm))
+               return 0;
+       for_each_dpa_resource(ndd, res) {
+               if (strcmp(res->name, "pmem-reserve") != 0)
+                       continue;
+               if (resource_size(res) > max)
+                       max = resource_size(res);
+       }
+       release_free_pmem(nvdimm_bus, nd_mapping);
+       return max;
+}
+
+/**
  * nd_pmem_available_dpa - for the given dimm+region account unallocated dpa
  * @nd_mapping: container of dpa-resource-root + labels
  * @nd_region: constrain available space check to this reference region
index 28afdd6..4a42662 100644 (file)
@@ -799,7 +799,7 @@ static int merge_dpa(struct nd_region *nd_region,
        return 0;
 }
 
-static int __reserve_free_pmem(struct device *dev, void *data)
+int __reserve_free_pmem(struct device *dev, void *data)
 {
        struct nvdimm *nvdimm = data;
        struct nd_region *nd_region;
@@ -836,7 +836,7 @@ static int __reserve_free_pmem(struct device *dev, void *data)
        return 0;
 }
 
-static void release_free_pmem(struct nvdimm_bus *nvdimm_bus,
+void release_free_pmem(struct nvdimm_bus *nvdimm_bus,
                struct nd_mapping *nd_mapping)
 {
        struct nvdimm_drvdata *ndd = to_ndd(nd_mapping);
@@ -1032,7 +1032,7 @@ static ssize_t __size_store(struct device *dev, unsigned long long val)
 
                allocated += nvdimm_allocated_dpa(ndd, &label_id);
        }
-       available = nd_region_available_dpa(nd_region);
+       available = nd_region_allocatable_dpa(nd_region);
 
        if (val > available + allocated)
                return -ENOSPC;
@@ -1144,6 +1144,26 @@ resource_size_t nvdimm_namespace_capacity(struct nd_namespace_common *ndns)
 }
 EXPORT_SYMBOL(nvdimm_namespace_capacity);
 
+bool nvdimm_namespace_locked(struct nd_namespace_common *ndns)
+{
+       int i;
+       bool locked = false;
+       struct device *dev = &ndns->dev;
+       struct nd_region *nd_region = to_nd_region(dev->parent);
+
+       for (i = 0; i < nd_region->ndr_mappings; i++) {
+               struct nd_mapping *nd_mapping = &nd_region->mapping[i];
+               struct nvdimm *nvdimm = nd_mapping->nvdimm;
+
+               if (test_bit(NDD_LOCKED, &nvdimm->flags)) {
+                       dev_dbg(dev, "%s locked\n", nvdimm_name(nvdimm));
+                       locked = true;
+               }
+       }
+       return locked;
+}
+EXPORT_SYMBOL(nvdimm_namespace_locked);
+
 static ssize_t size_show(struct device *dev,
                struct device_attribute *attr, char *buf)
 {
@@ -1695,6 +1715,9 @@ struct nd_namespace_common *nvdimm_namespace_common_probe(struct device *dev)
                }
        }
 
+       if (nvdimm_namespace_locked(ndns))
+               return ERR_PTR(-EACCES);
+
        size = nvdimm_namespace_capacity(ndns);
        if (size < ND_MIN_NAMESPACE_SIZE) {
                dev_dbg(&ndns->dev, "%pa, too small must be at least %#x\n",
index 79274ea..ac68072 100644 (file)
@@ -100,6 +100,14 @@ struct nd_region;
 struct nvdimm_drvdata;
 struct nd_mapping;
 void nd_mapping_free_labels(struct nd_mapping *nd_mapping);
+
+int __reserve_free_pmem(struct device *dev, void *data);
+void release_free_pmem(struct nvdimm_bus *nvdimm_bus,
+                      struct nd_mapping *nd_mapping);
+
+resource_size_t nd_pmem_max_contiguous_dpa(struct nd_region *nd_region,
+                                          struct nd_mapping *nd_mapping);
+resource_size_t nd_region_allocatable_dpa(struct nd_region *nd_region);
 resource_size_t nd_pmem_available_dpa(struct nd_region *nd_region,
                struct nd_mapping *nd_mapping, resource_size_t *overlap);
 resource_size_t nd_blk_available_dpa(struct nd_region *nd_region);
index 6ee7fd7..98317e7 100644 (file)
@@ -357,6 +357,7 @@ struct resource *nvdimm_allocate_dpa(struct nvdimm_drvdata *ndd,
                struct nd_label_id *label_id, resource_size_t start,
                resource_size_t n);
 resource_size_t nvdimm_namespace_capacity(struct nd_namespace_common *ndns);
+bool nvdimm_namespace_locked(struct nd_namespace_common *ndns);
 struct nd_namespace_common *nvdimm_namespace_common_probe(struct device *dev);
 int nvdimm_namespace_attach_btt(struct nd_namespace_common *ndns);
 int nvdimm_namespace_detach_btt(struct nd_btt *nd_btt);
index dd17acd..6071e29 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/hdreg.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
+#include <linux/set_memory.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/badblocks.h>
@@ -51,6 +52,30 @@ static struct nd_region *to_region(struct pmem_device *pmem)
        return to_nd_region(to_dev(pmem)->parent);
 }
 
+static void hwpoison_clear(struct pmem_device *pmem,
+               phys_addr_t phys, unsigned int len)
+{
+       unsigned long pfn_start, pfn_end, pfn;
+
+       /* only pmem in the linear map supports HWPoison */
+       if (is_vmalloc_addr(pmem->virt_addr))
+               return;
+
+       pfn_start = PHYS_PFN(phys);
+       pfn_end = pfn_start + PHYS_PFN(len);
+       for (pfn = pfn_start; pfn < pfn_end; pfn++) {
+               struct page *page = pfn_to_page(pfn);
+
+               /*
+                * Note, no need to hold a get_dev_pagemap() reference
+                * here since we're in the driver I/O path and
+                * outstanding I/O requests pin the dev_pagemap.
+                */
+               if (test_and_clear_pmem_poison(page))
+                       clear_mce_nospec(pfn);
+       }
+}
+
 static blk_status_t pmem_clear_poison(struct pmem_device *pmem,
                phys_addr_t offset, unsigned int len)
 {
@@ -65,6 +90,7 @@ static blk_status_t pmem_clear_poison(struct pmem_device *pmem,
        if (cleared < len)
                rc = BLK_STS_IOERR;
        if (cleared > 0 && cleared / 512) {
+               hwpoison_clear(pmem, pmem->phys_addr + offset, cleared);
                cleared /= 512;
                dev_dbg(dev, "%#llx clear %ld sector%s\n",
                                (unsigned long long) sector, cleared,
@@ -226,8 +252,11 @@ __weak long __pmem_direct_access(struct pmem_device *pmem, pgoff_t pgoff,
        if (unlikely(is_bad_pmem(&pmem->bb, PFN_PHYS(pgoff) / 512,
                                        PFN_PHYS(nr_pages))))
                return -EIO;
-       *kaddr = pmem->virt_addr + offset;
-       *pfn = phys_to_pfn_t(pmem->phys_addr + offset, pmem->pfn_flags);
+
+       if (kaddr)
+               *kaddr = pmem->virt_addr + offset;
+       if (pfn)
+               *pfn = phys_to_pfn_t(pmem->phys_addr + offset, pmem->pfn_flags);
 
        /*
         * If badblocks are present, limit known good range to the
index a64ebc7..59cfe13 100644 (file)
@@ -1,6 +1,7 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 #ifndef __NVDIMM_PMEM_H__
 #define __NVDIMM_PMEM_H__
+#include <linux/page-flags.h>
 #include <linux/badblocks.h>
 #include <linux/types.h>
 #include <linux/pfn_t.h>
@@ -27,4 +28,16 @@ struct pmem_device {
 
 long __pmem_direct_access(struct pmem_device *pmem, pgoff_t pgoff,
                long nr_pages, void **kaddr, pfn_t *pfn);
+
+#ifdef CONFIG_MEMORY_FAILURE
+static inline bool test_and_clear_pmem_poison(struct page *page)
+{
+       return TestClearPageHWPoison(page);
+}
+#else
+static inline bool test_and_clear_pmem_poison(struct page *page)
+{
+       return false;
+}
+#endif
 #endif /* __NVDIMM_PMEM_H__ */
index ec3543b..fa37afc 100644 (file)
@@ -389,6 +389,30 @@ resource_size_t nd_region_available_dpa(struct nd_region *nd_region)
        return available;
 }
 
+resource_size_t nd_region_allocatable_dpa(struct nd_region *nd_region)
+{
+       resource_size_t available = 0;
+       int i;
+
+       if (is_memory(&nd_region->dev))
+               available = PHYS_ADDR_MAX;
+
+       WARN_ON(!is_nvdimm_bus_locked(&nd_region->dev));
+       for (i = 0; i < nd_region->ndr_mappings; i++) {
+               struct nd_mapping *nd_mapping = &nd_region->mapping[i];
+
+               if (is_memory(&nd_region->dev))
+                       available = min(available,
+                                       nd_pmem_max_contiguous_dpa(nd_region,
+                                                                  nd_mapping));
+               else if (is_nd_blk(&nd_region->dev))
+                       available += nd_blk_available_dpa(nd_region);
+       }
+       if (is_memory(&nd_region->dev))
+               return available * nd_region->ndr_mappings;
+       return available;
+}
+
 static ssize_t available_size_show(struct device *dev,
                struct device_attribute *attr, char *buf)
 {
@@ -410,6 +434,21 @@ static ssize_t available_size_show(struct device *dev,
 }
 static DEVICE_ATTR_RO(available_size);
 
+static ssize_t max_available_extent_show(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       struct nd_region *nd_region = to_nd_region(dev);
+       unsigned long long available = 0;
+
+       nvdimm_bus_lock(dev);
+       wait_nvdimm_bus_probe_idle(dev);
+       available = nd_region_allocatable_dpa(nd_region);
+       nvdimm_bus_unlock(dev);
+
+       return sprintf(buf, "%llu\n", available);
+}
+static DEVICE_ATTR_RO(max_available_extent);
+
 static ssize_t init_namespaces_show(struct device *dev,
                struct device_attribute *attr, char *buf)
 {
@@ -561,6 +600,7 @@ static struct attribute *nd_region_attributes[] = {
        &dev_attr_read_only.attr,
        &dev_attr_set_cookie.attr,
        &dev_attr_available_size.attr,
+       &dev_attr_max_available_extent.attr,
        &dev_attr_namespace_seed.attr,
        &dev_attr_init_namespaces.attr,
        &dev_attr_badblocks.attr,
index 738e354..c2ab577 100644 (file)
@@ -615,13 +615,11 @@ static bool acpi_pci_need_resume(struct pci_dev *dev)
        /*
         * In some cases (eg. Samsung 305V4A) leaving a bridge in suspend over
         * system-wide suspend/resume confuses the platform firmware, so avoid
-        * doing that, unless the bridge has a driver that should take care of
-        * the PM handling.  According to Section 16.1.6 of ACPI 6.2, endpoint
+        * doing that.  According to Section 16.1.6 of ACPI 6.2, endpoint
         * devices are expected to be in D3 before invoking the S3 entry path
         * from the firmware, so they should not be affected by this issue.
         */
-       if (pci_is_bridge(dev) && !dev->driver &&
-           acpi_target_system_state() != ACPI_STATE_S0)
+       if (pci_is_bridge(dev) && acpi_target_system_state() != ACPI_STATE_S0)
                return true;
 
        if (!adev || !acpi_device_power_manageable(adev))
index 46f58a9..ef7143a 100644 (file)
@@ -66,9 +66,15 @@ static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f,
                     f->vendor == (u16) PCI_ANY_ID) &&
                    (f->device == dev->device ||
                     f->device == (u16) PCI_ANY_ID)) {
-                       calltime = fixup_debug_start(dev, f->hook);
-                       f->hook(dev);
-                       fixup_debug_report(dev, calltime, f->hook);
+                       void (*hook)(struct pci_dev *dev);
+#ifdef CONFIG_HAVE_ARCH_PREL32_RELOCATIONS
+                       hook = offset_to_ptr(&f->hook_offset);
+#else
+                       hook = f->hook;
+#endif
+                       calltime = fixup_debug_start(dev, hook);
+                       hook(dev);
+                       fixup_debug_report(dev, calltime, hook);
                }
 }
 
index 8d4b7e9..e86752b 100644 (file)
@@ -361,6 +361,7 @@ source "drivers/pinctrl/vt8500/Kconfig"
 source "drivers/pinctrl/mediatek/Kconfig"
 source "drivers/pinctrl/zte/Kconfig"
 source "drivers/pinctrl/meson/Kconfig"
+source "drivers/pinctrl/cirrus/Kconfig"
 
 config PINCTRL_XWAY
        bool
index de40863..46ef9bd 100644 (file)
@@ -64,3 +64,4 @@ obj-$(CONFIG_PINCTRL_UNIPHIER)        += uniphier/
 obj-$(CONFIG_ARCH_VT8500)      += vt8500/
 obj-y                          += mediatek/
 obj-$(CONFIG_PINCTRL_ZX)       += zte/
+obj-y                          += cirrus/
diff --git a/drivers/pinctrl/cirrus/Kconfig b/drivers/pinctrl/cirrus/Kconfig
new file mode 100644 (file)
index 0000000..27013e5
--- /dev/null
@@ -0,0 +1,14 @@
+# This is all selected by the Madera MFD driver Kconfig options
+config PINCTRL_MADERA
+       tristate
+       select PINMUX
+       select GENERIC_PINCONF
+
+config PINCTRL_CS47L35
+       bool
+
+config PINCTRL_CS47L85
+       bool
+
+config PINCTRL_CS47L90
+       bool
diff --git a/drivers/pinctrl/cirrus/Makefile b/drivers/pinctrl/cirrus/Makefile
new file mode 100644 (file)
index 0000000..6e4938c
--- /dev/null
@@ -0,0 +1,13 @@
+# Cirrus Logic pinctrl drivers
+pinctrl-madera-objs            := pinctrl-madera-core.o
+ifeq ($(CONFIG_PINCTRL_CS47L35),y)
+pinctrl-madera-objs            += pinctrl-cs47l35.o
+endif
+ifeq ($(CONFIG_PINCTRL_CS47L85),y)
+pinctrl-madera-objs            += pinctrl-cs47l85.o
+endif
+ifeq ($(CONFIG_PINCTRL_CS47L90),y)
+pinctrl-madera-objs            += pinctrl-cs47l90.o
+endif
+
+obj-$(CONFIG_PINCTRL_MADERA)   += pinctrl-madera.o
diff --git a/drivers/pinctrl/cirrus/pinctrl-cs47l35.c b/drivers/pinctrl/cirrus/pinctrl-cs47l35.c
new file mode 100644 (file)
index 0000000..06b5916
--- /dev/null
@@ -0,0 +1,45 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Pinctrl for Cirrus Logic CS47L35
+ *
+ * Copyright (C) 2016-2017 Cirrus Logic
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2.
+ */
+
+#include <linux/err.h>
+#include <linux/mfd/madera/core.h>
+
+#include "pinctrl-madera.h"
+
+/*
+ * The alt func groups are the most commonly used functions we place these at
+ * the lower function indexes for convenience, and the less commonly used gpio
+ * functions at higher indexes.
+ *
+ * To stay consistent with the datasheet the function names are the same as
+ * the group names for that function's pins
+ *
+ * Note - all 1 less than in datasheet because these are zero-indexed
+ */
+static const unsigned int cs47l35_aif3_pins[] = { 0, 1, 2, 3 };
+static const unsigned int cs47l35_spk_pins[] = { 4, 5 };
+static const unsigned int cs47l35_aif1_pins[] = { 7, 8, 9, 10 };
+static const unsigned int cs47l35_aif2_pins[] = { 11, 12, 13, 14 };
+static const unsigned int cs47l35_mif1_pins[] = { 6, 15 };
+
+static const struct madera_pin_groups cs47l35_pin_groups[] = {
+       { "aif1", cs47l35_aif1_pins, ARRAY_SIZE(cs47l35_aif1_pins) },
+       { "aif2", cs47l35_aif2_pins, ARRAY_SIZE(cs47l35_aif2_pins) },
+       { "aif3", cs47l35_aif3_pins, ARRAY_SIZE(cs47l35_aif3_pins) },
+       { "mif1", cs47l35_mif1_pins, ARRAY_SIZE(cs47l35_mif1_pins) },
+       { "pdmspk1", cs47l35_spk_pins, ARRAY_SIZE(cs47l35_spk_pins) },
+};
+
+const struct madera_pin_chip cs47l35_pin_chip = {
+       .n_pins = CS47L35_NUM_GPIOS,
+       .pin_groups = cs47l35_pin_groups,
+       .n_pin_groups = ARRAY_SIZE(cs47l35_pin_groups),
+};
diff --git a/drivers/pinctrl/cirrus/pinctrl-cs47l85.c b/drivers/pinctrl/cirrus/pinctrl-cs47l85.c
new file mode 100644 (file)
index 0000000..0a322e2
--- /dev/null
@@ -0,0 +1,59 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Pinctrl for Cirrus Logic CS47L85
+ *
+ * Copyright (C) 2016-2017 Cirrus Logic
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2.
+ */
+
+#include <linux/err.h>
+#include <linux/mfd/madera/core.h>
+
+#include "pinctrl-madera.h"
+
+/*
+ * The alt func groups are the most commonly used functions we place these at
+ * the lower function indexes for convenience, and the less commonly used gpio
+ * functions at higher indexes.
+ *
+ * To stay consistent with the datasheet the function names are the same as
+ * the group names for that function's pins
+ *
+ * Note - all 1 less than in datasheet because these are zero-indexed
+ */
+static const unsigned int cs47l85_mif1_pins[] = { 8, 9 };
+static const unsigned int cs47l85_mif2_pins[] = { 10, 11 };
+static const unsigned int cs47l85_mif3_pins[] = { 12, 13 };
+static const unsigned int cs47l85_aif1_pins[] = { 14, 15, 16, 17 };
+static const unsigned int cs47l85_aif2_pins[] = { 18, 19, 20, 21 };
+static const unsigned int cs47l85_aif3_pins[] = { 22, 23, 24, 25 };
+static const unsigned int cs47l85_aif4_pins[] = { 26, 27, 28, 29 };
+static const unsigned int cs47l85_dmic4_pins[] = { 30, 31 };
+static const unsigned int cs47l85_dmic5_pins[] = { 32, 33 };
+static const unsigned int cs47l85_dmic6_pins[] = { 34, 35 };
+static const unsigned int cs47l85_spk1_pins[] = { 36, 38 };
+static const unsigned int cs47l85_spk2_pins[] = { 37, 39 };
+
+static const struct madera_pin_groups cs47l85_pin_groups[] = {
+       { "aif1", cs47l85_aif1_pins, ARRAY_SIZE(cs47l85_aif1_pins) },
+       { "aif2", cs47l85_aif2_pins, ARRAY_SIZE(cs47l85_aif2_pins) },
+       { "aif3", cs47l85_aif3_pins, ARRAY_SIZE(cs47l85_aif3_pins) },
+       { "aif4", cs47l85_aif4_pins, ARRAY_SIZE(cs47l85_aif4_pins) },
+       { "mif1", cs47l85_mif1_pins, ARRAY_SIZE(cs47l85_mif1_pins) },
+       { "mif2", cs47l85_mif2_pins, ARRAY_SIZE(cs47l85_mif2_pins) },
+       { "mif3", cs47l85_mif3_pins, ARRAY_SIZE(cs47l85_mif3_pins) },
+       { "dmic4", cs47l85_dmic4_pins, ARRAY_SIZE(cs47l85_dmic4_pins) },
+       { "dmic5", cs47l85_dmic5_pins, ARRAY_SIZE(cs47l85_dmic5_pins) },
+       { "dmic6", cs47l85_dmic6_pins, ARRAY_SIZE(cs47l85_dmic6_pins) },
+       { "pdmspk1", cs47l85_spk1_pins, ARRAY_SIZE(cs47l85_spk1_pins) },
+       { "pdmspk2", cs47l85_spk2_pins, ARRAY_SIZE(cs47l85_spk2_pins) },
+};
+
+const struct madera_pin_chip cs47l85_pin_chip = {
+       .n_pins = CS47L85_NUM_GPIOS,
+       .pin_groups = cs47l85_pin_groups,
+       .n_pin_groups = ARRAY_SIZE(cs47l85_pin_groups),
+};
diff --git a/drivers/pinctrl/cirrus/pinctrl-cs47l90.c b/drivers/pinctrl/cirrus/pinctrl-cs47l90.c
new file mode 100644 (file)
index 0000000..fc38f57
--- /dev/null
@@ -0,0 +1,57 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Pinctrl for Cirrus Logic CS47L90
+ *
+ * Copyright (C) 2016-2017 Cirrus Logic
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2.
+ */
+
+#include <linux/err.h>
+#include <linux/mfd/madera/core.h>
+
+#include "pinctrl-madera.h"
+
+/*
+ * The alt func groups are the most commonly used functions we place these at
+ * the lower function indexes for convenience, and the less commonly used gpio
+ * functions at higher indexes.
+ *
+ * To stay consistent with the datasheet the function names are the same as
+ * the group names for that function's pins
+ *
+ * Note - all 1 less than in datasheet because these are zero-indexed
+ */
+static const unsigned int cs47l90_mif1_pins[] = { 8, 9 };
+static const unsigned int cs47l90_mif2_pins[] = { 10, 11 };
+static const unsigned int cs47l90_mif3_pins[] = { 12, 13 };
+static const unsigned int cs47l90_aif1_pins[] = { 14, 15, 16, 17 };
+static const unsigned int cs47l90_aif2_pins[] = { 18, 19, 20, 21 };
+static const unsigned int cs47l90_aif3_pins[] = { 22, 23, 24, 25 };
+static const unsigned int cs47l90_aif4_pins[] = { 26, 27, 28, 29 };
+static const unsigned int cs47l90_dmic4_pins[] = { 30, 31 };
+static const unsigned int cs47l90_dmic5_pins[] = { 32, 33 };
+static const unsigned int cs47l90_dmic3_pins[] = { 34, 35 };
+static const unsigned int cs47l90_spk1_pins[] = { 36, 37 };
+
+static const struct madera_pin_groups cs47l90_pin_groups[] = {
+       { "aif1", cs47l90_aif1_pins, ARRAY_SIZE(cs47l90_aif1_pins) },
+       { "aif2", cs47l90_aif2_pins, ARRAY_SIZE(cs47l90_aif2_pins) },
+       { "aif3", cs47l90_aif3_pins, ARRAY_SIZE(cs47l90_aif3_pins) },
+       { "aif4", cs47l90_aif4_pins, ARRAY_SIZE(cs47l90_aif4_pins) },
+       { "mif1", cs47l90_mif1_pins, ARRAY_SIZE(cs47l90_mif1_pins) },
+       { "mif2", cs47l90_mif2_pins, ARRAY_SIZE(cs47l90_mif2_pins) },
+       { "mif3", cs47l90_mif3_pins, ARRAY_SIZE(cs47l90_mif3_pins) },
+       { "dmic3", cs47l90_dmic3_pins, ARRAY_SIZE(cs47l90_dmic3_pins) },
+       { "dmic4", cs47l90_dmic4_pins, ARRAY_SIZE(cs47l90_dmic4_pins) },
+       { "dmic5", cs47l90_dmic5_pins, ARRAY_SIZE(cs47l90_dmic5_pins) },
+       { "pdmspk1", cs47l90_spk1_pins, ARRAY_SIZE(cs47l90_spk1_pins) },
+};
+
+const struct madera_pin_chip cs47l90_pin_chip = {
+       .n_pins = CS47L90_NUM_GPIOS,
+       .pin_groups = cs47l90_pin_groups,
+       .n_pin_groups = ARRAY_SIZE(cs47l90_pin_groups),
+};
diff --git a/drivers/pinctrl/cirrus/pinctrl-madera-core.c b/drivers/pinctrl/cirrus/pinctrl-madera-core.c
new file mode 100644 (file)
index 0000000..ece41fb
--- /dev/null
@@ -0,0 +1,1076 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Pinctrl for Cirrus Logic Madera codecs
+ *
+ * Copyright (C) 2016-2018 Cirrus Logic
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2.
+ */
+
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinconf-generic.h>
+
+#include <linux/mfd/madera/core.h>
+#include <linux/mfd/madera/registers.h>
+
+#include "../pinctrl-utils.h"
+
+#include "pinctrl-madera.h"
+
+/*
+ * Use pin GPIO names for consistency
+ * NOTE: IDs are zero-indexed for coding convenience
+ */
+static const struct pinctrl_pin_desc madera_pins[] = {
+       PINCTRL_PIN(0, "gpio1"),
+       PINCTRL_PIN(1, "gpio2"),
+       PINCTRL_PIN(2, "gpio3"),
+       PINCTRL_PIN(3, "gpio4"),
+       PINCTRL_PIN(4, "gpio5"),
+       PINCTRL_PIN(5, "gpio6"),
+       PINCTRL_PIN(6, "gpio7"),
+       PINCTRL_PIN(7, "gpio8"),
+       PINCTRL_PIN(8, "gpio9"),
+       PINCTRL_PIN(9, "gpio10"),
+       PINCTRL_PIN(10, "gpio11"),
+       PINCTRL_PIN(11, "gpio12"),
+       PINCTRL_PIN(12, "gpio13"),
+       PINCTRL_PIN(13, "gpio14"),
+       PINCTRL_PIN(14, "gpio15"),
+       PINCTRL_PIN(15, "gpio16"),
+       PINCTRL_PIN(16, "gpio17"),
+       PINCTRL_PIN(17, "gpio18"),
+       PINCTRL_PIN(18, "gpio19"),
+       PINCTRL_PIN(19, "gpio20"),
+       PINCTRL_PIN(20, "gpio21"),
+       PINCTRL_PIN(21, "gpio22"),
+       PINCTRL_PIN(22, "gpio23"),
+       PINCTRL_PIN(23, "gpio24"),
+       PINCTRL_PIN(24, "gpio25"),
+       PINCTRL_PIN(25, "gpio26"),
+       PINCTRL_PIN(26, "gpio27"),
+       PINCTRL_PIN(27, "gpio28"),
+       PINCTRL_PIN(28, "gpio29"),
+       PINCTRL_PIN(29, "gpio30"),
+       PINCTRL_PIN(30, "gpio31"),
+       PINCTRL_PIN(31, "gpio32"),
+       PINCTRL_PIN(32, "gpio33"),
+       PINCTRL_PIN(33, "gpio34"),
+       PINCTRL_PIN(34, "gpio35"),
+       PINCTRL_PIN(35, "gpio36"),
+       PINCTRL_PIN(36, "gpio37"),
+       PINCTRL_PIN(37, "gpio38"),
+       PINCTRL_PIN(38, "gpio39"),
+       PINCTRL_PIN(39, "gpio40"),
+};
+
+/*
+ * All single-pin functions can be mapped to any GPIO, however pinmux applies
+ * functions to pin groups and only those groups declared as supporting that
+ * function. To make this work we must put each pin in its own dummy group so
+ * that the functions can be described as applying to all pins.
+ * Since these do not correspond to anything in the actual hardware - they are
+ * merely an adaptation to pinctrl's view of the world - we use the same name
+ * as the pin to avoid confusion when comparing with datasheet instructions
+ */
+static const char * const madera_pin_single_group_names[] = {
+       "gpio1",  "gpio2",  "gpio3",  "gpio4",  "gpio5",  "gpio6",  "gpio7",
+       "gpio8",  "gpio9",  "gpio10", "gpio11", "gpio12", "gpio13", "gpio14",
+       "gpio15", "gpio16", "gpio17", "gpio18", "gpio19", "gpio20", "gpio21",
+       "gpio22", "gpio23", "gpio24", "gpio25", "gpio26", "gpio27", "gpio28",
+       "gpio29", "gpio30", "gpio31", "gpio32", "gpio33", "gpio34", "gpio35",
+       "gpio36", "gpio37", "gpio38", "gpio39", "gpio40",
+};
+
+/* set of pin numbers for single-pin groups, zero-indexed */
+static const unsigned int madera_pin_single_group_pins[] = {
+         0,  1,  2,  3,  4,  5,  6,
+         7,  8,  9, 10, 11, 12, 13,
+        14, 15, 16, 17, 18, 19, 20,
+        21, 22, 23, 24, 25, 26, 27,
+        28, 29, 30, 31, 32, 33, 34,
+        35, 36, 37, 38, 39,
+};
+
+static const char * const madera_aif1_group_names[] = { "aif1" };
+static const char * const madera_aif2_group_names[] = { "aif2" };
+static const char * const madera_aif3_group_names[] = { "aif3" };
+static const char * const madera_aif4_group_names[] = { "aif4" };
+static const char * const madera_mif1_group_names[] = { "mif1" };
+static const char * const madera_mif2_group_names[] = { "mif2" };
+static const char * const madera_mif3_group_names[] = { "mif3" };
+static const char * const madera_dmic3_group_names[] = { "dmic3" };
+static const char * const madera_dmic4_group_names[] = { "dmic4" };
+static const char * const madera_dmic5_group_names[] = { "dmic5" };
+static const char * const madera_dmic6_group_names[] = { "dmic6" };
+static const char * const madera_spk1_group_names[] = { "pdmspk1" };
+static const char * const madera_spk2_group_names[] = { "pdmspk2" };
+
+/*
+ * alt-functions always apply to a single pin group, other functions always
+ * apply to all pins
+ */
+static const struct {
+       const char *name;
+       const char * const *group_names;
+       u32 func;
+} madera_mux_funcs[] = {
+       {
+               .name = "aif1",
+               .group_names = madera_aif1_group_names,
+               .func = 0x000
+       },
+       {
+               .name = "aif2",
+               .group_names = madera_aif2_group_names,
+               .func = 0x000
+       },
+       {
+               .name = "aif3",
+               .group_names = madera_aif3_group_names,
+               .func = 0x000
+       },
+       {
+               .name = "aif4",
+               .group_names = madera_aif4_group_names,
+               .func = 0x000
+       },
+       {
+               .name = "mif1",
+               .group_names = madera_mif1_group_names,
+               .func = 0x000
+       },
+       {
+               .name = "mif2",
+               .group_names = madera_mif2_group_names,
+               .func = 0x000
+       },
+       {
+               .name = "mif3",
+               .group_names = madera_mif3_group_names,
+               .func = 0x000
+       },
+       {
+               .name = "dmic3",
+               .group_names = madera_dmic3_group_names,
+               .func = 0x000
+       },
+       {
+               .name = "dmic4",
+               .group_names = madera_dmic4_group_names,
+               .func = 0x000
+       },
+       {
+               .name = "dmic5",
+               .group_names = madera_dmic5_group_names,
+               .func = 0x000
+       },
+       {
+               .name = "dmic6",
+               .group_names = madera_dmic6_group_names,
+               .func = 0x000
+       },
+       {
+               .name = "pdmspk1",
+               .group_names = madera_spk1_group_names,
+               .func = 0x000
+       },
+       {
+               .name = "pdmspk2",
+               .group_names = madera_spk2_group_names,
+               .func = 0x000
+       },
+       {
+               .name = "io",
+               .group_names = madera_pin_single_group_names,
+               .func = 0x001
+       },
+       {
+               .name = "dsp-gpio",
+               .group_names = madera_pin_single_group_names,
+               .func = 0x002
+       },
+       {
+               .name = "irq1",
+               .group_names = madera_pin_single_group_names,
+               .func = 0x003
+       },
+       {
+               .name = "irq2",
+               .group_names = madera_pin_single_group_names,
+               .func = 0x004
+       },
+       {
+               .name = "fll1-clk",
+               .group_names = madera_pin_single_group_names,
+               .func = 0x010
+       },
+       {
+               .name = "fll2-clk",
+               .group_names = madera_pin_single_group_names,
+               .func = 0x011
+       },
+       {
+               .name = "fll3-clk",
+               .group_names = madera_pin_single_group_names,
+               .func = 0x012
+       },
+       {
+               .name = "fllao-clk",
+               .group_names = madera_pin_single_group_names,
+               .func = 0x013
+       },
+       {
+               .name = "fll1-lock",
+               .group_names = madera_pin_single_group_names,
+               .func = 0x018
+       },
+       {
+               .name = "fll2-lock",
+               .group_names = madera_pin_single_group_names,
+               .func = 0x019
+       },
+       {
+               .name = "fll3-lock",
+               .group_names = madera_pin_single_group_names,
+               .func = 0x01a
+       },
+       {
+               .name = "fllao-lock",
+               .group_names = madera_pin_single_group_names,
+               .func = 0x01b
+       },
+       {
+               .name = "opclk",
+               .group_names = madera_pin_single_group_names,
+               .func = 0x040
+       },
+       {
+               .name = "opclk-async",
+               .group_names = madera_pin_single_group_names,
+               .func = 0x041
+       },
+       {
+               .name = "pwm1",
+               .group_names = madera_pin_single_group_names,
+               .func = 0x048
+       },
+       {
+               .name = "pwm2",
+               .group_names = madera_pin_single_group_names,
+               .func = 0x049
+       },
+       {
+               .name = "spdif",
+               .group_names = madera_pin_single_group_names,
+               .func = 0x04c
+       },
+       {
+               .name = "asrc1-in1-lock",
+               .group_names = madera_pin_single_group_names,
+               .func = 0x088
+       },
+       {
+               .name = "asrc1-in2-lock",
+               .group_names = madera_pin_single_group_names,
+               .func = 0x089
+       },
+       {
+               .name = "asrc2-in1-lock",
+               .group_names = madera_pin_single_group_names,
+               .func = 0x08a
+       },
+       {
+               .name = "asrc2-in2-lock",
+               .group_names = madera_pin_single_group_names,
+               .func = 0x08b
+       },
+       {
+               .name = "spkl-short-circuit",
+               .group_names = madera_pin_single_group_names,
+               .func = 0x0b6
+       },
+       {
+               .name = "spkr-short-circuit",
+               .group_names = madera_pin_single_group_names,
+               .func = 0x0b7
+       },
+       {
+               .name = "spk-shutdown",
+               .group_names = madera_pin_single_group_names,
+               .func = 0x0e0
+       },
+       {
+               .name = "spk-overheat-shutdown",
+               .group_names = madera_pin_single_group_names,
+               .func = 0x0e1
+       },
+       {
+               .name = "spk-overheat-warn",
+               .group_names = madera_pin_single_group_names,
+               .func = 0x0e2
+       },
+       {
+               .name = "timer1-sts",
+               .group_names = madera_pin_single_group_names,
+               .func = 0x140
+       },
+       {
+               .name = "timer2-sts",
+               .group_names = madera_pin_single_group_names,
+               .func = 0x141
+       },
+       {
+               .name = "timer3-sts",
+               .group_names = madera_pin_single_group_names,
+               .func = 0x142
+       },
+       {
+               .name = "timer4-sts",
+               .group_names = madera_pin_single_group_names,
+               .func = 0x143
+       },
+       {
+               .name = "timer5-sts",
+               .group_names = madera_pin_single_group_names,
+               .func = 0x144
+       },
+       {
+               .name = "timer6-sts",
+               .group_names = madera_pin_single_group_names,
+               .func = 0x145
+       },
+       {
+               .name = "timer7-sts",
+               .group_names = madera_pin_single_group_names,
+               .func = 0x146
+       },
+       {
+               .name = "timer8-sts",
+               .group_names = madera_pin_single_group_names,
+               .func = 0x147
+       },
+       {
+               .name = "log1-fifo-ne",
+               .group_names = madera_pin_single_group_names,
+               .func = 0x150
+       },
+       {
+               .name = "log2-fifo-ne",
+               .group_names = madera_pin_single_group_names,
+               .func = 0x151
+       },
+       {
+               .name = "log3-fifo-ne",
+               .group_names = madera_pin_single_group_names,
+               .func = 0x152
+       },
+       {
+               .name = "log4-fifo-ne",
+               .group_names = madera_pin_single_group_names,
+               .func = 0x153
+       },
+       {
+               .name = "log5-fifo-ne",
+               .group_names = madera_pin_single_group_names,
+               .func = 0x154
+       },
+       {
+               .name = "log6-fifo-ne",
+               .group_names = madera_pin_single_group_names,
+               .func = 0x155
+       },
+       {
+               .name = "log7-fifo-ne",
+               .group_names = madera_pin_single_group_names,
+               .func = 0x156
+       },
+       {
+               .name = "log8-fifo-ne",
+               .group_names = madera_pin_single_group_names,
+               .func = 0x157
+       },
+};
+
+static u16 madera_pin_make_drv_str(struct madera_pin_private *priv,
+                                     unsigned int milliamps)
+{
+       switch (milliamps) {
+       case 4:
+               return 0;
+       case 8:
+               return 2 << MADERA_GP1_DRV_STR_SHIFT;
+       default:
+               break;
+       }
+
+       dev_warn(priv->dev, "%u mA not a valid drive strength", milliamps);
+
+       return 0;
+}
+
+static unsigned int madera_pin_unmake_drv_str(struct madera_pin_private *priv,
+                                             u16 regval)
+{
+       regval = (regval & MADERA_GP1_DRV_STR_MASK) >> MADERA_GP1_DRV_STR_SHIFT;
+
+       switch (regval) {
+       case 0:
+               return 4;
+       case 2:
+               return 8;
+       default:
+               return 0;
+       }
+}
+
+static int madera_get_groups_count(struct pinctrl_dev *pctldev)
+{
+       struct madera_pin_private *priv = pinctrl_dev_get_drvdata(pctldev);
+
+       /* Number of alt function groups plus number of single-pin groups */
+       return priv->chip->n_pin_groups + priv->chip->n_pins;
+}
+
+static const char *madera_get_group_name(struct pinctrl_dev *pctldev,
+                                        unsigned int selector)
+{
+       struct madera_pin_private *priv = pinctrl_dev_get_drvdata(pctldev);
+
+       if (selector < priv->chip->n_pin_groups)
+               return priv->chip->pin_groups[selector].name;
+
+       selector -= priv->chip->n_pin_groups;
+       return madera_pin_single_group_names[selector];
+}
+
+static int madera_get_group_pins(struct pinctrl_dev *pctldev,
+                                unsigned int selector,
+                                const unsigned int **pins,
+                                unsigned int *num_pins)
+{
+       struct madera_pin_private *priv = pinctrl_dev_get_drvdata(pctldev);
+
+       if (selector < priv->chip->n_pin_groups) {
+               *pins = priv->chip->pin_groups[selector].pins;
+               *num_pins = priv->chip->pin_groups[selector].n_pins;
+       } else {
+               /* return the dummy group for a single pin */
+               selector -= priv->chip->n_pin_groups;
+               *pins = &madera_pin_single_group_pins[selector];
+               *num_pins = 1;
+       }
+       return 0;
+}
+
+static void madera_pin_dbg_show_fn(struct madera_pin_private *priv,
+                                  struct seq_file *s,
+                                  unsigned int pin, unsigned int fn)
+{
+       const struct madera_pin_chip *chip = priv->chip;
+       int i, g_pin;
+
+       if (fn != 0) {
+               for (i = 0; i < ARRAY_SIZE(madera_mux_funcs); ++i) {
+                       if (madera_mux_funcs[i].func == fn) {
+                               seq_printf(s, " FN=%s",
+                                          madera_mux_funcs[i].name);
+                               return;
+                       }
+               }
+               return; /* ignore unknown function values */
+       }
+
+       /* alt function */
+       for (i = 0; i < chip->n_pin_groups; ++i) {
+               for (g_pin = 0; g_pin < chip->pin_groups[i].n_pins; ++g_pin) {
+                       if (chip->pin_groups[i].pins[g_pin] == pin) {
+                               seq_printf(s, " FN=%s",
+                                          chip->pin_groups[i].name);
+                               return;
+                       }
+               }
+       }
+}
+
+static void __maybe_unused madera_pin_dbg_show(struct pinctrl_dev *pctldev,
+                                              struct seq_file *s,
+                                              unsigned int pin)
+{
+       struct madera_pin_private *priv = pinctrl_dev_get_drvdata(pctldev);
+       unsigned int conf[2];
+       unsigned int reg = MADERA_GPIO1_CTRL_1 + (2 * pin);
+       unsigned int fn;
+       int ret;
+
+       ret = regmap_read(priv->madera->regmap, reg, &conf[0]);
+       if (ret)
+               return;
+
+       ret = regmap_read(priv->madera->regmap, reg + 1, &conf[1]);
+       if (ret)
+               return;
+
+       seq_printf(s, "%04x:%04x", conf[0], conf[1]);
+
+       fn = (conf[0] & MADERA_GP1_FN_MASK) >> MADERA_GP1_FN_SHIFT;
+       madera_pin_dbg_show_fn(priv, s, pin, fn);
+
+       /* State of direction bit is only relevant if function==1 */
+       if (fn == 1) {
+               if (conf[1] & MADERA_GP1_DIR_MASK)
+                       seq_puts(s, " IN");
+               else
+                       seq_puts(s, " OUT");
+       }
+
+       if (conf[1] & MADERA_GP1_PU_MASK)
+               seq_puts(s, " PU");
+
+       if (conf[1] & MADERA_GP1_PD_MASK)
+               seq_puts(s, " PD");
+
+       if (conf[0] & MADERA_GP1_DB_MASK)
+               seq_puts(s, " DB");
+
+       if (conf[0] & MADERA_GP1_OP_CFG_MASK)
+               seq_puts(s, " OD");
+       else
+               seq_puts(s, " CMOS");
+
+       seq_printf(s, " DRV=%umA", madera_pin_unmake_drv_str(priv, conf[1]));
+
+       if (conf[0] & MADERA_GP1_IP_CFG_MASK)
+               seq_puts(s, "SCHMITT");
+}
+
+
+static const struct pinctrl_ops madera_pin_group_ops = {
+       .get_groups_count = madera_get_groups_count,
+       .get_group_name = madera_get_group_name,
+       .get_group_pins = madera_get_group_pins,
+#if IS_ENABLED(CONFIG_OF)
+       .dt_node_to_map = pinconf_generic_dt_node_to_map_all,
+       .dt_free_map = pinctrl_utils_free_map,
+#endif
+#if IS_ENABLED(CONFIG_DEBUG_FS)
+       .pin_dbg_show = madera_pin_dbg_show,
+#endif
+};
+
+static int madera_mux_get_funcs_count(struct pinctrl_dev *pctldev)
+{
+       return ARRAY_SIZE(madera_mux_funcs);
+}
+
+static const char *madera_mux_get_func_name(struct pinctrl_dev *pctldev,
+                                           unsigned int selector)
+{
+       return madera_mux_funcs[selector].name;
+}
+
+static int madera_mux_get_groups(struct pinctrl_dev *pctldev,
+                                unsigned int selector,
+                                const char * const **groups,
+                                unsigned int * const num_groups)
+{
+       struct madera_pin_private *priv = pinctrl_dev_get_drvdata(pctldev);
+
+       *groups = madera_mux_funcs[selector].group_names;
+
+       if (madera_mux_funcs[selector].func == 0) {
+               /* alt func always maps to a single group */
+               *num_groups = 1;
+       } else {
+               /* other funcs map to all available gpio pins */
+               *num_groups = priv->chip->n_pins;
+       }
+
+       return 0;
+}
+
+static int madera_mux_set_mux(struct pinctrl_dev *pctldev,
+                             unsigned int selector,
+                             unsigned int group)
+{
+       struct madera_pin_private *priv = pinctrl_dev_get_drvdata(pctldev);
+       struct madera *madera = priv->madera;
+       const struct madera_pin_groups *pin_group = priv->chip->pin_groups;
+       unsigned int n_chip_groups = priv->chip->n_pin_groups;
+       const char *func_name = madera_mux_funcs[selector].name;
+       unsigned int reg;
+       int i, ret;
+
+       dev_dbg(priv->dev, "%s selecting %u (%s) for group %u (%s)\n",
+               __func__, selector, func_name, group,
+               madera_get_group_name(pctldev, group));
+
+       if (madera_mux_funcs[selector].func == 0) {
+               /* alt func pin assignments are codec-specific */
+               for (i = 0; i < n_chip_groups; ++i) {
+                       if (strcmp(func_name, pin_group->name) == 0)
+                               break;
+
+                       ++pin_group;
+               }
+
+               if (i == n_chip_groups)
+                       return -EINVAL;
+
+               for (i = 0; i < pin_group->n_pins; ++i) {
+                       reg = MADERA_GPIO1_CTRL_1 + (2 * pin_group->pins[i]);
+
+                       dev_dbg(priv->dev, "%s setting 0x%x func bits to 0\n",
+                               __func__, reg);
+
+                       ret = regmap_update_bits(madera->regmap, reg,
+                                                MADERA_GP1_FN_MASK, 0);
+                       if (ret)
+                               break;
+
+               }
+       } else {
+               /*
+                * for other funcs the group will be the gpio number and will
+                * be offset by the number of chip-specific functions at the
+                * start of the group list
+                */
+               group -= n_chip_groups;
+               reg = MADERA_GPIO1_CTRL_1 + (2 * group);
+
+               dev_dbg(priv->dev, "%s setting 0x%x func bits to 0x%x\n",
+                       __func__, reg, madera_mux_funcs[selector].func);
+
+               ret = regmap_update_bits(madera->regmap,
+                                        reg,
+                                        MADERA_GP1_FN_MASK,
+                                        madera_mux_funcs[selector].func);
+       }
+
+       if (ret)
+               dev_err(priv->dev, "Failed to write to 0x%x (%d)\n", reg, ret);
+
+       return ret;
+}
+
+static int madera_gpio_set_direction(struct pinctrl_dev *pctldev,
+                                    struct pinctrl_gpio_range *range,
+                                    unsigned int offset,
+                                    bool input)
+{
+       struct madera_pin_private *priv = pinctrl_dev_get_drvdata(pctldev);
+       struct madera *madera = priv->madera;
+       unsigned int reg = MADERA_GPIO1_CTRL_2 + (2 * offset);
+       unsigned int val;
+       int ret;
+
+       if (input)
+               val = MADERA_GP1_DIR;
+       else
+               val = 0;
+
+       ret = regmap_update_bits(madera->regmap, reg, MADERA_GP1_DIR_MASK, val);
+       if (ret)
+               dev_err(priv->dev, "Failed to write to 0x%x (%d)\n", reg, ret);
+
+       return ret;
+}
+
+static int madera_gpio_request_enable(struct pinctrl_dev *pctldev,
+                                     struct pinctrl_gpio_range *range,
+                                     unsigned int offset)
+{
+       struct madera_pin_private *priv = pinctrl_dev_get_drvdata(pctldev);
+       struct madera *madera = priv->madera;
+       unsigned int reg = MADERA_GPIO1_CTRL_1 + (2 * offset);
+       int ret;
+
+       /* put the pin into GPIO mode */
+       ret = regmap_update_bits(madera->regmap, reg, MADERA_GP1_FN_MASK, 1);
+       if (ret)
+               dev_err(priv->dev, "Failed to write to 0x%x (%d)\n", reg, ret);
+
+       return ret;
+}
+
+static void madera_gpio_disable_free(struct pinctrl_dev *pctldev,
+                                    struct pinctrl_gpio_range *range,
+                                    unsigned int offset)
+{
+       struct madera_pin_private *priv = pinctrl_dev_get_drvdata(pctldev);
+       struct madera *madera = priv->madera;
+       unsigned int reg = MADERA_GPIO1_CTRL_1 + (2 * offset);
+       int ret;
+
+       /* disable GPIO by setting to GPIO IN */
+       madera_gpio_set_direction(pctldev, range, offset, true);
+
+       ret = regmap_update_bits(madera->regmap, reg, MADERA_GP1_FN_MASK, 1);
+       if (ret)
+               dev_err(priv->dev, "Failed to write to 0x%x (%d)\n", reg, ret);
+}
+
+static const struct pinmux_ops madera_pin_mux_ops = {
+       .get_functions_count = madera_mux_get_funcs_count,
+       .get_function_name = madera_mux_get_func_name,
+       .get_function_groups = madera_mux_get_groups,
+       .set_mux = madera_mux_set_mux,
+       .gpio_request_enable = madera_gpio_request_enable,
+       .gpio_disable_free = madera_gpio_disable_free,
+       .gpio_set_direction = madera_gpio_set_direction,
+       .strict = true, /* GPIO and other functions are exclusive */
+};
+
+static int madera_pin_conf_get(struct pinctrl_dev *pctldev, unsigned int pin,
+                              unsigned long *config)
+{
+       struct madera_pin_private *priv = pinctrl_dev_get_drvdata(pctldev);
+       unsigned int param = pinconf_to_config_param(*config);
+       unsigned int result = 0;
+       unsigned int reg = MADERA_GPIO1_CTRL_1 + (2 * pin);
+       unsigned int conf[2];
+       int ret;
+
+       ret = regmap_read(priv->madera->regmap, reg, &conf[0]);
+       if (!ret)
+               ret = regmap_read(priv->madera->regmap, reg + 1, &conf[1]);
+
+       if (ret) {
+               dev_err(priv->dev, "Failed to read GP%d conf (%d)\n",
+                       pin + 1, ret);
+               return ret;
+       }
+
+       switch (param) {
+       case PIN_CONFIG_BIAS_BUS_HOLD:
+               conf[1] &= MADERA_GP1_PU_MASK | MADERA_GP1_PD_MASK;
+               if (conf[1] == (MADERA_GP1_PU | MADERA_GP1_PD))
+                       result = 1;
+               break;
+       case PIN_CONFIG_BIAS_DISABLE:
+               conf[1] &= MADERA_GP1_PU_MASK | MADERA_GP1_PD_MASK;
+               if (!conf[1])
+                       result = 1;
+               break;
+       case PIN_CONFIG_BIAS_PULL_DOWN:
+               conf[1] &= MADERA_GP1_PU_MASK | MADERA_GP1_PD_MASK;
+               if (conf[1] == MADERA_GP1_PD_MASK)
+                       result = 1;
+               break;
+       case PIN_CONFIG_BIAS_PULL_UP:
+               conf[1] &= MADERA_GP1_PU_MASK | MADERA_GP1_PD_MASK;
+               if (conf[1] == MADERA_GP1_PU_MASK)
+                       result = 1;
+               break;
+       case PIN_CONFIG_DRIVE_OPEN_DRAIN:
+               if (conf[0] & MADERA_GP1_OP_CFG_MASK)
+                       result = 1;
+               break;
+       case PIN_CONFIG_DRIVE_PUSH_PULL:
+               if (!(conf[0] & MADERA_GP1_OP_CFG_MASK))
+                       result = 1;
+               break;
+       case PIN_CONFIG_DRIVE_STRENGTH:
+               result = madera_pin_unmake_drv_str(priv, conf[1]);
+               break;
+       case PIN_CONFIG_INPUT_DEBOUNCE:
+               if (conf[0] & MADERA_GP1_DB_MASK)
+                       result = 1;
+               break;
+       case PIN_CONFIG_INPUT_ENABLE:
+               if (conf[0] & MADERA_GP1_DIR_MASK)
+                       result = 1;
+               break;
+       case PIN_CONFIG_INPUT_SCHMITT:
+       case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
+               if (conf[0] & MADERA_GP1_IP_CFG_MASK)
+                       result = 1;
+               break;
+       case PIN_CONFIG_OUTPUT:
+               if ((conf[1] & MADERA_GP1_DIR_MASK) &&
+                   (conf[0] & MADERA_GP1_LVL_MASK))
+                       result = 1;
+               break;
+       default:
+               break;
+       }
+
+       *config = pinconf_to_config_packed(param, result);
+
+       return 0;
+}
+
+static int madera_pin_conf_set(struct pinctrl_dev *pctldev, unsigned int pin,
+                              unsigned long *configs, unsigned int num_configs)
+{
+       struct madera_pin_private *priv = pinctrl_dev_get_drvdata(pctldev);
+       u16 conf[2] = {0, 0};
+       u16 mask[2] = {0, 0};
+       unsigned int reg = MADERA_GPIO1_CTRL_1 + (2 * pin);
+       unsigned int val;
+       int ret;
+
+       while (num_configs) {
+               dev_dbg(priv->dev, "%s config 0x%lx\n", __func__, *configs);
+
+               switch (pinconf_to_config_param(*configs)) {
+               case PIN_CONFIG_BIAS_BUS_HOLD:
+                       mask[1] |= MADERA_GP1_PU_MASK | MADERA_GP1_PD_MASK;
+                       conf[1] |= MADERA_GP1_PU | MADERA_GP1_PD;
+                       break;
+               case PIN_CONFIG_BIAS_DISABLE:
+                       mask[1] |= MADERA_GP1_PU_MASK | MADERA_GP1_PD_MASK;
+                       conf[1] &= ~(MADERA_GP1_PU | MADERA_GP1_PD);
+                       break;
+               case PIN_CONFIG_BIAS_PULL_DOWN:
+                       mask[1] |= MADERA_GP1_PU_MASK | MADERA_GP1_PD_MASK;
+                       conf[1] |= MADERA_GP1_PD;
+                       conf[1] &= ~MADERA_GP1_PU;
+                       break;
+               case PIN_CONFIG_BIAS_PULL_UP:
+                       mask[1] |= MADERA_GP1_PU_MASK | MADERA_GP1_PD_MASK;
+                       conf[1] |= MADERA_GP1_PU;
+                       conf[1] &= ~MADERA_GP1_PD;
+                       break;
+               case PIN_CONFIG_DRIVE_OPEN_DRAIN:
+                       mask[0] |= MADERA_GP1_OP_CFG_MASK;
+                       conf[0] |= MADERA_GP1_OP_CFG;
+                       break;
+               case PIN_CONFIG_DRIVE_PUSH_PULL:
+                       mask[0] |= MADERA_GP1_OP_CFG_MASK;
+                       conf[0] &= ~MADERA_GP1_OP_CFG;
+                       break;
+               case PIN_CONFIG_DRIVE_STRENGTH:
+                       val = pinconf_to_config_argument(*configs);
+                       mask[1] |= MADERA_GP1_DRV_STR_MASK;
+                       conf[1] &= ~MADERA_GP1_DRV_STR_MASK;
+                       conf[1] |= madera_pin_make_drv_str(priv, val);
+                       break;
+               case PIN_CONFIG_INPUT_DEBOUNCE:
+                       mask[0] |= MADERA_GP1_DB_MASK;
+
+                       /*
+                        * we can't configure debounce time per-pin so value
+                        * is just a flag
+                        */
+                       val = pinconf_to_config_argument(*configs);
+                       if (val)
+                               conf[0] |= MADERA_GP1_DB;
+                       else
+                               conf[0] &= ~MADERA_GP1_DB;
+                       break;
+               case PIN_CONFIG_INPUT_ENABLE:
+                       val = pinconf_to_config_argument(*configs);
+                       mask[1] |= MADERA_GP1_DIR_MASK;
+                       if (val)
+                               conf[1] |= MADERA_GP1_DIR;
+                       else
+                               conf[1] &= ~MADERA_GP1_DIR;
+                       break;
+               case PIN_CONFIG_INPUT_SCHMITT:
+                       val = pinconf_to_config_argument(*configs);
+                       mask[0] |= MADERA_GP1_IP_CFG;
+                       if (val)
+                               conf[0] |= MADERA_GP1_IP_CFG;
+                       else
+                               conf[0] &= ~MADERA_GP1_IP_CFG;
+
+                       mask[1] |= MADERA_GP1_DIR_MASK;
+                       conf[1] |= MADERA_GP1_DIR;
+                       break;
+               case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
+                       mask[0] |= MADERA_GP1_IP_CFG;
+                       conf[0] |= MADERA_GP1_IP_CFG;
+                       mask[1] |= MADERA_GP1_DIR_MASK;
+                       conf[1] |= MADERA_GP1_DIR;
+                       break;
+               case PIN_CONFIG_OUTPUT:
+                       val = pinconf_to_config_argument(*configs);
+                       mask[0] |= MADERA_GP1_LVL_MASK;
+                       if (val)
+                               conf[0] |= MADERA_GP1_LVL;
+                       else
+                               conf[0] &= ~MADERA_GP1_LVL;
+
+                       mask[1] |= MADERA_GP1_DIR_MASK;
+                       conf[1] &= ~MADERA_GP1_DIR;
+                       break;
+               default:
+                       break;
+               }
+
+               ++configs;
+               --num_configs;
+       }
+
+       dev_dbg(priv->dev,
+               "%s gpio%d 0x%x:0x%x 0x%x:0x%x\n",
+               __func__, pin + 1, reg, conf[0], reg + 1, conf[1]);
+
+       ret = regmap_update_bits(priv->madera->regmap, reg, mask[0], conf[0]);
+       if (ret)
+               goto err;
+
+       ++reg;
+       ret = regmap_update_bits(priv->madera->regmap, reg, mask[1], conf[1]);
+       if (ret)
+               goto err;
+
+       return 0;
+
+err:
+       dev_err(priv->dev,
+               "Failed to write GPIO%d conf (%d) reg 0x%x\n",
+               pin + 1, ret, reg);
+
+       return ret;
+}
+
+static int madera_pin_conf_group_set(struct pinctrl_dev *pctldev,
+                                    unsigned int selector,
+                                    unsigned long *configs,
+                                    unsigned int num_configs)
+{
+       struct madera_pin_private *priv = pinctrl_dev_get_drvdata(pctldev);
+       const struct madera_pin_groups *pin_group;
+       unsigned int n_groups = priv->chip->n_pin_groups;
+       int i, ret;
+
+       dev_dbg(priv->dev, "%s setting group %s\n", __func__,
+               madera_get_group_name(pctldev, selector));
+
+       if (selector >= n_groups) {
+               /* group is a single pin, convert to pin number and set */
+               return madera_pin_conf_set(pctldev,
+                                          selector - n_groups,
+                                          configs,
+                                          num_configs);
+       } else {
+               pin_group = &priv->chip->pin_groups[selector];
+
+               for (i = 0; i < pin_group->n_pins; ++i) {
+                       ret = madera_pin_conf_set(pctldev,
+                                                 pin_group->pins[i],
+                                                 configs,
+                                                 num_configs);
+                       if (ret)
+                               return ret;
+               }
+       }
+
+       return 0;
+}
+
+static const struct pinconf_ops madera_pin_conf_ops = {
+       .pin_config_get = madera_pin_conf_get,
+       .pin_config_set = madera_pin_conf_set,
+       .pin_config_group_set = madera_pin_conf_group_set,
+
+};
+
+static struct pinctrl_desc madera_pin_desc = {
+       .name = "madera-pinctrl",
+       .pins = madera_pins,
+       .pctlops = &madera_pin_group_ops,
+       .pmxops = &madera_pin_mux_ops,
+       .confops = &madera_pin_conf_ops,
+       .owner = THIS_MODULE,
+};
+
+static int madera_pin_probe(struct platform_device *pdev)
+{
+       struct madera *madera = dev_get_drvdata(pdev->dev.parent);
+       const struct madera_pdata *pdata = dev_get_platdata(madera->dev);
+       struct madera_pin_private *priv;
+       int ret;
+
+       BUILD_BUG_ON(ARRAY_SIZE(madera_pin_single_group_names) !=
+                    ARRAY_SIZE(madera_pin_single_group_pins));
+
+       dev_dbg(&pdev->dev, "%s\n", __func__);
+
+       priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
+
+       priv->dev = &pdev->dev;
+       priv->madera = madera;
+       pdev->dev.of_node = madera->dev->of_node;
+
+       switch (madera->type) {
+       case CS47L35:
+               if (IS_ENABLED(CONFIG_PINCTRL_CS47L35))
+                       priv->chip = &cs47l35_pin_chip;
+               break;
+       case CS47L85:
+       case WM1840:
+               if (IS_ENABLED(CONFIG_PINCTRL_CS47L85))
+                       priv->chip = &cs47l85_pin_chip;
+               break;
+       case CS47L90:
+       case CS47L91:
+               if (IS_ENABLED(CONFIG_PINCTRL_CS47L90))
+                       priv->chip = &cs47l90_pin_chip;
+               break;
+       default:
+               break;
+       }
+
+       if (!priv->chip)
+               return -ENODEV;
+
+       madera_pin_desc.npins = priv->chip->n_pins;
+
+       ret = devm_pinctrl_register_and_init(&pdev->dev,
+                                            &madera_pin_desc,
+                                            priv,
+                                            &priv->pctl);
+       if (ret) {
+               dev_err(priv->dev, "Failed pinctrl register (%d)\n", ret);
+               return ret;
+       }
+
+       /* if the configuration is provided through pdata, apply it */
+       if (pdata) {
+               ret = pinctrl_register_mappings(pdata->gpio_configs,
+                                               pdata->n_gpio_configs);
+               if (ret) {
+                       dev_err(priv->dev,
+                               "Failed to register pdata mappings (%d)\n",
+                               ret);
+                       return ret;
+               }
+       }
+
+       ret = pinctrl_enable(priv->pctl);
+       if (ret) {
+               dev_err(priv->dev, "Failed to enable pinctrl (%d)\n", ret);
+               return ret;
+       }
+
+       dev_dbg(priv->dev, "pinctrl probed ok\n");
+
+       return 0;
+}
+
+static struct platform_driver madera_pin_driver = {
+       .probe = madera_pin_probe,
+       .driver = {
+               .name = "madera-pinctrl",
+       },
+};
+
+module_platform_driver(madera_pin_driver);
+
+MODULE_DESCRIPTION("Madera pinctrl driver");
+MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pinctrl/cirrus/pinctrl-madera.h b/drivers/pinctrl/cirrus/pinctrl-madera.h
new file mode 100644 (file)
index 0000000..8000f4f
--- /dev/null
@@ -0,0 +1,41 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Pinctrl for Cirrus Logic Madera codecs
+ *
+ * Copyright (C) 2016-2017 Cirrus Logic
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2.
+ */
+
+#ifndef PINCTRL_MADERA_H
+#define PINCTRL_MADERA_H
+
+struct madera_pin_groups {
+       const char *name;
+       const unsigned int *pins;
+       unsigned int n_pins;
+};
+
+struct madera_pin_chip {
+       unsigned int n_pins;
+
+       const struct madera_pin_groups *pin_groups;
+       unsigned int n_pin_groups;
+};
+
+struct madera_pin_private {
+       struct madera *madera;
+
+       const struct madera_pin_chip *chip; /* chip-specific groups */
+
+       struct device *dev;
+       struct pinctrl_dev *pctl;
+};
+
+extern const struct madera_pin_chip cs47l35_pin_chip;
+extern const struct madera_pin_chip cs47l85_pin_chip;
+extern const struct madera_pin_chip cs47l90_pin_chip;
+
+#endif
index cb0df9e..16b1615 100644 (file)
@@ -52,6 +52,26 @@ config CHROMEOS_TBMC
 config CROS_EC_CTL
         tristate
 
+config CROS_EC_I2C
+       tristate "ChromeOS Embedded Controller (I2C)"
+       depends on MFD_CROS_EC && I2C
+
+       help
+         If you say Y here, you get support for talking to the ChromeOS
+         EC through an I2C bus. This uses a simple byte-level protocol with
+         a checksum. Failing accesses will be retried three times to
+         improve reliability.
+
+config CROS_EC_SPI
+       tristate "ChromeOS Embedded Controller (SPI)"
+       depends on MFD_CROS_EC && SPI
+
+       ---help---
+         If you say Y here, you get support for talking to the ChromeOS EC
+         through a SPI bus, using a byte-level protocol. Since the EC's
+         response time cannot be guaranteed, we support ignoring
+         'pre-amble' bytes before the response actually starts.
+
 config CROS_EC_LPC
         tristate "ChromeOS Embedded Controller (LPC)"
         depends on MFD_CROS_EC && ACPI && (X86 || COMPILE_TEST)
index e44c37a..cd591bf 100644 (file)
@@ -6,6 +6,8 @@ obj-$(CONFIG_CHROMEOS_TBMC)             += chromeos_tbmc.o
 cros_ec_ctl-objs                       := cros_ec_sysfs.o cros_ec_lightbar.o \
                                           cros_ec_vbc.o cros_ec_debugfs.o
 obj-$(CONFIG_CROS_EC_CTL)              += cros_ec_ctl.o
+obj-$(CONFIG_CROS_EC_I2C)              += cros_ec_i2c.o
+obj-$(CONFIG_CROS_EC_SPI)              += cros_ec_spi.o
 cros_ec_lpcs-objs                      := cros_ec_lpc.o cros_ec_lpc_reg.o
 cros_ec_lpcs-$(CONFIG_CROS_EC_LPC_MEC) += cros_ec_lpc_mec.o
 obj-$(CONFIG_CROS_EC_LPC)              += cros_ec_lpcs.o
index b935df6..1e81f81 100644 (file)
@@ -1,8 +1,16 @@
-// SPDX-License-Identifier: GPL-2.0+
+// SPDX-License-Identifier: GPL-2.0
 // Driver to detect Tablet Mode for ChromeOS convertible.
 //
 // Copyright (C) 2017 Google, Inc.
 // Author: Gwendal Grignou <gwendal@chromium.org>
+//
+// On Chromebook using ACPI, this device listens for notification
+// from GOOG0006 and issue method TBMC to retrieve the status.
+//
+// GOOG0006 issues the notification when it receives EC_HOST_EVENT_MODE_CHANGE
+// from the EC.
+// Method TBMC reads EC_ACPI_MEM_DEVICE_ORIENTATION byte from the shared
+// memory region.
 
 #include <linux/acpi.h>
 #include <linux/input.h>
index 8350ca2..398393a 100644 (file)
@@ -506,10 +506,31 @@ int cros_ec_cmd_xfer_status(struct cros_ec_device *ec_dev,
 }
 EXPORT_SYMBOL(cros_ec_cmd_xfer_status);
 
+static int get_next_event_xfer(struct cros_ec_device *ec_dev,
+                              struct cros_ec_command *msg,
+                              int version, uint32_t size)
+{
+       int ret;
+
+       msg->version = version;
+       msg->command = EC_CMD_GET_NEXT_EVENT;
+       msg->insize = size;
+       msg->outsize = 0;
+
+       ret = cros_ec_cmd_xfer(ec_dev, msg);
+       if (ret > 0) {
+               ec_dev->event_size = ret - 1;
+               memcpy(&ec_dev->event_data, msg->data, ec_dev->event_size);
+       }
+
+       return ret;
+}
+
 static int get_next_event(struct cros_ec_device *ec_dev)
 {
        u8 buffer[sizeof(struct cros_ec_command) + sizeof(ec_dev->event_data)];
        struct cros_ec_command *msg = (struct cros_ec_command *)&buffer;
+       static int cmd_version = 1;
        int ret;
 
        if (ec_dev->suspended) {
@@ -517,18 +538,19 @@ static int get_next_event(struct cros_ec_device *ec_dev)
                return -EHOSTDOWN;
        }
 
-       msg->version = 0;
-       msg->command = EC_CMD_GET_NEXT_EVENT;
-       msg->insize = sizeof(ec_dev->event_data);
-       msg->outsize = 0;
+       if (cmd_version == 1) {
+               ret = get_next_event_xfer(ec_dev, msg, cmd_version,
+                               sizeof(struct ec_response_get_next_event_v1));
+               if (ret < 0 || msg->result != EC_RES_INVALID_VERSION)
+                       return ret;
 
-       ret = cros_ec_cmd_xfer(ec_dev, msg);
-       if (ret > 0) {
-               ec_dev->event_size = ret - 1;
-               memcpy(&ec_dev->event_data, msg->data,
-                      sizeof(ec_dev->event_data));
+               /* Fallback to version 0 for future send attempts */
+               cmd_version = 0;
        }
 
+       ret = get_next_event_xfer(ec_dev, msg, cmd_version,
+                                 sizeof(struct ec_response_get_next_event));
+
        return ret;
 }
 
index 591bccd..cd8a908 100644 (file)
@@ -23,4 +23,15 @@ config MLXREG_HOTPLUG
          This driver handles hot-plug events for the power suppliers, power
          cables and fans on the wide range Mellanox IB and Ethernet systems.
 
+config MLXREG_IO
+       tristate "Mellanox platform register access driver support"
+       depends on REGMAP
+       depends on HWMON
+       help
+         This driver allows access to Mellanox programmable device register
+         space through sysfs interface. The sets of registers for sysfs access
+         are defined per system type bases and include the registers related
+         to system resets operation, system reset causes monitoring and some
+         kinds of mux selection.
+
 endif # MELLANOX_PLATFORM
index 7c8385e..57074d9 100644 (file)
@@ -4,3 +4,4 @@
 # Mellanox Platform-Specific Drivers
 #
 obj-$(CONFIG_MLXREG_HOTPLUG)   += mlxreg-hotplug.o
+obj-$(CONFIG_MLXREG_IO) += mlxreg-io.o
index ac97aa0..b6d4455 100644 (file)
@@ -50,9 +50,8 @@
 #define MLXREG_HOTPLUG_MASK_OFF                2
 #define MLXREG_HOTPLUG_AGGR_MASK_OFF   1
 
-/* ASIC health parameters. */
-#define MLXREG_HOTPLUG_HEALTH_MASK     0x02
-#define MLXREG_HOTPLUG_RST_CNTR                3
+/* ASIC good health mask. */
+#define MLXREG_HOTPLUG_GOOD_HEALTH_MASK        0x02
 
 #define MLXREG_HOTPLUG_ATTRS_MAX       24
 #define MLXREG_HOTPLUG_NOT_ASSERT      3
@@ -103,6 +102,9 @@ static int mlxreg_hotplug_device_create(struct mlxreg_hotplug_priv_data *priv,
 {
        struct mlxreg_core_hotplug_platform_data *pdata;
 
+       /* Notify user by sending hwmon uevent. */
+       kobject_uevent(&priv->hwmon->kobj, KOBJ_CHANGE);
+
        /*
         * Return if adapter number is negative. It could be in case hotplug
         * event is not associated with hotplug device.
@@ -134,8 +136,13 @@ static int mlxreg_hotplug_device_create(struct mlxreg_hotplug_priv_data *priv,
        return 0;
 }
 
-static void mlxreg_hotplug_device_destroy(struct mlxreg_core_data *data)
+static void
+mlxreg_hotplug_device_destroy(struct mlxreg_hotplug_priv_data *priv,
+                             struct mlxreg_core_data *data)
 {
+       /* Notify user by sending hwmon uevent. */
+       kobject_uevent(&priv->hwmon->kobj, KOBJ_CHANGE);
+
        if (data->hpdev.client) {
                i2c_unregister_device(data->hpdev.client);
                data->hpdev.client = NULL;
@@ -278,14 +285,14 @@ mlxreg_hotplug_work_helper(struct mlxreg_hotplug_priv_data *priv,
                data = item->data + bit;
                if (regval & BIT(bit)) {
                        if (item->inversed)
-                               mlxreg_hotplug_device_destroy(data);
+                               mlxreg_hotplug_device_destroy(priv, data);
                        else
                                mlxreg_hotplug_device_create(priv, data);
                } else {
                        if (item->inversed)
                                mlxreg_hotplug_device_create(priv, data);
                        else
-                               mlxreg_hotplug_device_destroy(data);
+                               mlxreg_hotplug_device_destroy(priv, data);
                }
        }
 
@@ -325,21 +332,40 @@ mlxreg_hotplug_health_work_helper(struct mlxreg_hotplug_priv_data *priv,
                        goto out;
 
                regval &= data->mask;
-               item->cache = regval;
-               if (regval == MLXREG_HOTPLUG_HEALTH_MASK) {
-                       if ((data->health_cntr++ == MLXREG_HOTPLUG_RST_CNTR) ||
-                           !priv->after_probe) {
+
+               if (item->cache == regval)
+                       goto ack_event;
+
+               /*
+                * ASIC health indication is provided through two bits. Bits
+                * value 0x2 indicates that ASIC reached the good health, value
+                * 0x0 indicates ASIC the bad health or dormant state and value
+                * 0x3 indicates the booting state. During ASIC reset it should
+                * pass the following states: dormant -> booting -> good.
+                */
+               if (regval == MLXREG_HOTPLUG_GOOD_HEALTH_MASK) {
+                       if (!data->attached) {
+                               /*
+                                * ASIC is in steady state. Connect associated
+                                * device, if configured.
+                                */
                                mlxreg_hotplug_device_create(priv, data);
                                data->attached = true;
                        }
                } else {
                        if (data->attached) {
-                               mlxreg_hotplug_device_destroy(data);
+                               /*
+                                * ASIC health is failed after ASIC has been
+                                * in steady state. Disconnect associated
+                                * device, if it has been connected.
+                                */
+                               mlxreg_hotplug_device_destroy(priv, data);
                                data->attached = false;
                                data->health_cntr = 0;
                        }
                }
-
+               item->cache = regval;
+ack_event:
                /* Acknowledge event. */
                ret = regmap_write(priv->regmap, data->reg +
                                   MLXREG_HOTPLUG_EVENT_OFF, 0);
@@ -551,7 +577,7 @@ static void mlxreg_hotplug_unset_irq(struct mlxreg_hotplug_priv_data *priv)
                /* Remove all the attached devices in group. */
                count = item->count;
                for (j = 0; j < count; j++, data++)
-                       mlxreg_hotplug_device_destroy(data);
+                       mlxreg_hotplug_device_destroy(priv, data);
        }
 }
 
@@ -616,10 +642,6 @@ static int mlxreg_hotplug_probe(struct platform_device *pdev)
        disable_irq(priv->irq);
        spin_lock_init(&priv->lock);
        INIT_DELAYED_WORK(&priv->dwork_irq, mlxreg_hotplug_work_handler);
-       /* Perform initial interrupts setup. */
-       mlxreg_hotplug_set_irq(priv);
-
-       priv->after_probe = true;
        dev_set_drvdata(&pdev->dev, priv);
 
        err = mlxreg_hotplug_attr_init(priv);
@@ -637,6 +659,10 @@ static int mlxreg_hotplug_probe(struct platform_device *pdev)
                return PTR_ERR(priv->hwmon);
        }
 
+       /* Perform initial interrupts setup. */
+       mlxreg_hotplug_set_irq(priv);
+       priv->after_probe = true;
+
        return 0;
 }
 
diff --git a/drivers/platform/mellanox/mlxreg-io.c b/drivers/platform/mellanox/mlxreg-io.c
new file mode 100644 (file)
index 0000000..acfaf64
--- /dev/null
@@ -0,0 +1,245 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Mellanox register access driver
+ *
+ * Copyright (C) 2018 Mellanox Technologies
+ * Copyright (C) 2018 Vadim Pasternak <vadimp@mellanox.com>
+ */
+
+#include <linux/bitops.h>
+#include <linux/device.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_data/mlxreg.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+/* Attribute parameters. */
+#define MLXREG_IO_ATT_SIZE     10
+#define MLXREG_IO_ATT_NUM      48
+
+/**
+ * struct mlxreg_io_priv_data - driver's private data:
+ *
+ * @pdev: platform device;
+ * @pdata: platform data;
+ * @hwmon: hwmon device;
+ * @mlxreg_io_attr: sysfs attributes array;
+ * @mlxreg_io_dev_attr: sysfs sensor device attribute array;
+ * @group: sysfs attribute group;
+ * @groups: list of sysfs attribute group for hwmon registration;
+ */
+struct mlxreg_io_priv_data {
+       struct platform_device *pdev;
+       struct mlxreg_core_platform_data *pdata;
+       struct device *hwmon;
+       struct attribute *mlxreg_io_attr[MLXREG_IO_ATT_NUM + 1];
+       struct sensor_device_attribute mlxreg_io_dev_attr[MLXREG_IO_ATT_NUM];
+       struct attribute_group group;
+       const struct attribute_group *groups[2];
+};
+
+static int
+mlxreg_io_get_reg(void *regmap, struct mlxreg_core_data *data, u32 in_val,
+                 bool rw_flag, u32 *regval)
+{
+       int ret;
+
+       ret = regmap_read(regmap, data->reg, regval);
+       if (ret)
+               goto access_error;
+
+       /*
+        * There are three kinds of attributes: single bit, full register's
+        * bits and bit sequence. For the first kind field mask indicates which
+        * bits are not related and field bit is set zero. For the second kind
+        * field mask is set to zero and field bit is set with all bits one.
+        * No special handling for such kind of attributes - pass value as is.
+        * For the third kind, field mask indicates which bits are related and
+        * field bit is set to the first bit number (from 1 to 32) is the bit
+        * sequence.
+        */
+       if (!data->bit) {
+               /* Single bit. */
+               if (rw_flag) {
+                       /* For show: expose effective bit value as 0 or 1. */
+                       *regval = !!(*regval & ~data->mask);
+               } else {
+                       /* For store: set effective bit value. */
+                       *regval &= data->mask;
+                       if (in_val)
+                               *regval |= ~data->mask;
+               }
+       } else if (data->mask) {
+               /* Bit sequence. */
+               if (rw_flag) {
+                       /* For show: mask and shift right. */
+                       *regval = ror32(*regval & data->mask, (data->bit - 1));
+               } else {
+                       /* For store: shift to the position and mask. */
+                       in_val = rol32(in_val, data->bit - 1) & data->mask;
+                       /* Clear relevant bits and set them to new value. */
+                       *regval = (*regval & ~data->mask) | in_val;
+               }
+       }
+
+access_error:
+       return ret;
+}
+
+static ssize_t
+mlxreg_io_attr_show(struct device *dev, struct device_attribute *attr,
+                   char *buf)
+{
+       struct mlxreg_io_priv_data *priv = dev_get_drvdata(dev);
+       int index = to_sensor_dev_attr(attr)->index;
+       struct mlxreg_core_data *data = priv->pdata->data + index;
+       u32 regval = 0;
+       int ret;
+
+       ret = mlxreg_io_get_reg(priv->pdata->regmap, data, 0, true, &regval);
+       if (ret)
+               goto access_error;
+
+       return sprintf(buf, "%u\n", regval);
+
+access_error:
+       return ret;
+}
+
+static ssize_t
+mlxreg_io_attr_store(struct device *dev, struct device_attribute *attr,
+                    const char *buf, size_t len)
+{
+       struct mlxreg_io_priv_data *priv = dev_get_drvdata(dev);
+       int index = to_sensor_dev_attr(attr)->index;
+       struct mlxreg_core_data *data = priv->pdata->data + index;
+       u32 input_val, regval;
+       int ret;
+
+       if (len > MLXREG_IO_ATT_SIZE)
+               return -EINVAL;
+
+       /* Convert buffer to input value. */
+       ret = kstrtou32(buf, len, &input_val);
+       if (ret)
+               return ret;
+
+       ret = mlxreg_io_get_reg(priv->pdata->regmap, data, input_val, false,
+                               &regval);
+       if (ret)
+               goto access_error;
+
+       ret = regmap_write(priv->pdata->regmap, data->reg, regval);
+       if (ret)
+               goto access_error;
+
+       return len;
+
+access_error:
+       dev_err(&priv->pdev->dev, "Bus access error\n");
+       return ret;
+}
+
+static struct device_attribute mlxreg_io_devattr_rw = {
+       .show   = mlxreg_io_attr_show,
+       .store  = mlxreg_io_attr_store,
+};
+
+static int mlxreg_io_attr_init(struct mlxreg_io_priv_data *priv)
+{
+       int i;
+
+       priv->group.attrs = devm_kcalloc(&priv->pdev->dev,
+                                        priv->pdata->counter,
+                                        sizeof(struct attribute *),
+                                        GFP_KERNEL);
+       if (!priv->group.attrs)
+               return -ENOMEM;
+
+       for (i = 0; i < priv->pdata->counter; i++) {
+               priv->mlxreg_io_attr[i] =
+                               &priv->mlxreg_io_dev_attr[i].dev_attr.attr;
+               memcpy(&priv->mlxreg_io_dev_attr[i].dev_attr,
+                      &mlxreg_io_devattr_rw, sizeof(struct device_attribute));
+
+               /* Set attribute name as a label. */
+               priv->mlxreg_io_attr[i]->name =
+                               devm_kasprintf(&priv->pdev->dev, GFP_KERNEL,
+                                              priv->pdata->data[i].label);
+
+               if (!priv->mlxreg_io_attr[i]->name) {
+                       dev_err(&priv->pdev->dev, "Memory allocation failed for sysfs attribute %d.\n",
+                               i + 1);
+                       return -ENOMEM;
+               }
+
+               priv->mlxreg_io_dev_attr[i].dev_attr.attr.mode =
+                                               priv->pdata->data[i].mode;
+               priv->mlxreg_io_dev_attr[i].dev_attr.attr.name =
+                                       priv->mlxreg_io_attr[i]->name;
+               priv->mlxreg_io_dev_attr[i].index = i;
+               sysfs_attr_init(&priv->mlxreg_io_dev_attr[i].dev_attr.attr);
+       }
+
+       priv->group.attrs = priv->mlxreg_io_attr;
+       priv->groups[0] = &priv->group;
+       priv->groups[1] = NULL;
+
+       return 0;
+}
+
+static int mlxreg_io_probe(struct platform_device *pdev)
+{
+       struct mlxreg_io_priv_data *priv;
+       int err;
+
+       priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
+
+       priv->pdata = dev_get_platdata(&pdev->dev);
+       if (!priv->pdata) {
+               dev_err(&pdev->dev, "Failed to get platform data.\n");
+               return -EINVAL;
+       }
+
+       priv->pdev = pdev;
+
+       err = mlxreg_io_attr_init(priv);
+       if (err) {
+               dev_err(&priv->pdev->dev, "Failed to allocate attributes: %d\n",
+                       err);
+               return err;
+       }
+
+       priv->hwmon = devm_hwmon_device_register_with_groups(&pdev->dev,
+                                                            "mlxreg_io",
+                                                             priv,
+                                                             priv->groups);
+       if (IS_ERR(priv->hwmon)) {
+               dev_err(&pdev->dev, "Failed to register hwmon device %ld\n",
+                       PTR_ERR(priv->hwmon));
+               return PTR_ERR(priv->hwmon);
+       }
+
+       dev_set_drvdata(&pdev->dev, priv);
+
+       return 0;
+}
+
+static struct platform_driver mlxreg_io_driver = {
+       .driver = {
+           .name = "mlxreg-io",
+       },
+       .probe = mlxreg_io_probe,
+};
+
+module_platform_driver(mlxreg_io_driver);
+
+MODULE_AUTHOR("Vadim Pasternak <vadimp@mellanox.com>");
+MODULE_DESCRIPTION("Mellanox regmap I/O access driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:mlxreg-io");
index 107d336..0c1aa6c 100644 (file)
@@ -1196,16 +1196,16 @@ config INTEL_TURBO_MAX_3
          This driver is only required when the system is not using Hardware
          P-States (HWP). In HWP mode, priority can be read from ACPI tables.
 
-config SILEAD_DMI
-       bool "Tablets with Silead touchscreens"
+config TOUCHSCREEN_DMI
+       bool "DMI based touchscreen configuration info"
        depends on ACPI && DMI && I2C=y && TOUCHSCREEN_SILEAD
        ---help---
-         Certain ACPI based tablets with Silead touchscreens do not have
-         enough data in ACPI tables for the touchscreen driver to handle
-         the touchscreen properly, as OEMs expected the data to be baked
-         into the tablet model specific version of the driver shipped
-         with the OS-image for the device. This option supplies the missing
-         information. Enable this for x86 tablets with Silead touchscreens.
+         Certain ACPI based tablets with e.g. Silead or Chipone touchscreens
+         do not have enough data in ACPI tables for the touchscreen driver to
+         handle the touchscreen properly, as OEMs expect the data to be baked
+         into the tablet model specific version of the driver shipped with the
+         the OS-image for the device. This option supplies the missing info.
+         Enable this for x86 tablets with Silead or Chipone touchscreens.
 
 config INTEL_CHTDC_TI_PWRBTN
        tristate "Intel Cherry Trail Dollar Cove TI power button driver"
index 50dc8f2..e6d1bec 100644 (file)
@@ -78,7 +78,7 @@ obj-$(CONFIG_INTEL_SMARTCONNECT)      += intel-smartconnect.o
 obj-$(CONFIG_PVPANIC)           += pvpanic.o
 obj-$(CONFIG_ALIENWARE_WMI)    += alienware-wmi.o
 obj-$(CONFIG_INTEL_PMC_IPC)    += intel_pmc_ipc.o
-obj-$(CONFIG_SILEAD_DMI)       += silead_dmi.o
+obj-$(CONFIG_TOUCHSCREEN_DMI)  += touchscreen_dmi.o
 obj-$(CONFIG_SURFACE_PRO3_BUTTON)      += surfacepro3_button.o
 obj-$(CONFIG_SURFACE_3_BUTTON) += surface3_button.o
 obj-$(CONFIG_INTEL_PUNIT_IPC)  += intel_punit_ipc.o
index 8952173..fcfeadd 100644 (file)
@@ -672,10 +672,7 @@ static void __init find_quirks(void)
 
 static bool has_cap(u32 cap)
 {
-       if ((interface->capability & cap) != 0)
-               return 1;
-
-       return 0;
+       return interface->capability & cap;
 }
 
 /*
@@ -2216,7 +2213,7 @@ static int __init acer_wmi_init(void)
        if (wmi_has_guid(AMW0_GUID1) &&
            !dmi_check_system(amw0_whitelist) &&
            quirks == &quirk_unknown) {
-               pr_err("Unsupported machine has AMW0_GUID1, unable to load\n");
+               pr_debug("Unsupported machine has AMW0_GUID1, unable to load\n");
                return -ENODEV;
        }
 
index 136ff2b..db2af09 100644 (file)
@@ -496,6 +496,7 @@ static const struct key_entry asus_nb_wmi_keymap[] = {
        { KE_KEY, 0xC4, { KEY_KBDILLUMUP } },
        { KE_KEY, 0xC5, { KEY_KBDILLUMDOWN } },
        { KE_IGNORE, 0xC6, },  /* Ambient Light Sensor notification */
+       { KE_KEY, 0xFA, { KEY_PROG2 } },           /* Lid flip action */
        { KE_END, 0},
 };
 
index 6afd011..7458f76 100644 (file)
@@ -52,13 +52,12 @@ static const struct acpi_device_id device_ids[] = {
 };
 MODULE_DEVICE_TABLE(acpi, device_ids);
 
-static u64 asus_wireless_method(acpi_handle handle, const char *method,
-                               int param)
+static acpi_status asus_wireless_method(acpi_handle handle, const char *method,
+                                       int param, u64 *ret)
 {
        struct acpi_object_list p;
        union acpi_object obj;
        acpi_status s;
-       u64 ret;
 
        acpi_handle_debug(handle, "Evaluating method %s, parameter %#x\n",
                          method, param);
@@ -67,24 +66,27 @@ static u64 asus_wireless_method(acpi_handle handle, const char *method,
        p.count = 1;
        p.pointer = &obj;
 
-       s = acpi_evaluate_integer(handle, (acpi_string) method, &p, &ret);
+       s = acpi_evaluate_integer(handle, (acpi_string) method, &p, ret);
        if (ACPI_FAILURE(s))
                acpi_handle_err(handle,
                                "Failed to eval method %s, param %#x (%d)\n",
                                method, param, s);
-       acpi_handle_debug(handle, "%s returned %#llx\n", method, ret);
-       return ret;
+       else
+               acpi_handle_debug(handle, "%s returned %#llx\n", method, *ret);
+
+       return s;
 }
 
 static enum led_brightness led_state_get(struct led_classdev *led)
 {
        struct asus_wireless_data *data;
-       int s;
+       acpi_status s;
+       u64 ret;
 
        data = container_of(led, struct asus_wireless_data, led);
        s = asus_wireless_method(acpi_device_handle(data->adev), "HSWC",
-                                data->hswc_params->status);
-       if (s == data->hswc_params->on)
+                                data->hswc_params->status, &ret);
+       if (ACPI_SUCCESS(s) && ret == data->hswc_params->on)
                return LED_FULL;
        return LED_OFF;
 }
@@ -92,10 +94,11 @@ static enum led_brightness led_state_get(struct led_classdev *led)
 static void led_state_update(struct work_struct *work)
 {
        struct asus_wireless_data *data;
+       u64 ret;
 
        data = container_of(work, struct asus_wireless_data, led_work);
        asus_wireless_method(acpi_device_handle(data->adev), "HSWC",
-                            data->led_state);
+                            data->led_state, &ret);
 }
 
 static void led_state_set(struct led_classdev *led, enum led_brightness value)
@@ -167,6 +170,7 @@ static int asus_wireless_add(struct acpi_device *adev)
        data->led.brightness_get = led_state_get;
        data->led.flags = LED_CORE_SUSPENDRESUME;
        data->led.max_brightness = 1;
+       data->led.default_trigger = "rfkill-none";
        err = devm_led_classdev_register(&adev->dev, &data->led);
        if (err)
                destroy_workqueue(data->wq);
index d67f32a..2d6e272 100644 (file)
@@ -67,6 +67,7 @@ MODULE_LICENSE("GPL");
 #define NOTIFY_BRNDOWN_MAX             0x2e
 #define NOTIFY_KBD_BRTUP               0xc4
 #define NOTIFY_KBD_BRTDWN              0xc5
+#define NOTIFY_KBD_BRTTOGGLE           0xc7
 
 /* WMI Methods */
 #define ASUS_WMI_METHODID_SPEC         0x43455053 /* BIOS SPECification */
@@ -470,6 +471,7 @@ static void kbd_led_update(struct work_struct *work)
                ctrl_param = 0x80 | (asus->kbd_led_wk & 0x7F);
 
        asus_wmi_set_devstate(ASUS_WMI_DEVID_KBD_BACKLIGHT, ctrl_param, NULL);
+       led_classdev_notify_brightness_hw_changed(&asus->kbd_led, asus->kbd_led_wk);
 }
 
 static int kbd_led_read(struct asus_wmi *asus, int *level, int *env)
@@ -500,15 +502,16 @@ static int kbd_led_read(struct asus_wmi *asus, int *level, int *env)
        return retval;
 }
 
-static void kbd_led_set(struct led_classdev *led_cdev,
-                       enum led_brightness value)
+static void do_kbd_led_set(struct led_classdev *led_cdev, int value)
 {
        struct asus_wmi *asus;
+       int max_level;
 
        asus = container_of(led_cdev, struct asus_wmi, kbd_led);
+       max_level = asus->kbd_led.max_brightness;
 
-       if (value > asus->kbd_led.max_brightness)
-               value = asus->kbd_led.max_brightness;
+       if (value > max_level)
+               value = max_level;
        else if (value < 0)
                value = 0;
 
@@ -516,6 +519,12 @@ static void kbd_led_set(struct led_classdev *led_cdev,
        queue_work(asus->led_workqueue, &asus->kbd_led_work);
 }
 
+static void kbd_led_set(struct led_classdev *led_cdev,
+                       enum led_brightness value)
+{
+       do_kbd_led_set(led_cdev, value);
+}
+
 static enum led_brightness kbd_led_get(struct led_classdev *led_cdev)
 {
        struct asus_wmi *asus;
@@ -666,6 +675,7 @@ static int asus_wmi_led_init(struct asus_wmi *asus)
 
                asus->kbd_led_wk = led_val;
                asus->kbd_led.name = "asus::kbd_backlight";
+               asus->kbd_led.flags = LED_BRIGHT_HW_CHANGED;
                asus->kbd_led.brightness_set = kbd_led_set;
                asus->kbd_led.brightness_get = kbd_led_get;
                asus->kbd_led.max_brightness = 3;
@@ -1754,6 +1764,22 @@ static void asus_wmi_notify(u32 value, void *context)
                }
        }
 
+       if (code == NOTIFY_KBD_BRTUP) {
+               do_kbd_led_set(&asus->kbd_led, asus->kbd_led_wk + 1);
+               goto exit;
+       }
+       if (code == NOTIFY_KBD_BRTDWN) {
+               do_kbd_led_set(&asus->kbd_led, asus->kbd_led_wk - 1);
+               goto exit;
+       }
+       if (code == NOTIFY_KBD_BRTTOGGLE) {
+               if (asus->kbd_led_wk == asus->kbd_led.max_brightness)
+                       do_kbd_led_set(&asus->kbd_led, 0);
+               else
+                       do_kbd_led_set(&asus->kbd_led, asus->kbd_led_wk + 1);
+               goto exit;
+       }
+
        if (is_display_toggle(code) &&
            asus->driver->quirks->no_display_toggle)
                goto exit;
index 9dc282e..0537d44 100644 (file)
@@ -212,6 +212,12 @@ int dell_smbios_call_filter(struct device *d,
        if ((buffer->cmd_class == CLASS_TOKEN_READ ||
             buffer->cmd_class == CLASS_TOKEN_WRITE) &&
             buffer->cmd_select < 3) {
+               /* tokens enabled ? */
+               if (!da_tokens) {
+                       dev_dbg(d, "no token support on this system\n");
+                       return -EINVAL;
+               }
+
                /* find the matching token ID */
                for (i = 0; i < da_num_tokens; i++) {
                        if (da_tokens[i].location != buffer->input[0])
@@ -315,6 +321,9 @@ struct calling_interface_token *dell_smbios_find_token(int tokenid)
 {
        int i;
 
+       if (!da_tokens)
+               return NULL;
+
        for (i = 0; i < da_num_tokens; i++) {
                if (da_tokens[i].tokenID == tokenid)
                        return &da_tokens[i];
@@ -565,11 +574,6 @@ static int __init dell_smbios_init(void)
 
        dmi_walk(find_tokens, NULL);
 
-       if (!da_tokens)  {
-               pr_info("Unable to find dmi tokens\n");
-               return -ENODEV;
-       }
-
        ret = platform_driver_register(&platform_driver);
        if (ret)
                goto fail_platform_driver;
@@ -583,13 +587,6 @@ static int __init dell_smbios_init(void)
        if (ret)
                goto fail_platform_device_add;
 
-       /* duplicate tokens will cause problems building sysfs files */
-       zero_duplicates(&platform_device->dev);
-
-       ret = build_tokens_sysfs(platform_device);
-       if (ret)
-               goto fail_create_group;
-
        /* register backends */
        wmi = init_dell_smbios_wmi();
        if (wmi)
@@ -600,7 +597,16 @@ static int __init dell_smbios_init(void)
        if (wmi && smm) {
                pr_err("No SMBIOS backends available (wmi: %d, smm: %d)\n",
                        wmi, smm);
-               goto fail_sysfs;
+               goto fail_create_group;
+       }
+
+       if (da_tokens)  {
+               /* duplicate tokens will cause problems building sysfs files */
+               zero_duplicates(&platform_device->dev);
+
+               ret = build_tokens_sysfs(platform_device);
+               if (ret)
+                       goto fail_sysfs;
        }
 
        return 0;
@@ -628,7 +634,8 @@ static void __exit dell_smbios_exit(void)
        exit_dell_smbios_smm();
        mutex_lock(&smbios_mutex);
        if (platform_device) {
-               free_group(platform_device);
+               if (da_tokens)
+                       free_group(platform_device);
                platform_device_unregister(platform_device);
                platform_driver_unregister(&platform_driver);
        }
index e9e9da5..97a90be 100644 (file)
@@ -24,7 +24,7 @@
 static int da_command_address;
 static int da_command_code;
 static struct calling_interface_buffer *buffer;
-struct platform_device *platform_device;
+static struct platform_device *platform_device;
 static DEFINE_MUTEX(smm_mutex);
 
 static const struct dmi_system_id dell_device_table[] __initconst = {
@@ -82,7 +82,7 @@ static void find_cmd_address(const struct dmi_header *dm, void *dummy)
        }
 }
 
-int dell_smbios_smm_call(struct calling_interface_buffer *input)
+static int dell_smbios_smm_call(struct calling_interface_buffer *input)
 {
        struct smi_cmd command;
        size_t size;
index fbefedb..88afe56 100644 (file)
@@ -82,7 +82,7 @@ static int run_smbios_call(struct wmi_device *wdev)
        return 0;
 }
 
-int dell_smbios_wmi_call(struct calling_interface_buffer *buffer)
+static int dell_smbios_wmi_call(struct calling_interface_buffer *buffer)
 {
        struct wmi_smbios_priv *priv;
        size_t difference;
index 45b7cb0..d4f1259 100644 (file)
@@ -1133,10 +1133,17 @@ static const struct dmi_system_id no_hw_rfkill_list[] = {
                },
        },
        {
-               .ident = "Lenovo Legion Y520-15IKBN",
+               .ident = "Lenovo Legion Y520-15IKB",
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
-                       DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Y520-15IKBN"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Y520-15IKB"),
+               },
+       },
+       {
+               .ident = "Lenovo Y520-15IKBM",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Y520-15IKBM"),
                },
        },
        {
@@ -1154,6 +1161,13 @@ static const struct dmi_system_id no_hw_rfkill_list[] = {
                },
        },
        {
+               .ident = "Lenovo Y720-15IKBM",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Y720-15IKBM"),
+               },
+       },
+       {
                .ident = "Lenovo Yoga 2 11 / 13 / Pro",
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
index b5adba2..6cf9b7f 100644 (file)
@@ -96,13 +96,140 @@ struct intel_hid_priv {
        bool wakeup_mode;
 };
 
-static int intel_hid_set_enable(struct device *device, bool enable)
+#define HID_EVENT_FILTER_UUID  "eeec56b3-4442-408f-a792-4edd4d758054"
+
+enum intel_hid_dsm_fn_codes {
+       INTEL_HID_DSM_FN_INVALID,
+       INTEL_HID_DSM_BTNL_FN,
+       INTEL_HID_DSM_HDMM_FN,
+       INTEL_HID_DSM_HDSM_FN,
+       INTEL_HID_DSM_HDEM_FN,
+       INTEL_HID_DSM_BTNS_FN,
+       INTEL_HID_DSM_BTNE_FN,
+       INTEL_HID_DSM_HEBC_V1_FN,
+       INTEL_HID_DSM_VGBS_FN,
+       INTEL_HID_DSM_HEBC_V2_FN,
+       INTEL_HID_DSM_FN_MAX
+};
+
+static const char *intel_hid_dsm_fn_to_method[INTEL_HID_DSM_FN_MAX] = {
+       NULL,
+       "BTNL",
+       "HDMM",
+       "HDSM",
+       "HDEM",
+       "BTNS",
+       "BTNE",
+       "HEBC",
+       "VGBS",
+       "HEBC"
+};
+
+static unsigned long long intel_hid_dsm_fn_mask;
+static guid_t intel_dsm_guid;
+
+static bool intel_hid_execute_method(acpi_handle handle,
+                                    enum intel_hid_dsm_fn_codes fn_index,
+                                    unsigned long long arg)
 {
+       union acpi_object *obj, argv4, req;
        acpi_status status;
+       char *method_name;
 
-       status = acpi_execute_simple_method(ACPI_HANDLE(device), "HDSM",
-                                           enable);
-       if (ACPI_FAILURE(status)) {
+       if (fn_index <= INTEL_HID_DSM_FN_INVALID ||
+           fn_index >= INTEL_HID_DSM_FN_MAX)
+               return false;
+
+       method_name = (char *)intel_hid_dsm_fn_to_method[fn_index];
+
+       if (!(intel_hid_dsm_fn_mask & fn_index))
+               goto skip_dsm_exec;
+
+       /* All methods expects a package with one integer element */
+       req.type = ACPI_TYPE_INTEGER;
+       req.integer.value = arg;
+
+       argv4.type = ACPI_TYPE_PACKAGE;
+       argv4.package.count = 1;
+       argv4.package.elements = &req;
+
+       obj = acpi_evaluate_dsm(handle, &intel_dsm_guid, 1, fn_index, &argv4);
+       if (obj) {
+               acpi_handle_debug(handle, "Exec DSM Fn code: %d[%s] success\n",
+                                 fn_index, method_name);
+               ACPI_FREE(obj);
+               return true;
+       }
+
+skip_dsm_exec:
+       status = acpi_execute_simple_method(handle, method_name, arg);
+       if (ACPI_SUCCESS(status))
+               return true;
+
+       return false;
+}
+
+static bool intel_hid_evaluate_method(acpi_handle handle,
+                                     enum intel_hid_dsm_fn_codes fn_index,
+                                     unsigned long long *result)
+{
+       union acpi_object *obj;
+       acpi_status status;
+       char *method_name;
+
+       if (fn_index <= INTEL_HID_DSM_FN_INVALID ||
+           fn_index >= INTEL_HID_DSM_FN_MAX)
+               return false;
+
+       method_name = (char *)intel_hid_dsm_fn_to_method[fn_index];
+
+       if (!(intel_hid_dsm_fn_mask & fn_index))
+               goto skip_dsm_eval;
+
+       obj = acpi_evaluate_dsm_typed(handle, &intel_dsm_guid,
+                                     1, fn_index,
+                                     NULL,  ACPI_TYPE_INTEGER);
+       if (obj) {
+               *result = obj->integer.value;
+               acpi_handle_debug(handle,
+                                 "Eval DSM Fn code: %d[%s] results: 0x%llx\n",
+                                 fn_index, method_name, *result);
+               ACPI_FREE(obj);
+               return true;
+       }
+
+skip_dsm_eval:
+       status = acpi_evaluate_integer(handle, method_name, NULL, result);
+       if (ACPI_SUCCESS(status))
+               return true;
+
+       return false;
+}
+
+static void intel_hid_init_dsm(acpi_handle handle)
+{
+       union acpi_object *obj;
+
+       guid_parse(HID_EVENT_FILTER_UUID, &intel_dsm_guid);
+
+       obj = acpi_evaluate_dsm_typed(handle, &intel_dsm_guid, 1, 0, NULL,
+                                     ACPI_TYPE_BUFFER);
+       if (obj) {
+               intel_hid_dsm_fn_mask = *obj->buffer.pointer;
+               ACPI_FREE(obj);
+       }
+
+       acpi_handle_debug(handle, "intel_hid_dsm_fn_mask = %llx\n",
+                         intel_hid_dsm_fn_mask);
+}
+
+static int intel_hid_set_enable(struct device *device, bool enable)
+{
+       acpi_handle handle = ACPI_HANDLE(device);
+
+       /* Enable|disable features - power button is always enabled */
+       if (!intel_hid_execute_method(handle, INTEL_HID_DSM_HDSM_FN,
+                                     enable)) {
                dev_warn(device, "failed to %sable hotkeys\n",
                         enable ? "en" : "dis");
                return -EIO;
@@ -129,9 +256,8 @@ static void intel_button_array_enable(struct device *device, bool enable)
        }
 
        /* Enable|disable features - power button is always enabled */
-       status = acpi_execute_simple_method(handle, "BTNE",
-                                           enable ? button_cap : 1);
-       if (ACPI_FAILURE(status))
+       if (!intel_hid_execute_method(handle, INTEL_HID_DSM_BTNE_FN,
+                                     enable ? button_cap : 1))
                dev_warn(device, "failed to set button capability\n");
 }
 
@@ -217,7 +343,6 @@ static void notify_handler(acpi_handle handle, u32 event, void *context)
        struct platform_device *device = context;
        struct intel_hid_priv *priv = dev_get_drvdata(&device->dev);
        unsigned long long ev_index;
-       acpi_status status;
 
        if (priv->wakeup_mode) {
                /*
@@ -269,8 +394,8 @@ wakeup:
                return;
        }
 
-       status = acpi_evaluate_integer(handle, "HDEM", NULL, &ev_index);
-       if (ACPI_FAILURE(status)) {
+       if (!intel_hid_evaluate_method(handle, INTEL_HID_DSM_HDEM_FN,
+                                      &ev_index)) {
                dev_warn(&device->dev, "failed to get event index\n");
                return;
        }
@@ -284,17 +409,24 @@ static bool button_array_present(struct platform_device *device)
 {
        acpi_handle handle = ACPI_HANDLE(&device->dev);
        unsigned long long event_cap;
-       acpi_status status;
-       bool supported = false;
 
-       status = acpi_evaluate_integer(handle, "HEBC", NULL, &event_cap);
-       if (ACPI_SUCCESS(status) && (event_cap & 0x20000))
-               supported = true;
+       if (intel_hid_evaluate_method(handle, INTEL_HID_DSM_HEBC_V2_FN,
+                                     &event_cap)) {
+               /* Check presence of 5 button array or v2 power button */
+               if (event_cap & 0x60000)
+                       return true;
+       }
+
+       if (intel_hid_evaluate_method(handle, INTEL_HID_DSM_HEBC_V1_FN,
+                                     &event_cap)) {
+               if (event_cap & 0x20000)
+                       return true;
+       }
 
        if (dmi_check_system(button_array_table))
-               supported = true;
+               return true;
 
-       return supported;
+       return false;
 }
 
 static int intel_hid_probe(struct platform_device *device)
@@ -305,8 +437,9 @@ static int intel_hid_probe(struct platform_device *device)
        acpi_status status;
        int err;
 
-       status = acpi_evaluate_integer(handle, "HDMM", NULL, &mode);
-       if (ACPI_FAILURE(status)) {
+       intel_hid_init_dsm(handle);
+
+       if (!intel_hid_evaluate_method(handle, INTEL_HID_DSM_HDMM_FN, &mode)) {
                dev_warn(&device->dev, "failed to read mode\n");
                return -ENODEV;
        }
@@ -352,13 +485,16 @@ static int intel_hid_probe(struct platform_device *device)
                goto err_remove_notify;
 
        if (priv->array) {
+               unsigned long long dummy;
+
                intel_button_array_enable(&device->dev, true);
 
                /* Call button load method to enable HID power button */
-               status = acpi_evaluate_object(handle, "BTNL", NULL, NULL);
-               if (ACPI_FAILURE(status))
+               if (!intel_hid_evaluate_method(handle, INTEL_HID_DSM_BTNL_FN,
+                                              &dummy)) {
                        dev_warn(&device->dev,
                                 "failed to enable HID power button\n");
+               }
        }
 
        device_init_wakeup(&device->dev, true);
index c13780b..06cd7e8 100644 (file)
@@ -17,6 +17,7 @@
 
 /* When NOT in tablet mode, VGBS returns with the flag 0x40 */
 #define TABLET_MODE_FLAG 0x40
+#define DOCK_MODE_FLAG   0x80
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("AceLan Kao");
@@ -38,6 +39,8 @@ static const struct key_entry intel_vbtn_keymap[] = {
        { KE_IGNORE, 0xC7, { KEY_VOLUMEDOWN } },        /* volume-down key release */
        { KE_KEY,    0xC8, { KEY_ROTATE_LOCK_TOGGLE } },        /* rotate-lock key press */
        { KE_KEY,    0xC9, { KEY_ROTATE_LOCK_TOGGLE } },        /* rotate-lock key release */
+       { KE_SW,     0xCA, { .sw = { SW_DOCK, 1 } } },          /* Docked */
+       { KE_SW,     0xCB, { .sw = { SW_DOCK, 0 } } },          /* Undocked */
        { KE_SW,     0xCC, { .sw = { SW_TABLET_MODE, 1 } } },   /* Tablet */
        { KE_SW,     0xCD, { .sw = { SW_TABLET_MODE, 0 } } },   /* Laptop */
        { KE_END },
@@ -121,6 +124,8 @@ static void detect_tablet_mode(struct platform_device *device)
 
        m = !(obj->integer.value & TABLET_MODE_FLAG);
        input_report_switch(priv->input_dev, SW_TABLET_MODE, m);
+       m = (obj->integer.value & DOCK_MODE_FLAG) ? 1 : 0;
+       input_report_switch(priv->input_dev, SW_DOCK, m);
 out:
        kfree(vgbs_output.pointer);
 }
index 014fc16..c5ece7e 100644 (file)
@@ -858,10 +858,7 @@ static u16 read_mgtv(struct ips_driver *ips)
 
 static u16 read_ptv(struct ips_driver *ips)
 {
-       u16 val, slope, offset;
-
-       slope = (ips->pta_val & PTA_SLOPE_MASK) >> PTA_SLOPE_SHIFT;
-       offset = ips->pta_val & PTA_OFFSET_MASK;
+       u16 val;
 
        val = thm_readw(THM_PTV) & PTV_MASK;
 
index 43bbe74..2d272a3 100644 (file)
@@ -196,9 +196,67 @@ static const struct pmc_bit_map cnp_pfear_map[] = {
        {}
 };
 
+static const struct pmc_bit_map cnp_slps0_dbg0_map[] = {
+       {"AUDIO_D3",            BIT(0)},
+       {"OTG_D3",              BIT(1)},
+       {"XHCI_D3",             BIT(2)},
+       {"LPIO_D3",             BIT(3)},
+       {"SDX_D3",              BIT(4)},
+       {"SATA_D3",             BIT(5)},
+       {"UFS0_D3",             BIT(6)},
+       {"UFS1_D3",             BIT(7)},
+       {"EMMC_D3",             BIT(8)},
+       {}
+};
+
+static const struct pmc_bit_map cnp_slps0_dbg1_map[] = {
+       {"SDIO_PLL_OFF",        BIT(0)},
+       {"USB2_PLL_OFF",        BIT(1)},
+       {"AUDIO_PLL_OFF",       BIT(2)},
+       {"OC_PLL_OFF",          BIT(3)},
+       {"MAIN_PLL_OFF",        BIT(4)},
+       {"XOSC_OFF",            BIT(5)},
+       {"LPC_CLKS_GATED",      BIT(6)},
+       {"PCIE_CLKREQS_IDLE",   BIT(7)},
+       {"AUDIO_ROSC_OFF",      BIT(8)},
+       {"HPET_XOSC_CLK_REQ",   BIT(9)},
+       {"PMC_ROSC_SLOW_CLK",   BIT(10)},
+       {"AON2_ROSC_GATED",     BIT(11)},
+       {"CLKACKS_DEASSERTED",  BIT(12)},
+       {}
+};
+
+static const struct pmc_bit_map cnp_slps0_dbg2_map[] = {
+       {"MPHY_CORE_GATED",     BIT(0)},
+       {"CSME_GATED",          BIT(1)},
+       {"USB2_SUS_GATED",      BIT(2)},
+       {"DYN_FLEX_IO_IDLE",    BIT(3)},
+       {"GBE_NO_LINK",         BIT(4)},
+       {"THERM_SEN_DISABLED",  BIT(5)},
+       {"PCIE_LOW_POWER",      BIT(6)},
+       {"ISH_VNNAON_REQ_ACT",  BIT(7)},
+       {"ISH_VNN_REQ_ACT",     BIT(8)},
+       {"CNV_VNNAON_REQ_ACT",  BIT(9)},
+       {"CNV_VNN_REQ_ACT",     BIT(10)},
+       {"NPK_VNNON_REQ_ACT",   BIT(11)},
+       {"PMSYNC_STATE_IDLE",   BIT(12)},
+       {"ALST_GT_THRES",       BIT(13)},
+       {"PMC_ARC_PG_READY",    BIT(14)},
+       {}
+};
+
+static const struct pmc_bit_map *cnp_slps0_dbg_maps[] = {
+       cnp_slps0_dbg0_map,
+       cnp_slps0_dbg1_map,
+       cnp_slps0_dbg2_map,
+       NULL,
+};
+
 static const struct pmc_reg_map cnp_reg_map = {
        .pfear_sts = cnp_pfear_map,
        .slp_s0_offset = CNP_PMC_SLP_S0_RES_COUNTER_OFFSET,
+       .slps0_dbg_maps = cnp_slps0_dbg_maps,
+       .slps0_dbg_offset = CNP_PMC_SLPS0_DBG_OFFSET,
        .ltr_ignore_offset = CNP_PMC_LTR_IGNORE_OFFSET,
        .regmap_length = CNP_PMC_MMIO_REG_LEN,
        .ppfear0_offset = CNP_PMC_HOST_PPFEAR0A,
@@ -252,6 +310,8 @@ static int pmc_core_check_read_lock_bit(void)
 }
 
 #if IS_ENABLED(CONFIG_DEBUG_FS)
+static bool slps0_dbg_latch;
+
 static void pmc_core_display_map(struct seq_file *s, int index,
                                 u8 pf_reg, const struct pmc_bit_map *pf_map)
 {
@@ -481,6 +541,57 @@ static const struct file_operations pmc_core_ltr_ignore_ops = {
        .release        = single_release,
 };
 
+static void pmc_core_slps0_dbg_latch(struct pmc_dev *pmcdev, bool reset)
+{
+       const struct pmc_reg_map *map = pmcdev->map;
+       u32 fd;
+
+       mutex_lock(&pmcdev->lock);
+
+       if (!reset && !slps0_dbg_latch)
+               goto out_unlock;
+
+       fd = pmc_core_reg_read(pmcdev, map->slps0_dbg_offset);
+       if (reset)
+               fd &= ~CNP_PMC_LATCH_SLPS0_EVENTS;
+       else
+               fd |= CNP_PMC_LATCH_SLPS0_EVENTS;
+       pmc_core_reg_write(pmcdev, map->slps0_dbg_offset, fd);
+
+       slps0_dbg_latch = 0;
+
+out_unlock:
+       mutex_unlock(&pmcdev->lock);
+}
+
+static int pmc_core_slps0_dbg_show(struct seq_file *s, void *unused)
+{
+       struct pmc_dev *pmcdev = s->private;
+       const struct pmc_bit_map **maps = pmcdev->map->slps0_dbg_maps;
+       const struct pmc_bit_map *map;
+       int offset;
+       u32 data;
+
+       pmc_core_slps0_dbg_latch(pmcdev, false);
+       offset = pmcdev->map->slps0_dbg_offset;
+       while (*maps) {
+               map = *maps;
+               data = pmc_core_reg_read(pmcdev, offset);
+               offset += 4;
+               while (map->name) {
+                       seq_printf(s, "SLP_S0_DBG: %-32s\tState: %s\n",
+                                  map->name,
+                                  data & map->bit_mask ?
+                                  "Yes" : "No");
+                       ++map;
+               }
+               ++maps;
+       }
+       pmc_core_slps0_dbg_latch(pmcdev, true);
+       return 0;
+}
+DEFINE_SHOW_ATTRIBUTE(pmc_core_slps0_dbg);
+
 static void pmc_core_dbgfs_unregister(struct pmc_dev *pmcdev)
 {
        debugfs_remove_recursive(pmcdev->dbgfs_dir);
@@ -514,6 +625,15 @@ static int pmc_core_dbgfs_register(struct pmc_dev *pmcdev)
                                    0444, dir, pmcdev,
                                    &pmc_core_mphy_pg_ops);
 
+       if (pmcdev->map->slps0_dbg_maps) {
+               debugfs_create_file("slp_s0_debug_status", 0444,
+                                   dir, pmcdev,
+                                   &pmc_core_slps0_dbg_fops);
+
+               debugfs_create_bool("slp_s0_dbg_latch", 0644,
+                                   dir, &slps0_dbg_latch);
+       }
+
        return 0;
 }
 #else
index 5fa5f97..93a7e99 100644 (file)
@@ -127,12 +127,14 @@ enum ppfear_regs {
 #define CNP_PMC_SLP_S0_RES_COUNTER_OFFSET      0x193C
 #define CNP_PMC_LTR_IGNORE_OFFSET              0x1B0C
 #define CNP_PMC_PM_CFG_OFFSET                  0x1818
+#define CNP_PMC_SLPS0_DBG_OFFSET               0x10B4
 /* Cannonlake: PGD PFET Enable Ack Status Register(s) start */
 #define CNP_PMC_HOST_PPFEAR0A                  0x1D90
 
 #define CNP_PMC_MMIO_REG_LEN                   0x2000
 #define CNP_PPFEAR_NUM_ENTRIES                 8
 #define CNP_PMC_READ_DISABLE_BIT               22
+#define CNP_PMC_LATCH_SLPS0_EVENTS             BIT(31)
 
 struct pmc_bit_map {
        const char *name;
@@ -145,6 +147,7 @@ struct pmc_bit_map {
  * @pfear_sts:         Maps name of IP block to PPFEAR* bit
  * @mphy_sts:          Maps name of MPHY lane to MPHY status lane status bit
  * @pll_sts:           Maps name of PLL to corresponding bit status
+ * @slps0_dbg_maps:    Array of SLP_S0_DBG* registers containing debug info
  * @slp_s0_offset:     PWRMBASE offset to read SLP_S0 residency
  * @ltr_ignore_offset: PWRMBASE offset to read/write LTR ignore bit
  * @regmap_length:     Length of memory to map from PWRMBASE address to access
@@ -153,6 +156,7 @@ struct pmc_bit_map {
  *                     PPFEAR
  * @pm_cfg_offset:     PWRMBASE offset to PM_CFG register
  * @pm_read_disable_bit: Bit index to read PMC_READ_DISABLE
+ * @slps0_dbg_offset:  PWRMBASE offset to SLP_S0_DEBUG_REG*
  *
  * Each PCH has unique set of register offsets and bit indexes. This structure
  * captures them to have a common implementation.
@@ -161,6 +165,7 @@ struct pmc_reg_map {
        const struct pmc_bit_map *pfear_sts;
        const struct pmc_bit_map *mphy_sts;
        const struct pmc_bit_map *pll_sts;
+       const struct pmc_bit_map **slps0_dbg_maps;
        const u32 slp_s0_offset;
        const u32 ltr_ignore_offset;
        const int regmap_length;
@@ -168,6 +173,7 @@ struct pmc_reg_map {
        const int ppfear_buckets;
        const u32 pm_cfg_offset;
        const int pm_read_disable_bit;
+       const u32 slps0_dbg_offset;
 };
 
 /**
index f1afc0e..2efeab6 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/bitops.h>
 #include <linux/device.h>
 #include <linux/interrupt.h>
+#include <linux/io.h>
 #include <linux/platform_device.h>
 #include <asm/intel_punit_ipc.h>
 
index a0fd9aa..d89936c 100644 (file)
 /* LPC bus IO offsets */
 #define MLXPLAT_CPLD_LPC_I2C_BASE_ADRR         0x2000
 #define MLXPLAT_CPLD_LPC_REG_BASE_ADRR         0x2500
+#define MLXPLAT_CPLD_LPC_REG_CPLD1_VER_OFFSET  0x00
+#define MLXPLAT_CPLD_LPC_REG_CPLD2_VER_OFFSET  0x01
+#define MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET        0x1d
 #define MLXPLAT_CPLD_LPC_REG_LED1_OFFSET       0x20
 #define MLXPLAT_CPLD_LPC_REG_LED2_OFFSET       0x21
 #define MLXPLAT_CPLD_LPC_REG_LED3_OFFSET       0x22
 #define MLXPLAT_CPLD_LPC_REG_LED4_OFFSET       0x23
 #define MLXPLAT_CPLD_LPC_REG_LED5_OFFSET       0x24
+#define MLXPLAT_CPLD_LPC_REG_GP1_OFFSET                0x30
+#define MLXPLAT_CPLD_LPC_REG_WP1_OFFSET                0x31
+#define MLXPLAT_CPLD_LPC_REG_GP2_OFFSET                0x32
+#define MLXPLAT_CPLD_LPC_REG_WP2_OFFSET                0x33
+#define MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET        0x37
 #define MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET       0x3a
 #define MLXPLAT_CPLD_LPC_REG_AGGR_MASK_OFFSET  0x3b
 #define MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET     0x40
 #define MLXPLAT_CPLD_LPC_REG_AGGRLO_MASK_OFFSET        0x41
+#define MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET 0x50
+#define MLXPLAT_CPLD_LPC_REG_ASIC_EVENT_OFFSET 0x51
+#define MLXPLAT_CPLD_LPC_REG_ASIC_MASK_OFFSET  0x52
 #define MLXPLAT_CPLD_LPC_REG_PSU_OFFSET                0x58
 #define MLXPLAT_CPLD_LPC_REG_PSU_EVENT_OFFSET  0x59
 #define MLXPLAT_CPLD_LPC_REG_PSU_MASK_OFFSET   0x5a
 #define MLXPLAT_CPLD_LPC_REG_FAN_OFFSET                0x88
 #define MLXPLAT_CPLD_LPC_REG_FAN_EVENT_OFFSET  0x89
 #define MLXPLAT_CPLD_LPC_REG_FAN_MASK_OFFSET   0x8a
+#define MLXPLAT_CPLD_LPC_REG_PWM1_OFFSET       0xe3
+#define MLXPLAT_CPLD_LPC_REG_TACHO1_OFFSET     0xe4
+#define MLXPLAT_CPLD_LPC_REG_TACHO2_OFFSET     0xe5
+#define MLXPLAT_CPLD_LPC_REG_TACHO3_OFFSET     0xe6
+#define MLXPLAT_CPLD_LPC_REG_TACHO4_OFFSET     0xe7
+#define MLXPLAT_CPLD_LPC_REG_TACHO5_OFFSET     0xe8
+#define MLXPLAT_CPLD_LPC_REG_TACHO6_OFFSET     0xe9
+#define MLXPLAT_CPLD_LPC_REG_TACHO7_OFFSET     0xea
+#define MLXPLAT_CPLD_LPC_REG_TACHO8_OFFSET     0xeb
+#define MLXPLAT_CPLD_LPC_REG_TACHO9_OFFSET     0xec
+#define MLXPLAT_CPLD_LPC_REG_TACHO10_OFFSET    0xed
+#define MLXPLAT_CPLD_LPC_REG_TACHO11_OFFSET    0xee
+#define MLXPLAT_CPLD_LPC_REG_TACHO12_OFFSET    0xef
 #define MLXPLAT_CPLD_LPC_IO_RANGE              0x100
 #define MLXPLAT_CPLD_LPC_I2C_CH1_OFF           0xdb
 #define MLXPLAT_CPLD_LPC_I2C_CH2_OFF           0xda
+
 #define MLXPLAT_CPLD_LPC_PIO_OFFSET            0x10000UL
 #define MLXPLAT_CPLD_LPC_REG1  ((MLXPLAT_CPLD_LPC_REG_BASE_ADRR + \
                                  MLXPLAT_CPLD_LPC_I2C_CH1_OFF) | \
                                  MLXPLAT_CPLD_LPC_PIO_OFFSET)
 
 /* Masks for aggregation, psu, pwr and fan event in CPLD related registers. */
+#define MLXPLAT_CPLD_AGGR_ASIC_MASK_DEF        0x04
 #define MLXPLAT_CPLD_AGGR_PSU_MASK_DEF 0x08
 #define MLXPLAT_CPLD_AGGR_PWR_MASK_DEF 0x08
 #define MLXPLAT_CPLD_AGGR_FAN_MASK_DEF 0x40
-#define MLXPLAT_CPLD_AGGR_MASK_DEF     (MLXPLAT_CPLD_AGGR_PSU_MASK_DEF | \
+#define MLXPLAT_CPLD_AGGR_MASK_DEF     (MLXPLAT_CPLD_AGGR_ASIC_MASK_DEF | \
+                                        MLXPLAT_CPLD_AGGR_PSU_MASK_DEF | \
                                         MLXPLAT_CPLD_AGGR_FAN_MASK_DEF)
+#define MLXPLAT_CPLD_AGGR_ASIC_MASK_NG 0x01
 #define MLXPLAT_CPLD_AGGR_MASK_NG_DEF  0x04
-#define MLXPLAT_CPLD_LOW_AGGR_MASK_LOW 0xc0
-#define MLXPLAT_CPLD_AGGR_MASK_MSN21XX 0x04
+#define MLXPLAT_CPLD_LOW_AGGR_MASK_LOW 0xc1
 #define MLXPLAT_CPLD_PSU_MASK          GENMASK(1, 0)
 #define MLXPLAT_CPLD_PWR_MASK          GENMASK(1, 0)
 #define MLXPLAT_CPLD_FAN_MASK          GENMASK(3, 0)
+#define MLXPLAT_CPLD_ASIC_MASK         GENMASK(1, 0)
 #define MLXPLAT_CPLD_FAN_NG_MASK       GENMASK(5, 0)
 #define MLXPLAT_CPLD_LED_LO_NIBBLE_MASK        GENMASK(7, 4)
 #define MLXPLAT_CPLD_LED_HI_NIBBLE_MASK        GENMASK(3, 0)
  * @pdev_mux - array of mux platform devices
  * @pdev_hotplug - hotplug platform devices
  * @pdev_led - led platform devices
+ * @pdev_io_regs - register access platform devices
+ * @pdev_fan - FAN platform devices
  */
 struct mlxplat_priv {
        struct platform_device *pdev_i2c;
        struct platform_device *pdev_mux[MLXPLAT_CPLD_LPC_MUX_DEVS];
        struct platform_device *pdev_hotplug;
        struct platform_device *pdev_led;
+       struct platform_device *pdev_io_regs;
+       struct platform_device *pdev_fan;
 };
 
 /* Regions for LPC I2C controller and LPC base register space */
@@ -288,6 +320,15 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_fan_items_data[] = {
        },
 };
 
+static struct mlxreg_core_data mlxplat_mlxcpld_default_asic_items_data[] = {
+       {
+               .label = "asic1",
+               .reg = MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET,
+               .mask = MLXPLAT_CPLD_ASIC_MASK,
+               .hpdev.nr = MLXPLAT_CPLD_NR_NONE,
+       },
+};
+
 static struct mlxreg_core_item mlxplat_mlxcpld_default_items[] = {
        {
                .data = mlxplat_mlxcpld_default_psu_items_data,
@@ -316,6 +357,15 @@ static struct mlxreg_core_item mlxplat_mlxcpld_default_items[] = {
                .inversed = 1,
                .health = false,
        },
+       {
+               .data = mlxplat_mlxcpld_default_asic_items_data,
+               .aggr_mask = MLXPLAT_CPLD_AGGR_ASIC_MASK_DEF,
+               .reg = MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET,
+               .mask = MLXPLAT_CPLD_ASIC_MASK,
+               .count = ARRAY_SIZE(mlxplat_mlxcpld_default_asic_items_data),
+               .inversed = 0,
+               .health = true,
+       },
 };
 
 static
@@ -324,6 +374,8 @@ struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_default_data = {
        .counter = ARRAY_SIZE(mlxplat_mlxcpld_default_items),
        .cell = MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET,
        .mask = MLXPLAT_CPLD_AGGR_MASK_DEF,
+       .cell_low = MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET,
+       .mask_low = MLXPLAT_CPLD_LOW_AGGR_MASK_LOW,
 };
 
 static struct mlxreg_core_data mlxplat_mlxcpld_msn21xx_pwr_items_data[] = {
@@ -352,6 +404,15 @@ static struct mlxreg_core_item mlxplat_mlxcpld_msn21xx_items[] = {
                .inversed = 0,
                .health = false,
        },
+       {
+               .data = mlxplat_mlxcpld_default_asic_items_data,
+               .aggr_mask = MLXPLAT_CPLD_AGGR_ASIC_MASK_DEF,
+               .reg = MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET,
+               .mask = MLXPLAT_CPLD_ASIC_MASK,
+               .count = ARRAY_SIZE(mlxplat_mlxcpld_default_asic_items_data),
+               .inversed = 0,
+               .health = true,
+       },
 };
 
 static
@@ -454,6 +515,15 @@ static struct mlxreg_core_item mlxplat_mlxcpld_msn274x_items[] = {
                .inversed = 1,
                .health = false,
        },
+       {
+               .data = mlxplat_mlxcpld_default_asic_items_data,
+               .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF,
+               .reg = MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET,
+               .mask = MLXPLAT_CPLD_ASIC_MASK,
+               .count = ARRAY_SIZE(mlxplat_mlxcpld_default_asic_items_data),
+               .inversed = 0,
+               .health = true,
+       },
 };
 
 static
@@ -492,6 +562,15 @@ static struct mlxreg_core_item mlxplat_mlxcpld_msn201x_items[] = {
                .inversed = 0,
                .health = false,
        },
+       {
+               .data = mlxplat_mlxcpld_default_asic_items_data,
+               .aggr_mask = MLXPLAT_CPLD_AGGR_ASIC_MASK_DEF,
+               .reg = MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET,
+               .mask = MLXPLAT_CPLD_ASIC_MASK,
+               .count = ARRAY_SIZE(mlxplat_mlxcpld_default_asic_items_data),
+               .inversed = 0,
+               .health = true,
+       },
 };
 
 static
@@ -589,6 +668,15 @@ static struct mlxreg_core_item mlxplat_mlxcpld_default_ng_items[] = {
                .inversed = 1,
                .health = false,
        },
+       {
+               .data = mlxplat_mlxcpld_default_asic_items_data,
+               .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF,
+               .reg = MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET,
+               .mask = MLXPLAT_CPLD_ASIC_MASK,
+               .count = ARRAY_SIZE(mlxplat_mlxcpld_default_asic_items_data),
+               .inversed = 0,
+               .health = true,
+       },
 };
 
 static
@@ -813,6 +901,278 @@ static struct mlxreg_core_platform_data mlxplat_default_ng_led_data = {
                .counter = ARRAY_SIZE(mlxplat_mlxcpld_default_ng_led_data),
 };
 
+/* Platform register access default */
+static struct mlxreg_core_data mlxplat_mlxcpld_default_regs_io_data[] = {
+       {
+               .label = "cpld1_version",
+               .reg = MLXPLAT_CPLD_LPC_REG_CPLD1_VER_OFFSET,
+               .bit = GENMASK(7, 0),
+               .mode = 0444,
+       },
+       {
+               .label = "cpld2_version",
+               .reg = MLXPLAT_CPLD_LPC_REG_CPLD2_VER_OFFSET,
+               .bit = GENMASK(7, 0),
+               .mode = 0444,
+       },
+       {
+               .label = "reset_long_pb",
+               .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET,
+               .mask = GENMASK(7, 0) & ~BIT(0),
+               .mode = 0444,
+       },
+       {
+               .label = "reset_short_pb",
+               .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET,
+               .mask = GENMASK(7, 0) & ~BIT(1),
+               .mode = 0444,
+       },
+       {
+               .label = "reset_aux_pwr_or_ref",
+               .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET,
+               .mask = GENMASK(7, 0) & ~BIT(2),
+               .mode = 0444,
+       },
+       {
+               .label = "reset_main_pwr_fail",
+               .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET,
+               .mask = GENMASK(7, 0) & ~BIT(3),
+               .mode = 0444,
+       },
+       {
+               .label = "reset_sw_reset",
+               .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET,
+               .mask = GENMASK(7, 0) & ~BIT(4),
+               .mode = 0444,
+       },
+       {
+               .label = "reset_fw_reset",
+               .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET,
+               .mask = GENMASK(7, 0) & ~BIT(5),
+               .mode = 0444,
+       },
+       {
+               .label = "reset_hotswap_or_wd",
+               .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET,
+               .mask = GENMASK(7, 0) & ~BIT(6),
+               .mode = 0444,
+       },
+       {
+               .label = "reset_asic_thermal",
+               .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET,
+               .mask = GENMASK(7, 0) & ~BIT(7),
+               .mode = 0444,
+       },
+       {
+               .label = "psu1_on",
+               .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET,
+               .mask = GENMASK(7, 0) & ~BIT(0),
+               .mode = 0200,
+       },
+       {
+               .label = "psu2_on",
+               .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET,
+               .mask = GENMASK(7, 0) & ~BIT(1),
+               .mode = 0200,
+       },
+       {
+               .label = "pwr_cycle",
+               .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET,
+               .mask = GENMASK(7, 0) & ~BIT(2),
+               .mode = 0200,
+       },
+       {
+               .label = "pwr_down",
+               .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET,
+               .mask = GENMASK(7, 0) & ~BIT(3),
+               .mode = 0200,
+       },
+       {
+               .label = "select_iio",
+               .reg = MLXPLAT_CPLD_LPC_REG_GP2_OFFSET,
+               .mask = GENMASK(7, 0) & ~BIT(6),
+               .mode = 0644,
+       },
+       {
+               .label = "asic_health",
+               .reg = MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET,
+               .mask = MLXPLAT_CPLD_ASIC_MASK,
+               .bit = 1,
+               .mode = 0444,
+       },
+};
+
+static struct mlxreg_core_platform_data mlxplat_default_regs_io_data = {
+               .data = mlxplat_mlxcpld_default_regs_io_data,
+               .counter = ARRAY_SIZE(mlxplat_mlxcpld_default_regs_io_data),
+};
+
+/* Platform register access MSN21xx, MSN201x, MSN274x systems families data */
+static struct mlxreg_core_data mlxplat_mlxcpld_msn21xx_regs_io_data[] = {
+       {
+               .label = "cpld1_version",
+               .reg = MLXPLAT_CPLD_LPC_REG_CPLD1_VER_OFFSET,
+               .bit = GENMASK(7, 0),
+               .mode = 0444,
+       },
+       {
+               .label = "cpld2_version",
+               .reg = MLXPLAT_CPLD_LPC_REG_CPLD2_VER_OFFSET,
+               .bit = GENMASK(7, 0),
+               .mode = 0444,
+       },
+       {
+               .label = "reset_long_pb",
+               .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET,
+               .mask = GENMASK(7, 0) & ~BIT(0),
+               .mode = 0444,
+       },
+       {
+               .label = "reset_short_pb",
+               .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET,
+               .mask = GENMASK(7, 0) & ~BIT(1),
+               .mode = 0444,
+       },
+       {
+               .label = "reset_aux_pwr_or_ref",
+               .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET,
+               .mask = GENMASK(7, 0) & ~BIT(2),
+               .mode = 0444,
+       },
+       {
+               .label = "reset_sw_reset",
+               .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET,
+               .mask = GENMASK(7, 0) & ~BIT(3),
+               .mode = 0444,
+       },
+       {
+               .label = "reset_main_pwr_fail",
+               .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET,
+               .mask = GENMASK(7, 0) & ~BIT(4),
+               .mode = 0444,
+       },
+       {
+               .label = "reset_asic_thermal",
+               .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET,
+               .mask = GENMASK(7, 0) & ~BIT(5),
+               .mode = 0444,
+       },
+       {
+               .label = "reset_hotswap_or_halt",
+               .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET,
+               .mask = GENMASK(7, 0) & ~BIT(6),
+               .mode = 0444,
+       },
+       {
+               .label = "psu1_on",
+               .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET,
+               .mask = GENMASK(7, 0) & ~BIT(0),
+               .mode = 0200,
+       },
+       {
+               .label = "psu2_on",
+               .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET,
+               .mask = GENMASK(7, 0) & ~BIT(1),
+               .mode = 0200,
+       },
+       {
+               .label = "pwr_cycle",
+               .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET,
+               .mask = GENMASK(7, 0) & ~BIT(2),
+               .mode = 0200,
+       },
+       {
+               .label = "pwr_down",
+               .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET,
+               .mask = GENMASK(7, 0) & ~BIT(3),
+               .mode = 0200,
+       },
+       {
+               .label = "asic_health",
+               .reg = MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET,
+               .mask = MLXPLAT_CPLD_ASIC_MASK,
+               .bit = 1,
+               .mode = 0444,
+       },
+};
+
+static struct mlxreg_core_platform_data mlxplat_msn21xx_regs_io_data = {
+               .data = mlxplat_mlxcpld_msn21xx_regs_io_data,
+               .counter = ARRAY_SIZE(mlxplat_mlxcpld_msn21xx_regs_io_data),
+};
+
+/* Platform FAN default */
+static struct mlxreg_core_data mlxplat_mlxcpld_default_fan_data[] = {
+       {
+               .label = "pwm1",
+               .reg = MLXPLAT_CPLD_LPC_REG_PWM1_OFFSET,
+       },
+       {
+               .label = "tacho1",
+               .reg = MLXPLAT_CPLD_LPC_REG_TACHO1_OFFSET,
+               .mask = GENMASK(7, 0),
+       },
+       {
+               .label = "tacho2",
+               .reg = MLXPLAT_CPLD_LPC_REG_TACHO2_OFFSET,
+               .mask = GENMASK(7, 0),
+       },
+       {
+               .label = "tacho3",
+               .reg = MLXPLAT_CPLD_LPC_REG_TACHO3_OFFSET,
+               .mask = GENMASK(7, 0),
+       },
+       {
+               .label = "tacho4",
+               .reg = MLXPLAT_CPLD_LPC_REG_TACHO4_OFFSET,
+               .mask = GENMASK(7, 0),
+       },
+       {
+               .label = "tacho5",
+               .reg = MLXPLAT_CPLD_LPC_REG_TACHO5_OFFSET,
+               .mask = GENMASK(7, 0),
+       },
+       {
+               .label = "tacho6",
+               .reg = MLXPLAT_CPLD_LPC_REG_TACHO6_OFFSET,
+               .mask = GENMASK(7, 0),
+       },
+       {
+               .label = "tacho7",
+               .reg = MLXPLAT_CPLD_LPC_REG_TACHO7_OFFSET,
+               .mask = GENMASK(7, 0),
+       },
+       {
+               .label = "tacho8",
+               .reg = MLXPLAT_CPLD_LPC_REG_TACHO8_OFFSET,
+               .mask = GENMASK(7, 0),
+       },
+       {
+               .label = "tacho9",
+               .reg = MLXPLAT_CPLD_LPC_REG_TACHO9_OFFSET,
+               .mask = GENMASK(7, 0),
+       },
+       {
+               .label = "tacho10",
+               .reg = MLXPLAT_CPLD_LPC_REG_TACHO10_OFFSET,
+               .mask = GENMASK(7, 0),
+       },
+       {
+               .label = "tacho11",
+               .reg = MLXPLAT_CPLD_LPC_REG_TACHO11_OFFSET,
+               .mask = GENMASK(7, 0),
+       },
+       {
+               .label = "tacho12",
+               .reg = MLXPLAT_CPLD_LPC_REG_TACHO12_OFFSET,
+               .mask = GENMASK(7, 0),
+       },
+};
+
+static struct mlxreg_core_platform_data mlxplat_default_fan_data = {
+               .data = mlxplat_mlxcpld_default_fan_data,
+               .counter = ARRAY_SIZE(mlxplat_mlxcpld_default_fan_data),
+};
 
 static bool mlxplat_mlxcpld_writeable_reg(struct device *dev, unsigned int reg)
 {
@@ -822,14 +1182,22 @@ static bool mlxplat_mlxcpld_writeable_reg(struct device *dev, unsigned int reg)
        case MLXPLAT_CPLD_LPC_REG_LED3_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_LED4_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_LED5_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_GP1_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_WP1_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_GP2_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_WP2_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_AGGR_MASK_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_AGGRLO_MASK_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_ASIC_EVENT_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_ASIC_MASK_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_PSU_EVENT_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_PSU_MASK_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_PWR_EVENT_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_PWR_MASK_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_FAN_EVENT_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_FAN_MASK_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_PWM1_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET:
                return true;
        }
        return false;
@@ -838,15 +1206,25 @@ static bool mlxplat_mlxcpld_writeable_reg(struct device *dev, unsigned int reg)
 static bool mlxplat_mlxcpld_readable_reg(struct device *dev, unsigned int reg)
 {
        switch (reg) {
+       case MLXPLAT_CPLD_LPC_REG_CPLD1_VER_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_CPLD2_VER_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_LED1_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_LED2_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_LED3_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_LED4_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_LED5_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_GP1_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_WP1_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_GP2_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_WP2_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_AGGR_MASK_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_AGGRLO_MASK_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_ASIC_EVENT_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_ASIC_MASK_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_PSU_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_PSU_EVENT_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_PSU_MASK_OFFSET:
@@ -856,6 +1234,20 @@ static bool mlxplat_mlxcpld_readable_reg(struct device *dev, unsigned int reg)
        case MLXPLAT_CPLD_LPC_REG_FAN_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_FAN_EVENT_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_FAN_MASK_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_PWM1_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_TACHO1_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_TACHO2_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_TACHO3_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_TACHO4_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_TACHO5_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_TACHO6_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_TACHO7_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_TACHO8_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_TACHO9_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_TACHO10_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_TACHO11_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_TACHO12_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET:
                return true;
        }
        return false;
@@ -864,15 +1256,23 @@ static bool mlxplat_mlxcpld_readable_reg(struct device *dev, unsigned int reg)
 static bool mlxplat_mlxcpld_volatile_reg(struct device *dev, unsigned int reg)
 {
        switch (reg) {
+       case MLXPLAT_CPLD_LPC_REG_CPLD1_VER_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_CPLD2_VER_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_LED1_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_LED2_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_LED3_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_LED4_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_LED5_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_GP1_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_GP2_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_AGGR_MASK_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_AGGRLO_MASK_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_ASIC_EVENT_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_ASIC_MASK_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_PSU_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_PSU_EVENT_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_PSU_MASK_OFFSET:
@@ -882,11 +1282,31 @@ static bool mlxplat_mlxcpld_volatile_reg(struct device *dev, unsigned int reg)
        case MLXPLAT_CPLD_LPC_REG_FAN_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_FAN_EVENT_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_FAN_MASK_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_PWM1_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_TACHO1_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_TACHO2_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_TACHO3_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_TACHO4_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_TACHO5_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_TACHO6_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_TACHO7_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_TACHO8_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_TACHO9_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_TACHO10_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_TACHO11_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_TACHO12_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET:
                return true;
        }
        return false;
 }
 
+static const struct reg_default mlxplat_mlxcpld_regmap_default[] = {
+       { MLXPLAT_CPLD_LPC_REG_WP1_OFFSET, 0x00 },
+       { MLXPLAT_CPLD_LPC_REG_WP2_OFFSET, 0x00 },
+       { MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET, 0x00 },
+};
+
 struct mlxplat_mlxcpld_regmap_context {
        void __iomem *base;
 };
@@ -919,6 +1339,8 @@ static const struct regmap_config mlxplat_mlxcpld_regmap_config = {
        .writeable_reg = mlxplat_mlxcpld_writeable_reg,
        .readable_reg = mlxplat_mlxcpld_readable_reg,
        .volatile_reg = mlxplat_mlxcpld_volatile_reg,
+       .reg_defaults = mlxplat_mlxcpld_regmap_default,
+       .num_reg_defaults = ARRAY_SIZE(mlxplat_mlxcpld_regmap_default),
        .reg_read = mlxplat_mlxcpld_reg_read,
        .reg_write = mlxplat_mlxcpld_reg_write,
 };
@@ -930,6 +1352,8 @@ static struct resource mlxplat_mlxcpld_resources[] = {
 static struct platform_device *mlxplat_dev;
 static struct mlxreg_core_hotplug_platform_data *mlxplat_hotplug;
 static struct mlxreg_core_platform_data *mlxplat_led;
+static struct mlxreg_core_platform_data *mlxplat_regs_io;
+static struct mlxreg_core_platform_data *mlxplat_fan;
 
 static int __init mlxplat_dmi_default_matched(const struct dmi_system_id *dmi)
 {
@@ -944,6 +1368,7 @@ static int __init mlxplat_dmi_default_matched(const struct dmi_system_id *dmi)
        mlxplat_hotplug->deferred_nr =
                mlxplat_default_channels[i - 1][MLXPLAT_CPLD_GRP_CHNL_NUM - 1];
        mlxplat_led = &mlxplat_default_led_data;
+       mlxplat_regs_io = &mlxplat_default_regs_io_data;
 
        return 1;
 };
@@ -961,6 +1386,7 @@ static int __init mlxplat_dmi_msn21xx_matched(const struct dmi_system_id *dmi)
        mlxplat_hotplug->deferred_nr =
                mlxplat_msn21xx_channels[MLXPLAT_CPLD_GRP_CHNL_NUM - 1];
        mlxplat_led = &mlxplat_msn21xx_led_data;
+       mlxplat_regs_io = &mlxplat_msn21xx_regs_io_data;
 
        return 1;
 };
@@ -978,6 +1404,7 @@ static int __init mlxplat_dmi_msn274x_matched(const struct dmi_system_id *dmi)
        mlxplat_hotplug->deferred_nr =
                mlxplat_msn21xx_channels[MLXPLAT_CPLD_GRP_CHNL_NUM - 1];
        mlxplat_led = &mlxplat_default_led_data;
+       mlxplat_regs_io = &mlxplat_msn21xx_regs_io_data;
 
        return 1;
 };
@@ -995,6 +1422,7 @@ static int __init mlxplat_dmi_msn201x_matched(const struct dmi_system_id *dmi)
        mlxplat_hotplug->deferred_nr =
                mlxplat_default_channels[i - 1][MLXPLAT_CPLD_GRP_CHNL_NUM - 1];
        mlxplat_led = &mlxplat_default_ng_led_data;
+       mlxplat_regs_io = &mlxplat_msn21xx_regs_io_data;
 
        return 1;
 };
@@ -1012,6 +1440,7 @@ static int __init mlxplat_dmi_qmb7xx_matched(const struct dmi_system_id *dmi)
        mlxplat_hotplug->deferred_nr =
                mlxplat_msn21xx_channels[MLXPLAT_CPLD_GRP_CHNL_NUM - 1];
        mlxplat_led = &mlxplat_msn21xx_led_data;
+       mlxplat_fan = &mlxplat_default_fan_data;
 
        return 1;
 };
@@ -1163,7 +1592,7 @@ static int mlxplat_mlxcpld_verify_bus_topology(int *nr)
 static int __init mlxplat_init(void)
 {
        struct mlxplat_priv *priv;
-       int i, nr, err;
+       int i, j, nr, err;
 
        if (!dmi_check_system(mlxplat_dmi_table))
                return -ENODEV;
@@ -1233,6 +1662,15 @@ static int __init mlxplat_init(void)
                goto fail_platform_mux_register;
        }
 
+       /* Set default registers. */
+       for (j = 0; j <  mlxplat_mlxcpld_regmap_config.num_reg_defaults; j++) {
+               err = regmap_write(mlxplat_hotplug->regmap,
+                                  mlxplat_mlxcpld_regmap_default[j].reg,
+                                  mlxplat_mlxcpld_regmap_default[j].def);
+               if (err)
+                       goto fail_platform_mux_register;
+       }
+
        /* Add LED driver. */
        mlxplat_led->regmap = mlxplat_hotplug->regmap;
        priv->pdev_led = platform_device_register_resndata(
@@ -1244,14 +1682,48 @@ static int __init mlxplat_init(void)
                goto fail_platform_hotplug_register;
        }
 
+       /* Add registers io access driver. */
+       if (mlxplat_regs_io) {
+               mlxplat_regs_io->regmap = mlxplat_hotplug->regmap;
+               priv->pdev_io_regs = platform_device_register_resndata(
+                                       &mlxplat_dev->dev, "mlxreg-io",
+                                       PLATFORM_DEVID_NONE, NULL, 0,
+                                       mlxplat_regs_io,
+                                       sizeof(*mlxplat_regs_io));
+               if (IS_ERR(priv->pdev_io_regs)) {
+                       err = PTR_ERR(priv->pdev_io_regs);
+                       goto fail_platform_led_register;
+               }
+       }
+
+       /* Add FAN driver. */
+       if (mlxplat_fan) {
+               mlxplat_fan->regmap = mlxplat_hotplug->regmap;
+               priv->pdev_fan = platform_device_register_resndata(
+                                       &mlxplat_dev->dev, "mlxreg-fan",
+                                       PLATFORM_DEVID_NONE, NULL, 0,
+                                       mlxplat_fan,
+                                       sizeof(*mlxplat_fan));
+               if (IS_ERR(priv->pdev_fan)) {
+                       err = PTR_ERR(priv->pdev_fan);
+                       goto fail_platform_io_regs_register;
+               }
+       }
+
        /* Sync registers with hardware. */
        regcache_mark_dirty(mlxplat_hotplug->regmap);
        err = regcache_sync(mlxplat_hotplug->regmap);
        if (err)
-               goto fail_platform_led_register;
+               goto fail_platform_fan_register;
 
        return 0;
 
+fail_platform_fan_register:
+       if (mlxplat_fan)
+               platform_device_unregister(priv->pdev_fan);
+fail_platform_io_regs_register:
+       if (mlxplat_regs_io)
+               platform_device_unregister(priv->pdev_io_regs);
 fail_platform_led_register:
        platform_device_unregister(priv->pdev_led);
 fail_platform_hotplug_register:
@@ -1272,6 +1744,10 @@ static void __exit mlxplat_exit(void)
        struct mlxplat_priv *priv = platform_get_drvdata(mlxplat_dev);
        int i;
 
+       if (priv->pdev_fan)
+               platform_device_unregister(priv->pdev_fan);
+       if (priv->pdev_io_regs)
+               platform_device_unregister(priv->pdev_io_regs);
        platform_device_unregister(priv->pdev_led);
        platform_device_unregister(priv->pdev_hotplug);
 
index cae9b05..fde08a9 100644 (file)
@@ -57,6 +57,7 @@
 #include <linux/list.h>
 #include <linux/mutex.h>
 #include <linux/sched.h>
+#include <linux/sched/signal.h>
 #include <linux/kthread.h>
 #include <linux/freezer.h>
 #include <linux/delay.h>
@@ -335,6 +336,7 @@ static struct {
        u32 second_fan:1;
        u32 beep_needs_two_args:1;
        u32 mixer_no_level_control:1;
+       u32 battery_force_primary:1;
        u32 input_device_registered:1;
        u32 platform_drv_registered:1;
        u32 platform_drv_attrs_registered:1;
@@ -343,7 +345,6 @@ static struct {
        u32 sensors_pdev_attrs_registered:1;
        u32 hotkey_poll_active:1;
        u32 has_adaptive_kbd:1;
-       u32 battery:1;
 } tp_features;
 
 static struct {
@@ -358,9 +359,9 @@ struct thinkpad_id_data {
        char *bios_version_str; /* Something like 1ZET51WW (1.03z) */
        char *ec_version_str;   /* Something like 1ZHT51WW-1.04a */
 
-       u16 bios_model;         /* 1Y = 0x5931, 0 = unknown */
-       u16 ec_model;
-       u16 bios_release;       /* 1ZETK1WW = 0x314b, 0 = unknown */
+       u32 bios_model;         /* 1Y = 0x3159, 0 = unknown */
+       u32 ec_model;
+       u16 bios_release;       /* 1ZETK1WW = 0x4b31, 0 = unknown */
        u16 ec_release;
 
        char *model_str;        /* ThinkPad T43 */
@@ -444,17 +445,20 @@ do {                                                                      \
 /*
  * Quirk handling helpers
  *
- * ThinkPad IDs and versions seen in the field so far
- * are two-characters from the set [0-9A-Z], i.e. base 36.
+ * ThinkPad IDs and versions seen in the field so far are
+ * two or three characters from the set [0-9A-Z], i.e. base 36.
  *
  * We use values well outside that range as specials.
  */
 
-#define TPACPI_MATCH_ANY               0xffffU
+#define TPACPI_MATCH_ANY               0xffffffffU
+#define TPACPI_MATCH_ANY_VERSION       0xffffU
 #define TPACPI_MATCH_UNKNOWN           0U
 
-/* TPID('1', 'Y') == 0x5931 */
-#define TPID(__c1, __c2) (((__c2) << 8) | (__c1))
+/* TPID('1', 'Y') == 0x3159 */
+#define TPID(__c1, __c2)       (((__c1) << 8) | (__c2))
+#define TPID3(__c1, __c2, __c3)        (((__c1) << 16) | ((__c2) << 8) | (__c3))
+#define TPVER TPID
 
 #define TPACPI_Q_IBM(__id1, __id2, __quirk)    \
        { .vendor = PCI_VENDOR_ID_IBM,          \
@@ -468,6 +472,12 @@ do {                                                                       \
          .ec = TPACPI_MATCH_ANY,               \
          .quirks = (__quirk) }
 
+#define TPACPI_Q_LNV3(__id1, __id2, __id3, __quirk) \
+       { .vendor = PCI_VENDOR_ID_LENOVO,       \
+         .bios = TPID3(__id1, __id2, __id3),   \
+         .ec = TPACPI_MATCH_ANY,               \
+         .quirks = (__quirk) }
+
 #define TPACPI_QEC_LNV(__id1, __id2, __quirk)  \
        { .vendor = PCI_VENDOR_ID_LENOVO,       \
          .bios = TPACPI_MATCH_ANY,             \
@@ -476,8 +486,8 @@ do {                                                                        \
 
 struct tpacpi_quirk {
        unsigned int vendor;
-       u16 bios;
-       u16 ec;
+       u32 bios;
+       u32 ec;
        unsigned long quirks;
 };
 
@@ -1647,16 +1657,16 @@ static void tpacpi_remove_driver_attributes(struct device_driver *drv)
        { .vendor       = (__v),                        \
          .bios         = TPID(__id1, __id2),           \
          .ec           = TPACPI_MATCH_ANY,             \
-         .quirks       = TPACPI_MATCH_ANY << 16        \
-                         | (__bv1) << 8 | (__bv2) }
+         .quirks       = TPACPI_MATCH_ANY_VERSION << 16 \
+                         | TPVER(__bv1, __bv2) }
 
 #define TPV_Q_X(__v, __bid1, __bid2, __bv1, __bv2,     \
                __eid, __ev1, __ev2)                    \
        { .vendor       = (__v),                        \
          .bios         = TPID(__bid1, __bid2),         \
          .ec           = __eid,                        \
-         .quirks       = (__ev1) << 24 | (__ev2) << 16 \
-                         | (__bv1) << 8 | (__bv2) }
+         .quirks       = TPVER(__ev1, __ev2) << 16     \
+                         | TPVER(__bv1, __bv2) }
 
 #define TPV_QI0(__id1, __id2, __bv1, __bv2) \
        TPV_Q(PCI_VENDOR_ID_IBM, __id1, __id2, __bv1, __bv2)
@@ -1798,7 +1808,7 @@ static void __init tpacpi_check_outdated_fw(void)
        /* note that unknown versions are set to 0x0000 and we use that */
        if ((bios_version > thinkpad_id.bios_release) ||
            (ec_version > thinkpad_id.ec_release &&
-                               ec_version != TPACPI_MATCH_ANY)) {
+                               ec_version != TPACPI_MATCH_ANY_VERSION)) {
                /*
                 * The changelogs would let us track down the exact
                 * reason, but it is just too much of a pain to track
@@ -1928,7 +1938,7 @@ enum {    /* hot key scan codes (derived from ACPI DSDT) */
        /* first new observed key (star, favorites) is 0x1311 */
        TP_ACPI_HOTKEYSCAN_STAR = 69,
        TP_ACPI_HOTKEYSCAN_CLIPPING_TOOL2,
-       TP_ACPI_HOTKEYSCAN_UNK25,
+       TP_ACPI_HOTKEYSCAN_CALCULATOR,
        TP_ACPI_HOTKEYSCAN_BLUETOOTH,
        TP_ACPI_HOTKEYSCAN_KEYBOARD,
 
@@ -3449,7 +3459,7 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
 
                KEY_FAVORITES,       /* Favorite app, 0x311 */
                KEY_RESERVED,        /* Clipping tool */
-               KEY_RESERVED,
+               KEY_CALC,            /* Calculator (above numpad, P52) */
                KEY_BLUETOOTH,       /* Bluetooth */
                KEY_KEYBOARD         /* Keyboard, 0x315 */
                },
@@ -9365,7 +9375,9 @@ static int tpacpi_battery_probe(int battery)
 {
        int ret = 0;
 
-       memset(&battery_info, 0, sizeof(struct tpacpi_battery_driver_data));
+       memset(&battery_info.batteries[battery], 0,
+               sizeof(battery_info.batteries[battery]));
+
        /*
         * 1) Get the current start threshold
         * 2) Check for support
@@ -9420,7 +9432,8 @@ static int tpacpi_battery_probe(int battery)
 static int tpacpi_battery_get_id(const char *battery_name)
 {
 
-       if (strcmp(battery_name, "BAT0") == 0)
+       if (strcmp(battery_name, "BAT0") == 0 ||
+           tp_features.battery_force_primary)
                return BAT_PRIMARY;
        if (strcmp(battery_name, "BAT1") == 0)
                return BAT_SECONDARY;
@@ -9596,8 +9609,26 @@ static struct acpi_battery_hook battery_hook = {
 
 /* Subdriver init/exit */
 
+static const struct tpacpi_quirk battery_quirk_table[] __initconst = {
+       /*
+        * Individual addressing is broken on models that expose the
+        * primary battery as BAT1.
+        */
+       TPACPI_Q_LNV('J', '7', true),       /* B5400 */
+       TPACPI_Q_LNV('J', 'I', true),       /* Thinkpad 11e */
+       TPACPI_Q_LNV3('R', '0', 'B', true), /* Thinkpad 11e gen 3 */
+       TPACPI_Q_LNV3('R', '0', 'C', true), /* Thinkpad 13 */
+       TPACPI_Q_LNV3('R', '0', 'J', true), /* Thinkpad 13 gen 2 */
+};
+
 static int __init tpacpi_battery_init(struct ibm_init_struct *ibm)
 {
+       memset(&battery_info, 0, sizeof(battery_info));
+
+       tp_features.battery_force_primary = tpacpi_check_quirks(
+                                       battery_quirk_table,
+                                       ARRAY_SIZE(battery_quirk_table));
+
        battery_hook_register(&battery_hook);
        return 0;
 }
@@ -9808,36 +9839,37 @@ err_out:
 
 /* Probing */
 
-static bool __pure __init tpacpi_is_fw_digit(const char c)
+static char __init tpacpi_parse_fw_id(const char * const s,
+                                     u32 *model, u16 *release)
 {
-       return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z');
-}
+       int i;
+
+       if (!s || strlen(s) < 8)
+               goto invalid;
+
+       for (i = 0; i < 8; i++)
+               if (!((s[i] >= '0' && s[i] <= '9') ||
+                     (s[i] >= 'A' && s[i] <= 'Z')))
+                       goto invalid;
 
-static bool __pure __init tpacpi_is_valid_fw_id(const char * const s,
-                                               const char t)
-{
        /*
         * Most models: xxyTkkWW (#.##c)
         * Ancient 570/600 and -SL lacks (#.##c)
         */
-       if (s && strlen(s) >= 8 &&
-               tpacpi_is_fw_digit(s[0]) &&
-               tpacpi_is_fw_digit(s[1]) &&
-               s[2] == t &&
-               (s[3] == 'T' || s[3] == 'N') &&
-               tpacpi_is_fw_digit(s[4]) &&
-               tpacpi_is_fw_digit(s[5]))
-               return true;
+       if (s[3] == 'T' || s[3] == 'N') {
+               *model = TPID(s[0], s[1]);
+               *release = TPVER(s[4], s[5]);
+               return s[2];
 
        /* New models: xxxyTkkW (#.##c); T550 and some others */
-       return s && strlen(s) >= 8 &&
-               tpacpi_is_fw_digit(s[0]) &&
-               tpacpi_is_fw_digit(s[1]) &&
-               tpacpi_is_fw_digit(s[2]) &&
-               s[3] == t &&
-               (s[4] == 'T' || s[4] == 'N') &&
-               tpacpi_is_fw_digit(s[5]) &&
-               tpacpi_is_fw_digit(s[6]);
+       } else if (s[4] == 'T' || s[4] == 'N') {
+               *model = TPID3(s[0], s[1], s[2]);
+               *release = TPVER(s[5], s[6]);
+               return s[3];
+       }
+
+invalid:
+       return '\0';
 }
 
 /* returns 0 - probe ok, or < 0 - probe error.
@@ -9849,6 +9881,7 @@ static int __must_check __init get_thinkpad_model_data(
        const struct dmi_device *dev = NULL;
        char ec_fw_string[18];
        char const *s;
+       char t;
 
        if (!tp)
                return -EINVAL;
@@ -9868,15 +9901,11 @@ static int __must_check __init get_thinkpad_model_data(
                return -ENOMEM;
 
        /* Really ancient ThinkPad 240X will fail this, which is fine */
-       if (!(tpacpi_is_valid_fw_id(tp->bios_version_str, 'E') ||
-             tpacpi_is_valid_fw_id(tp->bios_version_str, 'C')))
+       t = tpacpi_parse_fw_id(tp->bios_version_str,
+                              &tp->bios_model, &tp->bios_release);
+       if (t != 'E' && t != 'C')
                return 0;
 
-       tp->bios_model = tp->bios_version_str[0]
-                        | (tp->bios_version_str[1] << 8);
-       tp->bios_release = (tp->bios_version_str[4] << 8)
-                        | tp->bios_version_str[5];
-
        /*
         * ThinkPad T23 or newer, A31 or newer, R50e or newer,
         * X32 or newer, all Z series;  Some models must have an
@@ -9895,12 +9924,9 @@ static int __must_check __init get_thinkpad_model_data(
                        if (!tp->ec_version_str)
                                return -ENOMEM;
 
-                       if (tpacpi_is_valid_fw_id(ec_fw_string, 'H')) {
-                               tp->ec_model = ec_fw_string[0]
-                                               | (ec_fw_string[1] << 8);
-                               tp->ec_release = (ec_fw_string[4] << 8)
-                                               | ec_fw_string[5];
-                       } else {
+                       t = tpacpi_parse_fw_id(ec_fw_string,
+                                              &tp->ec_model, &tp->ec_release);
+                       if (t != 'H') {
                                pr_notice("ThinkPad firmware release %s doesn't match the known patterns\n",
                                          ec_fw_string);
                                pr_notice("please report this to %s\n",
index eef76bf..e366977 100644 (file)
@@ -34,6 +34,7 @@
 #define TOSHIBA_ACPI_VERSION   "0.24"
 #define PROC_INTERFACE_VERSION 1
 
+#include <linux/compiler.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
@@ -1682,7 +1683,7 @@ static const struct file_operations keys_proc_fops = {
        .write          = keys_proc_write,
 };
 
-static int version_proc_show(struct seq_file *m, void *v)
+static int __maybe_unused version_proc_show(struct seq_file *m, void *v)
 {
        seq_printf(m, "driver:                  %s\n", TOSHIBA_ACPI_VERSION);
        seq_printf(m, "proc_interface:          %d\n", PROC_INTERFACE_VERSION);
@@ -1836,6 +1837,7 @@ static ssize_t kbd_backlight_mode_store(struct device *dev,
                        return ret;
 
                toshiba->kbd_mode = mode;
+               toshiba_acpi->kbd_mode = mode;
 
                /*
                 * Some laptop models with the second generation backlit
@@ -1852,7 +1854,7 @@ static ssize_t kbd_backlight_mode_store(struct device *dev,
                 * event via genetlink.
                 */
                if (toshiba->kbd_type == 2 &&
-                   !toshiba_acpi->kbd_event_generated)
+                   !toshiba->kbd_event_generated)
                        schedule_work(&kbd_bl_work);
        }
 
@@ -2413,16 +2415,21 @@ static const struct attribute_group toshiba_attr_group = {
 
 static void toshiba_acpi_kbd_bl_work(struct work_struct *work)
 {
-       struct acpi_device *acpi_dev = toshiba_acpi->acpi_dev;
-
        /* Update the sysfs entries */
-       if (sysfs_update_group(&acpi_dev->dev.kobj,
+       if (sysfs_update_group(&toshiba_acpi->acpi_dev->dev.kobj,
                               &toshiba_attr_group))
                pr_err("Unable to update sysfs entries\n");
 
+       /* Notify LED subsystem about keyboard backlight change */
+       if (toshiba_acpi->kbd_type == 2 &&
+           toshiba_acpi->kbd_mode != SCI_KBD_MODE_AUTO)
+               led_classdev_notify_brightness_hw_changed(&toshiba_acpi->kbd_led,
+                               (toshiba_acpi->kbd_mode == SCI_KBD_MODE_ON) ?
+                               LED_FULL : LED_OFF);
+
        /* Emulate the keyboard backlight event */
-       acpi_bus_generate_netlink_event(acpi_dev->pnp.device_class,
-                                       dev_name(&acpi_dev->dev),
+       acpi_bus_generate_netlink_event(toshiba_acpi->acpi_dev->pnp.device_class,
+                                       dev_name(&toshiba_acpi->acpi_dev->dev),
                                        0x92, 0);
 }
 
@@ -3119,9 +3126,12 @@ static int toshiba_acpi_add(struct acpi_device *acpi_dev)
        /*
         * Only register the LED if KBD illumination is supported
         * and the keyboard backlight operation mode is set to FN-Z
+        * or we detect a second gen keyboard backlight
         */
-       if (dev->kbd_illum_supported && dev->kbd_mode == SCI_KBD_MODE_FNZ) {
+       if (dev->kbd_illum_supported &&
+           (dev->kbd_mode == SCI_KBD_MODE_FNZ || dev->kbd_type == 2)) {
                dev->kbd_led.name = "toshiba::kbd_backlight";
+               dev->kbd_led.flags = LED_BRIGHT_HW_CHANGED;
                dev->kbd_led.max_brightness = 1;
                dev->kbd_led.brightness_set = toshiba_kbd_backlight_set;
                dev->kbd_led.brightness_get = toshiba_kbd_backlight_get;
@@ -3237,11 +3247,16 @@ static void toshiba_acpi_notify(struct acpi_device *acpi_dev, u32 event)
                pr_info("SATA power event received %x\n", event);
                break;
        case 0x92: /* Keyboard backlight mode changed */
-               toshiba_acpi->kbd_event_generated = true;
+               dev->kbd_event_generated = true;
                /* Update sysfs entries */
                if (sysfs_update_group(&acpi_dev->dev.kobj,
                                       &toshiba_attr_group))
                        pr_err("Unable to update sysfs entries\n");
+               /* Notify LED subsystem about keyboard backlight change */
+               if (dev->kbd_type == 2 && dev->kbd_mode != SCI_KBD_MODE_AUTO)
+                       led_classdev_notify_brightness_hw_changed(&dev->kbd_led,
+                                       (dev->kbd_mode == SCI_KBD_MODE_ON) ?
+                                       LED_FULL : LED_OFF);
                break;
        case 0x85: /* Unknown */
        case 0x8d: /* Unknown */
similarity index 70%
rename from drivers/platform/x86/silead_dmi.c
rename to drivers/platform/x86/touchscreen_dmi.c
index 853a7ce..cb204f9 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Silead touchscreen driver DMI based configuration code
+ * Touchscreen driver DMI based configuration code
  *
  * Copyright (c) 2017 Red Hat Inc.
  *
 #include <linux/property.h>
 #include <linux/string.h>
 
-struct silead_ts_dmi_data {
+struct ts_dmi_data {
        const char *acpi_name;
        const struct property_entry *properties;
 };
 
-static const struct property_entry cube_iwork8_air_props[] = {
-       PROPERTY_ENTRY_U32("touchscreen-size-x", 1660),
-       PROPERTY_ENTRY_U32("touchscreen-size-y", 900),
+/* NOTE: Please keep all entries sorted alphabetically */
+
+static const struct property_entry chuwi_hi8_props[] = {
+       PROPERTY_ENTRY_U32("touchscreen-size-x", 1665),
+       PROPERTY_ENTRY_U32("touchscreen-size-y", 1140),
        PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
-       PROPERTY_ENTRY_STRING("firmware-name", "gsl3670-cube-iwork8-air.fw"),
-       PROPERTY_ENTRY_U32("silead,max-fingers", 10),
+       PROPERTY_ENTRY_BOOL("silead,home-button"),
+       PROPERTY_ENTRY_STRING("firmware-name", "gsl1680-chuwi-hi8.fw"),
        { }
 };
 
-static const struct silead_ts_dmi_data cube_iwork8_air_data = {
+static const struct ts_dmi_data chuwi_hi8_data = {
+       .acpi_name      = "MSSL0001:00",
+       .properties     = chuwi_hi8_props,
+};
+
+static const struct property_entry chuwi_hi8_pro_props[] = {
+       PROPERTY_ENTRY_U32("touchscreen-size-x", 1728),
+       PROPERTY_ENTRY_U32("touchscreen-size-y", 1148),
+       PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
+       PROPERTY_ENTRY_STRING("firmware-name", "gsl3680-chuwi-hi8-pro.fw"),
+       PROPERTY_ENTRY_BOOL("silead,home-button"),
+       { }
+};
+
+static const struct ts_dmi_data chuwi_hi8_pro_data = {
        .acpi_name      = "MSSL1680:00",
-       .properties     = cube_iwork8_air_props,
+       .properties     = chuwi_hi8_pro_props,
 };
 
-static const struct property_entry jumper_ezpad_mini3_props[] = {
-       PROPERTY_ENTRY_U32("touchscreen-size-x", 1700),
-       PROPERTY_ENTRY_U32("touchscreen-size-y", 1150),
+static const struct property_entry chuwi_vi8_props[] = {
+       PROPERTY_ENTRY_U32("touchscreen-size-x", 1724),
+       PROPERTY_ENTRY_U32("touchscreen-size-y", 1140),
        PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
-       PROPERTY_ENTRY_STRING("firmware-name", "gsl3676-jumper-ezpad-mini3.fw"),
+       PROPERTY_ENTRY_STRING("firmware-name", "gsl3676-chuwi-vi8.fw"),
        PROPERTY_ENTRY_U32("silead,max-fingers", 10),
+       PROPERTY_ENTRY_BOOL("silead,home-button"),
        { }
 };
 
-static const struct silead_ts_dmi_data jumper_ezpad_mini3_data = {
-       .acpi_name      = "MSSL1680:00",
-       .properties     = jumper_ezpad_mini3_props,
+static const struct ts_dmi_data chuwi_vi8_data = {
+       .acpi_name      = "MSSL1680:00",
+       .properties     = chuwi_vi8_props,
 };
 
-static const struct property_entry jumper_ezpad_6_pro_props[] = {
-       PROPERTY_ENTRY_U32("touchscreen-size-x", 1980),
-       PROPERTY_ENTRY_U32("touchscreen-size-y", 1500),
-       PROPERTY_ENTRY_STRING("firmware-name", "gsl3692-jumper-ezpad-6-pro.fw"),
+static const struct property_entry chuwi_vi10_props[] = {
+       PROPERTY_ENTRY_U32("touchscreen-min-x", 0),
+       PROPERTY_ENTRY_U32("touchscreen-min-y", 4),
+       PROPERTY_ENTRY_U32("touchscreen-size-x", 1858),
+       PROPERTY_ENTRY_U32("touchscreen-size-y", 1280),
+       PROPERTY_ENTRY_STRING("firmware-name", "gsl3680-chuwi-vi10.fw"),
        PROPERTY_ENTRY_U32("silead,max-fingers", 10),
        PROPERTY_ENTRY_BOOL("silead,home-button"),
        { }
 };
 
-static const struct silead_ts_dmi_data jumper_ezpad_6_pro_data = {
+static const struct ts_dmi_data chuwi_vi10_data = {
+       .acpi_name      = "MSSL0002:00",
+       .properties     = chuwi_vi10_props,
+};
+
+static const struct property_entry connect_tablet9_props[] = {
+       PROPERTY_ENTRY_U32("touchscreen-min-x", 9),
+       PROPERTY_ENTRY_U32("touchscreen-min-y", 8),
+       PROPERTY_ENTRY_U32("touchscreen-size-x", 1664),
+       PROPERTY_ENTRY_U32("touchscreen-size-y", 878),
+       PROPERTY_ENTRY_BOOL("touchscreen-inverted-y"),
+       PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
+       PROPERTY_ENTRY_STRING("firmware-name", "gsl1680-connect-tablet9.fw"),
+       PROPERTY_ENTRY_U32("silead,max-fingers", 10),
+       { }
+};
+
+static const struct ts_dmi_data connect_tablet9_data = {
+       .acpi_name      = "MSSL1680:00",
+       .properties     = connect_tablet9_props,
+};
+
+static const struct property_entry cube_iwork8_air_props[] = {
+       PROPERTY_ENTRY_U32("touchscreen-size-x", 1660),
+       PROPERTY_ENTRY_U32("touchscreen-size-y", 900),
+       PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
+       PROPERTY_ENTRY_STRING("firmware-name", "gsl3670-cube-iwork8-air.fw"),
+       PROPERTY_ENTRY_U32("silead,max-fingers", 10),
+       { }
+};
+
+static const struct ts_dmi_data cube_iwork8_air_data = {
        .acpi_name      = "MSSL1680:00",
-       .properties     = jumper_ezpad_6_pro_props,
+       .properties     = cube_iwork8_air_props,
 };
 
-static const struct property_entry dexp_ursus_7w_props[] = {
-       PROPERTY_ENTRY_U32("touchscreen-size-x", 890),
-       PROPERTY_ENTRY_U32("touchscreen-size-y", 630),
-       PROPERTY_ENTRY_STRING("firmware-name", "gsl1686-dexp-ursus-7w.fw"),
+static const struct property_entry cube_knote_i1101_props[] = {
+       PROPERTY_ENTRY_U32("touchscreen-min-x", 20),
+       PROPERTY_ENTRY_U32("touchscreen-min-y",  22),
+       PROPERTY_ENTRY_U32("touchscreen-size-x", 1961),
+       PROPERTY_ENTRY_U32("touchscreen-size-y", 1513),
+       PROPERTY_ENTRY_STRING("firmware-name", "gsl3692-cube-knote-i1101.fw"),
        PROPERTY_ENTRY_U32("silead,max-fingers", 10),
        PROPERTY_ENTRY_BOOL("silead,home-button"),
        { }
 };
 
-static const struct silead_ts_dmi_data dexp_ursus_7w_data = {
+static const struct ts_dmi_data cube_knote_i1101_data = {
        .acpi_name      = "MSSL1680:00",
-       .properties     = dexp_ursus_7w_props,
+       .properties     = cube_knote_i1101_props,
 };
 
-static const struct property_entry surftab_twin_10_1_st10432_8_props[] = {
-       PROPERTY_ENTRY_U32("touchscreen-size-x", 1900),
-       PROPERTY_ENTRY_U32("touchscreen-size-y", 1280),
-       PROPERTY_ENTRY_U32("touchscreen-inverted-y", 1),
-       PROPERTY_ENTRY_STRING("firmware-name",
-                             "gsl3670-surftab-twin-10-1-st10432-8.fw"),
+static const struct property_entry dexp_ursus_7w_props[] = {
+       PROPERTY_ENTRY_U32("touchscreen-size-x", 890),
+       PROPERTY_ENTRY_U32("touchscreen-size-y", 630),
+       PROPERTY_ENTRY_STRING("firmware-name", "gsl1686-dexp-ursus-7w.fw"),
        PROPERTY_ENTRY_U32("silead,max-fingers", 10),
+       PROPERTY_ENTRY_BOOL("silead,home-button"),
        { }
 };
 
-static const struct silead_ts_dmi_data surftab_twin_10_1_st10432_8_data = {
+static const struct ts_dmi_data dexp_ursus_7w_data = {
        .acpi_name      = "MSSL1680:00",
-       .properties     = surftab_twin_10_1_st10432_8_props,
+       .properties     = dexp_ursus_7w_props,
 };
 
-static const struct property_entry surftab_wintron70_st70416_6_props[] = {
-       PROPERTY_ENTRY_U32("touchscreen-size-x", 884),
-       PROPERTY_ENTRY_U32("touchscreen-size-y", 632),
+static const struct property_entry digma_citi_e200_props[] = {
+       PROPERTY_ENTRY_U32("touchscreen-size-x", 1980),
+       PROPERTY_ENTRY_U32("touchscreen-size-y", 1500),
+       PROPERTY_ENTRY_BOOL("touchscreen-inverted-y"),
        PROPERTY_ENTRY_STRING("firmware-name",
-                             "gsl1686-surftab-wintron70-st70416-6.fw"),
+                             "gsl1686-digma_citi_e200.fw"),
        PROPERTY_ENTRY_U32("silead,max-fingers", 10),
        PROPERTY_ENTRY_BOOL("silead,home-button"),
        { }
 };
 
-static const struct silead_ts_dmi_data surftab_wintron70_st70416_6_data = {
+static const struct ts_dmi_data digma_citi_e200_data = {
        .acpi_name      = "MSSL1680:00",
-       .properties     = surftab_wintron70_st70416_6_props,
+       .properties     = digma_citi_e200_props,
 };
 
 static const struct property_entry gp_electronic_t701_props[] = {
@@ -121,162 +173,181 @@ static const struct property_entry gp_electronic_t701_props[] = {
        { }
 };
 
-static const struct silead_ts_dmi_data gp_electronic_t701_data = {
+static const struct ts_dmi_data gp_electronic_t701_data = {
        .acpi_name      = "MSSL1680:00",
        .properties     = gp_electronic_t701_props,
 };
 
-static const struct property_entry pipo_w2s_props[] = {
-       PROPERTY_ENTRY_U32("touchscreen-size-x", 1660),
-       PROPERTY_ENTRY_U32("touchscreen-size-y", 880),
-       PROPERTY_ENTRY_BOOL("touchscreen-inverted-x"),
+static const struct property_entry itworks_tw891_props[] = {
+       PROPERTY_ENTRY_U32("touchscreen-size-x", 1600),
+       PROPERTY_ENTRY_U32("touchscreen-size-y", 890),
+       PROPERTY_ENTRY_BOOL("touchscreen-inverted-y"),
        PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
-       PROPERTY_ENTRY_STRING("firmware-name",
-                             "gsl1680-pipo-w2s.fw"),
+       PROPERTY_ENTRY_STRING("firmware-name", "gsl3670-itworks-tw891.fw"),
        { }
 };
 
-static const struct silead_ts_dmi_data pipo_w2s_data = {
+static const struct ts_dmi_data itworks_tw891_data = {
        .acpi_name      = "MSSL1680:00",
-       .properties     = pipo_w2s_props,
+       .properties     = itworks_tw891_props,
 };
 
-static const struct property_entry pov_mobii_wintab_p800w_v20_props[] = {
-       PROPERTY_ENTRY_U32("touchscreen-min-x", 32),
-       PROPERTY_ENTRY_U32("touchscreen-min-y", 16),
-       PROPERTY_ENTRY_U32("touchscreen-size-x", 1692),
-       PROPERTY_ENTRY_U32("touchscreen-size-y", 1146),
-       PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
-       PROPERTY_ENTRY_STRING("firmware-name",
-                             "gsl3680-pov-mobii-wintab-p800w-v20.fw"),
+static const struct property_entry jumper_ezpad_6_pro_props[] = {
+       PROPERTY_ENTRY_U32("touchscreen-size-x", 1980),
+       PROPERTY_ENTRY_U32("touchscreen-size-y", 1500),
+       PROPERTY_ENTRY_STRING("firmware-name", "gsl3692-jumper-ezpad-6-pro.fw"),
        PROPERTY_ENTRY_U32("silead,max-fingers", 10),
        PROPERTY_ENTRY_BOOL("silead,home-button"),
        { }
 };
 
-static const struct silead_ts_dmi_data pov_mobii_wintab_p800w_v20_data = {
+static const struct ts_dmi_data jumper_ezpad_6_pro_data = {
        .acpi_name      = "MSSL1680:00",
-       .properties     = pov_mobii_wintab_p800w_v20_props,
+       .properties     = jumper_ezpad_6_pro_props,
 };
 
-static const struct property_entry pov_mobii_wintab_p800w_v21_props[] = {
-       PROPERTY_ENTRY_U32("touchscreen-size-x", 1800),
+static const struct property_entry jumper_ezpad_mini3_props[] = {
+       PROPERTY_ENTRY_U32("touchscreen-size-x", 1700),
        PROPERTY_ENTRY_U32("touchscreen-size-y", 1150),
        PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
-       PROPERTY_ENTRY_STRING("firmware-name",
-                             "gsl3692-pov-mobii-wintab-p800w.fw"),
-       PROPERTY_ENTRY_BOOL("silead,home-button"),
+       PROPERTY_ENTRY_STRING("firmware-name", "gsl3676-jumper-ezpad-mini3.fw"),
+       PROPERTY_ENTRY_U32("silead,max-fingers", 10),
        { }
 };
 
-static const struct silead_ts_dmi_data pov_mobii_wintab_p800w_v21_data = {
+static const struct ts_dmi_data jumper_ezpad_mini3_data = {
        .acpi_name      = "MSSL1680:00",
-       .properties     = pov_mobii_wintab_p800w_v21_props,
+       .properties     = jumper_ezpad_mini3_props,
 };
 
-static const struct property_entry itworks_tw891_props[] = {
-       PROPERTY_ENTRY_U32("touchscreen-size-x", 1600),
-       PROPERTY_ENTRY_U32("touchscreen-size-y", 890),
+static const struct property_entry onda_obook_20_plus_props[] = {
+       PROPERTY_ENTRY_U32("touchscreen-size-x", 1728),
+       PROPERTY_ENTRY_U32("touchscreen-size-y", 1148),
+       PROPERTY_ENTRY_BOOL("touchscreen-inverted-x"),
        PROPERTY_ENTRY_BOOL("touchscreen-inverted-y"),
        PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
-       PROPERTY_ENTRY_STRING("firmware-name", "gsl3670-itworks-tw891.fw"),
+       PROPERTY_ENTRY_STRING("firmware-name", "gsl3676-onda-obook-20-plus.fw"),
+       PROPERTY_ENTRY_U32("silead,max-fingers", 10),
+       PROPERTY_ENTRY_BOOL("silead,home-button"),
        { }
 };
 
-static const struct silead_ts_dmi_data itworks_tw891_data = {
+static const struct ts_dmi_data onda_obook_20_plus_data = {
        .acpi_name      = "MSSL1680:00",
-       .properties     = itworks_tw891_props,
+       .properties     = onda_obook_20_plus_props,
 };
 
-static const struct property_entry chuwi_hi8_pro_props[] = {
-       PROPERTY_ENTRY_U32("touchscreen-size-x", 1728),
-       PROPERTY_ENTRY_U32("touchscreen-size-y", 1148),
+static const struct property_entry onda_v820w_32g_props[] = {
+       PROPERTY_ENTRY_U32("touchscreen-size-x", 1665),
+       PROPERTY_ENTRY_U32("touchscreen-size-y", 1140),
        PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
-       PROPERTY_ENTRY_STRING("firmware-name", "gsl3680-chuwi-hi8-pro.fw"),
+       PROPERTY_ENTRY_STRING("firmware-name",
+                             "gsl1680-onda-v820w-32g.fw"),
+       PROPERTY_ENTRY_U32("silead,max-fingers", 10),
        PROPERTY_ENTRY_BOOL("silead,home-button"),
        { }
 };
 
-static const struct silead_ts_dmi_data chuwi_hi8_pro_data = {
+static const struct ts_dmi_data onda_v820w_32g_data = {
        .acpi_name      = "MSSL1680:00",
-       .properties     = chuwi_hi8_pro_props,
+       .properties     = onda_v820w_32g_props,
 };
 
-static const struct property_entry digma_citi_e200_props[] = {
-       PROPERTY_ENTRY_U32("touchscreen-size-x", 1980),
-       PROPERTY_ENTRY_U32("touchscreen-size-y", 1500),
-       PROPERTY_ENTRY_BOOL("touchscreen-inverted-y"),
+static const struct property_entry onda_v891w_v1_props[] = {
+       PROPERTY_ENTRY_U32("touchscreen-min-x", 46),
+       PROPERTY_ENTRY_U32("touchscreen-min-y",  8),
+       PROPERTY_ENTRY_U32("touchscreen-size-x", 1676),
+       PROPERTY_ENTRY_U32("touchscreen-size-y", 1130),
        PROPERTY_ENTRY_STRING("firmware-name",
-                             "gsl1686-digma_citi_e200.fw"),
+                             "gsl3680-onda-v891w-v1.fw"),
        PROPERTY_ENTRY_U32("silead,max-fingers", 10),
        PROPERTY_ENTRY_BOOL("silead,home-button"),
        { }
 };
 
-static const struct silead_ts_dmi_data digma_citi_e200_data = {
+static const struct ts_dmi_data onda_v891w_v1_data = {
        .acpi_name      = "MSSL1680:00",
-       .properties     = digma_citi_e200_props,
+       .properties     = onda_v891w_v1_props,
 };
 
-static const struct property_entry onda_obook_20_plus_props[] = {
-       PROPERTY_ENTRY_U32("touchscreen-size-x", 1728),
-       PROPERTY_ENTRY_U32("touchscreen-size-y", 1148),
-       PROPERTY_ENTRY_BOOL("touchscreen-inverted-x"),
+static const struct property_entry onda_v891w_v3_props[] = {
+       PROPERTY_ENTRY_U32("touchscreen-min-x", 35),
+       PROPERTY_ENTRY_U32("touchscreen-min-y", 15),
+       PROPERTY_ENTRY_U32("touchscreen-size-x", 1625),
+       PROPERTY_ENTRY_U32("touchscreen-size-y", 1135),
        PROPERTY_ENTRY_BOOL("touchscreen-inverted-y"),
-       PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
-       PROPERTY_ENTRY_STRING("firmware-name", "gsl3676-onda-obook-20-plus.fw"),
+       PROPERTY_ENTRY_STRING("firmware-name",
+                             "gsl3676-onda-v891w-v3.fw"),
        PROPERTY_ENTRY_U32("silead,max-fingers", 10),
        PROPERTY_ENTRY_BOOL("silead,home-button"),
        { }
 };
 
-static const struct silead_ts_dmi_data onda_obook_20_plus_data = {
+static const struct ts_dmi_data onda_v891w_v3_data = {
        .acpi_name      = "MSSL1680:00",
-       .properties     = onda_obook_20_plus_props,
+       .properties     = onda_v891w_v3_props,
 };
 
-static const struct property_entry chuwi_hi8_props[] = {
-       PROPERTY_ENTRY_U32("touchscreen-size-x", 1665),
-       PROPERTY_ENTRY_U32("touchscreen-size-y", 1140),
+static const struct property_entry pipo_w2s_props[] = {
+       PROPERTY_ENTRY_U32("touchscreen-size-x", 1660),
+       PROPERTY_ENTRY_U32("touchscreen-size-y", 880),
+       PROPERTY_ENTRY_BOOL("touchscreen-inverted-x"),
        PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
-       PROPERTY_ENTRY_BOOL("silead,home-button"),
-       PROPERTY_ENTRY_STRING("firmware-name", "gsl1680-chuwi-hi8.fw"),
+       PROPERTY_ENTRY_STRING("firmware-name",
+                             "gsl1680-pipo-w2s.fw"),
        { }
 };
 
-static const struct silead_ts_dmi_data chuwi_hi8_data = {
-       .acpi_name      = "MSSL0001:00",
-       .properties     = chuwi_hi8_props,
+static const struct ts_dmi_data pipo_w2s_data = {
+       .acpi_name      = "MSSL1680:00",
+       .properties     = pipo_w2s_props,
 };
 
-static const struct property_entry chuwi_vi8_props[] = {
-       PROPERTY_ENTRY_U32("touchscreen-size-x", 1724),
-       PROPERTY_ENTRY_U32("touchscreen-size-y", 1140),
+static const struct property_entry pov_mobii_wintab_p800w_v20_props[] = {
+       PROPERTY_ENTRY_U32("touchscreen-min-x", 32),
+       PROPERTY_ENTRY_U32("touchscreen-min-y", 16),
+       PROPERTY_ENTRY_U32("touchscreen-size-x", 1692),
+       PROPERTY_ENTRY_U32("touchscreen-size-y", 1146),
        PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
-       PROPERTY_ENTRY_STRING("firmware-name", "gsl3676-chuwi-vi8.fw"),
+       PROPERTY_ENTRY_STRING("firmware-name",
+                             "gsl3680-pov-mobii-wintab-p800w-v20.fw"),
        PROPERTY_ENTRY_U32("silead,max-fingers", 10),
        PROPERTY_ENTRY_BOOL("silead,home-button"),
        { }
 };
 
-static const struct silead_ts_dmi_data chuwi_vi8_data = {
-       .acpi_name      = "MSSL1680:00",
-       .properties     = chuwi_vi8_props,
+static const struct ts_dmi_data pov_mobii_wintab_p800w_v20_data = {
+       .acpi_name      = "MSSL1680:00",
+       .properties     = pov_mobii_wintab_p800w_v20_props,
 };
 
-static const struct property_entry trekstor_primebook_c13_props[] = {
-       PROPERTY_ENTRY_U32("touchscreen-size-x", 2624),
-       PROPERTY_ENTRY_U32("touchscreen-size-y", 1920),
+static const struct property_entry pov_mobii_wintab_p800w_v21_props[] = {
+       PROPERTY_ENTRY_U32("touchscreen-size-x", 1800),
+       PROPERTY_ENTRY_U32("touchscreen-size-y", 1150),
+       PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
        PROPERTY_ENTRY_STRING("firmware-name",
-                             "gsl1680-trekstor-primebook-c13.fw"),
+                             "gsl3692-pov-mobii-wintab-p800w.fw"),
+       PROPERTY_ENTRY_BOOL("silead,home-button"),
+       { }
+};
+
+static const struct ts_dmi_data pov_mobii_wintab_p800w_v21_data = {
+       .acpi_name      = "MSSL1680:00",
+       .properties     = pov_mobii_wintab_p800w_v21_props,
+};
+
+static const struct property_entry teclast_x3_plus_props[] = {
+       PROPERTY_ENTRY_U32("touchscreen-size-x", 1980),
+       PROPERTY_ENTRY_U32("touchscreen-size-y", 1500),
+       PROPERTY_ENTRY_STRING("firmware-name", "gsl1680-teclast-x3-plus.fw"),
        PROPERTY_ENTRY_U32("silead,max-fingers", 10),
        PROPERTY_ENTRY_BOOL("silead,home-button"),
        { }
 };
 
-static const struct silead_ts_dmi_data trekstor_primebook_c13_data = {
+static const struct ts_dmi_data teclast_x3_plus_data = {
        .acpi_name      = "MSSL1680:00",
-       .properties     = trekstor_primebook_c13_props,
+       .properties     = teclast_x3_plus_props,
 };
 
 static const struct property_entry teclast_x98plus2_props[] = {
@@ -290,156 +361,162 @@ static const struct property_entry teclast_x98plus2_props[] = {
        { }
 };
 
-static const struct silead_ts_dmi_data teclast_x98plus2_data = {
+static const struct ts_dmi_data teclast_x98plus2_data = {
        .acpi_name      = "MSSL1680:00",
        .properties     = teclast_x98plus2_props,
 };
 
-static const struct property_entry teclast_x3_plus_props[] = {
-       PROPERTY_ENTRY_U32("touchscreen-size-x", 1980),
-       PROPERTY_ENTRY_U32("touchscreen-size-y", 1500),
-       PROPERTY_ENTRY_STRING("firmware-name", "gsl1680-teclast-x3-plus.fw"),
+static const struct property_entry trekstor_primebook_c13_props[] = {
+       PROPERTY_ENTRY_U32("touchscreen-size-x", 2624),
+       PROPERTY_ENTRY_U32("touchscreen-size-y", 1920),
+       PROPERTY_ENTRY_STRING("firmware-name",
+                             "gsl1680-trekstor-primebook-c13.fw"),
        PROPERTY_ENTRY_U32("silead,max-fingers", 10),
        PROPERTY_ENTRY_BOOL("silead,home-button"),
        { }
 };
 
-static const struct silead_ts_dmi_data teclast_x3_plus_data = {
+static const struct ts_dmi_data trekstor_primebook_c13_data = {
        .acpi_name      = "MSSL1680:00",
-       .properties     = teclast_x3_plus_props,
+       .properties     = trekstor_primebook_c13_props,
 };
 
-static const struct property_entry onda_v891w_v1_props[] = {
-       PROPERTY_ENTRY_U32("touchscreen-min-x", 46),
-       PROPERTY_ENTRY_U32("touchscreen-min-y",  8),
-       PROPERTY_ENTRY_U32("touchscreen-size-x", 1676),
-       PROPERTY_ENTRY_U32("touchscreen-size-y", 1130),
+static const struct property_entry trekstor_surftab_twin_10_1_props[] = {
+       PROPERTY_ENTRY_U32("touchscreen-size-x", 1900),
+       PROPERTY_ENTRY_U32("touchscreen-size-y", 1280),
+       PROPERTY_ENTRY_U32("touchscreen-inverted-y", 1),
        PROPERTY_ENTRY_STRING("firmware-name",
-                             "gsl3680-onda-v891w-v1.fw"),
+                             "gsl3670-surftab-twin-10-1-st10432-8.fw"),
+       PROPERTY_ENTRY_U32("silead,max-fingers", 10),
+       { }
+};
+
+static const struct ts_dmi_data trekstor_surftab_twin_10_1_data = {
+       .acpi_name      = "MSSL1680:00",
+       .properties     = trekstor_surftab_twin_10_1_props,
+};
+
+static const struct property_entry trekstor_surftab_wintron70_props[] = {
+       PROPERTY_ENTRY_U32("touchscreen-size-x", 884),
+       PROPERTY_ENTRY_U32("touchscreen-size-y", 632),
+       PROPERTY_ENTRY_STRING("firmware-name",
+                             "gsl1686-surftab-wintron70-st70416-6.fw"),
        PROPERTY_ENTRY_U32("silead,max-fingers", 10),
        PROPERTY_ENTRY_BOOL("silead,home-button"),
        { }
 };
 
-static const struct silead_ts_dmi_data onda_v891w_v1_data = {
+static const struct ts_dmi_data trekstor_surftab_wintron70_data = {
        .acpi_name      = "MSSL1680:00",
-       .properties     = onda_v891w_v1_props,
+       .properties     = trekstor_surftab_wintron70_props,
 };
 
-static const struct dmi_system_id silead_ts_dmi_table[] = {
+/* NOTE: Please keep this table sorted alphabetically */
+static const struct dmi_system_id touchscreen_dmi_table[] = {
        {
-               /* CUBE iwork8 Air */
-               .driver_data = (void *)&cube_iwork8_air_data,
+               /* Chuwi Hi8 */
+               .driver_data = (void *)&chuwi_hi8_data,
                .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "cube"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "i1-TF"),
-                       DMI_MATCH(DMI_BOARD_NAME, "Cherry Trail CR"),
+                       DMI_MATCH(DMI_SYS_VENDOR, "ilife"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "S806"),
                },
        },
        {
-               /* Jumper EZpad mini3 */
-               .driver_data = (void *)&jumper_ezpad_mini3_data,
+               /* Chuwi Hi8 (H1D_S806_206) */
+               .driver_data = (void *)&chuwi_hi8_data,
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "Insyde"),
-                       /* jumperx.T87.KFBNEEA02 with the version-nr dropped */
-                       DMI_MATCH(DMI_BIOS_VERSION, "jumperx.T87.KFBNEEA"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "BayTrail"),
+                       DMI_MATCH(DMI_BIOS_VERSION, "H1D_S806_206"),
                },
        },
        {
-               /* Jumper EZpad 6 Pro */
-               .driver_data = (void *)&jumper_ezpad_6_pro_data,
+               /* Chuwi Hi8 Pro (CWI513) */
+               .driver_data = (void *)&chuwi_hi8_pro_data,
                .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "Jumper"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "EZpad"),
-                       DMI_MATCH(DMI_BIOS_VERSION, "5.12"),
-                       /* Above matches are too generic, add bios-date match */
-                       DMI_MATCH(DMI_BIOS_DATE, "08/18/2017"),
+                       DMI_MATCH(DMI_SYS_VENDOR, "Hampoo"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "X1D3_C806N"),
                },
        },
        {
-               /* DEXP Ursus 7W */
-               .driver_data = (void *)&dexp_ursus_7w_data,
+               /* Chuwi Vi8 (CWI506) */
+               .driver_data = (void *)&chuwi_vi8_data,
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "Insyde"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "7W"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "i86"),
+                       DMI_MATCH(DMI_BIOS_VERSION, "CHUWI.D86JLBNR"),
                },
        },
        {
-               /* TrekStor SurfTab twin 10.1 ST10432-8 */
-               .driver_data = (void *)&surftab_twin_10_1_st10432_8_data,
+               /* Chuwi Vi10 (CWI505) */
+               .driver_data = (void *)&chuwi_vi10_data,
                .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "TrekStor"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "SurfTab twin 10.1"),
+                       DMI_MATCH(DMI_BOARD_VENDOR, "Hampoo"),
+                       DMI_MATCH(DMI_BOARD_NAME, "BYT-PF02"),
+                       DMI_MATCH(DMI_SYS_VENDOR, "ilife"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "S165"),
                },
        },
        {
-               /* Trekstor Surftab Wintron 7.0 ST70416-6 */
-               .driver_data = (void *)&surftab_wintron70_st70416_6_data,
+               /* Connect Tablet 9 */
+               .driver_data = (void *)&connect_tablet9_data,
                .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "Insyde"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "ST70416-6"),
-                       /* Exact match, different versions need different fw */
-                       DMI_MATCH(DMI_BIOS_VERSION, "TREK.G.WI71C.JGBMRBA04"),
+                       DMI_MATCH(DMI_SYS_VENDOR, "Connect"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Tablet 9"),
                },
        },
        {
-               /* Trekstor Surftab Wintron 7.0 ST70416-6, newer BIOS */
-               .driver_data = (void *)&surftab_wintron70_st70416_6_data,
+               /* CUBE iwork8 Air */
+               .driver_data = (void *)&cube_iwork8_air_data,
                .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "TrekStor"),
-                       DMI_MATCH(DMI_PRODUCT_NAME,
-                                            "SurfTab wintron 7.0 ST70416-6"),
-                       /* Exact match, different versions need different fw */
-                       DMI_MATCH(DMI_BIOS_VERSION, "TREK.G.WI71C.JGBMRBA05"),
+                       DMI_MATCH(DMI_SYS_VENDOR, "cube"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "i1-TF"),
+                       DMI_MATCH(DMI_BOARD_NAME, "Cherry Trail CR"),
                },
        },
        {
-               /* Ployer Momo7w (same hardware as the Trekstor ST70416-6) */
-               .driver_data = (void *)&surftab_wintron70_st70416_6_data,
+               /* Cube KNote i1101 */
+               .driver_data = (void *)&cube_knote_i1101_data,
                .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "Shenzhen PLOYER"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "MOMO7W"),
-                       /* Exact match, different versions need different fw */
-                       DMI_MATCH(DMI_BIOS_VERSION, "MOMO.G.WI71C.MABMRBA02"),
+                       DMI_MATCH(DMI_BOARD_VENDOR, "Hampoo"),
+                       DMI_MATCH(DMI_BOARD_NAME, "L1W6_I1101"),
+                       DMI_MATCH(DMI_SYS_VENDOR, "ALLDOCUBE"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "i1101"),
                },
        },
        {
-               /* GP-electronic T701 */
-               .driver_data = (void *)&gp_electronic_t701_data,
+               /* DEXP Ursus 7W */
+               .driver_data = (void *)&dexp_ursus_7w_data,
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "Insyde"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "T701"),
-                       DMI_MATCH(DMI_BIOS_VERSION, "BYT70A.YNCHENG.WIN.007"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "7W"),
                },
        },
        {
-               /* Pipo W2S */
-               .driver_data = (void *)&pipo_w2s_data,
+               /* Digma Citi E200 */
+               .driver_data = (void *)&digma_citi_e200_data,
                .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "PIPO"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "W2S"),
+                       DMI_MATCH(DMI_SYS_VENDOR, "Digma"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "CITI E200"),
+                       DMI_MATCH(DMI_BOARD_NAME, "Cherry Trail CR"),
                },
        },
        {
-               /* Point of View mobii wintab p800w (v2.0) */
-               .driver_data = (void *)&pov_mobii_wintab_p800w_v20_data,
+               /* GP-electronic T701 */
+               .driver_data = (void *)&gp_electronic_t701_data,
                .matches = {
-                       DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
-                       DMI_MATCH(DMI_BOARD_NAME, "Aptio CRB"),
-                       DMI_MATCH(DMI_BIOS_VERSION, "3BAIR1014"),
-                       /* Above matches are too generic, add bios-date match */
-                       DMI_MATCH(DMI_BIOS_DATE, "10/24/2014"),
+                       DMI_MATCH(DMI_SYS_VENDOR, "Insyde"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "T701"),
+                       DMI_MATCH(DMI_BIOS_VERSION, "BYT70A.YNCHENG.WIN.007"),
                },
        },
        {
-               /* Point of View mobii wintab p800w (v2.1) */
-               .driver_data = (void *)&pov_mobii_wintab_p800w_v21_data,
+               /* I.T.Works TW701 (same hardware as the Trekstor ST70416-6) */
+               .driver_data = (void *)&trekstor_surftab_wintron70_data,
                .matches = {
-                       DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
-                       DMI_MATCH(DMI_BOARD_NAME, "Aptio CRB"),
-                       DMI_MATCH(DMI_BIOS_VERSION, "3BAIR1013"),
-                       /* Above matches are too generic, add bios-date match */
-                       DMI_MATCH(DMI_BIOS_DATE, "08/22/2014"),
+                       DMI_MATCH(DMI_SYS_VENDOR, "Insyde"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "i71c"),
+                       DMI_MATCH(DMI_BIOS_VERSION, "itWORKS.G.WI71C.JGBMRB"),
                },
        },
        {
@@ -451,20 +528,23 @@ static const struct dmi_system_id silead_ts_dmi_table[] = {
                },
        },
        {
-               /* Chuwi Hi8 Pro */
-               .driver_data = (void *)&chuwi_hi8_pro_data,
+               /* Jumper EZpad 6 Pro */
+               .driver_data = (void *)&jumper_ezpad_6_pro_data,
                .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "Hampoo"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "X1D3_C806N"),
+                       DMI_MATCH(DMI_SYS_VENDOR, "Jumper"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "EZpad"),
+                       DMI_MATCH(DMI_BIOS_VERSION, "5.12"),
+                       /* Above matches are too generic, add bios-date match */
+                       DMI_MATCH(DMI_BIOS_DATE, "08/18/2017"),
                },
        },
        {
-               /* Digma Citi E200 */
-               .driver_data = (void *)&digma_citi_e200_data,
+               /* Jumper EZpad mini3 */
+               .driver_data = (void *)&jumper_ezpad_mini3_data,
                .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "Digma"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "CITI E200"),
-                       DMI_MATCH(DMI_BOARD_NAME, "Cherry Trail CR"),
+                       DMI_MATCH(DMI_SYS_VENDOR, "Insyde"),
+                       /* jumperx.T87.KFBNEEA02 with the version-nr dropped */
+                       DMI_MATCH(DMI_BIOS_VERSION, "jumperx.T87.KFBNEEA"),
                },
        },
        {
@@ -476,45 +556,71 @@ static const struct dmi_system_id silead_ts_dmi_table[] = {
                },
        },
        {
-               /* Chuwi Hi8 */
-               .driver_data = (void *)&chuwi_hi8_data,
+               /* ONDA V820w DualOS */
+               .driver_data = (void *)&onda_v820w_32g_data,
                .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "ilife"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "S806"),
+                       DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "ONDA"),
+                       DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "V820w DualOS")
                },
        },
        {
-               /* Chuwi Hi8 (H1D_S806_206) */
-               .driver_data = (void *)&chuwi_hi8_data,
+               /* ONDA V891w revision P891WBEBV1B00 aka v1 */
+               .driver_data = (void *)&onda_v891w_v1_data,
                .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "Insyde"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "BayTrail"),
-                       DMI_MATCH(DMI_BIOS_VERSION, "H1D_S806_206"),
+                       DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "ONDA"),
+                       DMI_EXACT_MATCH(DMI_BOARD_NAME, "ONDA Tablet"),
+                       DMI_EXACT_MATCH(DMI_BOARD_VERSION, "V001"),
+                       /* Exact match, different versions need different fw */
+                       DMI_EXACT_MATCH(DMI_BIOS_VERSION, "ONDA.W89EBBN08"),
                },
        },
        {
-               /* Chuwi Vi8 (CWI506) */
-               .driver_data = (void *)&chuwi_vi8_data,
+               /* ONDA V891w Dual OS P891DCF2V1A01274 64GB */
+               .driver_data = (void *)&onda_v891w_v3_data,
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "Insyde"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "i86"),
-                       DMI_MATCH(DMI_BIOS_VERSION, "CHUWI.D86JLBNR"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "ONDA Tablet"),
+                       DMI_MATCH(DMI_BIOS_VERSION, "ONDA.D890HBBNR0A"),
                },
        },
        {
-               /* Trekstor Primebook C13 */
-               .driver_data = (void *)&trekstor_primebook_c13_data,
+               /* Pipo W2S */
+               .driver_data = (void *)&pipo_w2s_data,
                .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "TREKSTOR"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "Primebook C13"),
+                       DMI_MATCH(DMI_SYS_VENDOR, "PIPO"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "W2S"),
                },
        },
        {
-               /* Teclast X98 Plus II */
-               .driver_data = (void *)&teclast_x98plus2_data,
+               /* Ployer Momo7w (same hardware as the Trekstor ST70416-6) */
+               .driver_data = (void *)&trekstor_surftab_wintron70_data,
                .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "TECLAST"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "X98 Plus II"),
+                       DMI_MATCH(DMI_SYS_VENDOR, "Shenzhen PLOYER"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "MOMO7W"),
+                       /* Exact match, different versions need different fw */
+                       DMI_MATCH(DMI_BIOS_VERSION, "MOMO.G.WI71C.MABMRBA02"),
+               },
+       },
+       {
+               /* Point of View mobii wintab p800w (v2.0) */
+               .driver_data = (void *)&pov_mobii_wintab_p800w_v20_data,
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
+                       DMI_MATCH(DMI_BOARD_NAME, "Aptio CRB"),
+                       DMI_MATCH(DMI_BIOS_VERSION, "3BAIR1014"),
+                       /* Above matches are too generic, add bios-date match */
+                       DMI_MATCH(DMI_BIOS_DATE, "10/24/2014"),
+               },
+       },
+       {
+               /* Point of View mobii wintab p800w (v2.1) */
+               .driver_data = (void *)&pov_mobii_wintab_p800w_v21_data,
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
+                       DMI_MATCH(DMI_BOARD_NAME, "Aptio CRB"),
+                       DMI_MATCH(DMI_BIOS_VERSION, "3BAIR1013"),
+                       /* Above matches are too generic, add bios-date match */
+                       DMI_MATCH(DMI_BIOS_DATE, "08/22/2014"),
                },
        },
        {
@@ -527,52 +633,77 @@ static const struct dmi_system_id silead_ts_dmi_table[] = {
                },
        },
        {
-               /* I.T.Works TW701 */
-               .driver_data = (void *)&surftab_wintron70_st70416_6_data,
+               /* Teclast X98 Plus II */
+               .driver_data = (void *)&teclast_x98plus2_data,
                .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "Insyde"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "i71c"),
-                       DMI_MATCH(DMI_BIOS_VERSION, "itWORKS.G.WI71C.JGBMRB"),
+                       DMI_MATCH(DMI_SYS_VENDOR, "TECLAST"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "X98 Plus II"),
                },
        },
        {
-               /* Yours Y8W81, same case and touchscreen as Chuwi Vi8 */
-               .driver_data = (void *)&chuwi_vi8_data,
+               /* Trekstor Primebook C13 */
+               .driver_data = (void *)&trekstor_primebook_c13_data,
                .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "YOURS"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "Y8W81"),
+                       DMI_MATCH(DMI_SYS_VENDOR, "TREKSTOR"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Primebook C13"),
                },
        },
        {
-               /* ONDA V891w revision P891WBEBV1B00 aka v1 */
-               .driver_data = (void *)&onda_v891w_v1_data,
+               /* TrekStor SurfTab twin 10.1 ST10432-8 */
+               .driver_data = (void *)&trekstor_surftab_twin_10_1_data,
                .matches = {
-                       DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "ONDA"),
-                       DMI_EXACT_MATCH(DMI_BOARD_NAME, "ONDA Tablet"),
-                       DMI_EXACT_MATCH(DMI_BOARD_VERSION, "V001"),
+                       DMI_MATCH(DMI_SYS_VENDOR, "TrekStor"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "SurfTab twin 10.1"),
+               },
+       },
+       {
+               /* Trekstor Surftab Wintron 7.0 ST70416-6 */
+               .driver_data = (void *)&trekstor_surftab_wintron70_data,
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Insyde"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "ST70416-6"),
                        /* Exact match, different versions need different fw */
-                       DMI_EXACT_MATCH(DMI_BIOS_VERSION, "ONDA.W89EBBN08"),
+                       DMI_MATCH(DMI_BIOS_VERSION, "TREK.G.WI71C.JGBMRBA04"),
+               },
+       },
+       {
+               /* Trekstor Surftab Wintron 7.0 ST70416-6, newer BIOS */
+               .driver_data = (void *)&trekstor_surftab_wintron70_data,
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "TrekStor"),
+                       DMI_MATCH(DMI_PRODUCT_NAME,
+                                            "SurfTab wintron 7.0 ST70416-6"),
+                       /* Exact match, different versions need different fw */
+                       DMI_MATCH(DMI_BIOS_VERSION, "TREK.G.WI71C.JGBMRBA05"),
+               },
+       },
+       {
+               /* Yours Y8W81, same case and touchscreen as Chuwi Vi8 */
+               .driver_data = (void *)&chuwi_vi8_data,
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "YOURS"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Y8W81"),
                },
        },
        { },
 };
 
-static const struct silead_ts_dmi_data *silead_ts_data;
+static const struct ts_dmi_data *ts_data;
 
-static void silead_ts_dmi_add_props(struct i2c_client *client)
+static void ts_dmi_add_props(struct i2c_client *client)
 {
        struct device *dev = &client->dev;
        int error;
 
        if (has_acpi_companion(dev) &&
-           !strncmp(silead_ts_data->acpi_name, client->name, I2C_NAME_SIZE)) {
-               error = device_add_properties(dev, silead_ts_data->properties);
+           !strncmp(ts_data->acpi_name, client->name, I2C_NAME_SIZE)) {
+               error = device_add_properties(dev, ts_data->properties);
                if (error)
                        dev_err(dev, "failed to add properties: %d\n", error);
        }
 }
 
-static int silead_ts_dmi_notifier_call(struct notifier_block *nb,
+static int ts_dmi_notifier_call(struct notifier_block *nb,
                                       unsigned long action, void *data)
 {
        struct device *dev = data;
@@ -582,7 +713,7 @@ static int silead_ts_dmi_notifier_call(struct notifier_block *nb,
        case BUS_NOTIFY_ADD_DEVICE:
                client = i2c_verify_client(dev);
                if (client)
-                       silead_ts_dmi_add_props(client);
+                       ts_dmi_add_props(client);
                break;
 
        default:
@@ -592,22 +723,22 @@ static int silead_ts_dmi_notifier_call(struct notifier_block *nb,
        return 0;
 }
 
-static struct notifier_block silead_ts_dmi_notifier = {
-       .notifier_call = silead_ts_dmi_notifier_call,
+static struct notifier_block ts_dmi_notifier = {
+       .notifier_call = ts_dmi_notifier_call,
 };
 
-static int __init silead_ts_dmi_init(void)
+static int __init ts_dmi_init(void)
 {
        const struct dmi_system_id *dmi_id;
        int error;
 
-       dmi_id = dmi_first_match(silead_ts_dmi_table);
+       dmi_id = dmi_first_match(touchscreen_dmi_table);
        if (!dmi_id)
                return 0; /* Not an error */
 
-       silead_ts_data = dmi_id->driver_data;
+       ts_data = dmi_id->driver_data;
 
-       error = bus_register_notifier(&i2c_bus_type, &silead_ts_dmi_notifier);
+       error = bus_register_notifier(&i2c_bus_type, &ts_dmi_notifier);
        if (error)
                pr_err("%s: failed to register i2c bus notifier: %d\n",
                        __func__, error);
@@ -620,4 +751,4 @@ static int __init silead_ts_dmi_init(void)
  * itself is ready (which happens at postcore initcall level), but before
  * ACPI starts enumerating devices (at subsys initcall level).
  */
-arch_initcall(silead_ts_dmi_init);
+arch_initcall(ts_dmi_init);
index 8e3d014..04791ea 100644 (file)
@@ -895,7 +895,6 @@ static int wmi_dev_probe(struct device *dev)
        struct wmi_driver *wdriver =
                container_of(dev->driver, struct wmi_driver, driver);
        int ret = 0;
-       int count;
        char *buf;
 
        if (ACPI_FAILURE(wmi_method_enable(wblock, 1)))
@@ -917,9 +916,8 @@ static int wmi_dev_probe(struct device *dev)
                        goto probe_failure;
                }
 
-               count = get_order(wblock->req_buf_size);
-               wblock->handler_data = (void *)__get_free_pages(GFP_KERNEL,
-                                                               count);
+               wblock->handler_data = kmalloc(wblock->req_buf_size,
+                                              GFP_KERNEL);
                if (!wblock->handler_data) {
                        ret = -ENOMEM;
                        goto probe_failure;
@@ -964,8 +962,7 @@ static int wmi_dev_remove(struct device *dev)
        if (wdriver->filter_callback) {
                misc_deregister(&wblock->char_dev);
                kfree(wblock->char_dev.name);
-               free_pages((unsigned long)wblock->handler_data,
-                          get_order(wblock->req_buf_size));
+               kfree(wblock->handler_data);
        }
 
        if (wdriver->remove)
index df58fc8..6533aa5 100644 (file)
@@ -104,6 +104,17 @@ config POWER_RESET_MSM
        help
          Power off and restart support for Qualcomm boards.
 
+config POWER_RESET_QCOM_PON
+       tristate "Qualcomm power-on driver"
+       depends on ARCH_QCOM
+       depends on MFD_SPMI_PMIC
+       select REBOOT_MODE
+       help
+         Power On support for Qualcomm boards.
+         If you have a Qualcomm platform and need support for
+         power-on and reboot reason, Say Y.
+         If unsure, Say N.
+
 config POWER_RESET_OCELOT_RESET
        bool "Microsemi Ocelot reset driver"
        depends on MSCC_OCELOT || COMPILE_TEST
index 7778c74..0aebee9 100644 (file)
@@ -11,6 +11,7 @@ obj-$(CONFIG_POWER_RESET_GPIO) += gpio-poweroff.o
 obj-$(CONFIG_POWER_RESET_GPIO_RESTART) += gpio-restart.o
 obj-$(CONFIG_POWER_RESET_HISI) += hisi-reboot.o
 obj-$(CONFIG_POWER_RESET_MSM) += msm-poweroff.o
+obj-$(CONFIG_POWER_RESET_QCOM_PON) += qcom-pon.o
 obj-$(CONFIG_POWER_RESET_OCELOT_RESET) += ocelot-reset.o
 obj-$(CONFIG_POWER_RESET_PIIX4_POWEROFF) += piix4-poweroff.o
 obj-$(CONFIG_POWER_RESET_LTC2952) += ltc2952-poweroff.o
index 2ac291a..90e35c0 100644 (file)
@@ -130,7 +130,17 @@ static int gemini_poweroff_probe(struct platform_device *pdev)
        val |= GEMINI_CTRL_ENABLE;
        writel(val, gpw->base + GEMINI_PWC_CTRLREG);
 
-       /* Now that the state machine is active, clear the IRQ */
+       /* Clear the IRQ */
+       val = readl(gpw->base + GEMINI_PWC_CTRLREG);
+       val |= GEMINI_CTRL_IRQ_CLR;
+       writel(val, gpw->base + GEMINI_PWC_CTRLREG);
+
+       /* Wait for this to clear */
+       val = readl(gpw->base + GEMINI_PWC_STATREG);
+       while (val & 0x70U)
+               val = readl(gpw->base + GEMINI_PWC_STATREG);
+
+       /* Clear the IRQ again */
        val = readl(gpw->base + GEMINI_PWC_CTRLREG);
        val |= GEMINI_CTRL_IRQ_CLR;
        writel(val, gpw->base + GEMINI_PWC_CTRLREG);
index 6b911b6..c484584 100644 (file)
@@ -2,7 +2,7 @@
  * LTC2952 (PowerPath) driver
  *
  * Copyright (C) 2014, Xsens Technologies BV <info@xsens.com>
- * Maintainer: René Moll <linux@r-moll.nl>
+ * Maintainer: René Moll <linux@r-moll.nl>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -319,6 +319,6 @@ static struct platform_driver ltc2952_poweroff_driver = {
 
 module_platform_driver(ltc2952_poweroff_driver);
 
-MODULE_AUTHOR("René Moll <rene.moll@xsens.com>");
+MODULE_AUTHOR("René Moll <rene.moll@xsens.com>");
 MODULE_DESCRIPTION("LTC PowerPath power-off driver");
 MODULE_LICENSE("GPL v2");
diff --git a/drivers/power/reset/qcom-pon.c b/drivers/power/reset/qcom-pon.c
new file mode 100644 (file)
index 0000000..0c4caaa
--- /dev/null
@@ -0,0 +1,91 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) 2017-18 Linaro Limited
+
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/reboot.h>
+#include <linux/reboot-mode.h>
+#include <linux/regmap.h>
+
+#define PON_SOFT_RB_SPARE              0x8f
+
+struct pm8916_pon {
+       struct device *dev;
+       struct regmap *regmap;
+       u32 baseaddr;
+       struct reboot_mode_driver reboot_mode;
+};
+
+static int pm8916_reboot_mode_write(struct reboot_mode_driver *reboot,
+                                   unsigned int magic)
+{
+       struct pm8916_pon *pon = container_of
+                       (reboot, struct pm8916_pon, reboot_mode);
+       int ret;
+
+       ret = regmap_update_bits(pon->regmap,
+                                pon->baseaddr + PON_SOFT_RB_SPARE,
+                                0xfc, magic << 2);
+       if (ret < 0)
+               dev_err(pon->dev, "update reboot mode bits failed\n");
+
+       return ret;
+}
+
+static int pm8916_pon_probe(struct platform_device *pdev)
+{
+       struct pm8916_pon *pon;
+       int error;
+
+       pon = devm_kzalloc(&pdev->dev, sizeof(*pon), GFP_KERNEL);
+       if (!pon)
+               return -ENOMEM;
+
+       pon->dev = &pdev->dev;
+
+       pon->regmap = dev_get_regmap(pdev->dev.parent, NULL);
+       if (!pon->regmap) {
+               dev_err(&pdev->dev, "failed to locate regmap\n");
+               return -ENODEV;
+       }
+
+       error = of_property_read_u32(pdev->dev.of_node, "reg",
+                                    &pon->baseaddr);
+       if (error)
+               return error;
+
+       pon->reboot_mode.dev = &pdev->dev;
+       pon->reboot_mode.write = pm8916_reboot_mode_write;
+       error = devm_reboot_mode_register(&pdev->dev, &pon->reboot_mode);
+       if (error) {
+               dev_err(&pdev->dev, "can't register reboot mode\n");
+               return error;
+       }
+
+       platform_set_drvdata(pdev, pon);
+
+       return devm_of_platform_populate(&pdev->dev);
+}
+
+static const struct of_device_id pm8916_pon_id_table[] = {
+       { .compatible = "qcom,pm8916-pon" },
+       { }
+};
+MODULE_DEVICE_TABLE(of, pm8916_pon_id_table);
+
+static struct platform_driver pm8916_pon_driver = {
+       .probe = pm8916_pon_probe,
+       .driver = {
+               .name = "pm8916-pon",
+               .of_match_table = of_match_ptr(pm8916_pon_id_table),
+       },
+};
+module_platform_driver(pm8916_pon_driver);
+
+MODULE_DESCRIPTION("pm8916 Power On driver");
+MODULE_LICENSE("GPL v2");
index 102f95a..e9e749f 100644 (file)
@@ -35,6 +35,7 @@ static void vexpress_reset_do(struct device *dev, const char *what)
 }
 
 static struct device *vexpress_power_off_device;
+static atomic_t vexpress_restart_nb_refcnt = ATOMIC_INIT(0);
 
 static void vexpress_power_off(void)
 {
@@ -99,10 +100,13 @@ static int _vexpress_register_restart_handler(struct device *dev)
        int err;
 
        vexpress_restart_device = dev;
-       err = register_restart_handler(&vexpress_restart_nb);
-       if (err) {
-               dev_err(dev, "cannot register restart handler (err=%d)\n", err);
-               return err;
+       if (atomic_inc_return(&vexpress_restart_nb_refcnt) == 1) {
+               err = register_restart_handler(&vexpress_restart_nb);
+               if (err) {
+                       dev_err(dev, "cannot register restart handler (err=%d)\n", err);
+                       atomic_dec(&vexpress_restart_nb_refcnt);
+                       return err;
+               }
        }
        device_create_file(dev, &dev_attr_active);
 
index c03e96e..186901c 100644 (file)
@@ -51,6 +51,7 @@ static int zx_reboot_probe(struct platform_device *pdev)
 
        np = of_find_compatible_node(NULL, NULL, "zte,zx296702-pcu");
        pcu_base = of_iomap(np, 0);
+       of_node_put(np);
        if (!pcu_base) {
                iounmap(base);
                WARN(1, "failed to map pcu_base address");
index 428b426..ff6dab0 100644 (file)
@@ -75,6 +75,17 @@ config BATTERY_88PM860X
        help
          Say Y here to enable battery monitor for Marvell 88PM860x chip.
 
+config CHARGER_ADP5061
+       tristate "ADP5061 battery charger driver"
+       depends on I2C
+       select REGMAP_I2C
+       help
+         Say Y here to enable support for the ADP5061 standalone battery
+         charger.
+
+         This driver can be built as a module. If so, the module will be
+         called adp5061.
+
 config BATTERY_ACT8945A
        tristate "Active-semi ACT8945A charger driver"
        depends on MFD_ACT8945A || COMPILE_TEST
@@ -92,7 +103,7 @@ config BATTERY_CPCAP
 
 config BATTERY_DS2760
        tristate "DS2760 battery driver (HP iPAQ & others)"
-       depends on W1 && W1_SLAVE_DS2760
+       depends on W1
        help
          Say Y here to enable support for batteries with ds2760 chip.
 
@@ -624,4 +635,14 @@ config CHARGER_RT9455
        help
          Say Y to enable support for Richtek RT9455 battery charger.
 
+config CHARGER_CROS_USBPD
+       tristate "ChromeOS EC based USBPD charger"
+       depends on MFD_CROS_EC
+       default n
+       help
+         Say Y here to enable ChromeOS EC based USBPD charger
+         driver. This driver gets various bits of information about
+         what is connected to USB PD ports from the EC and converts
+         that into power_supply properties.
+
 endif # POWER_SUPPLY
index e83aa84..a26b402 100644 (file)
@@ -18,6 +18,7 @@ obj-$(CONFIG_WM8350_POWER)    += wm8350_power.o
 obj-$(CONFIG_TEST_POWER)       += test_power.o
 
 obj-$(CONFIG_BATTERY_88PM860X) += 88pm860x_battery.o
+obj-$(CONFIG_CHARGER_ADP5061)  += adp5061.o
 obj-$(CONFIG_BATTERY_ACT8945A) += act8945a_charger.o
 obj-$(CONFIG_BATTERY_AXP20X)   += axp20x_battery.o
 obj-$(CONFIG_CHARGER_AXP20X)   += axp20x_ac_power.o
@@ -83,3 +84,4 @@ obj-$(CONFIG_CHARGER_TPS65090)        += tps65090-charger.o
 obj-$(CONFIG_CHARGER_TPS65217) += tps65217_charger.o
 obj-$(CONFIG_AXP288_FUEL_GAUGE) += axp288_fuel_gauge.o
 obj-$(CONFIG_AXP288_CHARGER)   += axp288_charger.o
+obj-$(CONFIG_CHARGER_CROS_USBPD)       += cros_usbpd-charger.o
index d9c6c7b..02356f9 100644 (file)
@@ -379,15 +379,13 @@ static int ab8500_fg_is_low_curr(struct ab8500_fg *di, int curr)
  */
 static int ab8500_fg_add_cap_sample(struct ab8500_fg *di, int sample)
 {
-       struct timespec64 ts64;
+       time64_t now = ktime_get_boottime_seconds();
        struct ab8500_fg_avg_cap *avg = &di->avg_cap;
 
-       getnstimeofday64(&ts64);
-
        do {
                avg->sum += sample - avg->samples[avg->pos];
                avg->samples[avg->pos] = sample;
-               avg->time_stamps[avg->pos] = ts64.tv_sec;
+               avg->time_stamps[avg->pos] = now;
                avg->pos++;
 
                if (avg->pos == NBR_AVG_SAMPLES)
@@ -400,7 +398,7 @@ static int ab8500_fg_add_cap_sample(struct ab8500_fg *di, int sample)
                 * Check the time stamp for each sample. If too old,
                 * replace with latest sample
                 */
-       } while (ts64.tv_sec - VALID_CAPACITY_SEC > avg->time_stamps[avg->pos]);
+       } while (now - VALID_CAPACITY_SEC > avg->time_stamps[avg->pos]);
 
        avg->avg = avg->sum / avg->nbr_samples;
 
@@ -439,14 +437,14 @@ static void ab8500_fg_clear_cap_samples(struct ab8500_fg *di)
 static void ab8500_fg_fill_cap_sample(struct ab8500_fg *di, int sample)
 {
        int i;
-       struct timespec64 ts64;
+       time64_t now;
        struct ab8500_fg_avg_cap *avg = &di->avg_cap;
 
-       getnstimeofday64(&ts64);
+       now = ktime_get_boottime_seconds();
 
        for (i = 0; i < NBR_AVG_SAMPLES; i++) {
                avg->samples[i] = sample;
-               avg->time_stamps[i] = ts64.tv_sec;
+               avg->time_stamps[i] = now;
        }
 
        avg->pos = 0;
diff --git a/drivers/power/supply/adp5061.c b/drivers/power/supply/adp5061.c
new file mode 100644 (file)
index 0000000..939fd3d
--- /dev/null
@@ -0,0 +1,745 @@
+/*
+ * ADP5061 I2C Programmable Linear Battery Charger
+ *
+ * Copyright 2018 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/mod_devicetable.h>
+#include <linux/power_supply.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/regmap.h>
+
+/* ADP5061 registers definition */
+#define ADP5061_ID                     0x00
+#define ADP5061_REV                    0x01
+#define ADP5061_VINX_SET               0x02
+#define ADP5061_TERM_SET               0x03
+#define ADP5061_CHG_CURR               0x04
+#define ADP5061_VOLTAGE_TH             0x05
+#define ADP5061_TIMER_SET              0x06
+#define ADP5061_FUNC_SET_1             0x07
+#define ADP5061_FUNC_SET_2             0x08
+#define ADP5061_INT_EN                 0x09
+#define ADP5061_INT_ACT                        0x0A
+#define ADP5061_CHG_STATUS_1           0x0B
+#define ADP5061_CHG_STATUS_2           0x0C
+#define ADP5061_FAULT                  0x0D
+#define ADP5061_BATTERY_SHORT          0x10
+#define ADP5061_IEND                   0x11
+
+/* ADP5061_VINX_SET */
+#define ADP5061_VINX_SET_ILIM_MSK              GENMASK(3, 0)
+#define ADP5061_VINX_SET_ILIM_MODE(x)          (((x) & 0x0F) << 0)
+
+/* ADP5061_TERM_SET */
+#define ADP5061_TERM_SET_VTRM_MSK              GENMASK(7, 2)
+#define ADP5061_TERM_SET_VTRM_MODE(x)          (((x) & 0x3F) << 2)
+#define ADP5061_TERM_SET_CHG_VLIM_MSK          GENMASK(1, 0)
+#define ADP5061_TERM_SET_CHG_VLIM_MODE(x)      (((x) & 0x03) << 0)
+
+/* ADP5061_CHG_CURR */
+#define ADP5061_CHG_CURR_ICHG_MSK              GENMASK(6, 2)
+#define ADP5061_CHG_CURR_ICHG_MODE(x)          (((x) & 0x1F) << 2)
+#define ADP5061_CHG_CURR_ITRK_DEAD_MSK         GENMASK(1, 0)
+#define ADP5061_CHG_CURR_ITRK_DEAD_MODE(x)     (((x) & 0x03) << 0)
+
+/* ADP5061_VOLTAGE_TH */
+#define ADP5061_VOLTAGE_TH_DIS_RCH_MSK         BIT(7)
+#define ADP5061_VOLTAGE_TH_DIS_RCH_MODE(x)     (((x) & 0x01) << 7)
+#define ADP5061_VOLTAGE_TH_VRCH_MSK            GENMASK(6, 5)
+#define ADP5061_VOLTAGE_TH_VRCH_MODE(x)                (((x) & 0x03) << 5)
+#define ADP5061_VOLTAGE_TH_VTRK_DEAD_MSK       GENMASK(4, 3)
+#define ADP5061_VOLTAGE_TH_VTRK_DEAD_MODE(x)   (((x) & 0x03) << 3)
+#define ADP5061_VOLTAGE_TH_VWEAK_MSK           GENMASK(2, 0)
+#define ADP5061_VOLTAGE_TH_VWEAK_MODE(x)       (((x) & 0x07) << 0)
+
+/* ADP5061_CHG_STATUS_1 */
+#define ADP5061_CHG_STATUS_1_VIN_OV(x)         (((x) >> 7) & 0x1)
+#define ADP5061_CHG_STATUS_1_VIN_OK(x)         (((x) >> 6) & 0x1)
+#define ADP5061_CHG_STATUS_1_VIN_ILIM(x)       (((x) >> 5) & 0x1)
+#define ADP5061_CHG_STATUS_1_THERM_LIM(x)      (((x) >> 4) & 0x1)
+#define ADP5061_CHG_STATUS_1_CHDONE(x)         (((x) >> 3) & 0x1)
+#define ADP5061_CHG_STATUS_1_CHG_STATUS(x)     (((x) >> 0) & 0x7)
+
+/* ADP5061_CHG_STATUS_2 */
+#define ADP5061_CHG_STATUS_2_THR_STATUS(x)     (((x) >> 5) & 0x7)
+#define ADP5061_CHG_STATUS_2_RCH_LIM_INFO(x)   (((x) >> 3) & 0x1)
+#define ADP5061_CHG_STATUS_2_BAT_STATUS(x)     (((x) >> 0) & 0x7)
+
+/* ADP5061_IEND */
+#define ADP5061_IEND_IEND_MSK                  GENMASK(7, 5)
+#define ADP5061_IEND_IEND_MODE(x)              (((x) & 0x07) << 5)
+
+#define ADP5061_NO_BATTERY     0x01
+#define ADP5061_ICHG_MAX       1300 // mA
+
+enum adp5061_chg_status {
+       ADP5061_CHG_OFF,
+       ADP5061_CHG_TRICKLE,
+       ADP5061_CHG_FAST_CC,
+       ADP5061_CHG_FAST_CV,
+       ADP5061_CHG_COMPLETE,
+       ADP5061_CHG_LDO_MODE,
+       ADP5061_CHG_TIMER_EXP,
+       ADP5061_CHG_BAT_DET,
+};
+
+static const int adp5061_chg_type[4] = {
+       [ADP5061_CHG_OFF] = POWER_SUPPLY_CHARGE_TYPE_NONE,
+       [ADP5061_CHG_TRICKLE] = POWER_SUPPLY_CHARGE_TYPE_TRICKLE,
+       [ADP5061_CHG_FAST_CC] = POWER_SUPPLY_CHARGE_TYPE_FAST,
+       [ADP5061_CHG_FAST_CV] = POWER_SUPPLY_CHARGE_TYPE_FAST,
+};
+
+static const int adp5061_vweak_th[8] = {
+       2700, 2800, 2900, 3000, 3100, 3200, 3300, 3400,
+};
+
+static const int adp5061_prechg_current[4] = {
+       5, 10, 20, 80,
+};
+
+static const int adp5061_vmin[4] = {
+       2000, 2500, 2600, 2900,
+};
+
+static const int adp5061_const_chg_vmax[4] = {
+       3200, 3400, 3700, 3800,
+};
+
+static const int adp5061_const_ichg[24] = {
+       50, 100, 150, 200, 250, 300, 350, 400, 450, 500, 550, 600, 650,
+       700, 750, 800, 850, 900, 950, 1000, 1050, 1100, 1200, 1300,
+};
+
+static const int adp5061_vmax[36] = {
+       3800, 3820, 3840, 3860, 3880, 3900, 3920, 3940, 3960, 3980,
+       4000, 4020, 4040, 4060, 4080, 4100, 4120, 4140, 4160, 4180,
+       4200, 4220, 4240, 4260, 4280, 4300, 4320, 4340, 4360, 4380,
+       4400, 4420, 4440, 4460, 4480, 4500,
+};
+
+static const int adp5061_in_current_lim[16] = {
+       100, 150, 200, 250, 300, 400, 500, 600, 700,
+       800, 900, 1000, 1200, 1500, 1800, 2100,
+};
+
+static const int adp5061_iend[8] = {
+       12500, 32500, 52500, 72500, 92500, 117500, 142500, 170000,
+};
+
+struct adp5061_state {
+       struct i2c_client               *client;
+       struct regmap                   *regmap;
+       struct power_supply             *psy;
+};
+
+static int adp5061_get_array_index(const int *array, u8 size, int val)
+{
+       int i;
+
+       for (i = 1; i < size; i++) {
+               if (val < array[i])
+                       break;
+       }
+
+       return i-1;
+}
+
+static int adp5061_get_status(struct adp5061_state *st,
+                             u8 *status1, u8 *status2)
+{
+       u8 buf[2];
+       int ret;
+
+       /* CHG_STATUS1 and CHG_STATUS2 are adjacent regs */
+       ret = regmap_bulk_read(st->regmap, ADP5061_CHG_STATUS_1,
+                              &buf[0], 2);
+       if (ret < 0)
+               return ret;
+
+       *status1 = buf[0];
+       *status2 = buf[1];
+
+       return ret;
+}
+
+static int adp5061_get_input_current_limit(struct adp5061_state *st,
+               union power_supply_propval *val)
+{
+       unsigned int regval;
+       int mode, ret;
+
+       ret = regmap_read(st->regmap, ADP5061_VINX_SET, &regval);
+       if (ret < 0)
+               return ret;
+
+       mode = ADP5061_VINX_SET_ILIM_MODE(regval);
+       val->intval = adp5061_in_current_lim[mode] * 1000;
+
+       return ret;
+}
+
+static int adp5061_set_input_current_limit(struct adp5061_state *st, int val)
+{
+       int index;
+
+       /* Convert from uA to mA */
+       val /= 1000;
+       index = adp5061_get_array_index(adp5061_in_current_lim,
+                                       ARRAY_SIZE(adp5061_in_current_lim),
+                                       val);
+       if (index < 0)
+               return index;
+
+       return regmap_update_bits(st->regmap, ADP5061_VINX_SET,
+                                 ADP5061_VINX_SET_ILIM_MSK,
+                                 ADP5061_VINX_SET_ILIM_MODE(index));
+}
+
+static int adp5061_set_min_voltage(struct adp5061_state *st, int val)
+{
+       int index;
+
+       /* Convert from uV to mV */
+       val /= 1000;
+       index = adp5061_get_array_index(adp5061_vmin,
+                                       ARRAY_SIZE(adp5061_vmin),
+                                       val);
+       if (index < 0)
+               return index;
+
+       return regmap_update_bits(st->regmap, ADP5061_VOLTAGE_TH,
+                                 ADP5061_VOLTAGE_TH_VTRK_DEAD_MSK,
+                                 ADP5061_VOLTAGE_TH_VTRK_DEAD_MODE(index));
+}
+
+static int adp5061_get_min_voltage(struct adp5061_state *st,
+                                  union power_supply_propval *val)
+{
+       unsigned int regval;
+       int ret;
+
+       ret = regmap_read(st->regmap, ADP5061_VOLTAGE_TH, &regval);
+       if (ret < 0)
+               return ret;
+
+       regval = ((regval & ADP5061_VOLTAGE_TH_VTRK_DEAD_MSK) >> 3);
+       val->intval = adp5061_vmin[regval] * 1000;
+
+       return ret;
+}
+
+static int adp5061_get_chg_volt_lim(struct adp5061_state *st,
+                                   union power_supply_propval *val)
+{
+       unsigned int regval;
+       int mode, ret;
+
+       ret = regmap_read(st->regmap, ADP5061_TERM_SET, &regval);
+       if (ret < 0)
+               return ret;
+
+       mode = ADP5061_TERM_SET_CHG_VLIM_MODE(regval);
+       val->intval = adp5061_const_chg_vmax[mode] * 1000;
+
+       return ret;
+}
+
+static int adp5061_get_max_voltage(struct adp5061_state *st,
+                                  union power_supply_propval *val)
+{
+       unsigned int regval;
+       int ret;
+
+       ret = regmap_read(st->regmap, ADP5061_TERM_SET, &regval);
+       if (ret < 0)
+               return ret;
+
+       regval = ((regval & ADP5061_TERM_SET_VTRM_MSK) >> 2) - 0x0F;
+       if (regval >= ARRAY_SIZE(adp5061_vmax))
+               regval = ARRAY_SIZE(adp5061_vmax) - 1;
+
+       val->intval = adp5061_vmax[regval] * 1000;
+
+       return ret;
+}
+
+static int adp5061_set_max_voltage(struct adp5061_state *st, int val)
+{
+       int vmax_index;
+
+       /* Convert from uV to mV */
+       val /= 1000;
+       if (val > 4500)
+               val = 4500;
+
+       vmax_index = adp5061_get_array_index(adp5061_vmax,
+                                            ARRAY_SIZE(adp5061_vmax), val);
+       if (vmax_index < 0)
+               return vmax_index;
+
+       vmax_index += 0x0F;
+
+       return regmap_update_bits(st->regmap, ADP5061_TERM_SET,
+                                 ADP5061_TERM_SET_VTRM_MSK,
+                                 ADP5061_TERM_SET_VTRM_MODE(vmax_index));
+}
+
+static int adp5061_set_const_chg_vmax(struct adp5061_state *st, int val)
+{
+       int index;
+
+       /* Convert from uV to mV */
+       val /= 1000;
+       index = adp5061_get_array_index(adp5061_const_chg_vmax,
+                                       ARRAY_SIZE(adp5061_const_chg_vmax),
+                                       val);
+       if (index < 0)
+               return index;
+
+       return regmap_update_bits(st->regmap, ADP5061_TERM_SET,
+                                 ADP5061_TERM_SET_CHG_VLIM_MSK,
+                                 ADP5061_TERM_SET_CHG_VLIM_MODE(index));
+}
+
+static int adp5061_set_const_chg_current(struct adp5061_state *st, int val)
+{
+
+       int index;
+
+       /* Convert from uA to mA */
+       val /= 1000;
+       if (val > ADP5061_ICHG_MAX)
+               val = ADP5061_ICHG_MAX;
+
+       index = adp5061_get_array_index(adp5061_const_ichg,
+                                       ARRAY_SIZE(adp5061_const_ichg),
+                                       val);
+       if (index < 0)
+               return index;
+
+       return regmap_update_bits(st->regmap, ADP5061_CHG_CURR,
+                                 ADP5061_CHG_CURR_ICHG_MSK,
+                                 ADP5061_CHG_CURR_ICHG_MODE(index));
+}
+
+static int adp5061_get_const_chg_current(struct adp5061_state *st,
+               union power_supply_propval *val)
+{
+       unsigned int regval;
+       int ret;
+
+       ret = regmap_read(st->regmap, ADP5061_CHG_CURR, &regval);
+       if (ret < 0)
+               return ret;
+
+       regval = ((regval & ADP5061_CHG_CURR_ICHG_MSK) >> 2);
+       if (regval >= ARRAY_SIZE(adp5061_const_ichg))
+               regval = ARRAY_SIZE(adp5061_const_ichg) - 1;
+
+       val->intval = adp5061_const_ichg[regval] * 1000;
+
+       return ret;
+}
+
+static int adp5061_get_prechg_current(struct adp5061_state *st,
+                                     union power_supply_propval *val)
+{
+       unsigned int regval;
+       int ret;
+
+       ret = regmap_read(st->regmap, ADP5061_CHG_CURR, &regval);
+       if (ret < 0)
+               return ret;
+
+       regval &= ADP5061_CHG_CURR_ITRK_DEAD_MSK;
+       val->intval = adp5061_prechg_current[regval] * 1000;
+
+       return ret;
+}
+
+static int adp5061_set_prechg_current(struct adp5061_state *st, int val)
+{
+       int index;
+
+       /* Convert from uA to mA */
+       val /= 1000;
+       index = adp5061_get_array_index(adp5061_prechg_current,
+                                       ARRAY_SIZE(adp5061_prechg_current),
+                                       val);
+       if (index < 0)
+               return index;
+
+       return regmap_update_bits(st->regmap, ADP5061_CHG_CURR,
+                                 ADP5061_CHG_CURR_ITRK_DEAD_MSK,
+                                 ADP5061_CHG_CURR_ITRK_DEAD_MODE(index));
+}
+
+static int adp5061_get_vweak_th(struct adp5061_state *st,
+                               union power_supply_propval *val)
+{
+       unsigned int regval;
+       int ret;
+
+       ret = regmap_read(st->regmap, ADP5061_VOLTAGE_TH, &regval);
+       if (ret < 0)
+               return ret;
+
+       regval &= ADP5061_VOLTAGE_TH_VWEAK_MSK;
+       val->intval = adp5061_vweak_th[regval] * 1000;
+
+       return ret;
+}
+
+static int adp5061_set_vweak_th(struct adp5061_state *st, int val)
+{
+       int index;
+
+       /* Convert from uV to mV */
+       val /= 1000;
+       index = adp5061_get_array_index(adp5061_vweak_th,
+                                       ARRAY_SIZE(adp5061_vweak_th),
+                                       val);
+       if (index < 0)
+               return index;
+
+       return regmap_update_bits(st->regmap, ADP5061_VOLTAGE_TH,
+                                 ADP5061_VOLTAGE_TH_VWEAK_MSK,
+                                 ADP5061_VOLTAGE_TH_VWEAK_MODE(index));
+}
+
+static int adp5061_get_chg_type(struct adp5061_state *st,
+                               union power_supply_propval *val)
+{
+       u8 status1, status2;
+       int chg_type, ret;
+
+       ret = adp5061_get_status(st, &status1, &status2);
+       if (ret < 0)
+               return ret;
+
+       chg_type = adp5061_chg_type[ADP5061_CHG_STATUS_1_CHG_STATUS(status1)];
+       if (chg_type > ADP5061_CHG_FAST_CV)
+               val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
+       else
+               val->intval = chg_type;
+
+       return ret;
+}
+
+static int adp5061_get_charger_status(struct adp5061_state *st,
+                                     union power_supply_propval *val)
+{
+       u8 status1, status2;
+       int ret;
+
+       ret = adp5061_get_status(st, &status1, &status2);
+       if (ret < 0)
+               return ret;
+
+       switch (ADP5061_CHG_STATUS_1_CHG_STATUS(status1)) {
+       case ADP5061_CHG_OFF:
+               val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
+               break;
+       case ADP5061_CHG_TRICKLE:
+       case ADP5061_CHG_FAST_CC:
+       case ADP5061_CHG_FAST_CV:
+               val->intval = POWER_SUPPLY_STATUS_CHARGING;
+               break;
+       case ADP5061_CHG_COMPLETE:
+               val->intval = POWER_SUPPLY_STATUS_FULL;
+               break;
+       case ADP5061_CHG_TIMER_EXP:
+               /* The battery must be discharging if there is a charge fault */
+               val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
+               break;
+       default:
+               val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
+       }
+
+       return ret;
+}
+
+static int adp5061_get_battery_status(struct adp5061_state *st,
+                                     union power_supply_propval *val)
+{
+       u8 status1, status2;
+       int ret;
+
+       ret = adp5061_get_status(st, &status1, &status2);
+       if (ret < 0)
+               return ret;
+
+       switch (ADP5061_CHG_STATUS_2_BAT_STATUS(status2)) {
+       case 0x0: /* Battery monitor off */
+       case 0x1: /* No battery */
+               val->intval = POWER_SUPPLY_CAPACITY_LEVEL_UNKNOWN;
+               break;
+       case 0x2: /* VBAT < VTRK */
+               val->intval = POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL;
+               break;
+       case 0x3: /* VTRK < VBAT_SNS < VWEAK */
+               val->intval = POWER_SUPPLY_CAPACITY_LEVEL_LOW;
+               break;
+       case 0x4: /* VBAT_SNS > VWEAK */
+               val->intval = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL;
+               break;
+       }
+
+       return ret;
+}
+
+static int adp5061_get_termination_current(struct adp5061_state *st,
+                                          union power_supply_propval *val)
+{
+       unsigned int regval;
+       int ret;
+
+       ret = regmap_read(st->regmap, ADP5061_IEND, &regval);
+       if (ret < 0)
+               return ret;
+
+       regval = (regval & ADP5061_IEND_IEND_MSK) >> 5;
+       val->intval = adp5061_iend[regval];
+
+       return ret;
+}
+
+static int adp5061_set_termination_current(struct adp5061_state *st, int val)
+{
+       int index;
+
+       index = adp5061_get_array_index(adp5061_iend,
+                                       ARRAY_SIZE(adp5061_iend),
+                                       val);
+       if (index < 0)
+               return index;
+
+       return regmap_update_bits(st->regmap, ADP5061_IEND,
+                                 ADP5061_IEND_IEND_MSK,
+                                 ADP5061_IEND_IEND_MODE(index));
+}
+
+static int adp5061_get_property(struct power_supply *psy,
+                               enum power_supply_property psp,
+                               union power_supply_propval *val)
+{
+       struct adp5061_state *st = power_supply_get_drvdata(psy);
+       u8 status1, status2;
+       int mode, ret;
+
+       switch (psp) {
+       case POWER_SUPPLY_PROP_PRESENT:
+               ret = adp5061_get_status(st, &status1, &status2);
+               if (ret < 0)
+                       return ret;
+
+               mode = ADP5061_CHG_STATUS_2_BAT_STATUS(status2);
+               if (mode == ADP5061_NO_BATTERY)
+                       val->intval = 0;
+               else
+                       val->intval = 1;
+               break;
+       case POWER_SUPPLY_PROP_CHARGE_TYPE:
+               return adp5061_get_chg_type(st, val);
+       case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
+               /* This property is used to indicate the input current
+                * limit into VINx (ILIM)
+                */
+               return adp5061_get_input_current_limit(st, val);
+       case POWER_SUPPLY_PROP_VOLTAGE_MAX:
+               /* This property is used to indicate the termination
+                * voltage (VTRM)
+                */
+               return adp5061_get_max_voltage(st, val);
+       case POWER_SUPPLY_PROP_VOLTAGE_MIN:
+               /*
+                * This property is used to indicate the trickle to fast
+                * charge threshold (VTRK_DEAD)
+                */
+               return adp5061_get_min_voltage(st, val);
+       case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX:
+               /* This property is used to indicate the charging
+                * voltage limit (CHG_VLIM)
+                */
+               return adp5061_get_chg_volt_lim(st, val);
+       case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
+               /*
+                * This property is used to indicate the value of the constant
+                * current charge (ICHG)
+                */
+               return adp5061_get_const_chg_current(st, val);
+       case POWER_SUPPLY_PROP_PRECHARGE_CURRENT:
+               /*
+                * This property is used to indicate the value of the trickle
+                * and weak charge currents (ITRK_DEAD)
+                */
+               return adp5061_get_prechg_current(st, val);
+       case POWER_SUPPLY_PROP_VOLTAGE_AVG:
+               /*
+                * This property is used to set the VWEAK threshold
+                * bellow this value, weak charge mode is entered
+                * above this value, fast chargerge mode is entered
+                */
+               return adp5061_get_vweak_th(st, val);
+       case POWER_SUPPLY_PROP_STATUS:
+               /*
+                * Indicate the charger status in relation to power
+                * supply status property
+                */
+               return adp5061_get_charger_status(st, val);
+       case POWER_SUPPLY_PROP_CAPACITY_LEVEL:
+               /*
+                * Indicate the battery status in relation to power
+                * supply capacity level property
+                */
+               return adp5061_get_battery_status(st, val);
+       case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT:
+               /* Indicate the values of the termination current */
+               return adp5061_get_termination_current(st, val);
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int adp5061_set_property(struct power_supply *psy,
+                               enum power_supply_property psp,
+                               const union power_supply_propval *val)
+{
+       struct adp5061_state *st = power_supply_get_drvdata(psy);
+
+       switch (psp) {
+       case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
+               return adp5061_set_input_current_limit(st, val->intval);
+       case POWER_SUPPLY_PROP_VOLTAGE_MAX:
+               return adp5061_set_max_voltage(st, val->intval);
+       case POWER_SUPPLY_PROP_VOLTAGE_MIN:
+               return adp5061_set_min_voltage(st, val->intval);
+       case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX:
+               return adp5061_set_const_chg_vmax(st, val->intval);
+       case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
+               return adp5061_set_const_chg_current(st, val->intval);
+       case POWER_SUPPLY_PROP_PRECHARGE_CURRENT:
+               return adp5061_set_prechg_current(st, val->intval);
+       case POWER_SUPPLY_PROP_VOLTAGE_AVG:
+               return adp5061_set_vweak_th(st, val->intval);
+       case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT:
+               return adp5061_set_termination_current(st, val->intval);
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int adp5061_prop_writeable(struct power_supply *psy,
+                                 enum power_supply_property psp)
+{
+       switch (psp) {
+       case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
+       case POWER_SUPPLY_PROP_VOLTAGE_MAX:
+       case POWER_SUPPLY_PROP_VOLTAGE_MIN:
+       case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX:
+       case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
+       case POWER_SUPPLY_PROP_PRECHARGE_CURRENT:
+       case POWER_SUPPLY_PROP_VOLTAGE_AVG:
+       case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT:
+               return 1;
+       default:
+               return 0;
+       }
+}
+
+static enum power_supply_property adp5061_props[] = {
+       POWER_SUPPLY_PROP_PRESENT,
+       POWER_SUPPLY_PROP_CHARGE_TYPE,
+       POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,
+       POWER_SUPPLY_PROP_VOLTAGE_MAX,
+       POWER_SUPPLY_PROP_VOLTAGE_MIN,
+       POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX,
+       POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT,
+       POWER_SUPPLY_PROP_PRECHARGE_CURRENT,
+       POWER_SUPPLY_PROP_VOLTAGE_AVG,
+       POWER_SUPPLY_PROP_STATUS,
+       POWER_SUPPLY_PROP_CAPACITY_LEVEL,
+       POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT,
+};
+
+static const struct regmap_config adp5061_regmap_config = {
+       .reg_bits = 8,
+       .val_bits = 8,
+};
+
+static const struct power_supply_desc adp5061_desc = {
+       .name                   = "adp5061",
+       .type                   = POWER_SUPPLY_TYPE_USB,
+       .get_property           = adp5061_get_property,
+       .set_property           = adp5061_set_property,
+       .property_is_writeable  = adp5061_prop_writeable,
+       .properties             = adp5061_props,
+       .num_properties         = ARRAY_SIZE(adp5061_props),
+};
+
+static int adp5061_probe(struct i2c_client *client,
+                        const struct i2c_device_id *id)
+{
+       struct power_supply_config psy_cfg = {};
+       struct adp5061_state *st;
+
+       st = devm_kzalloc(&client->dev, sizeof(*st), GFP_KERNEL);
+       if (!st)
+               return -ENOMEM;
+
+       st->client = client;
+       st->regmap = devm_regmap_init_i2c(client,
+                                         &adp5061_regmap_config);
+       if (IS_ERR(st->regmap)) {
+               dev_err(&client->dev, "Failed to initialize register map\n");
+               return -EINVAL;
+       }
+
+       i2c_set_clientdata(client, st);
+       psy_cfg.drv_data = st;
+
+       st->psy = devm_power_supply_register(&client->dev,
+                                            &adp5061_desc,
+                                            &psy_cfg);
+
+       if (IS_ERR(st->psy)) {
+               dev_err(&client->dev, "Failed to register power supply\n");
+               return PTR_ERR(st->psy);
+       }
+
+       return 0;
+}
+
+static const struct i2c_device_id adp5061_id[] = {
+       { "adp5061", 0},
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, adp5061_id);
+
+static struct i2c_driver adp5061_driver = {
+       .driver = {
+               .name = KBUILD_MODNAME,
+       },
+       .probe = adp5061_probe,
+       .id_table = adp5061_id,
+};
+module_i2c_driver(adp5061_driver);
+
+MODULE_DESCRIPTION("Analog Devices adp5061 battery charger driver");
+MODULE_AUTHOR("Stefan Popa <stefan.popa@analog.com>");
+MODULE_LICENSE("GPL v2");
index 44f70dc..42001df 100644 (file)
@@ -222,6 +222,7 @@ static int axp20x_usb_power_set_current_max(struct axp20x_usb_power *power,
        case 100000:
                if (power->axp20x_id == AXP221_ID)
                        return -EINVAL;
+               /* fall through */
        case 500000:
        case 900000:
                val = (900000 - intval) / 400000;
index 6e1bc14..735658e 100644 (file)
@@ -718,7 +718,7 @@ static int charger_init_hw_regs(struct axp288_chrg_info *info)
        }
 
        /* Determine charge current limit */
-       cc = (ret & CHRG_CCCV_CC_MASK) >> CHRG_CCCV_CC_BIT_POS;
+       cc = (val & CHRG_CCCV_CC_MASK) >> CHRG_CCCV_CC_BIT_POS;
        cc = (cc * CHRG_CCCV_CC_LSB_RES) + CHRG_CCCV_CC_OFFSET;
        info->cc = cc;
 
index d44ed8e..f022e1b 100644 (file)
@@ -26,7 +26,6 @@
  * http://www.ti.com/product/bq27510-g1
  * http://www.ti.com/product/bq27510-g2
  * http://www.ti.com/product/bq27510-g3
- * http://www.ti.com/product/bq27520-g4
  * http://www.ti.com/product/bq27520-g1
  * http://www.ti.com/product/bq27520-g2
  * http://www.ti.com/product/bq27520-g3
@@ -40,7 +39,9 @@
  * http://www.ti.com/product/bq27545-g1
  * http://www.ti.com/product/bq27421-g1
  * http://www.ti.com/product/bq27425-g1
+ * http://www.ti.com/product/bq27426
  * http://www.ti.com/product/bq27411-g1
+ * http://www.ti.com/product/bq27441-g1
  * http://www.ti.com/product/bq27621-g1
  */
 
diff --git a/drivers/power/supply/cros_usbpd-charger.c b/drivers/power/supply/cros_usbpd-charger.c
new file mode 100644 (file)
index 0000000..688a16b
--- /dev/null
@@ -0,0 +1,545 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Power supply driver for ChromeOS EC based USB PD Charger.
+ *
+ * Copyright (c) 2014 - 2018 Google, Inc
+ */
+
+#include <linux/module.h>
+#include <linux/mfd/cros_ec.h>
+#include <linux/mfd/cros_ec_commands.h>
+#include <linux/platform_device.h>
+#include <linux/power_supply.h>
+#include <linux/slab.h>
+
+#define CHARGER_DIR_NAME                       "CROS_USBPD_CHARGER%d"
+#define CHARGER_DIR_NAME_LENGTH                        sizeof(CHARGER_DIR_NAME)
+#define CHARGER_CACHE_UPDATE_DELAY             msecs_to_jiffies(500)
+#define CHARGER_MANUFACTURER_MODEL_LENGTH      32
+
+#define DRV_NAME "cros-usbpd-charger"
+
+struct port_data {
+       int port_number;
+       char name[CHARGER_DIR_NAME_LENGTH];
+       char manufacturer[CHARGER_MANUFACTURER_MODEL_LENGTH];
+       char model_name[CHARGER_MANUFACTURER_MODEL_LENGTH];
+       struct power_supply *psy;
+       struct power_supply_desc psy_desc;
+       int psy_usb_type;
+       int psy_online;
+       int psy_status;
+       int psy_current_max;
+       int psy_voltage_max_design;
+       int psy_voltage_now;
+       int psy_power_max;
+       struct charger_data *charger;
+       unsigned long last_update;
+};
+
+struct charger_data {
+       struct device *dev;
+       struct cros_ec_dev *ec_dev;
+       struct cros_ec_device *ec_device;
+       int num_charger_ports;
+       int num_registered_psy;
+       struct port_data *ports[EC_USB_PD_MAX_PORTS];
+       struct notifier_block notifier;
+};
+
+static enum power_supply_property cros_usbpd_charger_props[] = {
+       POWER_SUPPLY_PROP_ONLINE,
+       POWER_SUPPLY_PROP_STATUS,
+       POWER_SUPPLY_PROP_CURRENT_MAX,
+       POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
+       POWER_SUPPLY_PROP_VOLTAGE_NOW,
+       POWER_SUPPLY_PROP_MODEL_NAME,
+       POWER_SUPPLY_PROP_MANUFACTURER,
+       POWER_SUPPLY_PROP_USB_TYPE
+};
+
+static enum power_supply_usb_type cros_usbpd_charger_usb_types[] = {
+       POWER_SUPPLY_USB_TYPE_UNKNOWN,
+       POWER_SUPPLY_USB_TYPE_SDP,
+       POWER_SUPPLY_USB_TYPE_DCP,
+       POWER_SUPPLY_USB_TYPE_CDP,
+       POWER_SUPPLY_USB_TYPE_C,
+       POWER_SUPPLY_USB_TYPE_PD,
+       POWER_SUPPLY_USB_TYPE_PD_DRP,
+       POWER_SUPPLY_USB_TYPE_APPLE_BRICK_ID
+};
+
+static int cros_usbpd_charger_ec_command(struct charger_data *charger,
+                                        unsigned int version,
+                                        unsigned int command,
+                                        void *outdata,
+                                        unsigned int outsize,
+                                        void *indata,
+                                        unsigned int insize)
+{
+       struct cros_ec_dev *ec_dev = charger->ec_dev;
+       struct cros_ec_command *msg;
+       int ret;
+
+       msg = kzalloc(sizeof(*msg) + max(outsize, insize), GFP_KERNEL);
+       if (!msg)
+               return -ENOMEM;
+
+       msg->version = version;
+       msg->command = ec_dev->cmd_offset + command;
+       msg->outsize = outsize;
+       msg->insize = insize;
+
+       if (outsize)
+               memcpy(msg->data, outdata, outsize);
+
+       ret = cros_ec_cmd_xfer_status(charger->ec_device, msg);
+       if (ret >= 0 && insize)
+               memcpy(indata, msg->data, insize);
+
+       kfree(msg);
+       return ret;
+}
+
+static int cros_usbpd_charger_get_num_ports(struct charger_data *charger)
+{
+       struct ec_response_usb_pd_ports resp;
+       int ret;
+
+       ret = cros_usbpd_charger_ec_command(charger, 0, EC_CMD_USB_PD_PORTS,
+                                           NULL, 0, &resp, sizeof(resp));
+       if (ret < 0) {
+               dev_err(charger->dev,
+                       "Unable to get the number or ports (err:0x%x)\n", ret);
+               return ret;
+       }
+
+       return resp.num_ports;
+}
+
+static int cros_usbpd_charger_get_discovery_info(struct port_data *port)
+{
+       struct charger_data *charger = port->charger;
+       struct ec_params_usb_pd_discovery_entry resp;
+       struct ec_params_usb_pd_info_request req;
+       int ret;
+
+       req.port = port->port_number;
+
+       ret = cros_usbpd_charger_ec_command(charger, 0,
+                                           EC_CMD_USB_PD_DISCOVERY,
+                                           &req, sizeof(req),
+                                           &resp, sizeof(resp));
+       if (ret < 0) {
+               dev_err(charger->dev,
+                       "Unable to query discovery info (err:0x%x)\n", ret);
+               return ret;
+       }
+
+       dev_dbg(charger->dev, "Port %d: VID = 0x%x, PID=0x%x, PTYPE=0x%x\n",
+               port->port_number, resp.vid, resp.pid, resp.ptype);
+
+       snprintf(port->manufacturer, sizeof(port->manufacturer), "%x",
+                resp.vid);
+       snprintf(port->model_name, sizeof(port->model_name), "%x", resp.pid);
+
+       return 0;
+}
+
+static int cros_usbpd_charger_get_power_info(struct port_data *port)
+{
+       struct charger_data *charger = port->charger;
+       struct ec_response_usb_pd_power_info resp;
+       struct ec_params_usb_pd_power_info req;
+       int last_psy_status, last_psy_usb_type;
+       struct device *dev = charger->dev;
+       int ret;
+
+       req.port = port->port_number;
+       ret = cros_usbpd_charger_ec_command(charger, 0,
+                                           EC_CMD_USB_PD_POWER_INFO,
+                                           &req, sizeof(req),
+                                           &resp, sizeof(resp));
+       if (ret < 0) {
+               dev_err(dev, "Unable to query PD power info (err:0x%x)\n", ret);
+               return ret;
+       }
+
+       last_psy_status = port->psy_status;
+       last_psy_usb_type = port->psy_usb_type;
+
+       switch (resp.role) {
+       case USB_PD_PORT_POWER_DISCONNECTED:
+               port->psy_status = POWER_SUPPLY_STATUS_NOT_CHARGING;
+               port->psy_online = 0;
+               break;
+       case USB_PD_PORT_POWER_SOURCE:
+               port->psy_status = POWER_SUPPLY_STATUS_NOT_CHARGING;
+               port->psy_online = 0;
+               break;
+       case USB_PD_PORT_POWER_SINK:
+               port->psy_status = POWER_SUPPLY_STATUS_CHARGING;
+               port->psy_online = 1;
+               break;
+       case USB_PD_PORT_POWER_SINK_NOT_CHARGING:
+               port->psy_status = POWER_SUPPLY_STATUS_NOT_CHARGING;
+               port->psy_online = 1;
+               break;
+       default:
+               dev_err(dev, "Unknown role %d\n", resp.role);
+               break;
+       }
+
+       port->psy_voltage_max_design = resp.meas.voltage_max;
+       port->psy_voltage_now = resp.meas.voltage_now;
+       port->psy_current_max = resp.meas.current_max;
+       port->psy_power_max = resp.max_power;
+
+       switch (resp.type) {
+       case USB_CHG_TYPE_BC12_SDP:
+       case USB_CHG_TYPE_VBUS:
+               port->psy_usb_type = POWER_SUPPLY_USB_TYPE_SDP;
+               break;
+       case USB_CHG_TYPE_NONE:
+               /*
+                * For dual-role devices when we are a source, the firmware
+                * reports the type as NONE. Report such chargers as type
+                * USB_PD_DRP.
+                */
+               if (resp.role == USB_PD_PORT_POWER_SOURCE && resp.dualrole)
+                       port->psy_usb_type = POWER_SUPPLY_USB_TYPE_PD_DRP;
+               else
+                       port->psy_usb_type = POWER_SUPPLY_USB_TYPE_SDP;
+               break;
+       case USB_CHG_TYPE_OTHER:
+       case USB_CHG_TYPE_PROPRIETARY:
+               port->psy_usb_type = POWER_SUPPLY_USB_TYPE_APPLE_BRICK_ID;
+               break;
+       case USB_CHG_TYPE_C:
+               port->psy_usb_type = POWER_SUPPLY_USB_TYPE_C;
+               break;
+       case USB_CHG_TYPE_BC12_DCP:
+               port->psy_usb_type = POWER_SUPPLY_USB_TYPE_DCP;
+               break;
+       case USB_CHG_TYPE_BC12_CDP:
+               port->psy_usb_type = POWER_SUPPLY_USB_TYPE_CDP;
+               break;
+       case USB_CHG_TYPE_PD:
+               if (resp.dualrole)
+                       port->psy_usb_type = POWER_SUPPLY_USB_TYPE_PD_DRP;
+               else
+                       port->psy_usb_type = POWER_SUPPLY_USB_TYPE_PD;
+               break;
+       case USB_CHG_TYPE_UNKNOWN:
+               /*
+                * While the EC is trying to determine the type of charger that
+                * has been plugged in, it will report the charger type as
+                * unknown. Additionally since the power capabilities are
+                * unknown, report the max current and voltage as zero.
+                */
+               port->psy_usb_type = POWER_SUPPLY_USB_TYPE_UNKNOWN;
+               port->psy_voltage_max_design = 0;
+               port->psy_current_max = 0;
+               break;
+       default:
+               dev_err(dev, "Port %d: default case!\n", port->port_number);
+               port->psy_usb_type = POWER_SUPPLY_USB_TYPE_SDP;
+       }
+
+       port->psy_desc.type = POWER_SUPPLY_TYPE_USB;
+
+       dev_dbg(dev,
+               "Port %d: type=%d vmax=%d vnow=%d cmax=%d clim=%d pmax=%d\n",
+               port->port_number, resp.type, resp.meas.voltage_max,
+               resp.meas.voltage_now, resp.meas.current_max,
+               resp.meas.current_lim, resp.max_power);
+
+       /*
+        * If power supply type or status changed, explicitly call
+        * power_supply_changed. This results in udev event getting generated
+        * and allows user mode apps to react quicker instead of waiting for
+        * their next poll of power supply status.
+        */
+       if (last_psy_usb_type != port->psy_usb_type ||
+           last_psy_status != port->psy_status)
+               power_supply_changed(port->psy);
+
+       return 0;
+}
+
+static int cros_usbpd_charger_get_port_status(struct port_data *port,
+                                             bool ratelimit)
+{
+       int ret;
+
+       if (ratelimit &&
+           time_is_after_jiffies(port->last_update +
+                                 CHARGER_CACHE_UPDATE_DELAY))
+               return 0;
+
+       ret = cros_usbpd_charger_get_power_info(port);
+       if (ret < 0)
+               return ret;
+
+       ret = cros_usbpd_charger_get_discovery_info(port);
+       port->last_update = jiffies;
+
+       return ret;
+}
+
+static void cros_usbpd_charger_power_changed(struct power_supply *psy)
+{
+       struct port_data *port = power_supply_get_drvdata(psy);
+       struct charger_data *charger = port->charger;
+       int i;
+
+       for (i = 0; i < charger->num_registered_psy; i++)
+               cros_usbpd_charger_get_port_status(charger->ports[i], false);
+}
+
+static int cros_usbpd_charger_get_prop(struct power_supply *psy,
+                                      enum power_supply_property psp,
+                                      union power_supply_propval *val)
+{
+       struct port_data *port = power_supply_get_drvdata(psy);
+       struct charger_data *charger = port->charger;
+       struct cros_ec_device *ec_device = charger->ec_device;
+       struct device *dev = charger->dev;
+       int ret;
+
+       /* Only refresh ec_port_status for dynamic properties */
+       switch (psp) {
+       case POWER_SUPPLY_PROP_ONLINE:
+               /*
+                * If mkbp_event_supported, then we can be assured that
+                * the driver's state for the online property is consistent
+                * with the hardware. However, if we aren't event driven,
+                * the optimization before to skip an ec_port_status get
+                * and only returned cached values of the online property will
+                * cause a delay in detecting a cable attach until one of the
+                * other properties are read.
+                *
+                * Allow an ec_port_status refresh for online property check
+                * if we're not already online to check for plug events if
+                * not mkbp_event_supported.
+                */
+               if (ec_device->mkbp_event_supported || port->psy_online)
+                       break;
+               /* fall through */
+       case POWER_SUPPLY_PROP_CURRENT_MAX:
+       case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
+       case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+               ret = cros_usbpd_charger_get_port_status(port, true);
+               if (ret < 0) {
+                       dev_err(dev, "Failed to get port status (err:0x%x)\n",
+                               ret);
+                       return -EINVAL;
+               }
+               break;
+       default:
+               break;
+       }
+
+       switch (psp) {
+       case POWER_SUPPLY_PROP_ONLINE:
+               val->intval = port->psy_online;
+               break;
+       case POWER_SUPPLY_PROP_STATUS:
+               val->intval = port->psy_status;
+               break;
+       case POWER_SUPPLY_PROP_CURRENT_MAX:
+               val->intval = port->psy_current_max * 1000;
+               break;
+       case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
+               val->intval = port->psy_voltage_max_design * 1000;
+               break;
+       case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+               val->intval = port->psy_voltage_now * 1000;
+               break;
+       case POWER_SUPPLY_PROP_USB_TYPE:
+               val->intval = port->psy_usb_type;
+               break;
+       case POWER_SUPPLY_PROP_MODEL_NAME:
+               val->strval = port->model_name;
+               break;
+       case POWER_SUPPLY_PROP_MANUFACTURER:
+               val->strval = port->manufacturer;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int cros_usbpd_charger_ec_event(struct notifier_block *nb,
+                                      unsigned long queued_during_suspend,
+                                      void *_notify)
+{
+       struct cros_ec_device *ec_device;
+       struct charger_data *charger;
+       struct device *dev;
+       u32 host_event;
+
+       charger = container_of(nb, struct charger_data, notifier);
+       ec_device = charger->ec_device;
+       dev = charger->dev;
+
+       host_event = cros_ec_get_host_event(ec_device);
+       if (host_event & EC_HOST_EVENT_MASK(EC_HOST_EVENT_PD_MCU)) {
+               cros_usbpd_charger_power_changed(charger->ports[0]->psy);
+               return NOTIFY_OK;
+       } else {
+               return NOTIFY_DONE;
+       }
+}
+
+static void cros_usbpd_charger_unregister_notifier(void *data)
+{
+       struct charger_data *charger = data;
+       struct cros_ec_device *ec_device = charger->ec_device;
+
+       blocking_notifier_chain_unregister(&ec_device->event_notifier,
+                                          &charger->notifier);
+}
+
+static int cros_usbpd_charger_probe(struct platform_device *pd)
+{
+       struct cros_ec_dev *ec_dev = dev_get_drvdata(pd->dev.parent);
+       struct cros_ec_device *ec_device = ec_dev->ec_dev;
+       struct power_supply_desc *psy_desc;
+       struct device *dev = &pd->dev;
+       struct charger_data *charger;
+       struct power_supply *psy;
+       struct port_data *port;
+       int ret = -EINVAL;
+       int i;
+
+       charger = devm_kzalloc(dev, sizeof(struct charger_data),
+                              GFP_KERNEL);
+       if (!charger)
+               return -ENOMEM;
+
+       charger->dev = dev;
+       charger->ec_dev = ec_dev;
+       charger->ec_device = ec_device;
+
+       platform_set_drvdata(pd, charger);
+
+       charger->num_charger_ports = cros_usbpd_charger_get_num_ports(charger);
+       if (charger->num_charger_ports <= 0) {
+               /*
+                * This can happen on a system that doesn't support USB PD.
+                * Log a message, but no need to warn.
+                */
+               dev_info(dev, "No charging ports found\n");
+               ret = -ENODEV;
+               goto fail_nowarn;
+       }
+
+       for (i = 0; i < charger->num_charger_ports; i++) {
+               struct power_supply_config psy_cfg = {};
+
+               port = devm_kzalloc(dev, sizeof(struct port_data), GFP_KERNEL);
+               if (!port) {
+                       ret = -ENOMEM;
+                       goto fail;
+               }
+
+               port->charger = charger;
+               port->port_number = i;
+               sprintf(port->name, CHARGER_DIR_NAME, i);
+
+               psy_desc = &port->psy_desc;
+               psy_desc->name = port->name;
+               psy_desc->type = POWER_SUPPLY_TYPE_USB;
+               psy_desc->get_property = cros_usbpd_charger_get_prop;
+               psy_desc->external_power_changed =
+                                       cros_usbpd_charger_power_changed;
+               psy_desc->properties = cros_usbpd_charger_props;
+               psy_desc->num_properties =
+                                       ARRAY_SIZE(cros_usbpd_charger_props);
+               psy_desc->usb_types = cros_usbpd_charger_usb_types;
+               psy_desc->num_usb_types =
+                               ARRAY_SIZE(cros_usbpd_charger_usb_types);
+               psy_cfg.drv_data = port;
+
+               psy = devm_power_supply_register_no_ws(dev, psy_desc,
+                                                      &psy_cfg);
+               if (IS_ERR(psy)) {
+                       dev_err(dev, "Failed to register power supply\n");
+                       continue;
+               }
+               port->psy = psy;
+
+               charger->ports[charger->num_registered_psy++] = port;
+       }
+
+       if (!charger->num_registered_psy) {
+               ret = -ENODEV;
+               dev_err(dev, "No power supplies registered\n");
+               goto fail;
+       }
+
+       if (ec_device->mkbp_event_supported) {
+               /* Get PD events from the EC */
+               charger->notifier.notifier_call = cros_usbpd_charger_ec_event;
+               ret = blocking_notifier_chain_register(
+                                               &ec_device->event_notifier,
+                                               &charger->notifier);
+               if (ret < 0) {
+                       dev_warn(dev, "failed to register notifier\n");
+               } else {
+                       ret = devm_add_action_or_reset(dev,
+                                       cros_usbpd_charger_unregister_notifier,
+                                       charger);
+                       if (ret < 0)
+                               goto fail;
+               }
+       }
+
+       return 0;
+
+fail:
+       WARN(1, "%s: Failing probe (err:0x%x)\n", dev_name(dev), ret);
+
+fail_nowarn:
+       dev_info(dev, "Failing probe (err:0x%x)\n", ret);
+       return ret;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int cros_usbpd_charger_resume(struct device *dev)
+{
+       struct charger_data *charger = dev_get_drvdata(dev);
+       int i;
+
+       if (!charger)
+               return 0;
+
+       for (i = 0; i < charger->num_registered_psy; i++) {
+               power_supply_changed(charger->ports[i]->psy);
+               charger->ports[i]->last_update =
+                               jiffies - CHARGER_CACHE_UPDATE_DELAY;
+       }
+
+       return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(cros_usbpd_charger_pm_ops, NULL,
+                        cros_usbpd_charger_resume);
+
+static struct platform_driver cros_usbpd_charger_driver = {
+       .driver = {
+               .name = DRV_NAME,
+               .pm = &cros_usbpd_charger_pm_ops,
+       },
+       .probe = cros_usbpd_charger_probe
+};
+
+module_platform_driver(cros_usbpd_charger_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("ChromeOS EC USBPD charger");
+MODULE_ALIAS("platform:" DRV_NAME);
index ae180dc..11bed88 100644 (file)
 #include <linux/slab.h>
 #include <linux/platform_device.h>
 #include <linux/power_supply.h>
-
+#include <linux/suspend.h>
 #include <linux/w1.h>
-#include "../../w1/slaves/w1_ds2760.h"
+#include <linux/of.h>
+
+static unsigned int cache_time = 1000;
+module_param(cache_time, uint, 0644);
+MODULE_PARM_DESC(cache_time, "cache time in milliseconds");
+
+static bool pmod_enabled;
+module_param(pmod_enabled, bool, 0644);
+MODULE_PARM_DESC(pmod_enabled, "PMOD enable bit");
+
+static unsigned int rated_capacity;
+module_param(rated_capacity, uint, 0644);
+MODULE_PARM_DESC(rated_capacity, "rated battery capacity, 10*mAh or index");
+
+static unsigned int current_accum;
+module_param(current_accum, uint, 0644);
+MODULE_PARM_DESC(current_accum, "current accumulator value");
+
+#define W1_FAMILY_DS2760               0x30
+
+/* Known commands to the DS2760 chip */
+#define W1_DS2760_SWAP                 0xAA
+#define W1_DS2760_READ_DATA            0x69
+#define W1_DS2760_WRITE_DATA           0x6C
+#define W1_DS2760_COPY_DATA            0x48
+#define W1_DS2760_RECALL_DATA          0xB8
+#define W1_DS2760_LOCK                 0x6A
+
+/* Number of valid register addresses */
+#define DS2760_DATA_SIZE               0x40
+
+#define DS2760_PROTECTION_REG          0x00
+
+#define DS2760_STATUS_REG              0x01
+#define DS2760_STATUS_IE               (1 << 2)
+#define DS2760_STATUS_SWEN             (1 << 3)
+#define DS2760_STATUS_RNAOP            (1 << 4)
+#define DS2760_STATUS_PMOD             (1 << 5)
+
+#define DS2760_EEPROM_REG              0x07
+#define DS2760_SPECIAL_FEATURE_REG     0x08
+#define DS2760_VOLTAGE_MSB             0x0c
+#define DS2760_VOLTAGE_LSB             0x0d
+#define DS2760_CURRENT_MSB             0x0e
+#define DS2760_CURRENT_LSB             0x0f
+#define DS2760_CURRENT_ACCUM_MSB       0x10
+#define DS2760_CURRENT_ACCUM_LSB       0x11
+#define DS2760_TEMP_MSB                        0x18
+#define DS2760_TEMP_LSB                        0x19
+#define DS2760_EEPROM_BLOCK0           0x20
+#define DS2760_ACTIVE_FULL             0x20
+#define DS2760_EEPROM_BLOCK1           0x30
+#define DS2760_STATUS_WRITE_REG                0x31
+#define DS2760_RATED_CAPACITY          0x32
+#define DS2760_CURRENT_OFFSET_BIAS     0x33
+#define DS2760_ACTIVE_EMPTY            0x3b
 
 struct ds2760_device_info {
        struct device *dev;
@@ -55,28 +110,113 @@ struct ds2760_device_info {
        int full_counter;
        struct power_supply *bat;
        struct power_supply_desc bat_desc;
-       struct device *w1_dev;
        struct workqueue_struct *monitor_wqueue;
        struct delayed_work monitor_work;
        struct delayed_work set_charged_work;
+       struct notifier_block pm_notifier;
 };
 
-static unsigned int cache_time = 1000;
-module_param(cache_time, uint, 0644);
-MODULE_PARM_DESC(cache_time, "cache time in milliseconds");
+static int w1_ds2760_io(struct device *dev, char *buf, int addr, size_t count,
+                       int io)
+{
+       struct w1_slave *sl = container_of(dev, struct w1_slave, dev);
 
-static bool pmod_enabled;
-module_param(pmod_enabled, bool, 0644);
-MODULE_PARM_DESC(pmod_enabled, "PMOD enable bit");
+       if (!dev)
+               return 0;
 
-static unsigned int rated_capacity;
-module_param(rated_capacity, uint, 0644);
-MODULE_PARM_DESC(rated_capacity, "rated battery capacity, 10*mAh or index");
+       mutex_lock(&sl->master->bus_mutex);
 
-static unsigned int current_accum;
-module_param(current_accum, uint, 0644);
-MODULE_PARM_DESC(current_accum, "current accumulator value");
+       if (addr > DS2760_DATA_SIZE || addr < 0) {
+               count = 0;
+               goto out;
+       }
+       if (addr + count > DS2760_DATA_SIZE)
+               count = DS2760_DATA_SIZE - addr;
+
+       if (!w1_reset_select_slave(sl)) {
+               if (!io) {
+                       w1_write_8(sl->master, W1_DS2760_READ_DATA);
+                       w1_write_8(sl->master, addr);
+                       count = w1_read_block(sl->master, buf, count);
+               } else {
+                       w1_write_8(sl->master, W1_DS2760_WRITE_DATA);
+                       w1_write_8(sl->master, addr);
+                       w1_write_block(sl->master, buf, count);
+                       /* XXX w1_write_block returns void, not n_written */
+               }
+       }
+
+out:
+       mutex_unlock(&sl->master->bus_mutex);
+
+       return count;
+}
+
+static int w1_ds2760_read(struct device *dev,
+                         char *buf, int addr,
+                         size_t count)
+{
+       return w1_ds2760_io(dev, buf, addr, count, 0);
+}
+
+static int w1_ds2760_write(struct device *dev,
+                          char *buf,
+                          int addr, size_t count)
+{
+       return w1_ds2760_io(dev, buf, addr, count, 1);
+}
+
+static int w1_ds2760_eeprom_cmd(struct device *dev, int addr, int cmd)
+{
+       struct w1_slave *sl = container_of(dev, struct w1_slave, dev);
+
+       if (!dev)
+               return -EINVAL;
+
+       mutex_lock(&sl->master->bus_mutex);
+
+       if (w1_reset_select_slave(sl) == 0) {
+               w1_write_8(sl->master, cmd);
+               w1_write_8(sl->master, addr);
+       }
+
+       mutex_unlock(&sl->master->bus_mutex);
+       return 0;
+}
+
+static int w1_ds2760_store_eeprom(struct device *dev, int addr)
+{
+       return w1_ds2760_eeprom_cmd(dev, addr, W1_DS2760_COPY_DATA);
+}
+
+static int w1_ds2760_recall_eeprom(struct device *dev, int addr)
+{
+       return w1_ds2760_eeprom_cmd(dev, addr, W1_DS2760_RECALL_DATA);
+}
+
+static ssize_t w1_slave_read(struct file *filp, struct kobject *kobj,
+                            struct bin_attribute *bin_attr, char *buf,
+                            loff_t off, size_t count)
+{
+       struct device *dev = container_of(kobj, struct device, kobj);
+       return w1_ds2760_read(dev, buf, off, count);
+}
+
+static BIN_ATTR_RO(w1_slave, DS2760_DATA_SIZE);
+
+static struct bin_attribute *w1_ds2760_bin_attrs[] = {
+       &bin_attr_w1_slave,
+       NULL,
+};
+
+static const struct attribute_group w1_ds2760_group = {
+       .bin_attrs = w1_ds2760_bin_attrs,
+};
 
+static const struct attribute_group *w1_ds2760_groups[] = {
+       &w1_ds2760_group,
+       NULL,
+};
 /* Some batteries have their rated capacity stored a N * 10 mAh, while
  * others use an index into this table. */
 static int rated_capacities[] = {
@@ -138,10 +278,10 @@ static int ds2760_battery_read_status(struct ds2760_device_info *di)
                count = DS2760_TEMP_LSB - start + 1;
        }
 
-       ret = w1_ds2760_read(di->w1_dev, di->raw + start, start, count);
+       ret = w1_ds2760_read(di->dev, di->raw + start, start, count);
        if (ret != count) {
                dev_warn(di->dev, "call to w1_ds2760_read failed (0x%p)\n",
-                        di->w1_dev);
+                        di->dev);
                return 1;
        }
 
@@ -242,7 +382,7 @@ static void ds2760_battery_set_current_accum(struct ds2760_device_info *di,
        acr[0] = acr_val >> 8;
        acr[1] = acr_val & 0xff;
 
-       if (w1_ds2760_write(di->w1_dev, acr, DS2760_CURRENT_ACCUM_MSB, 2) < 2)
+       if (w1_ds2760_write(di->dev, acr, DS2760_CURRENT_ACCUM_MSB, 2) < 2)
                dev_warn(di->dev, "ACR write failed\n");
 }
 
@@ -297,9 +437,9 @@ static void ds2760_battery_write_status(struct ds2760_device_info *di,
        if (status == di->raw[DS2760_STATUS_REG])
                return;
 
-       w1_ds2760_write(di->w1_dev, &status, DS2760_STATUS_WRITE_REG, 1);
-       w1_ds2760_store_eeprom(di->w1_dev, DS2760_EEPROM_BLOCK1);
-       w1_ds2760_recall_eeprom(di->w1_dev, DS2760_EEPROM_BLOCK1);
+       w1_ds2760_write(di->dev, &status, DS2760_STATUS_WRITE_REG, 1);
+       w1_ds2760_store_eeprom(di->dev, DS2760_EEPROM_BLOCK1);
+       w1_ds2760_recall_eeprom(di->dev, DS2760_EEPROM_BLOCK1);
 }
 
 static void ds2760_battery_write_rated_capacity(struct ds2760_device_info *di,
@@ -308,9 +448,9 @@ static void ds2760_battery_write_rated_capacity(struct ds2760_device_info *di,
        if (rated_capacity == di->raw[DS2760_RATED_CAPACITY])
                return;
 
-       w1_ds2760_write(di->w1_dev, &rated_capacity, DS2760_RATED_CAPACITY, 1);
-       w1_ds2760_store_eeprom(di->w1_dev, DS2760_EEPROM_BLOCK1);
-       w1_ds2760_recall_eeprom(di->w1_dev, DS2760_EEPROM_BLOCK1);
+       w1_ds2760_write(di->dev, &rated_capacity, DS2760_RATED_CAPACITY, 1);
+       w1_ds2760_store_eeprom(di->dev, DS2760_EEPROM_BLOCK1);
+       w1_ds2760_recall_eeprom(di->dev, DS2760_EEPROM_BLOCK1);
 }
 
 static void ds2760_battery_write_active_full(struct ds2760_device_info *di,
@@ -325,9 +465,9 @@ static void ds2760_battery_write_active_full(struct ds2760_device_info *di,
            tmp[1] == di->raw[DS2760_ACTIVE_FULL + 1])
                return;
 
-       w1_ds2760_write(di->w1_dev, tmp, DS2760_ACTIVE_FULL, sizeof(tmp));
-       w1_ds2760_store_eeprom(di->w1_dev, DS2760_EEPROM_BLOCK0);
-       w1_ds2760_recall_eeprom(di->w1_dev, DS2760_EEPROM_BLOCK0);
+       w1_ds2760_write(di->dev, tmp, DS2760_ACTIVE_FULL, sizeof(tmp));
+       w1_ds2760_store_eeprom(di->dev, DS2760_EEPROM_BLOCK0);
+       w1_ds2760_recall_eeprom(di->dev, DS2760_EEPROM_BLOCK0);
 
        /* Write to the di->raw[] buffer directly - the DS2760_ACTIVE_FULL
         * values won't be read back by ds2760_battery_read_status() */
@@ -383,9 +523,9 @@ static void ds2760_battery_set_charged_work(struct work_struct *work)
 
        dev_dbg(di->dev, "%s: bias = %d\n", __func__, bias);
 
-       w1_ds2760_write(di->w1_dev, &bias, DS2760_CURRENT_OFFSET_BIAS, 1);
-       w1_ds2760_store_eeprom(di->w1_dev, DS2760_EEPROM_BLOCK1);
-       w1_ds2760_recall_eeprom(di->w1_dev, DS2760_EEPROM_BLOCK1);
+       w1_ds2760_write(di->dev, &bias, DS2760_CURRENT_OFFSET_BIAS, 1);
+       w1_ds2760_store_eeprom(di->dev, DS2760_EEPROM_BLOCK1);
+       w1_ds2760_recall_eeprom(di->dev, DS2760_EEPROM_BLOCK1);
 
        /* Write to the di->raw[] buffer directly - the CURRENT_OFFSET_BIAS
         * value won't be read back by ds2760_battery_read_status() */
@@ -504,24 +644,55 @@ static enum power_supply_property ds2760_battery_props[] = {
        POWER_SUPPLY_PROP_CAPACITY,
 };
 
-static int ds2760_battery_probe(struct platform_device *pdev)
+static int ds2760_pm_notifier(struct notifier_block *notifier,
+                             unsigned long pm_event,
+                             void *unused)
+{
+       struct ds2760_device_info *di =
+               container_of(notifier, struct ds2760_device_info, pm_notifier);
+
+       switch (pm_event) {
+       case PM_HIBERNATION_PREPARE:
+       case PM_SUSPEND_PREPARE:
+               di->charge_status = POWER_SUPPLY_STATUS_UNKNOWN;
+               break;
+
+       case PM_POST_RESTORE:
+       case PM_POST_HIBERNATION:
+       case PM_POST_SUSPEND:
+               di->charge_status = POWER_SUPPLY_STATUS_UNKNOWN;
+               power_supply_changed(di->bat);
+               mod_delayed_work(di->monitor_wqueue, &di->monitor_work, HZ);
+
+               break;
+
+       case PM_RESTORE_PREPARE:
+       default:
+               break;
+       }
+
+       return NOTIFY_DONE;
+}
+
+static int w1_ds2760_add_slave(struct w1_slave *sl)
 {
        struct power_supply_config psy_cfg = {};
-       char status;
-       int retval = 0;
        struct ds2760_device_info *di;
+       struct device *dev = &sl->dev;
+       int retval = 0;
+       char name[32];
+       char status;
 
-       di = devm_kzalloc(&pdev->dev, sizeof(*di), GFP_KERNEL);
+       di = devm_kzalloc(dev, sizeof(*di), GFP_KERNEL);
        if (!di) {
                retval = -ENOMEM;
                goto di_alloc_failed;
        }
 
-       platform_set_drvdata(pdev, di);
+       snprintf(name, sizeof(name), "ds2760-battery.%d", dev->id);
 
-       di->dev                         = &pdev->dev;
-       di->w1_dev                      = pdev->dev.parent;
-       di->bat_desc.name               = dev_name(&pdev->dev);
+       di->dev                         = dev;
+       di->bat_desc.name               = name;
        di->bat_desc.type               = POWER_SUPPLY_TYPE_BATTERY;
        di->bat_desc.properties         = ds2760_battery_props;
        di->bat_desc.num_properties     = ARRAY_SIZE(ds2760_battery_props);
@@ -533,10 +704,30 @@ static int ds2760_battery_probe(struct platform_device *pdev)
        di->bat_desc.external_power_changed =
                                  ds2760_battery_external_power_changed;
 
-       psy_cfg.drv_data                = di;
+       psy_cfg.drv_data = di;
+
+       if (dev->of_node) {
+               u32 tmp;
+
+               psy_cfg.of_node = dev->of_node;
+
+               if (!of_property_read_bool(dev->of_node, "maxim,pmod-enabled"))
+                       pmod_enabled = true;
+
+               if (!of_property_read_u32(dev->of_node,
+                                         "maxim,cache-time-ms", &tmp))
+                       cache_time = tmp;
+
+               if (!of_property_read_u32(dev->of_node,
+                                         "rated-capacity-microamp-hours",
+                                         &tmp))
+                       rated_capacity = tmp / 10; /* property is in mAh */
+       }
 
        di->charge_status = POWER_SUPPLY_STATUS_UNKNOWN;
 
+       sl->family_data = di;
+
        /* enable sleep mode feature */
        ds2760_battery_read_status(di);
        status = di->raw[DS2760_STATUS_REG];
@@ -547,7 +738,7 @@ static int ds2760_battery_probe(struct platform_device *pdev)
 
        ds2760_battery_write_status(di, status);
 
-       /* set rated capacity from module param */
+       /* set rated capacity from module param or device tree */
        if (rated_capacity)
                ds2760_battery_write_rated_capacity(di, rated_capacity);
 
@@ -556,7 +747,7 @@ static int ds2760_battery_probe(struct platform_device *pdev)
        if (current_accum)
                ds2760_battery_set_current_accum(di, current_accum);
 
-       di->bat = power_supply_register(&pdev->dev, &di->bat_desc, &psy_cfg);
+       di->bat = power_supply_register(dev, &di->bat_desc, &psy_cfg);
        if (IS_ERR(di->bat)) {
                dev_err(di->dev, "failed to register battery\n");
                retval = PTR_ERR(di->bat);
@@ -566,14 +757,16 @@ static int ds2760_battery_probe(struct platform_device *pdev)
        INIT_DELAYED_WORK(&di->monitor_work, ds2760_battery_work);
        INIT_DELAYED_WORK(&di->set_charged_work,
                          ds2760_battery_set_charged_work);
-       di->monitor_wqueue = alloc_ordered_workqueue(dev_name(&pdev->dev),
-                                                    WQ_MEM_RECLAIM);
+       di->monitor_wqueue = alloc_ordered_workqueue(name, WQ_MEM_RECLAIM);
        if (!di->monitor_wqueue) {
                retval = -ESRCH;
                goto workqueue_failed;
        }
        queue_delayed_work(di->monitor_wqueue, &di->monitor_work, HZ * 1);
 
+       di->pm_notifier.notifier_call = ds2760_pm_notifier;
+       register_pm_notifier(&di->pm_notifier);
+
        goto success;
 
 workqueue_failed:
@@ -584,65 +777,40 @@ success:
        return retval;
 }
 
-static int ds2760_battery_remove(struct platform_device *pdev)
+static void w1_ds2760_remove_slave(struct w1_slave *sl)
 {
-       struct ds2760_device_info *di = platform_get_drvdata(pdev);
+       struct ds2760_device_info *di = sl->family_data;
 
+       unregister_pm_notifier(&di->pm_notifier);
        cancel_delayed_work_sync(&di->monitor_work);
        cancel_delayed_work_sync(&di->set_charged_work);
        destroy_workqueue(di->monitor_wqueue);
        power_supply_unregister(di->bat);
-
-       return 0;
-}
-
-#ifdef CONFIG_PM
-
-static int ds2760_battery_suspend(struct platform_device *pdev,
-                                 pm_message_t state)
-{
-       struct ds2760_device_info *di = platform_get_drvdata(pdev);
-
-       di->charge_status = POWER_SUPPLY_STATUS_UNKNOWN;
-
-       return 0;
-}
-
-static int ds2760_battery_resume(struct platform_device *pdev)
-{
-       struct ds2760_device_info *di = platform_get_drvdata(pdev);
-
-       di->charge_status = POWER_SUPPLY_STATUS_UNKNOWN;
-       power_supply_changed(di->bat);
-
-       mod_delayed_work(di->monitor_wqueue, &di->monitor_work, HZ);
-
-       return 0;
 }
 
-#else
-
-#define ds2760_battery_suspend NULL
-#define ds2760_battery_resume NULL
-
-#endif /* CONFIG_PM */
-
-MODULE_ALIAS("platform:ds2760-battery");
+#ifdef CONFIG_OF
+static const struct of_device_id w1_ds2760_of_ids[] = {
+       { .compatible = "maxim,ds2760" },
+       {}
+};
+#endif
 
-static struct platform_driver ds2760_battery_driver = {
-       .driver = {
-               .name = "ds2760-battery",
-       },
-       .probe    = ds2760_battery_probe,
-       .remove   = ds2760_battery_remove,
-       .suspend  = ds2760_battery_suspend,
-       .resume   = ds2760_battery_resume,
+static struct w1_family_ops w1_ds2760_fops = {
+       .add_slave      = w1_ds2760_add_slave,
+       .remove_slave   = w1_ds2760_remove_slave,
+       .groups         = w1_ds2760_groups,
 };
 
-module_platform_driver(ds2760_battery_driver);
+static struct w1_family w1_ds2760_family = {
+       .fid            = W1_FAMILY_DS2760,
+       .fops           = &w1_ds2760_fops,
+       .of_match_table = of_match_ptr(w1_ds2760_of_ids),
+};
+module_w1_family(w1_ds2760_family);
 
-MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Szabolcs Gyurko <szabolcs.gyurko@tlt.hu>, "
              "Matt Reimer <mreimer@vpop.net>, "
              "Anton Vorontsov <cbou@mail.ru>");
-MODULE_DESCRIPTION("ds2760 battery driver");
+MODULE_DESCRIPTION("1-wire Driver Dallas 2760 battery monitor chip");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("w1-family-" __stringify(W1_FAMILY_DS2760));
index 28dc056..bc462d1 100644 (file)
@@ -241,10 +241,10 @@ static int gab_probe(struct platform_device *pdev)
        struct power_supply_desc *psy_desc;
        struct power_supply_config psy_cfg = {};
        struct gab_platform_data *pdata = pdev->dev.platform_data;
-       enum power_supply_property *properties;
        int ret = 0;
        int chan;
-       int index = 0;
+       int index = ARRAY_SIZE(gab_props);
+       bool any = false;
 
        adc_bat = devm_kzalloc(&pdev->dev, sizeof(*adc_bat), GFP_KERNEL);
        if (!adc_bat) {
@@ -278,8 +278,6 @@ static int gab_probe(struct platform_device *pdev)
        }
 
        memcpy(psy_desc->properties, gab_props, sizeof(gab_props));
-       properties = (enum power_supply_property *)
-                       ((char *)psy_desc->properties + sizeof(gab_props));
 
        /*
         * getting channel from iio and copying the battery properties
@@ -293,15 +291,22 @@ static int gab_probe(struct platform_device *pdev)
                        adc_bat->channel[chan] = NULL;
                } else {
                        /* copying properties for supported channels only */
-                       memcpy(properties + sizeof(*(psy_desc->properties)) * index,
-                                       &gab_dyn_props[chan],
-                                       sizeof(gab_dyn_props[chan]));
-                       index++;
+                       int index2;
+
+                       for (index2 = 0; index2 < index; index2++) {
+                               if (psy_desc->properties[index2] ==
+                                   gab_dyn_props[chan])
+                                       break;  /* already known */
+                       }
+                       if (index2 == index)    /* really new */
+                               psy_desc->properties[index++] =
+                                       gab_dyn_props[chan];
+                       any = true;
                }
        }
 
        /* none of the channels are supported so let's bail out */
-       if (index == 0) {
+       if (!any) {
                ret = -ENODEV;
                goto second_mem_fail;
        }
@@ -312,7 +317,7 @@ static int gab_probe(struct platform_device *pdev)
         * as come channels may be not be supported by the device.So
         * we need to take care of that.
         */
-       psy_desc->num_properties = ARRAY_SIZE(gab_props) + index;
+       psy_desc->num_properties = index;
 
        adc_bat->psy = power_supply_register(&pdev->dev, psy_desc, &psy_cfg);
        if (IS_ERR(adc_bat->psy)) {
index 7b993d6..1ae3710 100644 (file)
@@ -39,7 +39,7 @@ static int lego_ev3_battery_get_property(struct power_supply *psy,
                                         union power_supply_propval *val)
 {
        struct lego_ev3_battery *batt = power_supply_get_drvdata(psy);
-       int val2;
+       int ret, val2;
 
        switch (psp) {
        case POWER_SUPPLY_PROP_TECHNOLOGY:
@@ -47,11 +47,18 @@ static int lego_ev3_battery_get_property(struct power_supply *psy,
                break;
        case POWER_SUPPLY_PROP_VOLTAGE_NOW:
                /* battery voltage is iio channel * 2 + Vce of transistor */
-               iio_read_channel_processed(batt->iio_v, &val->intval);
+               ret = iio_read_channel_processed(batt->iio_v, &val->intval);
+               if (ret)
+                       return ret;
+
                val->intval *= 2000;
-               val->intval += 200000;
+               val->intval += 50000;
+
                /* plus adjust for shunt resistor drop */
-               iio_read_channel_processed(batt->iio_i, &val2);
+               ret = iio_read_channel_processed(batt->iio_i, &val2);
+               if (ret)
+                       return ret;
+
                val2 *= 1000;
                val2 /= 15;
                val->intval += val2;
@@ -64,7 +71,10 @@ static int lego_ev3_battery_get_property(struct power_supply *psy,
                break;
        case POWER_SUPPLY_PROP_CURRENT_NOW:
                /* battery current is iio channel / 15 / 0.05 ohms */
-               iio_read_channel_processed(batt->iio_i, &val->intval);
+               ret = iio_read_channel_processed(batt->iio_i, &val->intval);
+               if (ret)
+                       return ret;
+
                val->intval *= 20000;
                val->intval /= 15;
                break;
index 9ee601a..9ca895b 100644 (file)
@@ -372,7 +372,7 @@ static int devm_w1_max1721x_add_device(struct w1_slave *sl)
        }
 
        if (!info->rsense) {
-               dev_warn(info->w1_dev, "RSenese not calibrated, set 10 mOhms!\n");
+               dev_warn(info->w1_dev, "RSense not calibrated, set 10 mOhms!\n");
                info->rsense = 1000; /* in regs in 10^-5 */
        }
        dev_info(info->w1_dev, "RSense: %d mOhms.\n", info->rsense / 100);
index 6c78884..749c792 100644 (file)
@@ -567,6 +567,7 @@ static int max77693_set_charge_input_threshold_volt(struct max77693_charger *chg
        case 4800000:
        case 4900000:
                data = (uvolt - 4700000) / 100000;
+               break;
        default:
                dev_err(chg->dev, "Wrong value for charge input voltage regulation threshold\n");
                return -EINVAL;
index d21f478..e853618 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/types.h>
 #include <linux/init.h>
 #include <linux/slab.h>
+#include <linux/delay.h>
 #include <linux/device.h>
 #include <linux/notifier.h>
 #include <linux/err.h>
@@ -140,8 +141,13 @@ static void power_supply_deferred_register_work(struct work_struct *work)
        struct power_supply *psy = container_of(work, struct power_supply,
                                                deferred_register_work.work);
 
-       if (psy->dev.parent)
-               mutex_lock(&psy->dev.parent->mutex);
+       if (psy->dev.parent) {
+               while (!mutex_trylock(&psy->dev.parent->mutex)) {
+                       if (psy->removing)
+                               return;
+                       msleep(10);
+               }
+       }
 
        power_supply_changed(psy);
 
@@ -1082,6 +1088,7 @@ EXPORT_SYMBOL_GPL(devm_power_supply_register_no_ws);
 void power_supply_unregister(struct power_supply *psy)
 {
        WARN_ON(atomic_dec_return(&psy->use_cnt));
+       psy->removing = true;
        cancel_work_sync(&psy->changed_work);
        cancel_delayed_work_sync(&psy->deferred_register_work);
        sysfs_remove_link(&psy->dev.kobj, "powers");
index 83d7b41..8ba6abf 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/of.h>
+#include <linux/of_device.h>
 #include <linux/power/sbs-battery.h>
 #include <linux/power_supply.h>
 #include <linux/slab.h>
@@ -156,6 +157,9 @@ static enum power_supply_property sbs_properties[] = {
        POWER_SUPPLY_PROP_MODEL_NAME
 };
 
+/* Supports special manufacturer commands from TI BQ20Z75 IC. */
+#define SBS_FLAGS_TI_BQ20Z75           BIT(0)
+
 struct sbs_info {
        struct i2c_client               *client;
        struct power_supply             *power_supply;
@@ -168,6 +172,7 @@ struct sbs_info {
        u32                             poll_retry_count;
        struct delayed_work             work;
        struct mutex                    mode_lock;
+       u32                             flags;
 };
 
 static char model_name[I2C_SMBUS_BLOCK_MAX + 1];
@@ -316,16 +321,40 @@ static int sbs_get_battery_presence_and_health(
        struct i2c_client *client, enum power_supply_property psp,
        union power_supply_propval *val)
 {
+       int ret;
+
+       if (psp == POWER_SUPPLY_PROP_PRESENT) {
+               /* Dummy command; if it succeeds, battery is present. */
+               ret = sbs_read_word_data(client, sbs_data[REG_STATUS].addr);
+               if (ret < 0)
+                       val->intval = 0; /* battery disconnected */
+               else
+                       val->intval = 1; /* battery present */
+       } else { /* POWER_SUPPLY_PROP_HEALTH */
+               /* SBS spec doesn't have a general health command. */
+               val->intval = POWER_SUPPLY_HEALTH_UNKNOWN;
+       }
+
+       return 0;
+}
+
+static int sbs_get_ti_battery_presence_and_health(
+       struct i2c_client *client, enum power_supply_property psp,
+       union power_supply_propval *val)
+{
        s32 ret;
 
        /*
         * Write to ManufacturerAccess with ManufacturerAccess command
-        * and then read the status. Do not check for error on the write
-        * since not all batteries implement write access to this command,
-        * while others mandate it.
+        * and then read the status.
         */
-       sbs_write_word_data(client, sbs_data[REG_MANUFACTURER_DATA].addr,
-                           MANUFACTURER_ACCESS_STATUS);
+       ret = sbs_write_word_data(client, sbs_data[REG_MANUFACTURER_DATA].addr,
+                                 MANUFACTURER_ACCESS_STATUS);
+       if (ret < 0) {
+               if (psp == POWER_SUPPLY_PROP_PRESENT)
+                       val->intval = 0; /* battery removed */
+               return ret;
+       }
 
        ret = sbs_read_word_data(client, sbs_data[REG_MANUFACTURER_DATA].addr);
        if (ret < 0) {
@@ -600,7 +629,12 @@ static int sbs_get_property(struct power_supply *psy,
        switch (psp) {
        case POWER_SUPPLY_PROP_PRESENT:
        case POWER_SUPPLY_PROP_HEALTH:
-               ret = sbs_get_battery_presence_and_health(client, psp, val);
+               if (client->flags & SBS_FLAGS_TI_BQ20Z75)
+                       ret = sbs_get_ti_battery_presence_and_health(client,
+                                                                    psp, val);
+               else
+                       ret = sbs_get_battery_presence_and_health(client, psp,
+                                                                 val);
                if (psp == POWER_SUPPLY_PROP_PRESENT)
                        return 0;
                break;
@@ -806,6 +840,7 @@ static int sbs_probe(struct i2c_client *client,
        if (!chip)
                return -ENOMEM;
 
+       chip->flags = (u32)(uintptr_t)of_device_get_match_data(&client->dev);
        chip->client = client;
        chip->enable_detection = false;
        psy_cfg.of_node = client->dev.of_node;
@@ -911,16 +946,19 @@ static int sbs_suspend(struct device *dev)
 {
        struct i2c_client *client = to_i2c_client(dev);
        struct sbs_info *chip = i2c_get_clientdata(client);
+       int ret;
 
        if (chip->poll_time > 0)
                cancel_delayed_work_sync(&chip->work);
 
-       /*
-        * Write to manufacturer access with sleep command.
-        * Support is manufacturer dependend, so ignore errors.
-        */
-       sbs_write_word_data(client, sbs_data[REG_MANUFACTURER_DATA].addr,
-               MANUFACTURER_ACCESS_SLEEP);
+       if (chip->flags & SBS_FLAGS_TI_BQ20Z75) {
+               /* Write to manufacturer access with sleep command. */
+               ret = sbs_write_word_data(client,
+                                         sbs_data[REG_MANUFACTURER_DATA].addr,
+                                         MANUFACTURER_ACCESS_SLEEP);
+               if (chip->is_present && ret < 0)
+                       return ret;
+       }
 
        return 0;
 }
@@ -941,7 +979,10 @@ MODULE_DEVICE_TABLE(i2c, sbs_id);
 
 static const struct of_device_id sbs_dt_ids[] = {
        { .compatible = "sbs,sbs-battery" },
-       { .compatible = "ti,bq20z75" },
+       {
+               .compatible = "ti,bq20z75",
+               .data = (void *)SBS_FLAGS_TI_BQ20Z75,
+       },
        { }
 };
 MODULE_DEVICE_TABLE(of, sbs_dt_ids);
index 1f52340..814c2b8 100644 (file)
@@ -1,20 +1,8 @@
-/*
- * Battery charger driver for TI's tps65217
- *
- * Copyright (c) 2015, Collabora Ltd.
-
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
-
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
+// SPDX-License-Identifier: GPL-2.0
+// Battery charger driver for TI's tps65217
+//
+// Copyright (C) 2015 Collabora Ltd.
+// Author: Enric Balletbo i Serra <enric.balletbo@collabora.com>
 
 /*
  * Battery charger driver for TI's tps65217
index a2740cf..15c0ca1 100644 (file)
@@ -230,7 +230,8 @@ static irqreturn_t wm8350_charger_handler(int irq, void *data)
        case WM8350_IRQ_EXT_USB_FB:
        case WM8350_IRQ_EXT_WALL_FB:
                wm8350_charger_config(wm8350, policy);
-       case WM8350_IRQ_EXT_BAT_FB:   /* Fall through */
+               /* Fall through */
+       case WM8350_IRQ_EXT_BAT_FB:
                power_supply_changed(power->battery);
                power_supply_changed(power->usb);
                power_supply_changed(power->ac);
index a4d262d..504d252 100644 (file)
@@ -286,7 +286,7 @@ config PWM_MTK_DISP
 
 config PWM_MEDIATEK
        tristate "MediaTek PWM support"
-       depends on ARCH_MEDIATEK || COMPILE_TEST
+       depends on ARCH_MEDIATEK || RALINK || COMPILE_TEST
        help
          Generic PWM framework driver for Mediatek ARM SoC.
 
index 771859a..7c8d6a1 100644 (file)
 #define BERLIN_PWM_EN                  0x0
 #define  BERLIN_PWM_ENABLE             BIT(0)
 #define BERLIN_PWM_CONTROL             0x4
-#define  BERLIN_PWM_PRESCALE_MASK      0x7
-#define  BERLIN_PWM_PRESCALE_MAX       4096
+/*
+ * The prescaler claims to support 8 different moduli, configured using the
+ * low three bits of PWM_CONTROL. (Sequentially, they are 1, 4, 8, 16, 64,
+ * 256, 1024, and 4096.)  However, the moduli from 4 to 1024 appear to be
+ * implemented by internally shifting TCNT left without adding additional
+ * bits. So, the max TCNT that actually works for a modulus of 4 is 0x3fff;
+ * for 8, 0x1fff; and so on. This means that those moduli are entirely
+ * useless, as we could just do the shift ourselves. The 4096 modulus is
+ * implemented with a real prescaler, so we do use that, but we treat it
+ * as a flag instead of pretending the modulus is actually configurable.
+ */
+#define  BERLIN_PWM_PRESCALE_4096      0x7
 #define  BERLIN_PWM_INVERT_POLARITY    BIT(3)
 #define BERLIN_PWM_DUTY                        0x8
 #define BERLIN_PWM_TCNT                        0xc
@@ -46,10 +56,6 @@ static inline struct berlin_pwm_chip *to_berlin_pwm_chip(struct pwm_chip *chip)
        return container_of(chip, struct berlin_pwm_chip, chip);
 }
 
-static const u32 prescaler_table[] = {
-       1, 4, 8, 16, 64, 256, 1024, 4096
-};
-
 static inline u32 berlin_pwm_readl(struct berlin_pwm_chip *chip,
                                   unsigned int channel, unsigned long offset)
 {
@@ -86,33 +92,32 @@ static int berlin_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm_dev,
                             int duty_ns, int period_ns)
 {
        struct berlin_pwm_chip *pwm = to_berlin_pwm_chip(chip);
-       unsigned int prescale;
+       bool prescale_4096 = false;
        u32 value, duty, period;
-       u64 cycles, tmp;
+       u64 cycles;
 
        cycles = clk_get_rate(pwm->clk);
        cycles *= period_ns;
        do_div(cycles, NSEC_PER_SEC);
 
-       for (prescale = 0; prescale < ARRAY_SIZE(prescaler_table); prescale++) {
-               tmp = cycles;
-               do_div(tmp, prescaler_table[prescale]);
+       if (cycles > BERLIN_PWM_MAX_TCNT) {
+               prescale_4096 = true;
+               cycles >>= 12; // Prescaled by 4096
 
-               if (tmp <= BERLIN_PWM_MAX_TCNT)
-                       break;
+               if (cycles > BERLIN_PWM_MAX_TCNT)
+                       return -ERANGE;
        }
 
-       if (tmp > BERLIN_PWM_MAX_TCNT)
-               return -ERANGE;
-
-       period = tmp;
-       cycles = tmp * duty_ns;
+       period = cycles;
+       cycles *= duty_ns;
        do_div(cycles, period_ns);
        duty = cycles;
 
        value = berlin_pwm_readl(pwm, pwm_dev->hwpwm, BERLIN_PWM_CONTROL);
-       value &= ~BERLIN_PWM_PRESCALE_MASK;
-       value |= prescale;
+       if (prescale_4096)
+               value |= BERLIN_PWM_PRESCALE_4096;
+       else
+               value &= ~BERLIN_PWM_PRESCALE_4096;
        berlin_pwm_writel(pwm, pwm_dev->hwpwm, value, BERLIN_PWM_CONTROL);
 
        berlin_pwm_writel(pwm, pwm_dev->hwpwm, duty, BERLIN_PWM_DUTY);
index 9c13694..98f6ac6 100644 (file)
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
- * Copyright (C) 2016 Google, 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.
- *
  * Expose a PWM controlled by the ChromeOS EC to the host processor.
+ *
+ * Copyright (C) 2016 Google, Inc.
  */
 
 #include <linux/module.h>
index 557b4ea..883378d 100644 (file)
@@ -16,6 +16,7 @@
 #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/pm.h>
 #include <linux/pwm.h>
@@ -75,6 +76,10 @@ enum fsl_pwm_clk {
        FSL_PWM_CLK_MAX
 };
 
+struct fsl_ftm_soc {
+       bool has_enable_bits;
+};
+
 struct fsl_pwm_chip {
        struct pwm_chip chip;
 
@@ -87,7 +92,10 @@ struct fsl_pwm_chip {
 
        int period_ns;
 
+       struct clk *ipg_clk;
        struct clk *clk[FSL_PWM_CLK_MAX];
+
+       const struct fsl_ftm_soc *soc;
 };
 
 static inline struct fsl_pwm_chip *to_fsl_chip(struct pwm_chip *chip)
@@ -97,16 +105,32 @@ static inline struct fsl_pwm_chip *to_fsl_chip(struct pwm_chip *chip)
 
 static int fsl_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)
 {
+       int ret;
        struct fsl_pwm_chip *fpc = to_fsl_chip(chip);
 
-       return clk_prepare_enable(fpc->clk[FSL_PWM_CLK_SYS]);
+       ret = clk_prepare_enable(fpc->ipg_clk);
+       if (!ret && fpc->soc->has_enable_bits) {
+               mutex_lock(&fpc->lock);
+               regmap_update_bits(fpc->regmap, FTM_SC, BIT(pwm->hwpwm + 16),
+                                  BIT(pwm->hwpwm + 16));
+               mutex_unlock(&fpc->lock);
+       }
+
+       return ret;
 }
 
 static void fsl_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
 {
        struct fsl_pwm_chip *fpc = to_fsl_chip(chip);
 
-       clk_disable_unprepare(fpc->clk[FSL_PWM_CLK_SYS]);
+       if (fpc->soc->has_enable_bits) {
+               mutex_lock(&fpc->lock);
+               regmap_update_bits(fpc->regmap, FTM_SC, BIT(pwm->hwpwm + 16),
+                                  0);
+               mutex_unlock(&fpc->lock);
+       }
+
+       clk_disable_unprepare(fpc->ipg_clk);
 }
 
 static int fsl_pwm_calculate_default_ps(struct fsl_pwm_chip *fpc,
@@ -363,7 +387,7 @@ static int fsl_pwm_init(struct fsl_pwm_chip *fpc)
 {
        int ret;
 
-       ret = clk_prepare_enable(fpc->clk[FSL_PWM_CLK_SYS]);
+       ret = clk_prepare_enable(fpc->ipg_clk);
        if (ret)
                return ret;
 
@@ -371,7 +395,7 @@ static int fsl_pwm_init(struct fsl_pwm_chip *fpc)
        regmap_write(fpc->regmap, FTM_OUTINIT, 0x00);
        regmap_write(fpc->regmap, FTM_OUTMASK, 0xFF);
 
-       clk_disable_unprepare(fpc->clk[FSL_PWM_CLK_SYS]);
+       clk_disable_unprepare(fpc->ipg_clk);
 
        return 0;
 }
@@ -408,6 +432,7 @@ static int fsl_pwm_probe(struct platform_device *pdev)
 
        mutex_init(&fpc->lock);
 
+       fpc->soc = of_device_get_match_data(&pdev->dev);
        fpc->chip.dev = &pdev->dev;
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -441,6 +466,15 @@ static int fsl_pwm_probe(struct platform_device *pdev)
        if (IS_ERR(fpc->clk[FSL_PWM_CLK_CNTEN]))
                return PTR_ERR(fpc->clk[FSL_PWM_CLK_CNTEN]);
 
+       /*
+        * ipg_clk is the interface clock for the IP. If not provided, use the
+        * ftm_sys clock as the default.
+        */
+       fpc->ipg_clk = devm_clk_get(&pdev->dev, "ipg");
+       if (IS_ERR(fpc->ipg_clk))
+               fpc->ipg_clk = fpc->clk[FSL_PWM_CLK_SYS];
+
+
        fpc->chip.ops = &fsl_pwm_ops;
        fpc->chip.of_xlate = of_pwm_xlate_with_flags;
        fpc->chip.of_pwm_n_cells = 3;
@@ -480,7 +514,7 @@ static int fsl_pwm_suspend(struct device *dev)
                if (!test_bit(PWMF_REQUESTED, &pwm->flags))
                        continue;
 
-               clk_disable_unprepare(fpc->clk[FSL_PWM_CLK_SYS]);
+               clk_disable_unprepare(fpc->ipg_clk);
 
                if (!pwm_is_enabled(pwm))
                        continue;
@@ -503,7 +537,7 @@ static int fsl_pwm_resume(struct device *dev)
                if (!test_bit(PWMF_REQUESTED, &pwm->flags))
                        continue;
 
-               clk_prepare_enable(fpc->clk[FSL_PWM_CLK_SYS]);
+               clk_prepare_enable(fpc->ipg_clk);
 
                if (!pwm_is_enabled(pwm))
                        continue;
@@ -524,8 +558,17 @@ static const struct dev_pm_ops fsl_pwm_pm_ops = {
        SET_SYSTEM_SLEEP_PM_OPS(fsl_pwm_suspend, fsl_pwm_resume)
 };
 
+static const struct fsl_ftm_soc vf610_ftm_pwm = {
+       .has_enable_bits = false,
+};
+
+static const struct fsl_ftm_soc imx8qm_ftm_pwm = {
+       .has_enable_bits = true,
+};
+
 static const struct of_device_id fsl_pwm_dt_ids[] = {
-       { .compatible = "fsl,vf610-ftm-pwm", },
+       { .compatible = "fsl,vf610-ftm-pwm", .data = &vf610_ftm_pwm },
+       { .compatible = "fsl,imx8qm-ftm-pwm", .data = &imx8qm_ftm_pwm },
        { /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, fsl_pwm_dt_ids);
index 08cbe81..1d5242c 100644 (file)
@@ -1,10 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * simple driver for PWM (Pulse Width Modulator) controller
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
  * Derived from pxa PWM driver by eric miao <eric.miao@marvell.com>
  */
 
index 328c124..eb6674c 100644 (file)
@@ -57,6 +57,7 @@ static const char * const mtk_pwm_clk_name[MTK_CLK_MAX] = {
 struct mtk_pwm_platform_data {
        unsigned int num_pwms;
        bool pwm45_fixup;
+       bool has_clks;
 };
 
 /**
@@ -86,6 +87,9 @@ static int mtk_pwm_clk_enable(struct pwm_chip *chip, struct pwm_device *pwm)
        struct mtk_pwm_chip *pc = to_mtk_pwm_chip(chip);
        int ret;
 
+       if (!pc->soc->has_clks)
+               return 0;
+
        ret = clk_prepare_enable(pc->clks[MTK_CLK_TOP]);
        if (ret < 0)
                return ret;
@@ -112,6 +116,9 @@ static void mtk_pwm_clk_disable(struct pwm_chip *chip, struct pwm_device *pwm)
 {
        struct mtk_pwm_chip *pc = to_mtk_pwm_chip(chip);
 
+       if (!pc->soc->has_clks)
+               return;
+
        clk_disable_unprepare(pc->clks[MTK_CLK_PWM1 + pwm->hwpwm]);
        clk_disable_unprepare(pc->clks[MTK_CLK_MAIN]);
        clk_disable_unprepare(pc->clks[MTK_CLK_TOP]);
@@ -239,7 +246,7 @@ static int mtk_pwm_probe(struct platform_device *pdev)
        if (IS_ERR(pc->regs))
                return PTR_ERR(pc->regs);
 
-       for (i = 0; i < data->num_pwms + 2; i++) {
+       for (i = 0; i < data->num_pwms + 2 && pc->soc->has_clks; i++) {
                pc->clks[i] = devm_clk_get(&pdev->dev, mtk_pwm_clk_name[i]);
                if (IS_ERR(pc->clks[i])) {
                        dev_err(&pdev->dev, "clock: %s fail: %ld\n",
@@ -274,22 +281,32 @@ static int mtk_pwm_remove(struct platform_device *pdev)
 static const struct mtk_pwm_platform_data mt2712_pwm_data = {
        .num_pwms = 8,
        .pwm45_fixup = false,
+       .has_clks = true,
 };
 
 static const struct mtk_pwm_platform_data mt7622_pwm_data = {
        .num_pwms = 6,
        .pwm45_fixup = false,
+       .has_clks = true,
 };
 
 static const struct mtk_pwm_platform_data mt7623_pwm_data = {
        .num_pwms = 5,
        .pwm45_fixup = true,
+       .has_clks = true,
+};
+
+static const struct mtk_pwm_platform_data mt7628_pwm_data = {
+       .num_pwms = 4,
+       .pwm45_fixup = true,
+       .has_clks = false,
 };
 
 static const struct of_device_id mtk_pwm_of_match[] = {
        { .compatible = "mediatek,mt2712-pwm", .data = &mt2712_pwm_data },
        { .compatible = "mediatek,mt7622-pwm", .data = &mt7622_pwm_data },
        { .compatible = "mediatek,mt7623-pwm", .data = &mt7623_pwm_data },
+       { .compatible = "mediatek,mt7628-pwm", .data = &mt7628_pwm_data },
        { },
 };
 MODULE_DEVICE_TABLE(of, mtk_pwm_of_match);
index 822860b..c1ed641 100644 (file)
@@ -458,7 +458,6 @@ static int meson_pwm_init_channels(struct meson_pwm *meson,
                                   struct meson_pwm_channel *channels)
 {
        struct device *dev = meson->chip.dev;
-       struct device_node *np = dev->of_node;
        struct clk_init_data init;
        unsigned int i;
        char name[255];
@@ -467,7 +466,7 @@ static int meson_pwm_init_channels(struct meson_pwm *meson,
        for (i = 0; i < meson->chip.npwm; i++) {
                struct meson_pwm_channel *channel = &channels[i];
 
-               snprintf(name, sizeof(name), "%pOF#mux%u", np, i);
+               snprintf(name, sizeof(name), "%s#mux%u", dev_name(dev), i);
 
                init.name = name;
                init.ops = &clk_mux_ops;
index a6017ad..04c0f6b 100644 (file)
@@ -1,12 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright 2012 Freescale Semiconductor, Inc.
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
  */
 
 #include <linux/clk.h>
index 665da3c..f457986 100644 (file)
@@ -264,8 +264,9 @@ static int pwm_omap_dmtimer_probe(struct platform_device *pdev)
 
        timer_pdata = dev_get_platdata(&timer_pdev->dev);
        if (!timer_pdata) {
-               dev_err(&pdev->dev, "dmtimer pdata structure NULL\n");
-               ret = -EINVAL;
+               dev_dbg(&pdev->dev,
+                        "dmtimer pdata structure NULL, deferring probe\n");
+               ret = -EPROBE_DEFER;
                goto put;
        }
 
index 7c13e25..0059b24 100644 (file)
@@ -217,10 +217,8 @@ static int stm32_pwm_lp_probe(struct platform_device *pdev)
 static int stm32_pwm_lp_remove(struct platform_device *pdev)
 {
        struct stm32_pwm_lp *priv = platform_get_drvdata(pdev);
-       unsigned int i;
 
-       for (i = 0; i < priv->chip.npwm; i++)
-               pwm_disable(&priv->chip.pwms[i]);
+       pwm_disable(&priv->chip.pwms[0]);
 
        return pwmchip_remove(&priv->chip);
 }
index 4c22cb3..f7b8a86 100644 (file)
 #define TBCTL                  0x00
 #define TBPRD                  0x0A
 
-#define TBCTL_RUN_MASK         (BIT(15) | BIT(14))
-#define TBCTL_STOP_NEXT                0
-#define TBCTL_STOP_ON_CYCLE    BIT(14)
-#define TBCTL_FREE_RUN         (BIT(15) | BIT(14))
 #define TBCTL_PRDLD_MASK       BIT(3)
 #define TBCTL_PRDLD_SHDW       0
 #define TBCTL_PRDLD_IMDT       BIT(3)
@@ -360,7 +356,7 @@ static int ehrpwm_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
        /* Channels polarity can be configured from action qualifier module */
        configure_polarity(pc, pwm->hwpwm);
 
-       /* Enable TBCLK before enabling PWM device */
+       /* Enable TBCLK */
        ret = clk_enable(pc->tbclk);
        if (ret) {
                dev_err(chip->dev, "Failed to enable TBCLK for %s: %d\n",
@@ -368,9 +364,6 @@ static int ehrpwm_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
                return ret;
        }
 
-       /* Enable time counter for free_run */
-       ehrpwm_modify(pc->mmio_base, TBCTL, TBCTL_RUN_MASK, TBCTL_FREE_RUN);
-
        return 0;
 }
 
@@ -388,6 +381,8 @@ static void ehrpwm_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
                aqcsfrc_mask = AQCSFRC_CSFA_MASK;
        }
 
+       /* Update shadow register first before modifying active register */
+       ehrpwm_modify(pc->mmio_base, AQCSFRC, aqcsfrc_mask, aqcsfrc_val);
        /*
         * Changes to immediate action on Action Qualifier. This puts
         * Action Qualifier control on PWM output from next TBCLK
@@ -400,9 +395,6 @@ static void ehrpwm_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
        /* Disabling TBCLK on PWM disable */
        clk_disable(pc->tbclk);
 
-       /* Stop Time base counter */
-       ehrpwm_modify(pc->mmio_base, TBCTL, TBCTL_RUN_MASK, TBCTL_STOP_NEXT);
-
        /* Disable clock on PWM disable */
        pm_runtime_put_sync(chip->dev);
 }
index a8cb8d2..cbe467f 100644 (file)
@@ -1006,7 +1006,6 @@ out_free:
 static int rio_mport_wait_for_async_dma(struct file *filp, void __user *arg)
 {
        struct mport_cdev_priv *priv;
-       struct mport_dev *md;
        struct rio_async_tx_wait w_param;
        struct mport_dma_req *req;
        dma_cookie_t cookie;
@@ -1016,7 +1015,6 @@ static int rio_mport_wait_for_async_dma(struct file *filp, void __user *arg)
        int ret;
 
        priv = (struct mport_cdev_priv *)filp->private_data;
-       md = priv->md;
 
        if (unlikely(copy_from_user(&w_param, arg, sizeof(w_param))))
                return -EFAULT;
index 2df26f3..8cbcd2a 100644 (file)
@@ -98,7 +98,7 @@ struct da9063_regulator_info {
 struct da9063_dev_model {
        const struct da9063_regulator_info      *regulator_info;
        unsigned                                n_regulators;
-       unsigned                                dev_model;
+       enum da9063_type                        type;
 };
 
 /* Single regulator settings */
@@ -530,6 +530,32 @@ static const struct da9063_regulator_info da9063_regulator_info[] = {
                                 DA9063_BMEM_ILIM_MASK),
        },
        {
+               DA9063_LDO(DA9063, LDO3, 900, 20, 3440),
+               .suspend = BFIELD(DA9063_REG_DVC_1, DA9063_VLDO3_SEL),
+               .oc_event = BFIELD(DA9063_REG_STATUS_D, DA9063_LDO3_LIM),
+       },
+       {
+               DA9063_LDO(DA9063, LDO7, 900, 50, 3600),
+               .suspend = BFIELD(DA9063_REG_LDO7_CONT, DA9063_VLDO7_SEL),
+               .oc_event = BFIELD(DA9063_REG_STATUS_D, DA9063_LDO7_LIM),
+       },
+       {
+               DA9063_LDO(DA9063, LDO8, 900, 50, 3600),
+               .suspend = BFIELD(DA9063_REG_LDO8_CONT, DA9063_VLDO8_SEL),
+               .oc_event = BFIELD(DA9063_REG_STATUS_D, DA9063_LDO8_LIM),
+       },
+       {
+               DA9063_LDO(DA9063, LDO9, 950, 50, 3600),
+               .suspend = BFIELD(DA9063_REG_LDO9_CONT, DA9063_VLDO9_SEL),
+       },
+       {
+               DA9063_LDO(DA9063, LDO11, 900, 50, 3600),
+               .suspend = BFIELD(DA9063_REG_LDO11_CONT, DA9063_VLDO11_SEL),
+               .oc_event = BFIELD(DA9063_REG_STATUS_D, DA9063_LDO11_LIM),
+       },
+
+       /* The following LDOs are present only on DA9063, not on DA9063L */
+       {
                DA9063_LDO(DA9063, LDO1, 600, 20, 1860),
                .suspend = BFIELD(DA9063_REG_DVC_1, DA9063_VLDO1_SEL),
        },
@@ -538,11 +564,6 @@ static const struct da9063_regulator_info da9063_regulator_info[] = {
                .suspend = BFIELD(DA9063_REG_DVC_1, DA9063_VLDO2_SEL),
        },
        {
-               DA9063_LDO(DA9063, LDO3, 900, 20, 3440),
-               .suspend = BFIELD(DA9063_REG_DVC_1, DA9063_VLDO3_SEL),
-               .oc_event = BFIELD(DA9063_REG_STATUS_D, DA9063_LDO3_LIM),
-       },
-       {
                DA9063_LDO(DA9063, LDO4, 900, 20, 3440),
                .suspend = BFIELD(DA9063_REG_DVC_2, DA9063_VLDO4_SEL),
                .oc_event = BFIELD(DA9063_REG_STATUS_D, DA9063_LDO4_LIM),
@@ -555,29 +576,11 @@ static const struct da9063_regulator_info da9063_regulator_info[] = {
                DA9063_LDO(DA9063, LDO6, 900, 50, 3600),
                .suspend = BFIELD(DA9063_REG_LDO6_CONT, DA9063_VLDO6_SEL),
        },
-       {
-               DA9063_LDO(DA9063, LDO7, 900, 50, 3600),
-               .suspend = BFIELD(DA9063_REG_LDO7_CONT, DA9063_VLDO7_SEL),
-               .oc_event = BFIELD(DA9063_REG_STATUS_D, DA9063_LDO7_LIM),
-       },
-       {
-               DA9063_LDO(DA9063, LDO8, 900, 50, 3600),
-               .suspend = BFIELD(DA9063_REG_LDO8_CONT, DA9063_VLDO8_SEL),
-               .oc_event = BFIELD(DA9063_REG_STATUS_D, DA9063_LDO8_LIM),
-       },
-       {
-               DA9063_LDO(DA9063, LDO9, 950, 50, 3600),
-               .suspend = BFIELD(DA9063_REG_LDO9_CONT, DA9063_VLDO9_SEL),
-       },
+
        {
                DA9063_LDO(DA9063, LDO10, 900, 50, 3600),
                .suspend = BFIELD(DA9063_REG_LDO10_CONT, DA9063_VLDO10_SEL),
        },
-       {
-               DA9063_LDO(DA9063, LDO11, 900, 50, 3600),
-               .suspend = BFIELD(DA9063_REG_LDO11_CONT, DA9063_VLDO11_SEL),
-               .oc_event = BFIELD(DA9063_REG_STATUS_D, DA9063_LDO11_LIM),
-       },
 };
 
 /* Link chip model with regulators info table */
@@ -585,7 +588,12 @@ static struct da9063_dev_model regulators_models[] = {
        {
                .regulator_info = da9063_regulator_info,
                .n_regulators = ARRAY_SIZE(da9063_regulator_info),
-               .dev_model = PMIC_DA9063,
+               .type = PMIC_TYPE_DA9063,
+       },
+       {
+               .regulator_info = da9063_regulator_info,
+               .n_regulators = ARRAY_SIZE(da9063_regulator_info) - 6,
+               .type = PMIC_TYPE_DA9063L,
        },
        { }
 };
@@ -641,28 +649,34 @@ static struct of_regulator_match da9063_matches[] = {
        [DA9063_ID_BPERI]            = { .name = "bperi",           },
        [DA9063_ID_BCORES_MERGED]    = { .name = "bcores-merged"    },
        [DA9063_ID_BMEM_BIO_MERGED]  = { .name = "bmem-bio-merged", },
+       [DA9063_ID_LDO3]             = { .name = "ldo3",            },
+       [DA9063_ID_LDO7]             = { .name = "ldo7",            },
+       [DA9063_ID_LDO8]             = { .name = "ldo8",            },
+       [DA9063_ID_LDO9]             = { .name = "ldo9",            },
+       [DA9063_ID_LDO11]            = { .name = "ldo11",           },
+       /* The following LDOs are present only on DA9063, not on DA9063L */
        [DA9063_ID_LDO1]             = { .name = "ldo1",            },
        [DA9063_ID_LDO2]             = { .name = "ldo2",            },
-       [DA9063_ID_LDO3]             = { .name = "ldo3",            },
        [DA9063_ID_LDO4]             = { .name = "ldo4",            },
        [DA9063_ID_LDO5]             = { .name = "ldo5",            },
        [DA9063_ID_LDO6]             = { .name = "ldo6",            },
-       [DA9063_ID_LDO7]             = { .name = "ldo7",            },
-       [DA9063_ID_LDO8]             = { .name = "ldo8",            },
-       [DA9063_ID_LDO9]             = { .name = "ldo9",            },
        [DA9063_ID_LDO10]            = { .name = "ldo10",           },
-       [DA9063_ID_LDO11]            = { .name = "ldo11",           },
 };
 
 static struct da9063_regulators_pdata *da9063_parse_regulators_dt(
                struct platform_device *pdev,
                struct of_regulator_match **da9063_reg_matches)
 {
+       struct da9063 *da9063 = dev_get_drvdata(pdev->dev.parent);
        struct da9063_regulators_pdata *pdata;
        struct da9063_regulator_data *rdata;
        struct device_node *node;
+       int da9063_matches_len = ARRAY_SIZE(da9063_matches);
        int i, n, num;
 
+       if (da9063->type == PMIC_TYPE_DA9063L)
+               da9063_matches_len -= 6;
+
        node = of_get_child_by_name(pdev->dev.parent->of_node, "regulators");
        if (!node) {
                dev_err(&pdev->dev, "Regulators device node not found\n");
@@ -670,7 +684,7 @@ static struct da9063_regulators_pdata *da9063_parse_regulators_dt(
        }
 
        num = of_regulator_match(&pdev->dev, node, da9063_matches,
-                                ARRAY_SIZE(da9063_matches));
+                                da9063_matches_len);
        of_node_put(node);
        if (num < 0) {
                dev_err(&pdev->dev, "Failed to match regulators\n");
@@ -689,7 +703,7 @@ static struct da9063_regulators_pdata *da9063_parse_regulators_dt(
        pdata->n_regulators = num;
 
        n = 0;
-       for (i = 0; i < ARRAY_SIZE(da9063_matches); i++) {
+       for (i = 0; i < da9063_matches_len; i++) {
                if (!da9063_matches[i].init_data)
                        continue;
 
@@ -741,12 +755,12 @@ static int da9063_regulator_probe(struct platform_device *pdev)
 
        /* Find regulators set for particular device model */
        for (model = regulators_models; model->regulator_info; model++) {
-               if (model->dev_model == da9063->model)
+               if (model->type == da9063->type)
                        break;
        }
        if (!model->regulator_info) {
                dev_err(&pdev->dev, "Chip model not recognised (%u)\n",
-                       da9063->model);
+                       da9063->type);
                return -ENODEV;
        }
 
index c0b292b..13d28fd 100644 (file)
@@ -73,6 +73,13 @@ config RESET_MESON
        help
          This enables the reset driver for Amlogic Meson SoCs.
 
+config RESET_MESON_AUDIO_ARB
+       tristate "Meson Audio Memory Arbiter Reset Driver"
+       depends on ARCH_MESON || COMPILE_TEST
+       help
+         This enables the reset driver for Audio Memory Arbiter of
+         Amlogic's A113 based SoCs
+
 config RESET_OXNAS
        bool
 
@@ -82,6 +89,15 @@ config RESET_PISTACHIO
        help
          This enables the reset driver for ImgTec Pistachio SoCs.
 
+config RESET_QCOM_AOSS
+       bool "Qcom AOSS Reset Driver"
+       depends on ARCH_QCOM || COMPILE_TEST
+       help
+         This enables the AOSS (always on subsystem) reset driver
+         for Qualcomm SDM845 SoCs. Say Y if you want to control
+         reset signals provided by AOSS for Modem, Venus, ADSP,
+         GPU, Camera, Wireless, Display subsystem. Otherwise, say N.
+
 config RESET_SIMPLE
        bool "Simple Reset Controller Driver" if COMPILE_TEST
        default ARCH_SOCFPGA || ARCH_STM32 || ARCH_STRATIX10 || ARCH_SUNXI || ARCH_ZX || ARCH_ASPEED
@@ -138,6 +154,16 @@ config RESET_UNIPHIER
          Say Y if you want to control reset signals provided by System Control
          block, Media I/O block, Peripheral Block.
 
+config RESET_UNIPHIER_USB3
+       tristate "USB3 reset driver for UniPhier SoCs"
+       depends on (ARCH_UNIPHIER || COMPILE_TEST) && OF
+       default ARCH_UNIPHIER
+       select RESET_SIMPLE
+       help
+         Support for the USB3 core reset on UniPhier SoCs.
+         Say Y if you want to control reset signals provided by
+         USB3 glue layer.
+
 config RESET_ZYNQ
        bool "ZYNQ Reset Driver" if COMPILE_TEST
        default ARCH_ZYNQ
index c1261dc..4243c38 100644 (file)
@@ -12,13 +12,16 @@ obj-$(CONFIG_RESET_IMX7) += reset-imx7.o
 obj-$(CONFIG_RESET_LANTIQ) += reset-lantiq.o
 obj-$(CONFIG_RESET_LPC18XX) += reset-lpc18xx.o
 obj-$(CONFIG_RESET_MESON) += reset-meson.o
+obj-$(CONFIG_RESET_MESON_AUDIO_ARB) += reset-meson-audio-arb.o
 obj-$(CONFIG_RESET_OXNAS) += reset-oxnas.o
 obj-$(CONFIG_RESET_PISTACHIO) += reset-pistachio.o
+obj-$(CONFIG_RESET_QCOM_AOSS) += reset-qcom-aoss.o
 obj-$(CONFIG_RESET_SIMPLE) += reset-simple.o
 obj-$(CONFIG_RESET_STM32MP157) += reset-stm32mp1.o
 obj-$(CONFIG_RESET_SUNXI) += reset-sunxi.o
 obj-$(CONFIG_RESET_TI_SCI) += reset-ti-sci.o
 obj-$(CONFIG_RESET_TI_SYSCON) += reset-ti-syscon.o
 obj-$(CONFIG_RESET_UNIPHIER) += reset-uniphier.o
+obj-$(CONFIG_RESET_UNIPHIER_USB3) += reset-uniphier-usb3.o
 obj-$(CONFIG_RESET_ZYNQ) += reset-zynq.o
 
index 14bc78d..97d9f08 100644 (file)
@@ -81,7 +81,7 @@ static int imx7_reset_set(struct reset_controller_dev *rcdev,
 {
        struct imx7_src *imx7src = to_imx7_src(rcdev);
        const struct imx7_src_signal *signal = &imx7_src_signals[id];
-       unsigned int value = 0;
+       unsigned int value = assert ? signal->bit : 0;
 
        switch (id) {
        case IMX7_RESET_PCIEPHY:
diff --git a/drivers/reset/reset-meson-audio-arb.c b/drivers/reset/reset-meson-audio-arb.c
new file mode 100644 (file)
index 0000000..9175161
--- /dev/null
@@ -0,0 +1,168 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+// Copyright (c) 2018 BayLibre, SAS.
+// Author: Jerome Brunet <jbrunet@baylibre.com>
+
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/reset-controller.h>
+#include <linux/spinlock.h>
+
+#include <dt-bindings/reset/amlogic,meson-axg-audio-arb.h>
+
+struct meson_audio_arb_data {
+       struct reset_controller_dev rstc;
+       void __iomem *regs;
+       struct clk *clk;
+       const unsigned int *reset_bits;
+       spinlock_t lock;
+};
+
+#define ARB_GENERAL_BIT        31
+
+static const unsigned int axg_audio_arb_reset_bits[] = {
+       [AXG_ARB_TODDR_A]       = 0,
+       [AXG_ARB_TODDR_B]       = 1,
+       [AXG_ARB_TODDR_C]       = 2,
+       [AXG_ARB_FRDDR_A]       = 4,
+       [AXG_ARB_FRDDR_B]       = 5,
+       [AXG_ARB_FRDDR_C]       = 6,
+};
+
+static int meson_audio_arb_update(struct reset_controller_dev *rcdev,
+                                 unsigned long id, bool assert)
+{
+       u32 val;
+       struct meson_audio_arb_data *arb =
+               container_of(rcdev, struct meson_audio_arb_data, rstc);
+
+       spin_lock(&arb->lock);
+       val = readl(arb->regs);
+
+       if (assert)
+               val &= ~BIT(arb->reset_bits[id]);
+       else
+               val |= BIT(arb->reset_bits[id]);
+
+       writel(val, arb->regs);
+       spin_unlock(&arb->lock);
+
+       return 0;
+}
+
+static int meson_audio_arb_status(struct reset_controller_dev *rcdev,
+                                 unsigned long id)
+{
+       u32 val;
+       struct meson_audio_arb_data *arb =
+               container_of(rcdev, struct meson_audio_arb_data, rstc);
+
+       val = readl(arb->regs);
+
+       return !(val & BIT(arb->reset_bits[id]));
+}
+
+static int meson_audio_arb_assert(struct reset_controller_dev *rcdev,
+                                 unsigned long id)
+{
+       return meson_audio_arb_update(rcdev, id, true);
+}
+
+static int meson_audio_arb_deassert(struct reset_controller_dev *rcdev,
+                                   unsigned long id)
+{
+       return meson_audio_arb_update(rcdev, id, false);
+}
+
+static const struct reset_control_ops meson_audio_arb_rstc_ops = {
+       .assert = meson_audio_arb_assert,
+       .deassert = meson_audio_arb_deassert,
+       .status = meson_audio_arb_status,
+};
+
+static const struct of_device_id meson_audio_arb_of_match[] = {
+       { .compatible = "amlogic,meson-axg-audio-arb", },
+       {}
+};
+MODULE_DEVICE_TABLE(of, meson_audio_arb_of_match);
+
+static int meson_audio_arb_remove(struct platform_device *pdev)
+{
+       struct meson_audio_arb_data *arb = platform_get_drvdata(pdev);
+
+       /* Disable all access */
+       spin_lock(&arb->lock);
+       writel(0, arb->regs);
+       spin_unlock(&arb->lock);
+
+       clk_disable_unprepare(arb->clk);
+
+       return 0;
+}
+
+static int meson_audio_arb_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct meson_audio_arb_data *arb;
+       struct resource *res;
+       int ret;
+
+       arb = devm_kzalloc(dev, sizeof(*arb), GFP_KERNEL);
+       if (!arb)
+               return -ENOMEM;
+       platform_set_drvdata(pdev, arb);
+
+       arb->clk = devm_clk_get(dev, NULL);
+       if (IS_ERR(arb->clk)) {
+               if (PTR_ERR(arb->clk) != -EPROBE_DEFER)
+                       dev_err(dev, "failed to get clock\n");
+               return PTR_ERR(arb->clk);
+       }
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       arb->regs = devm_ioremap_resource(dev, res);
+       if (IS_ERR(arb->regs))
+               return PTR_ERR(arb->regs);
+
+       spin_lock_init(&arb->lock);
+       arb->reset_bits = axg_audio_arb_reset_bits;
+       arb->rstc.nr_resets = ARRAY_SIZE(axg_audio_arb_reset_bits);
+       arb->rstc.ops = &meson_audio_arb_rstc_ops;
+       arb->rstc.of_node = dev->of_node;
+
+       /*
+        * Enable general :
+        * In the initial state, all memory interfaces are disabled
+        * and the general bit is on
+        */
+       ret = clk_prepare_enable(arb->clk);
+       if (ret) {
+               dev_err(dev, "failed to enable arb clock\n");
+               return ret;
+       }
+       writel(BIT(ARB_GENERAL_BIT), arb->regs);
+
+       /* Register reset controller */
+       ret = devm_reset_controller_register(dev, &arb->rstc);
+       if (ret) {
+               dev_err(dev, "failed to register arb reset controller\n");
+               meson_audio_arb_remove(pdev);
+       }
+
+       return ret;
+}
+
+static struct platform_driver meson_audio_arb_pdrv = {
+       .probe = meson_audio_arb_probe,
+       .remove = meson_audio_arb_remove,
+       .driver = {
+               .name = "meson-audio-arb-reset",
+               .of_match_table = meson_audio_arb_of_match,
+       },
+};
+module_platform_driver(meson_audio_arb_pdrv);
+
+MODULE_DESCRIPTION("Amlogic A113 Audio Memory Arbiter");
+MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/reset/reset-qcom-aoss.c b/drivers/reset/reset-qcom-aoss.c
new file mode 100644 (file)
index 0000000..36db967
--- /dev/null
@@ -0,0 +1,133 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2018 The Linux Foundation. All rights reserved.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/reset-controller.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/of_device.h>
+#include <dt-bindings/reset/qcom,sdm845-aoss.h>
+
+struct qcom_aoss_reset_map {
+       unsigned int reg;
+};
+
+struct qcom_aoss_desc {
+       const struct qcom_aoss_reset_map *resets;
+       size_t num_resets;
+};
+
+struct qcom_aoss_reset_data {
+       struct reset_controller_dev rcdev;
+       void __iomem *base;
+       const struct qcom_aoss_desc *desc;
+};
+
+static const struct qcom_aoss_reset_map sdm845_aoss_resets[] = {
+       [AOSS_CC_MSS_RESTART] = {0x10000},
+       [AOSS_CC_CAMSS_RESTART] = {0x11000},
+       [AOSS_CC_VENUS_RESTART] = {0x12000},
+       [AOSS_CC_GPU_RESTART] = {0x13000},
+       [AOSS_CC_DISPSS_RESTART] = {0x14000},
+       [AOSS_CC_WCSS_RESTART] = {0x20000},
+       [AOSS_CC_LPASS_RESTART] = {0x30000},
+};
+
+static const struct qcom_aoss_desc sdm845_aoss_desc = {
+       .resets = sdm845_aoss_resets,
+       .num_resets = ARRAY_SIZE(sdm845_aoss_resets),
+};
+
+static inline struct qcom_aoss_reset_data *to_qcom_aoss_reset_data(
+                               struct reset_controller_dev *rcdev)
+{
+       return container_of(rcdev, struct qcom_aoss_reset_data, rcdev);
+}
+
+static int qcom_aoss_control_assert(struct reset_controller_dev *rcdev,
+                                   unsigned long idx)
+{
+       struct qcom_aoss_reset_data *data = to_qcom_aoss_reset_data(rcdev);
+       const struct qcom_aoss_reset_map *map = &data->desc->resets[idx];
+
+       writel(1, data->base + map->reg);
+       /* Wait 6 32kHz sleep cycles for reset */
+       usleep_range(200, 300);
+       return 0;
+}
+
+static int qcom_aoss_control_deassert(struct reset_controller_dev *rcdev,
+                                     unsigned long idx)
+{
+       struct qcom_aoss_reset_data *data = to_qcom_aoss_reset_data(rcdev);
+       const struct qcom_aoss_reset_map *map = &data->desc->resets[idx];
+
+       writel(0, data->base + map->reg);
+       /* Wait 6 32kHz sleep cycles for reset */
+       usleep_range(200, 300);
+       return 0;
+}
+
+static int qcom_aoss_control_reset(struct reset_controller_dev *rcdev,
+                                       unsigned long idx)
+{
+       qcom_aoss_control_assert(rcdev, idx);
+
+       return qcom_aoss_control_deassert(rcdev, idx);
+}
+
+static const struct reset_control_ops qcom_aoss_reset_ops = {
+       .reset = qcom_aoss_control_reset,
+       .assert = qcom_aoss_control_assert,
+       .deassert = qcom_aoss_control_deassert,
+};
+
+static int qcom_aoss_reset_probe(struct platform_device *pdev)
+{
+       struct qcom_aoss_reset_data *data;
+       struct device *dev = &pdev->dev;
+       const struct qcom_aoss_desc *desc;
+       struct resource *res;
+
+       desc = of_device_get_match_data(dev);
+       if (!desc)
+               return -EINVAL;
+
+       data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
+       if (!data)
+               return -ENOMEM;
+
+       data->desc = desc;
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       data->base = devm_ioremap_resource(dev, res);
+       if (IS_ERR(data->base))
+               return PTR_ERR(data->base);
+
+       data->rcdev.owner = THIS_MODULE;
+       data->rcdev.ops = &qcom_aoss_reset_ops;
+       data->rcdev.nr_resets = desc->num_resets;
+       data->rcdev.of_node = dev->of_node;
+
+       return devm_reset_controller_register(dev, &data->rcdev);
+}
+
+static const struct of_device_id qcom_aoss_reset_of_match[] = {
+       { .compatible = "qcom,sdm845-aoss-cc", .data = &sdm845_aoss_desc },
+       {}
+};
+
+static struct platform_driver qcom_aoss_reset_driver = {
+       .probe = qcom_aoss_reset_probe,
+       .driver  = {
+               .name = "qcom_aoss_reset",
+               .of_match_table = qcom_aoss_reset_of_match,
+       },
+};
+
+builtin_platform_driver(qcom_aoss_reset_driver);
+
+MODULE_DESCRIPTION("Qualcomm AOSS Reset Driver");
+MODULE_LICENSE("GPL v2");
index f7ce891..a91107f 100644 (file)
@@ -87,6 +87,7 @@ const struct reset_control_ops reset_simple_ops = {
        .deassert       = reset_simple_deassert,
        .status         = reset_simple_status,
 };
+EXPORT_SYMBOL_GPL(reset_simple_ops);
 
 /**
  * struct reset_simple_devdata - simple reset controller properties
diff --git a/drivers/reset/reset-uniphier-usb3.c b/drivers/reset/reset-uniphier-usb3.c
new file mode 100644 (file)
index 0000000..ffa1b19
--- /dev/null
@@ -0,0 +1,171 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// reset-uniphier-usb3.c - USB3 reset driver for UniPhier
+// Copyright 2018 Socionext Inc.
+// Author: Kunihiko Hayashi <hayashi.kunihiko@socionext.com>
+
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/reset.h>
+
+#include "reset-simple.h"
+
+#define MAX_CLKS       2
+#define MAX_RSTS       2
+
+struct uniphier_usb3_reset_soc_data {
+       int nclks;
+       const char * const *clock_names;
+       int nrsts;
+       const char * const *reset_names;
+};
+
+struct uniphier_usb3_reset_priv {
+       struct clk_bulk_data clk[MAX_CLKS];
+       struct reset_control *rst[MAX_RSTS];
+       struct reset_simple_data rdata;
+       const struct uniphier_usb3_reset_soc_data *data;
+};
+
+static int uniphier_usb3_reset_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct uniphier_usb3_reset_priv *priv;
+       struct resource *res;
+       resource_size_t size;
+       const char *name;
+       int i, ret, nr;
+
+       priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
+
+       priv->data = of_device_get_match_data(dev);
+       if (WARN_ON(!priv->data || priv->data->nclks > MAX_CLKS ||
+                   priv->data->nrsts > MAX_RSTS))
+               return -EINVAL;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       size = resource_size(res);
+       priv->rdata.membase = devm_ioremap_resource(dev, res);
+       if (IS_ERR(priv->rdata.membase))
+               return PTR_ERR(priv->rdata.membase);
+
+       for (i = 0; i < priv->data->nclks; i++)
+               priv->clk[i].id = priv->data->clock_names[i];
+       ret = devm_clk_bulk_get(dev, priv->data->nclks, priv->clk);
+       if (ret)
+               return ret;
+
+       for (i = 0; i < priv->data->nrsts; i++) {
+               name = priv->data->reset_names[i];
+               priv->rst[i] = devm_reset_control_get_shared(dev, name);
+               if (IS_ERR(priv->rst[i]))
+                       return PTR_ERR(priv->rst[i]);
+       }
+
+       ret = clk_bulk_prepare_enable(priv->data->nclks, priv->clk);
+       if (ret)
+               return ret;
+
+       for (nr = 0; nr < priv->data->nrsts; nr++) {
+               ret = reset_control_deassert(priv->rst[nr]);
+               if (ret)
+                       goto out_rst_assert;
+       }
+
+       spin_lock_init(&priv->rdata.lock);
+       priv->rdata.rcdev.owner = THIS_MODULE;
+       priv->rdata.rcdev.nr_resets = size * BITS_PER_BYTE;
+       priv->rdata.rcdev.ops = &reset_simple_ops;
+       priv->rdata.rcdev.of_node = dev->of_node;
+       priv->rdata.active_low = true;
+
+       platform_set_drvdata(pdev, priv);
+
+       ret = devm_reset_controller_register(dev, &priv->rdata.rcdev);
+       if (ret)
+               goto out_rst_assert;
+
+       return 0;
+
+out_rst_assert:
+       while (nr--)
+               reset_control_assert(priv->rst[nr]);
+
+       clk_bulk_disable_unprepare(priv->data->nclks, priv->clk);
+
+       return ret;
+}
+
+static int uniphier_usb3_reset_remove(struct platform_device *pdev)
+{
+       struct uniphier_usb3_reset_priv *priv = platform_get_drvdata(pdev);
+       int i;
+
+       for (i = 0; i < priv->data->nrsts; i++)
+               reset_control_assert(priv->rst[i]);
+
+       clk_bulk_disable_unprepare(priv->data->nclks, priv->clk);
+
+       return 0;
+}
+
+static const char * const uniphier_pro4_clock_reset_names[] = {
+       "gio", "link",
+};
+
+static const struct uniphier_usb3_reset_soc_data uniphier_pro4_data = {
+       .nclks = ARRAY_SIZE(uniphier_pro4_clock_reset_names),
+       .clock_names = uniphier_pro4_clock_reset_names,
+       .nrsts = ARRAY_SIZE(uniphier_pro4_clock_reset_names),
+       .reset_names = uniphier_pro4_clock_reset_names,
+};
+
+static const char * const uniphier_pxs2_clock_reset_names[] = {
+       "link",
+};
+
+static const struct uniphier_usb3_reset_soc_data uniphier_pxs2_data = {
+       .nclks = ARRAY_SIZE(uniphier_pxs2_clock_reset_names),
+       .clock_names = uniphier_pxs2_clock_reset_names,
+       .nrsts = ARRAY_SIZE(uniphier_pxs2_clock_reset_names),
+       .reset_names = uniphier_pxs2_clock_reset_names,
+};
+
+static const struct of_device_id uniphier_usb3_reset_match[] = {
+       {
+               .compatible = "socionext,uniphier-pro4-usb3-reset",
+               .data = &uniphier_pro4_data,
+       },
+       {
+               .compatible = "socionext,uniphier-pxs2-usb3-reset",
+               .data = &uniphier_pxs2_data,
+       },
+       {
+               .compatible = "socionext,uniphier-ld20-usb3-reset",
+               .data = &uniphier_pxs2_data,
+       },
+       {
+               .compatible = "socionext,uniphier-pxs3-usb3-reset",
+               .data = &uniphier_pxs2_data,
+       },
+       { /* Sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, uniphier_usb3_reset_match);
+
+static struct platform_driver uniphier_usb3_reset_driver = {
+       .probe = uniphier_usb3_reset_probe,
+       .remove = uniphier_usb3_reset_remove,
+       .driver = {
+               .name = "uniphier-usb3-reset",
+               .of_match_table = uniphier_usb3_reset_match,
+       },
+};
+module_platform_driver(uniphier_usb3_reset_driver);
+
+MODULE_AUTHOR("Kunihiko Hayashi <hayashi.kunihiko@socionext.com>");
+MODULE_DESCRIPTION("UniPhier USB3 Reset Driver");
+MODULE_LICENSE("GPL");
index e9030ff..5605745 100644 (file)
@@ -202,6 +202,12 @@ static const struct uniphier_reset_data uniphier_pro5_sd_reset_data[] = {
 #define UNIPHIER_PERI_RESET_FI2C(id, ch)               \
        UNIPHIER_RESETX((id), 0x114, 24 + (ch))
 
+#define UNIPHIER_PERI_RESET_SCSSI(id)                  \
+       UNIPHIER_RESETX((id), 0x110, 17)
+
+#define UNIPHIER_PERI_RESET_MCSSI(id)                  \
+       UNIPHIER_RESETX((id), 0x114, 14)
+
 static const struct uniphier_reset_data uniphier_ld4_peri_reset_data[] = {
        UNIPHIER_PERI_RESET_UART(0, 0),
        UNIPHIER_PERI_RESET_UART(1, 1),
@@ -212,6 +218,7 @@ static const struct uniphier_reset_data uniphier_ld4_peri_reset_data[] = {
        UNIPHIER_PERI_RESET_I2C(6, 2),
        UNIPHIER_PERI_RESET_I2C(7, 3),
        UNIPHIER_PERI_RESET_I2C(8, 4),
+       UNIPHIER_PERI_RESET_SCSSI(11),
        UNIPHIER_RESET_END,
 };
 
@@ -227,6 +234,8 @@ static const struct uniphier_reset_data uniphier_pro4_peri_reset_data[] = {
        UNIPHIER_PERI_RESET_FI2C(8, 4),
        UNIPHIER_PERI_RESET_FI2C(9, 5),
        UNIPHIER_PERI_RESET_FI2C(10, 6),
+       UNIPHIER_PERI_RESET_SCSSI(11),
+       UNIPHIER_PERI_RESET_MCSSI(12),
        UNIPHIER_RESET_END,
 };
 
index a2ba5db..7d7be60 100644 (file)
@@ -244,15 +244,6 @@ config RTC_DRV_DS1307
          This driver can also be built as a module. If so, the module
          will be called rtc-ds1307.
 
-config RTC_DRV_DS1307_HWMON
-       bool "HWMON support for rtc-ds1307"
-       depends on RTC_DRV_DS1307 && HWMON
-       depends on !(RTC_DRV_DS1307=y && HWMON=m)
-       default y
-       help
-         Say Y here if you want to expose temperature sensor data on
-         rtc-ds1307 (only DS3231)
-
 config RTC_DRV_DS1307_CENTURY
        bool "Century bit support for rtc-ds1307"
        depends on RTC_DRV_DS1307
@@ -1027,18 +1018,6 @@ config RTC_DS1685_PROC_REGS
 
          Unless you are debugging this driver, choose N.
 
-config RTC_DS1685_SYSFS_REGS
-       bool "SysFS access to RTC register bits"
-       depends on RTC_DRV_DS1685_FAMILY && SYSFS
-       help
-         Enable this to provide access to the RTC control register bits
-         in /sys.  Some of the bits are read-write, others are read-only.
-
-         Keep in mind that reading Control C's bits automatically clears
-         all pending IRQ flags - this can cause lost interrupts.
-
-         If you know that you need access to these bits, choose Y, Else N.
-
 config RTC_DRV_DS1742
        tristate "Maxim/Dallas DS1742/1743"
        depends on HAS_IOMEM
index d37588f..0fca4d7 100644 (file)
@@ -68,7 +68,7 @@ static int rtc_suspend(struct device *dev)
                return 0;
        }
 
-       getnstimeofday64(&old_system);
+       ktime_get_real_ts64(&old_system);
        old_rtc.tv_sec = rtc_tm_to_time64(&tm);
 
 
@@ -110,7 +110,7 @@ static int rtc_resume(struct device *dev)
                return 0;
 
        /* snapshot the current rtc and system time at resume */
-       getnstimeofday64(&new_system);
+       ktime_get_real_ts64(&new_system);
        err = rtc_read_time(rtc, &tm);
        if (err < 0) {
                pr_debug("%s:  fail to read rtc time\n", dev_name(&rtc->dev));
@@ -172,7 +172,6 @@ static struct rtc_device *rtc_allocate_device(void)
 
        mutex_init(&rtc->ops_lock);
        spin_lock_init(&rtc->irq_lock);
-       spin_lock_init(&rtc->irq_task_lock);
        init_waitqueue_head(&rtc->irq_queue);
 
        /* Init timerqueue */
index bac1eeb..3d577e2 100644 (file)
@@ -607,12 +607,6 @@ void rtc_handle_legacy_irq(struct rtc_device *rtc, int num, int mode)
        rtc->irq_data = (rtc->irq_data + (num << 8)) | (RTC_IRQF|mode);
        spin_unlock_irqrestore(&rtc->irq_lock, flags);
 
-       /* call the task func */
-       spin_lock_irqsave(&rtc->irq_task_lock, flags);
-       if (rtc->irq_task)
-               rtc->irq_task->func(rtc->irq_task->private_data);
-       spin_unlock_irqrestore(&rtc->irq_task_lock, flags);
-
        wake_up_interruptible(&rtc->irq_queue);
        kill_fasync(&rtc->async_queue, SIGIO, POLL_IN);
 }
@@ -721,39 +715,6 @@ void rtc_class_close(struct rtc_device *rtc)
 }
 EXPORT_SYMBOL_GPL(rtc_class_close);
 
-int rtc_irq_register(struct rtc_device *rtc, struct rtc_task *task)
-{
-       int retval = -EBUSY;
-
-       if (task == NULL || task->func == NULL)
-               return -EINVAL;
-
-       /* Cannot register while the char dev is in use */
-       if (test_and_set_bit_lock(RTC_DEV_BUSY, &rtc->flags))
-               return -EBUSY;
-
-       spin_lock_irq(&rtc->irq_task_lock);
-       if (rtc->irq_task == NULL) {
-               rtc->irq_task = task;
-               retval = 0;
-       }
-       spin_unlock_irq(&rtc->irq_task_lock);
-
-       clear_bit_unlock(RTC_DEV_BUSY, &rtc->flags);
-
-       return retval;
-}
-EXPORT_SYMBOL_GPL(rtc_irq_register);
-
-void rtc_irq_unregister(struct rtc_device *rtc, struct rtc_task *task)
-{
-       spin_lock_irq(&rtc->irq_task_lock);
-       if (rtc->irq_task == task)
-               rtc->irq_task = NULL;
-       spin_unlock_irq(&rtc->irq_task_lock);
-}
-EXPORT_SYMBOL_GPL(rtc_irq_unregister);
-
 static int rtc_update_hrtimer(struct rtc_device *rtc, int enabled)
 {
        /*
@@ -785,71 +746,45 @@ static int rtc_update_hrtimer(struct rtc_device *rtc, int enabled)
  * Context: any
  *
  * Note that rtc_irq_set_freq() should previously have been used to
- * specify the desired frequency of periodic IRQ task->func() callbacks.
+ * specify the desired frequency of periodic IRQ.
  */
-int rtc_irq_set_state(struct rtc_device *rtc, struct rtc_task *task, int enabled)
+int rtc_irq_set_state(struct rtc_device *rtc, int enabled)
 {
        int err = 0;
-       unsigned long flags;
 
-retry:
-       spin_lock_irqsave(&rtc->irq_task_lock, flags);
-       if (rtc->irq_task != NULL && task == NULL)
-               err = -EBUSY;
-       else if (rtc->irq_task != task)
-               err = -EACCES;
-       else {
-               if (rtc_update_hrtimer(rtc, enabled) < 0) {
-                       spin_unlock_irqrestore(&rtc->irq_task_lock, flags);
-                       cpu_relax();
-                       goto retry;
-               }
-               rtc->pie_enabled = enabled;
-       }
-       spin_unlock_irqrestore(&rtc->irq_task_lock, flags);
+       while (rtc_update_hrtimer(rtc, enabled) < 0)
+               cpu_relax();
+
+       rtc->pie_enabled = enabled;
 
        trace_rtc_irq_set_state(enabled, err);
        return err;
 }
-EXPORT_SYMBOL_GPL(rtc_irq_set_state);
 
 /**
  * rtc_irq_set_freq - set 2^N Hz periodic IRQ frequency for IRQ
  * @rtc: the rtc device
  * @task: currently registered with rtc_irq_register()
- * @freq: positive frequency with which task->func() will be called
+ * @freq: positive frequency
  * Context: any
  *
  * Note that rtc_irq_set_state() is used to enable or disable the
  * periodic IRQs.
  */
-int rtc_irq_set_freq(struct rtc_device *rtc, struct rtc_task *task, int freq)
+int rtc_irq_set_freq(struct rtc_device *rtc, int freq)
 {
        int err = 0;
-       unsigned long flags;
 
        if (freq <= 0 || freq > RTC_MAX_FREQ)
                return -EINVAL;
-retry:
-       spin_lock_irqsave(&rtc->irq_task_lock, flags);
-       if (rtc->irq_task != NULL && task == NULL)
-               err = -EBUSY;
-       else if (rtc->irq_task != task)
-               err = -EACCES;
-       else {
-               rtc->irq_freq = freq;
-               if (rtc->pie_enabled && rtc_update_hrtimer(rtc, 1) < 0) {
-                       spin_unlock_irqrestore(&rtc->irq_task_lock, flags);
-                       cpu_relax();
-                       goto retry;
-               }
-       }
-       spin_unlock_irqrestore(&rtc->irq_task_lock, flags);
+
+       rtc->irq_freq = freq;
+       while (rtc->pie_enabled && rtc_update_hrtimer(rtc, 1) < 0)
+               cpu_relax();
 
        trace_rtc_irq_set_freq(freq, err);
        return err;
 }
-EXPORT_SYMBOL_GPL(rtc_irq_set_freq);
 
 /**
  * rtc_timer_enqueue - Adds a rtc_timer to the rtc_device timerqueue
@@ -979,8 +914,8 @@ again:
                timerqueue_del(&rtc->timerqueue, &timer->node);
                trace_rtc_timer_dequeue(timer);
                timer->enabled = 0;
-               if (timer->task.func)
-                       timer->task.func(timer->task.private_data);
+               if (timer->func)
+                       timer->func(timer->private_data);
 
                trace_rtc_timer_fired(timer);
                /* Re-add/fwd periodic timers */
@@ -1035,8 +970,8 @@ void rtc_timer_init(struct rtc_timer *timer, void (*f)(void *p), void *data)
 {
        timerqueue_init(&timer->node);
        timer->enabled = 0;
-       timer->task.func = f;
-       timer->task.private_data = data;
+       timer->func = f;
+       timer->private_data = data;
 }
 
 /* rtc_timer_start - Sets an rtc_timer to fire in the future
index 1e4978c..bde53c8 100644 (file)
@@ -30,6 +30,8 @@
 #define RTC_IRQ_FREQ_1HZ           BIT(2)
 #define RTC_CCR                    0x18
 #define RTC_CCR_MODE               BIT(15)
+#define RTC_CONF_TEST      0x1C
+#define RTC_NOMINAL_TIMING         BIT(13)
 
 #define RTC_TIME           0xC
 #define RTC_ALARM1         0x10
@@ -75,6 +77,7 @@ struct armada38x_rtc {
        void __iomem        *regs_soc;
        spinlock_t          lock;
        int                 irq;
+       bool                initialized;
        struct value_to_freq *val_to_freq;
        struct armada38x_rtc_data *data;
 };
@@ -226,6 +229,23 @@ static int armada38x_rtc_read_time(struct device *dev, struct rtc_time *tm)
        return 0;
 }
 
+static void armada38x_rtc_reset(struct armada38x_rtc *rtc)
+{
+       u32 reg;
+
+       reg = rtc->data->read_rtc_reg(rtc, RTC_CONF_TEST);
+       /* If bits [7:0] are non-zero, assume RTC was uninitialized */
+       if (reg & 0xff) {
+               rtc_delayed_write(0, rtc, RTC_CONF_TEST);
+               msleep(500); /* Oscillator startup time */
+               rtc_delayed_write(0, rtc, RTC_TIME);
+               rtc_delayed_write(SOC_RTC_ALARM1 | SOC_RTC_ALARM2, rtc,
+                                 RTC_STATUS);
+               rtc_delayed_write(RTC_NOMINAL_TIMING, rtc, RTC_CCR);
+       }
+       rtc->initialized = true;
+}
+
 static int armada38x_rtc_set_time(struct device *dev, struct rtc_time *tm)
 {
        struct armada38x_rtc *rtc = dev_get_drvdata(dev);
@@ -237,6 +257,9 @@ static int armada38x_rtc_set_time(struct device *dev, struct rtc_time *tm)
        if (ret)
                goto out;
 
+       if (!rtc->initialized)
+               armada38x_rtc_reset(rtc);
+
        spin_lock_irqsave(&rtc->lock, flags);
        rtc_delayed_write(time, rtc, RTC_TIME);
        spin_unlock_irqrestore(&rtc->lock, flags);
index d768f67..113493b 100644 (file)
@@ -162,6 +162,10 @@ static int bq4802_probe(struct platform_device *pdev)
        } else if (p->r->flags & IORESOURCE_MEM) {
                p->regs = devm_ioremap(&pdev->dev, p->r->start,
                                        resource_size(p->r));
+               if (!p->regs){
+                       err = -ENOMEM;
+                       goto out;
+               }
                p->read = bq4802_read_mem;
                p->write = bq4802_write_mem;
        } else {
index 0abf989..ccc17a2 100644 (file)
@@ -40,9 +40,23 @@ static inline void rtc_proc_del_device(struct rtc_device *rtc)
 
 #ifdef CONFIG_RTC_INTF_SYSFS
 const struct attribute_group **rtc_get_dev_attribute_groups(void);
+int rtc_add_group(struct rtc_device *rtc, const struct attribute_group *grp);
+int rtc_add_groups(struct rtc_device *rtc, const struct attribute_group **grps);
 #else
 static inline const struct attribute_group **rtc_get_dev_attribute_groups(void)
 {
        return NULL;
 }
+
+static inline
+int rtc_add_group(struct rtc_device *rtc, const struct attribute_group *grp)
+{
+       return 0;
+}
+
+static inline
+int rtc_add_groups(struct rtc_device *rtc, const struct attribute_group **grps)
+{
+       return 0;
+}
 #endif
index efa221e..43d962a 100644 (file)
@@ -341,11 +341,11 @@ static long rtc_dev_ioctl(struct file *file,
                return rtc_set_time(rtc, &tm);
 
        case RTC_PIE_ON:
-               err = rtc_irq_set_state(rtc, NULL, 1);
+               err = rtc_irq_set_state(rtc, 1);
                break;
 
        case RTC_PIE_OFF:
-               err = rtc_irq_set_state(rtc, NULL, 0);
+               err = rtc_irq_set_state(rtc, 0);
                break;
 
        case RTC_AIE_ON:
@@ -365,7 +365,7 @@ static long rtc_dev_ioctl(struct file *file,
                return rtc_update_irq_enable(rtc, 0);
 
        case RTC_IRQP_SET:
-               err = rtc_irq_set_freq(rtc, NULL, arg);
+               err = rtc_irq_set_freq(rtc, arg);
                break;
 
        case RTC_IRQP_READ:
@@ -427,7 +427,7 @@ static int rtc_dev_release(struct inode *inode, struct file *file)
        /* Keep ioctl until all drivers are converted */
        rtc_dev_ioctl(file, RTC_UIE_OFF, 0);
        rtc_update_irq_enable(rtc, 0);
-       rtc_irq_set_state(rtc, NULL, 0);
+       rtc_irq_set_state(rtc, 0);
 
        clear_bit_unlock(RTC_DEV_BUSY, &rtc->flags);
        return 0;
index e9ec416..4b2b462 100644 (file)
@@ -44,6 +44,7 @@ enum ds_type {
        ds_3231,
        m41t0,
        m41t00,
+       m41t11,
        mcp794xx,
        rx_8025,
        rx_8130,
@@ -227,6 +228,11 @@ static const struct chip_desc chips[last_ds_type] = {
                .irq_handler = rx8130_irq,
                .rtc_ops = &rx8130_rtc_ops,
        },
+       [m41t11] = {
+               /* this is battery backed SRAM */
+               .nvram_offset   = 8,
+               .nvram_size     = 56,
+       },
        [mcp794xx] = {
                .alarm          = 1,
                /* this is battery backed SRAM */
@@ -249,6 +255,7 @@ static const struct i2c_device_id ds1307_id[] = {
        { "ds3231", ds_3231 },
        { "m41t0", m41t0 },
        { "m41t00", m41t00 },
+       { "m41t11", m41t11 },
        { "mcp7940x", mcp794xx },
        { "mcp7941x", mcp794xx },
        { "pt7c4338", ds_1307 },
@@ -299,13 +306,17 @@ static const struct of_device_id ds1307_of_match[] = {
        },
        {
                .compatible = "st,m41t0",
-               .data = (void *)m41t00
+               .data = (void *)m41t0
        },
        {
                .compatible = "st,m41t00",
                .data = (void *)m41t00
        },
        {
+               .compatible = "st,m41t11",
+               .data = (void *)m41t11
+       },
+       {
                .compatible = "microchip,mcp7940x",
                .data = (void *)mcp794xx
        },
@@ -347,6 +358,7 @@ static const struct acpi_device_id ds1307_acpi_ids[] = {
        { .id = "DS3231", .driver_data = ds_3231 },
        { .id = "M41T0", .driver_data = m41t0 },
        { .id = "M41T00", .driver_data = m41t00 },
+       { .id = "M41T11", .driver_data = m41t11 },
        { .id = "MCP7940X", .driver_data = mcp794xx },
        { .id = "MCP7941X", .driver_data = mcp794xx },
        { .id = "PT7C4338", .driver_data = ds_1307 },
@@ -1030,7 +1042,7 @@ static u8 ds1307_trickle_init(struct ds1307 *ds1307,
 
 /*----------------------------------------------------------------------*/
 
-#ifdef CONFIG_RTC_DRV_DS1307_HWMON
+#if IS_REACHABLE(CONFIG_HWMON)
 
 /*
  * Temperature sensor support for ds3231 devices.
@@ -1576,6 +1588,7 @@ read_rtc:
        case ds_1307:
        case m41t0:
        case m41t00:
+       case m41t11:
                /* clock halted?  turn it on, so clock can tick. */
                if (tmp & DS1307_BIT_CH) {
                        regmap_write(ds1307->regmap, DS1307_REG_SECS, 0);
@@ -1641,6 +1654,7 @@ read_rtc:
        case ds_1340:
        case m41t0:
        case m41t00:
+       case m41t11:
                /*
                 * NOTE: ignores century bits; fix before deploying
                 * systems that will run through year 2100.
index 5c0db6c..6f39f68 100644 (file)
@@ -1188,552 +1188,6 @@ ds1685_rtc_sysfs_misc_grp = {
        .attrs = ds1685_rtc_sysfs_misc_attrs,
 };
 
-#ifdef CONFIG_RTC_DS1685_SYSFS_REGS
-/**
- * struct ds1685_rtc_ctrl_regs.
- * @name: char pointer for the bit name.
- * @reg: control register the bit is in.
- * @bit: the bit's offset in the register.
- */
-struct ds1685_rtc_ctrl_regs {
-       const char *name;
-       const u8 reg;
-       const u8 bit;
-};
-
-/*
- * Ctrl register bit lookup table.
- */
-static const struct ds1685_rtc_ctrl_regs
-ds1685_ctrl_regs_table[] = {
-       { "uip",  RTC_CTRL_A,      RTC_CTRL_A_UIP   },
-       { "dv2",  RTC_CTRL_A,      RTC_CTRL_A_DV2   },
-       { "dv1",  RTC_CTRL_A,      RTC_CTRL_A_DV1   },
-       { "dv0",  RTC_CTRL_A,      RTC_CTRL_A_DV0   },
-       { "rs3",  RTC_CTRL_A,      RTC_CTRL_A_RS3   },
-       { "rs2",  RTC_CTRL_A,      RTC_CTRL_A_RS2   },
-       { "rs1",  RTC_CTRL_A,      RTC_CTRL_A_RS1   },
-       { "rs0",  RTC_CTRL_A,      RTC_CTRL_A_RS0   },
-       { "set",  RTC_CTRL_B,      RTC_CTRL_B_SET   },
-       { "pie",  RTC_CTRL_B,      RTC_CTRL_B_PIE   },
-       { "aie",  RTC_CTRL_B,      RTC_CTRL_B_AIE   },
-       { "uie",  RTC_CTRL_B,      RTC_CTRL_B_UIE   },
-       { "sqwe", RTC_CTRL_B,      RTC_CTRL_B_SQWE  },
-       { "dm",   RTC_CTRL_B,      RTC_CTRL_B_DM    },
-       { "2412", RTC_CTRL_B,      RTC_CTRL_B_2412  },
-       { "dse",  RTC_CTRL_B,      RTC_CTRL_B_DSE   },
-       { "irqf", RTC_CTRL_C,      RTC_CTRL_C_IRQF  },
-       { "pf",   RTC_CTRL_C,      RTC_CTRL_C_PF    },
-       { "af",   RTC_CTRL_C,      RTC_CTRL_C_AF    },
-       { "uf",   RTC_CTRL_C,      RTC_CTRL_C_UF    },
-       { "vrt",  RTC_CTRL_D,      RTC_CTRL_D_VRT   },
-       { "vrt2", RTC_EXT_CTRL_4A, RTC_CTRL_4A_VRT2 },
-       { "incr", RTC_EXT_CTRL_4A, RTC_CTRL_4A_INCR },
-       { "pab",  RTC_EXT_CTRL_4A, RTC_CTRL_4A_PAB  },
-       { "rf",   RTC_EXT_CTRL_4A, RTC_CTRL_4A_RF   },
-       { "wf",   RTC_EXT_CTRL_4A, RTC_CTRL_4A_WF   },
-       { "kf",   RTC_EXT_CTRL_4A, RTC_CTRL_4A_KF   },
-#if !defined(CONFIG_RTC_DRV_DS1685) && !defined(CONFIG_RTC_DRV_DS1689)
-       { "bme",  RTC_EXT_CTRL_4A, RTC_CTRL_4A_BME  },
-#endif
-       { "abe",  RTC_EXT_CTRL_4B, RTC_CTRL_4B_ABE  },
-       { "e32k", RTC_EXT_CTRL_4B, RTC_CTRL_4B_E32K },
-       { "cs",   RTC_EXT_CTRL_4B, RTC_CTRL_4B_CS   },
-       { "rce",  RTC_EXT_CTRL_4B, RTC_CTRL_4B_RCE  },
-       { "prs",  RTC_EXT_CTRL_4B, RTC_CTRL_4B_PRS  },
-       { "rie",  RTC_EXT_CTRL_4B, RTC_CTRL_4B_RIE  },
-       { "wie",  RTC_EXT_CTRL_4B, RTC_CTRL_4B_WIE  },
-       { "kse",  RTC_EXT_CTRL_4B, RTC_CTRL_4B_KSE  },
-       { NULL,   0,               0                },
-};
-
-/**
- * ds1685_rtc_sysfs_ctrl_regs_lookup - ctrl register bit lookup function.
- * @name: ctrl register bit to look up in ds1685_ctrl_regs_table.
- */
-static const struct ds1685_rtc_ctrl_regs*
-ds1685_rtc_sysfs_ctrl_regs_lookup(const char *name)
-{
-       const struct ds1685_rtc_ctrl_regs *p = ds1685_ctrl_regs_table;
-
-       for (; p->name != NULL; ++p)
-               if (strcmp(p->name, name) == 0)
-                       return p;
-
-       return NULL;
-}
-
-/**
- * ds1685_rtc_sysfs_ctrl_regs_show - reads a ctrl register bit via sysfs.
- * @dev: pointer to device structure.
- * @attr: pointer to device_attribute structure.
- * @buf: pointer to char array to hold the output.
- */
-static ssize_t
-ds1685_rtc_sysfs_ctrl_regs_show(struct device *dev,
-                               struct device_attribute *attr, char *buf)
-{
-       u8 tmp;
-       struct ds1685_priv *rtc = dev_get_drvdata(dev);
-       const struct ds1685_rtc_ctrl_regs *reg_info =
-               ds1685_rtc_sysfs_ctrl_regs_lookup(attr->attr.name);
-
-       /* Make sure we actually matched something. */
-       if (!reg_info)
-               return -EINVAL;
-
-       /* No spinlock during a read -- mutex is already held. */
-       ds1685_rtc_switch_to_bank1(rtc);
-       tmp = rtc->read(rtc, reg_info->reg) & reg_info->bit;
-       ds1685_rtc_switch_to_bank0(rtc);
-
-       return sprintf(buf, "%d\n", (tmp ? 1 : 0));
-}
-
-/**
- * ds1685_rtc_sysfs_ctrl_regs_store - writes a ctrl register bit via sysfs.
- * @dev: pointer to device structure.
- * @attr: pointer to device_attribute structure.
- * @buf: pointer to char array to hold the output.
- * @count: number of bytes written.
- */
-static ssize_t
-ds1685_rtc_sysfs_ctrl_regs_store(struct device *dev,
-                                struct device_attribute *attr,
-                                const char *buf, size_t count)
-{
-       struct ds1685_priv *rtc = dev_get_drvdata(dev);
-       u8 reg = 0, bit = 0, tmp;
-       unsigned long flags;
-       long int val = 0;
-       const struct ds1685_rtc_ctrl_regs *reg_info =
-               ds1685_rtc_sysfs_ctrl_regs_lookup(attr->attr.name);
-
-       /* We only accept numbers. */
-       if (kstrtol(buf, 10, &val) < 0)
-               return -EINVAL;
-
-       /* bits are binary, 0 or 1 only. */
-       if ((val != 0) && (val != 1))
-               return -ERANGE;
-
-       /* Make sure we actually matched something. */
-       if (!reg_info)
-               return -EINVAL;
-
-       reg = reg_info->reg;
-       bit = reg_info->bit;
-
-       /* Safe to spinlock during a write. */
-       ds1685_rtc_begin_ctrl_access(rtc, &flags);
-       tmp = rtc->read(rtc, reg);
-       rtc->write(rtc, reg, (val ? (tmp | bit) : (tmp & ~(bit))));
-       ds1685_rtc_end_ctrl_access(rtc, flags);
-
-       return count;
-}
-
-/**
- * DS1685_RTC_SYSFS_CTRL_REG_RO - device_attribute for read-only register bit.
- * @bit: bit to read.
- */
-#define DS1685_RTC_SYSFS_CTRL_REG_RO(bit)                              \
-       static DEVICE_ATTR(bit, S_IRUGO,                                \
-       ds1685_rtc_sysfs_ctrl_regs_show, NULL)
-
-/**
- * DS1685_RTC_SYSFS_CTRL_REG_RW - device_attribute for read-write register bit.
- * @bit: bit to read or write.
- */
-#define DS1685_RTC_SYSFS_CTRL_REG_RW(bit)                              \
-       static DEVICE_ATTR(bit, S_IRUGO | S_IWUSR,                      \
-       ds1685_rtc_sysfs_ctrl_regs_show,                                \
-       ds1685_rtc_sysfs_ctrl_regs_store)
-
-/*
- * Control Register A bits.
- */
-DS1685_RTC_SYSFS_CTRL_REG_RO(uip);
-DS1685_RTC_SYSFS_CTRL_REG_RW(dv2);
-DS1685_RTC_SYSFS_CTRL_REG_RW(dv1);
-DS1685_RTC_SYSFS_CTRL_REG_RO(dv0);
-DS1685_RTC_SYSFS_CTRL_REG_RW(rs3);
-DS1685_RTC_SYSFS_CTRL_REG_RW(rs2);
-DS1685_RTC_SYSFS_CTRL_REG_RW(rs1);
-DS1685_RTC_SYSFS_CTRL_REG_RW(rs0);
-
-static struct attribute*
-ds1685_rtc_sysfs_ctrla_attrs[] = {
-       &dev_attr_uip.attr,
-       &dev_attr_dv2.attr,
-       &dev_attr_dv1.attr,
-       &dev_attr_dv0.attr,
-       &dev_attr_rs3.attr,
-       &dev_attr_rs2.attr,
-       &dev_attr_rs1.attr,
-       &dev_attr_rs0.attr,
-       NULL,
-};
-
-static const struct attribute_group
-ds1685_rtc_sysfs_ctrla_grp = {
-       .name = "ctrla",
-       .attrs = ds1685_rtc_sysfs_ctrla_attrs,
-};
-
-
-/*
- * Control Register B bits.
- */
-DS1685_RTC_SYSFS_CTRL_REG_RO(set);
-DS1685_RTC_SYSFS_CTRL_REG_RW(pie);
-DS1685_RTC_SYSFS_CTRL_REG_RW(aie);
-DS1685_RTC_SYSFS_CTRL_REG_RW(uie);
-DS1685_RTC_SYSFS_CTRL_REG_RW(sqwe);
-DS1685_RTC_SYSFS_CTRL_REG_RO(dm);
-DS1685_RTC_SYSFS_CTRL_REG_RO(2412);
-DS1685_RTC_SYSFS_CTRL_REG_RO(dse);
-
-static struct attribute*
-ds1685_rtc_sysfs_ctrlb_attrs[] = {
-       &dev_attr_set.attr,
-       &dev_attr_pie.attr,
-       &dev_attr_aie.attr,
-       &dev_attr_uie.attr,
-       &dev_attr_sqwe.attr,
-       &dev_attr_dm.attr,
-       &dev_attr_2412.attr,
-       &dev_attr_dse.attr,
-       NULL,
-};
-
-static const struct attribute_group
-ds1685_rtc_sysfs_ctrlb_grp = {
-       .name = "ctrlb",
-       .attrs = ds1685_rtc_sysfs_ctrlb_attrs,
-};
-
-/*
- * Control Register C bits.
- *
- * Reading Control C clears these bits!  Reading them individually can
- * possibly cause an interrupt to be missed.  Use the /proc interface
- * to see all the bits in this register simultaneously.
- */
-DS1685_RTC_SYSFS_CTRL_REG_RO(irqf);
-DS1685_RTC_SYSFS_CTRL_REG_RO(pf);
-DS1685_RTC_SYSFS_CTRL_REG_RO(af);
-DS1685_RTC_SYSFS_CTRL_REG_RO(uf);
-
-static struct attribute*
-ds1685_rtc_sysfs_ctrlc_attrs[] = {
-       &dev_attr_irqf.attr,
-       &dev_attr_pf.attr,
-       &dev_attr_af.attr,
-       &dev_attr_uf.attr,
-       NULL,
-};
-
-static const struct attribute_group
-ds1685_rtc_sysfs_ctrlc_grp = {
-       .name = "ctrlc",
-       .attrs = ds1685_rtc_sysfs_ctrlc_attrs,
-};
-
-/*
- * Control Register D bits.
- */
-DS1685_RTC_SYSFS_CTRL_REG_RO(vrt);
-
-static struct attribute*
-ds1685_rtc_sysfs_ctrld_attrs[] = {
-       &dev_attr_vrt.attr,
-       NULL,
-};
-
-static const struct attribute_group
-ds1685_rtc_sysfs_ctrld_grp = {
-       .name = "ctrld",
-       .attrs = ds1685_rtc_sysfs_ctrld_attrs,
-};
-
-/*
- * Control Register 4A bits.
- */
-DS1685_RTC_SYSFS_CTRL_REG_RO(vrt2);
-DS1685_RTC_SYSFS_CTRL_REG_RO(incr);
-DS1685_RTC_SYSFS_CTRL_REG_RW(pab);
-DS1685_RTC_SYSFS_CTRL_REG_RW(rf);
-DS1685_RTC_SYSFS_CTRL_REG_RW(wf);
-DS1685_RTC_SYSFS_CTRL_REG_RW(kf);
-#if !defined(CONFIG_RTC_DRV_DS1685) && !defined(CONFIG_RTC_DRV_DS1689)
-DS1685_RTC_SYSFS_CTRL_REG_RO(bme);
-#endif
-
-static struct attribute*
-ds1685_rtc_sysfs_ctrl4a_attrs[] = {
-       &dev_attr_vrt2.attr,
-       &dev_attr_incr.attr,
-       &dev_attr_pab.attr,
-       &dev_attr_rf.attr,
-       &dev_attr_wf.attr,
-       &dev_attr_kf.attr,
-#if !defined(CONFIG_RTC_DRV_DS1685) && !defined(CONFIG_RTC_DRV_DS1689)
-       &dev_attr_bme.attr,
-#endif
-       NULL,
-};
-
-static const struct attribute_group
-ds1685_rtc_sysfs_ctrl4a_grp = {
-       .name = "ctrl4a",
-       .attrs = ds1685_rtc_sysfs_ctrl4a_attrs,
-};
-
-/*
- * Control Register 4B bits.
- */
-DS1685_RTC_SYSFS_CTRL_REG_RW(abe);
-DS1685_RTC_SYSFS_CTRL_REG_RW(e32k);
-DS1685_RTC_SYSFS_CTRL_REG_RO(cs);
-DS1685_RTC_SYSFS_CTRL_REG_RW(rce);
-DS1685_RTC_SYSFS_CTRL_REG_RW(prs);
-DS1685_RTC_SYSFS_CTRL_REG_RW(rie);
-DS1685_RTC_SYSFS_CTRL_REG_RW(wie);
-DS1685_RTC_SYSFS_CTRL_REG_RW(kse);
-
-static struct attribute*
-ds1685_rtc_sysfs_ctrl4b_attrs[] = {
-       &dev_attr_abe.attr,
-       &dev_attr_e32k.attr,
-       &dev_attr_cs.attr,
-       &dev_attr_rce.attr,
-       &dev_attr_prs.attr,
-       &dev_attr_rie.attr,
-       &dev_attr_wie.attr,
-       &dev_attr_kse.attr,
-       NULL,
-};
-
-static const struct attribute_group
-ds1685_rtc_sysfs_ctrl4b_grp = {
-       .name = "ctrl4b",
-       .attrs = ds1685_rtc_sysfs_ctrl4b_attrs,
-};
-
-
-/**
- * struct ds1685_rtc_ctrl_regs.
- * @name: char pointer for the bit name.
- * @reg: control register the bit is in.
- * @bit: the bit's offset in the register.
- */
-struct ds1685_rtc_time_regs {
-       const char *name;
-       const u8 reg;
-       const u8 mask;
-       const u8 min;
-       const u8 max;
-};
-
-/*
- * Time/Date register lookup tables.
- */
-static const struct ds1685_rtc_time_regs
-ds1685_time_regs_bcd_table[] = {
-       { "seconds",       RTC_SECS,       RTC_SECS_BCD_MASK,   0, 59 },
-       { "minutes",       RTC_MINS,       RTC_MINS_BCD_MASK,   0, 59 },
-       { "hours",         RTC_HRS,        RTC_HRS_24_BCD_MASK, 0, 23 },
-       { "wday",          RTC_WDAY,       RTC_WDAY_MASK,       1,  7 },
-       { "mday",          RTC_MDAY,       RTC_MDAY_BCD_MASK,   1, 31 },
-       { "month",         RTC_MONTH,      RTC_MONTH_BCD_MASK,  1, 12 },
-       { "year",          RTC_YEAR,       RTC_YEAR_BCD_MASK,   0, 99 },
-       { "century",       RTC_CENTURY,    RTC_CENTURY_MASK,    0, 99 },
-       { "alarm_seconds", RTC_SECS_ALARM, RTC_SECS_BCD_MASK,   0, 59 },
-       { "alarm_minutes", RTC_MINS_ALARM, RTC_MINS_BCD_MASK,   0, 59 },
-       { "alarm_hours",   RTC_HRS_ALARM,  RTC_HRS_24_BCD_MASK, 0, 23 },
-       { "alarm_mday",    RTC_MDAY_ALARM, RTC_MDAY_ALARM_MASK, 1, 31 },
-       { NULL,            0,              0,                   0,  0 },
-};
-
-static const struct ds1685_rtc_time_regs
-ds1685_time_regs_bin_table[] = {
-       { "seconds",       RTC_SECS,       RTC_SECS_BIN_MASK,   0x00, 0x3b },
-       { "minutes",       RTC_MINS,       RTC_MINS_BIN_MASK,   0x00, 0x3b },
-       { "hours",         RTC_HRS,        RTC_HRS_24_BIN_MASK, 0x00, 0x17 },
-       { "wday",          RTC_WDAY,       RTC_WDAY_MASK,       0x01, 0x07 },
-       { "mday",          RTC_MDAY,       RTC_MDAY_BIN_MASK,   0x01, 0x1f },
-       { "month",         RTC_MONTH,      RTC_MONTH_BIN_MASK,  0x01, 0x0c },
-       { "year",          RTC_YEAR,       RTC_YEAR_BIN_MASK,   0x00, 0x63 },
-       { "century",       RTC_CENTURY,    RTC_CENTURY_MASK,    0x00, 0x63 },
-       { "alarm_seconds", RTC_SECS_ALARM, RTC_SECS_BIN_MASK,   0x00, 0x3b },
-       { "alarm_minutes", RTC_MINS_ALARM, RTC_MINS_BIN_MASK,   0x00, 0x3b },
-       { "alarm_hours",   RTC_HRS_ALARM,  RTC_HRS_24_BIN_MASK, 0x00, 0x17 },
-       { "alarm_mday",    RTC_MDAY_ALARM, RTC_MDAY_ALARM_MASK, 0x01, 0x1f },
-       { NULL,            0,              0,                   0x00, 0x00 },
-};
-
-/**
- * ds1685_rtc_sysfs_time_regs_bcd_lookup - time/date reg bit lookup function.
- * @name: register bit to look up in ds1685_time_regs_bcd_table.
- */
-static const struct ds1685_rtc_time_regs*
-ds1685_rtc_sysfs_time_regs_lookup(const char *name, bool bcd_mode)
-{
-       const struct ds1685_rtc_time_regs *p;
-
-       if (bcd_mode)
-               p = ds1685_time_regs_bcd_table;
-       else
-               p = ds1685_time_regs_bin_table;
-
-       for (; p->name != NULL; ++p)
-               if (strcmp(p->name, name) == 0)
-                       return p;
-
-       return NULL;
-}
-
-/**
- * ds1685_rtc_sysfs_time_regs_show - reads a time/date register via sysfs.
- * @dev: pointer to device structure.
- * @attr: pointer to device_attribute structure.
- * @buf: pointer to char array to hold the output.
- */
-static ssize_t
-ds1685_rtc_sysfs_time_regs_show(struct device *dev,
-                               struct device_attribute *attr, char *buf)
-{
-       u8 tmp;
-       struct ds1685_priv *rtc = dev_get_drvdata(dev);
-       const struct ds1685_rtc_time_regs *bcd_reg_info =
-               ds1685_rtc_sysfs_time_regs_lookup(attr->attr.name, true);
-       const struct ds1685_rtc_time_regs *bin_reg_info =
-               ds1685_rtc_sysfs_time_regs_lookup(attr->attr.name, false);
-
-       /* Make sure we actually matched something. */
-       if (!bcd_reg_info || !bin_reg_info)
-               return -EINVAL;
-
-       /* bcd_reg_info->reg == bin_reg_info->reg. */
-       ds1685_rtc_begin_data_access(rtc);
-       tmp = rtc->read(rtc, bcd_reg_info->reg);
-       ds1685_rtc_end_data_access(rtc);
-
-       tmp = ds1685_rtc_bcd2bin(rtc, tmp, bcd_reg_info->mask,
-                                bin_reg_info->mask);
-
-       return sprintf(buf, "%d\n", tmp);
-}
-
-/**
- * ds1685_rtc_sysfs_time_regs_store - writes a time/date register via sysfs.
- * @dev: pointer to device structure.
- * @attr: pointer to device_attribute structure.
- * @buf: pointer to char array to hold the output.
- * @count: number of bytes written.
- */
-static ssize_t
-ds1685_rtc_sysfs_time_regs_store(struct device *dev,
-                                struct device_attribute *attr,
-                                const char *buf, size_t count)
-{
-       long int val = 0;
-       struct ds1685_priv *rtc = dev_get_drvdata(dev);
-       const struct ds1685_rtc_time_regs *bcd_reg_info =
-               ds1685_rtc_sysfs_time_regs_lookup(attr->attr.name, true);
-       const struct ds1685_rtc_time_regs *bin_reg_info =
-               ds1685_rtc_sysfs_time_regs_lookup(attr->attr.name, false);
-
-       /* We only accept numbers. */
-       if (kstrtol(buf, 10, &val) < 0)
-               return -EINVAL;
-
-       /* Make sure we actually matched something. */
-       if (!bcd_reg_info || !bin_reg_info)
-               return -EINVAL;
-
-       /* Check for a valid range. */
-       if (rtc->bcd_mode) {
-               if ((val < bcd_reg_info->min) || (val > bcd_reg_info->max))
-                       return -ERANGE;
-       } else {
-               if ((val < bin_reg_info->min) || (val > bin_reg_info->max))
-                       return -ERANGE;
-       }
-
-       val = ds1685_rtc_bin2bcd(rtc, val, bin_reg_info->mask,
-                                bcd_reg_info->mask);
-
-       /* bcd_reg_info->reg == bin_reg_info->reg. */
-       ds1685_rtc_begin_data_access(rtc);
-       rtc->write(rtc, bcd_reg_info->reg, val);
-       ds1685_rtc_end_data_access(rtc);
-
-       return count;
-}
-
-/**
- * DS1685_RTC_SYSFS_REG_RW - device_attribute for a read-write time register.
- * @reg: time/date register to read or write.
- */
-#define DS1685_RTC_SYSFS_TIME_REG_RW(reg)                              \
-       static DEVICE_ATTR(reg, S_IRUGO | S_IWUSR,                      \
-       ds1685_rtc_sysfs_time_regs_show,                                \
-       ds1685_rtc_sysfs_time_regs_store)
-
-/*
- * Time/Date Register bits.
- */
-DS1685_RTC_SYSFS_TIME_REG_RW(seconds);
-DS1685_RTC_SYSFS_TIME_REG_RW(minutes);
-DS1685_RTC_SYSFS_TIME_REG_RW(hours);
-DS1685_RTC_SYSFS_TIME_REG_RW(wday);
-DS1685_RTC_SYSFS_TIME_REG_RW(mday);
-DS1685_RTC_SYSFS_TIME_REG_RW(month);
-DS1685_RTC_SYSFS_TIME_REG_RW(year);
-DS1685_RTC_SYSFS_TIME_REG_RW(century);
-DS1685_RTC_SYSFS_TIME_REG_RW(alarm_seconds);
-DS1685_RTC_SYSFS_TIME_REG_RW(alarm_minutes);
-DS1685_RTC_SYSFS_TIME_REG_RW(alarm_hours);
-DS1685_RTC_SYSFS_TIME_REG_RW(alarm_mday);
-
-static struct attribute*
-ds1685_rtc_sysfs_time_attrs[] = {
-       &dev_attr_seconds.attr,
-       &dev_attr_minutes.attr,
-       &dev_attr_hours.attr,
-       &dev_attr_wday.attr,
-       &dev_attr_mday.attr,
-       &dev_attr_month.attr,
-       &dev_attr_year.attr,
-       &dev_attr_century.attr,
-       NULL,
-};
-
-static const struct attribute_group
-ds1685_rtc_sysfs_time_grp = {
-       .name = "datetime",
-       .attrs = ds1685_rtc_sysfs_time_attrs,
-};
-
-static struct attribute*
-ds1685_rtc_sysfs_alarm_attrs[] = {
-       &dev_attr_alarm_seconds.attr,
-       &dev_attr_alarm_minutes.attr,
-       &dev_attr_alarm_hours.attr,
-       &dev_attr_alarm_mday.attr,
-       NULL,
-};
-
-static const struct attribute_group
-ds1685_rtc_sysfs_alarm_grp = {
-       .name = "alarm",
-       .attrs = ds1685_rtc_sysfs_alarm_attrs,
-};
-#endif /* CONFIG_RTC_DS1685_SYSFS_REGS */
-
-
 /**
  * ds1685_rtc_sysfs_register - register sysfs files.
  * @dev: pointer to device structure.
@@ -1752,39 +1206,6 @@ ds1685_rtc_sysfs_register(struct device *dev)
        if (ret)
                return ret;
 
-#ifdef CONFIG_RTC_DS1685_SYSFS_REGS
-       ret = sysfs_create_group(&dev->kobj, &ds1685_rtc_sysfs_ctrla_grp);
-       if (ret)
-               return ret;
-
-       ret = sysfs_create_group(&dev->kobj, &ds1685_rtc_sysfs_ctrlb_grp);
-       if (ret)
-               return ret;
-
-       ret = sysfs_create_group(&dev->kobj, &ds1685_rtc_sysfs_ctrlc_grp);
-       if (ret)
-               return ret;
-
-       ret = sysfs_create_group(&dev->kobj, &ds1685_rtc_sysfs_ctrld_grp);
-       if (ret)
-               return ret;
-
-       ret = sysfs_create_group(&dev->kobj, &ds1685_rtc_sysfs_ctrl4a_grp);
-       if (ret)
-               return ret;
-
-       ret = sysfs_create_group(&dev->kobj, &ds1685_rtc_sysfs_ctrl4b_grp);
-       if (ret)
-               return ret;
-
-       ret = sysfs_create_group(&dev->kobj, &ds1685_rtc_sysfs_time_grp);
-       if (ret)
-               return ret;
-
-       ret = sysfs_create_group(&dev->kobj, &ds1685_rtc_sysfs_alarm_grp);
-       if (ret)
-               return ret;
-#endif
        return 0;
 }
 
@@ -1798,17 +1219,6 @@ ds1685_rtc_sysfs_unregister(struct device *dev)
        sysfs_remove_bin_file(&dev->kobj, &ds1685_rtc_sysfs_nvram_attr);
        sysfs_remove_group(&dev->kobj, &ds1685_rtc_sysfs_misc_grp);
 
-#ifdef CONFIG_RTC_DS1685_SYSFS_REGS
-       sysfs_remove_group(&dev->kobj, &ds1685_rtc_sysfs_ctrla_grp);
-       sysfs_remove_group(&dev->kobj, &ds1685_rtc_sysfs_ctrlb_grp);
-       sysfs_remove_group(&dev->kobj, &ds1685_rtc_sysfs_ctrlc_grp);
-       sysfs_remove_group(&dev->kobj, &ds1685_rtc_sysfs_ctrld_grp);
-       sysfs_remove_group(&dev->kobj, &ds1685_rtc_sysfs_ctrl4a_grp);
-       sysfs_remove_group(&dev->kobj, &ds1685_rtc_sysfs_ctrl4b_grp);
-       sysfs_remove_group(&dev->kobj, &ds1685_rtc_sysfs_time_grp);
-       sysfs_remove_group(&dev->kobj, &ds1685_rtc_sysfs_alarm_grp);
-#endif
-
        return 0;
 }
 #endif /* CONFIG_SYSFS */
index 1a2c38c..ea18a8f 100644 (file)
@@ -14,6 +14,8 @@
 #include <linux/i2c.h>
 #include <linux/bcd.h>
 #include <linux/rtc.h>
+#include "rtc-core.h"
+#include <linux/of_irq.h>
 
 /* Register map */
 /* rtc section */
 #define ISL1208_REG_SR_ARST    (1<<7)  /* auto reset */
 #define ISL1208_REG_SR_XTOSCB  (1<<6)  /* crystal oscillator */
 #define ISL1208_REG_SR_WRTC    (1<<4)  /* write rtc */
+#define ISL1208_REG_SR_EVT     (1<<3)  /* event */
 #define ISL1208_REG_SR_ALM     (1<<2)  /* alarm */
 #define ISL1208_REG_SR_BAT     (1<<1)  /* battery */
 #define ISL1208_REG_SR_RTCF    (1<<0)  /* rtc fail */
 #define ISL1208_REG_INT 0x08
 #define ISL1208_REG_INT_ALME   (1<<6)   /* alarm enable */
 #define ISL1208_REG_INT_IM     (1<<7)   /* interrupt/alarm mode */
-#define ISL1208_REG_09  0x09   /* reserved */
+#define ISL1219_REG_EV  0x09
+#define ISL1219_REG_EV_EVEN    (1<<4)   /* event detection enable */
+#define ISL1219_REG_EV_EVIENB  (1<<7)   /* event in pull-up disable */
 #define ISL1208_REG_ATR 0x0a
 #define ISL1208_REG_DTR 0x0b
 
 #define ISL1208_REG_USR2 0x13
 #define ISL1208_USR_SECTION_LEN 2
 
+/* event section */
+#define ISL1219_REG_SCT 0x14
+#define ISL1219_REG_MNT 0x15
+#define ISL1219_REG_HRT 0x16
+#define ISL1219_REG_DTT 0x17
+#define ISL1219_REG_MOT 0x18
+#define ISL1219_REG_YRT 0x19
+#define ISL1219_EVT_SECTION_LEN 6
+
 static struct i2c_driver isl1208_driver;
 
+/* ISL1208 various variants */
+enum {
+       TYPE_ISL1208 = 0,
+       TYPE_ISL1218,
+       TYPE_ISL1219,
+};
+
 /* block read */
 static int
 isl1208_i2c_read_regs(struct i2c_client *client, u8 reg, u8 buf[],
@@ -80,8 +101,8 @@ isl1208_i2c_read_regs(struct i2c_client *client, u8 reg, u8 buf[],
        };
        int ret;
 
-       BUG_ON(reg > ISL1208_REG_USR2);
-       BUG_ON(reg + len > ISL1208_REG_USR2 + 1);
+       WARN_ON(reg > ISL1219_REG_YRT);
+       WARN_ON(reg + len > ISL1219_REG_YRT + 1);
 
        ret = i2c_transfer(client->adapter, msgs, 2);
        if (ret > 0)
@@ -104,8 +125,8 @@ isl1208_i2c_set_regs(struct i2c_client *client, u8 reg, u8 const buf[],
        };
        int ret;
 
-       BUG_ON(reg > ISL1208_REG_USR2);
-       BUG_ON(reg + len > ISL1208_REG_USR2 + 1);
+       WARN_ON(reg > ISL1219_REG_YRT);
+       WARN_ON(reg + len > ISL1219_REG_YRT + 1);
 
        i2c_buf[0] = reg;
        memcpy(&i2c_buf[1], &buf[0], len);
@@ -493,6 +514,73 @@ isl1208_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
        return isl1208_i2c_set_alarm(to_i2c_client(dev), alarm);
 }
 
+static ssize_t timestamp0_store(struct device *dev,
+                               struct device_attribute *attr,
+                               const char *buf, size_t count)
+{
+       struct i2c_client *client = dev_get_drvdata(dev);
+       int sr;
+
+       sr = isl1208_i2c_get_sr(client);
+       if (sr < 0) {
+               dev_err(dev, "%s: reading SR failed\n", __func__);
+               return sr;
+       }
+
+       sr &= ~ISL1208_REG_SR_EVT;
+
+       sr = i2c_smbus_write_byte_data(client, ISL1208_REG_SR, sr);
+       if (sr < 0)
+               dev_err(dev, "%s: writing SR failed\n",
+                       __func__);
+
+       return count;
+};
+
+static ssize_t timestamp0_show(struct device *dev,
+                              struct device_attribute *attr, char *buf)
+{
+       struct i2c_client *client = dev_get_drvdata(dev);
+       u8 regs[ISL1219_EVT_SECTION_LEN] = { 0, };
+       struct rtc_time tm;
+       int sr;
+
+       sr = isl1208_i2c_get_sr(client);
+       if (sr < 0) {
+               dev_err(dev, "%s: reading SR failed\n", __func__);
+               return sr;
+       }
+
+       if (!(sr & ISL1208_REG_SR_EVT))
+               return 0;
+
+       sr = isl1208_i2c_read_regs(client, ISL1219_REG_SCT, regs,
+                                  ISL1219_EVT_SECTION_LEN);
+       if (sr < 0) {
+               dev_err(dev, "%s: reading event section failed\n",
+                       __func__);
+               return 0;
+       }
+
+       /* MSB of each alarm register is an enable bit */
+       tm.tm_sec = bcd2bin(regs[ISL1219_REG_SCT - ISL1219_REG_SCT] & 0x7f);
+       tm.tm_min = bcd2bin(regs[ISL1219_REG_MNT - ISL1219_REG_SCT] & 0x7f);
+       tm.tm_hour = bcd2bin(regs[ISL1219_REG_HRT - ISL1219_REG_SCT] & 0x3f);
+       tm.tm_mday = bcd2bin(regs[ISL1219_REG_DTT - ISL1219_REG_SCT] & 0x3f);
+       tm.tm_mon =
+               bcd2bin(regs[ISL1219_REG_MOT - ISL1219_REG_SCT] & 0x1f) - 1;
+       tm.tm_year = bcd2bin(regs[ISL1219_REG_YRT - ISL1219_REG_SCT]) + 100;
+
+       sr = rtc_valid_tm(&tm);
+       if (sr)
+               return sr;
+
+       return sprintf(buf, "%llu\n",
+                               (unsigned long long)rtc_tm_to_time64(&tm));
+};
+
+static DEVICE_ATTR_RW(timestamp0);
+
 static irqreturn_t
 isl1208_rtc_interrupt(int irq, void *data)
 {
@@ -538,6 +626,13 @@ isl1208_rtc_interrupt(int irq, void *data)
                        return err;
        }
 
+       if (sr & ISL1208_REG_SR_EVT) {
+               sysfs_notify(&rtc->dev.kobj, NULL,
+                            dev_attr_timestamp0.attr.name);
+               dev_warn(&client->dev, "event detected");
+               handled = 1;
+       }
+
        return handled ? IRQ_HANDLED : IRQ_NONE;
 }
 
@@ -623,11 +718,39 @@ static const struct attribute_group isl1208_rtc_sysfs_files = {
        .attrs  = isl1208_rtc_attrs,
 };
 
+static struct attribute *isl1219_rtc_attrs[] = {
+       &dev_attr_timestamp0.attr,
+       NULL
+};
+
+static const struct attribute_group isl1219_rtc_sysfs_files = {
+       .attrs  = isl1219_rtc_attrs,
+};
+
+static int isl1208_setup_irq(struct i2c_client *client, int irq)
+{
+       int rc = devm_request_threaded_irq(&client->dev, irq, NULL,
+                                       isl1208_rtc_interrupt,
+                                       IRQF_SHARED | IRQF_ONESHOT,
+                                       isl1208_driver.driver.name,
+                                       client);
+       if (!rc) {
+               device_init_wakeup(&client->dev, 1);
+               enable_irq_wake(irq);
+       } else {
+               dev_err(&client->dev,
+                       "Unable to request irq %d, no alarm support\n",
+                       irq);
+       }
+       return rc;
+}
+
 static int
 isl1208_probe(struct i2c_client *client, const struct i2c_device_id *id)
 {
        int rc = 0;
        struct rtc_device *rtc;
+       int evdet_irq = -1;
 
        if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
                return -ENODEV;
@@ -642,6 +765,7 @@ isl1208_probe(struct i2c_client *client, const struct i2c_device_id *id)
        rtc->ops = &isl1208_rtc_ops;
 
        i2c_set_clientdata(client, rtc);
+       dev_set_drvdata(&rtc->dev, client);
 
        rc = isl1208_i2c_get_sr(client);
        if (rc < 0) {
@@ -653,26 +777,46 @@ isl1208_probe(struct i2c_client *client, const struct i2c_device_id *id)
                dev_warn(&client->dev, "rtc power failure detected, "
                         "please set clock.\n");
 
+       if (id->driver_data == TYPE_ISL1219) {
+               struct device_node *np = client->dev.of_node;
+               u32 evienb;
+
+               rc = i2c_smbus_read_byte_data(client, ISL1219_REG_EV);
+               if (rc < 0) {
+                       dev_err(&client->dev, "failed to read EV reg\n");
+                       return rc;
+               }
+               rc |= ISL1219_REG_EV_EVEN;
+               if (!of_property_read_u32(np, "isil,ev-evienb", &evienb)) {
+                       if (evienb)
+                               rc |= ISL1219_REG_EV_EVIENB;
+                       else
+                               rc &= ~ISL1219_REG_EV_EVIENB;
+               }
+               rc = i2c_smbus_write_byte_data(client, ISL1219_REG_EV, rc);
+               if (rc < 0) {
+                       dev_err(&client->dev, "could not enable tamper detection\n");
+                       return rc;
+               }
+               rc = rtc_add_group(rtc, &isl1219_rtc_sysfs_files);
+               if (rc)
+                       return rc;
+               evdet_irq = of_irq_get_byname(np, "evdet");
+       }
+
        rc = sysfs_create_group(&client->dev.kobj, &isl1208_rtc_sysfs_files);
        if (rc)
                return rc;
 
-       if (client->irq > 0) {
-               rc = devm_request_threaded_irq(&client->dev, client->irq, NULL,
-                                              isl1208_rtc_interrupt,
-                                              IRQF_SHARED | IRQF_ONESHOT,
-                                              isl1208_driver.driver.name,
-                                              client);
-               if (!rc) {
-                       device_init_wakeup(&client->dev, 1);
-                       enable_irq_wake(client->irq);
-               } else {
-                       dev_err(&client->dev,
-                               "Unable to request irq %d, no alarm support\n",
-                               client->irq);
-                       client->irq = 0;
-               }
-       }
+       if (client->irq > 0)
+               rc = isl1208_setup_irq(client, client->irq);
+       if (rc)
+               return rc;
+
+       if (evdet_irq > 0 && evdet_irq != client->irq)
+               rc = isl1208_setup_irq(client, evdet_irq);
+       if (rc)
+               return rc;
 
        return rtc_register_device(rtc);
 }
@@ -686,8 +830,9 @@ isl1208_remove(struct i2c_client *client)
 }
 
 static const struct i2c_device_id isl1208_id[] = {
-       { "isl1208", 0 },
-       { "isl1218", 0 },
+       { "isl1208", TYPE_ISL1208 },
+       { "isl1218", TYPE_ISL1218 },
+       { "isl1219", TYPE_ISL1219 },
        { }
 };
 MODULE_DEVICE_TABLE(i2c, isl1208_id);
@@ -695,6 +840,7 @@ MODULE_DEVICE_TABLE(i2c, isl1208_id);
 static const struct of_device_id isl1208_of_match[] = {
        { .compatible = "isil,isl1208" },
        { .compatible = "isil,isl1218" },
+       { .compatible = "isil,isl1219" },
        { }
 };
 MODULE_DEVICE_TABLE(of, isl1208_of_match);
index 1053a40..ac9ca10 100644 (file)
@@ -373,7 +373,6 @@ static int m48t59_rtc_probe(struct platform_device *pdev)
        struct m48t59_private *m48t59 = NULL;
        struct resource *res;
        int ret = -ENOMEM;
-       char *name;
        const struct rtc_class_ops *ops;
        struct nvmem_config nvmem_cfg = {
                .name = "m48t59-",
@@ -448,17 +447,14 @@ static int m48t59_rtc_probe(struct platform_device *pdev)
        }
        switch (pdata->type) {
        case M48T59RTC_TYPE_M48T59:
-               name = "m48t59";
                ops = &m48t59_rtc_ops;
                pdata->offset = 0x1ff0;
                break;
        case M48T59RTC_TYPE_M48T02:
-               name = "m48t02";
                ops = &m48t02_rtc_ops;
                pdata->offset = 0x7f0;
                break;
        case M48T59RTC_TYPE_M48T08:
-               name = "m48t08";
                ops = &m48t02_rtc_ops;
                pdata->offset = 0x1ff0;
                break;
index cefde27..8a60900 100644 (file)
@@ -1,16 +1,10 @@
-/*
- * RTC driver for Maxim MAX77686 and MAX77802
- *
- * Copyright (C) 2012 Samsung Electronics Co.Ltd
- *
- *  based on rtc-max8997.c
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- */
+// SPDX-License-Identifier: GPL-2.0+
+//
+// RTC driver for Maxim MAX77686 and MAX77802
+//
+// Copyright (C) 2012 Samsung Electronics Co.Ltd
+//
+//  based on rtc-max8997.c
 
 #include <linux/i2c.h>
 #include <linux/slab.h>
index e8cee12..08c661a 100644 (file)
@@ -1,16 +1,10 @@
-/*
- * RTC driver for Maxim MAX8997
- *
- * Copyright (C) 2013 Samsung Electronics Co.Ltd
- *
- *  based on rtc-max8998.c
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- */
+// SPDX-License-Identifier: GPL-2.0+
+//
+// RTC driver for Maxim MAX8997
+//
+// Copyright (C) 2013 Samsung Electronics Co.Ltd
+//
+//  based on rtc-max8998.c
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
index d8c0f9b..c873b45 100644 (file)
@@ -1,16 +1,10 @@
-/*
- * RTC driver for Maxim MAX8998
- *
- * Copyright (C) 2010 Samsung Electronics Co.Ltd
- * Author: Minkyu Kang <mk7.kang@samsung.com>
- * Author: Joonyoung Shim <jy0922.shim@samsung.com>
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- */
+// SPDX-License-Identifier: GPL-2.0+
+//
+// RTC driver for Maxim MAX8998
+//
+// Copyright (C) 2010 Samsung Electronics Co.Ltd
+// Author: Minkyu Kang <mk7.kang@samsung.com>
+// Author: Joonyoung Shim <jy0922.shim@samsung.com>
 
 #include <linux/module.h>
 #include <linux/i2c.h>
index 3908639..323ff55 100644 (file)
@@ -449,6 +449,7 @@ static void omap_rtc_power_off(void)
 
        if (tm2bcd(&tm) < 0) {
                dev_err(&rtc->rtc->dev, "power off failed\n");
+               rtc->type->lock(rtc);
                return;
        }
 
@@ -582,9 +583,7 @@ static int rtc_pinconf_get(struct pinctrl_dev *pctldev,
        u32 val;
        u16 arg = 0;
 
-       rtc->type->unlock(rtc);
        val = rtc_readl(rtc, OMAP_RTC_PMIC_REG);
-       rtc->type->lock(rtc);
 
        switch (param) {
        case PIN_CONFIG_INPUT_ENABLE:
@@ -614,9 +613,7 @@ static int rtc_pinconf_set(struct pinctrl_dev *pctldev,
        u32 param_val;
        int i;
 
-       rtc->type->unlock(rtc);
        val = rtc_readl(rtc, OMAP_RTC_PMIC_REG);
-       rtc->type->lock(rtc);
 
        /* active low by default */
        val |= OMAP_RTC_PMIC_EXT_WKUP_POL(pin);
@@ -861,13 +858,6 @@ static int omap_rtc_probe(struct platform_device *pdev)
                        goto err;
        }
 
-       if (rtc->is_pmic_controller) {
-               if (!pm_power_off) {
-                       omap_rtc_power_off_rtc = rtc;
-                       pm_power_off = omap_rtc_power_off;
-               }
-       }
-
        /* Support ext_wakeup pinconf */
        rtc_pinctrl_desc.name = dev_name(&pdev->dev);
 
@@ -880,12 +870,21 @@ static int omap_rtc_probe(struct platform_device *pdev)
 
        ret = rtc_register_device(rtc->rtc);
        if (ret)
-               goto err;
+               goto err_deregister_pinctrl;
 
        rtc_nvmem_register(rtc->rtc, &omap_rtc_nvmem_config);
 
+       if (rtc->is_pmic_controller) {
+               if (!pm_power_off) {
+                       omap_rtc_power_off_rtc = rtc;
+                       pm_power_off = omap_rtc_power_off;
+               }
+       }
+
        return 0;
 
+err_deregister_pinctrl:
+       pinctrl_unregister(rtc->pctldev);
 err:
        clk_disable_unprepare(rtc->clk);
        device_init_wakeup(&pdev->dev, false);
index e83be18..9f99a09 100644 (file)
 #define PCF2127_REG_MO          (0x08)
 #define PCF2127_REG_YR          (0x09)
 
+/* the pcf2127 has 512 bytes nvmem, pcf2129 doesn't */
+#define PCF2127_REG_RAM_addr_MSB       0x1a
+#define PCF2127_REG_RAM_wrt_cmd        0x1c
+#define PCF2127_REG_RAM_rd_cmd         0x1d
+
 #define PCF2127_OSF             BIT(7)  /* Oscillator Fail flag */
 
 struct pcf2127 {
@@ -183,10 +188,47 @@ static const struct rtc_class_ops pcf2127_rtc_ops = {
        .set_time       = pcf2127_rtc_set_time,
 };
 
+static int pcf2127_nvmem_read(void *priv, unsigned int offset,
+                             void *val, size_t bytes)
+{
+       struct pcf2127 *pcf2127 = priv;
+       int ret;
+       unsigned char offsetbuf[] = { offset >> 8, offset };
+
+       ret = regmap_bulk_write(pcf2127->regmap, PCF2127_REG_RAM_addr_MSB,
+                               offsetbuf, 2);
+       if (ret)
+               return ret;
+
+       ret = regmap_bulk_read(pcf2127->regmap, PCF2127_REG_RAM_rd_cmd,
+                              val, bytes);
+
+       return ret ?: bytes;
+}
+
+static int pcf2127_nvmem_write(void *priv, unsigned int offset,
+                              void *val, size_t bytes)
+{
+       struct pcf2127 *pcf2127 = priv;
+       int ret;
+       unsigned char offsetbuf[] = { offset >> 8, offset };
+
+       ret = regmap_bulk_write(pcf2127->regmap, PCF2127_REG_RAM_addr_MSB,
+                               offsetbuf, 2);
+       if (ret)
+               return ret;
+
+       ret = regmap_bulk_write(pcf2127->regmap, PCF2127_REG_RAM_wrt_cmd,
+                               val, bytes);
+
+       return ret ?: bytes;
+}
+
 static int pcf2127_probe(struct device *dev, struct regmap *regmap,
-                       const char *name)
+                       const char *name, bool has_nvmem)
 {
        struct pcf2127 *pcf2127;
+       int ret = 0;
 
        dev_dbg(dev, "%s\n", __func__);
 
@@ -200,8 +242,21 @@ static int pcf2127_probe(struct device *dev, struct regmap *regmap,
 
        pcf2127->rtc = devm_rtc_device_register(dev, name, &pcf2127_rtc_ops,
                                                THIS_MODULE);
+       if (IS_ERR(pcf2127->rtc))
+               return PTR_ERR(pcf2127->rtc);
+
+       if (has_nvmem) {
+               struct nvmem_config nvmem_cfg = {
+                       .priv = pcf2127,
+                       .reg_read = pcf2127_nvmem_read,
+                       .reg_write = pcf2127_nvmem_write,
+                       .size = 512,
+               };
+
+               ret = rtc_nvmem_register(pcf2127->rtc, &nvmem_cfg);
+       }
 
-       return PTR_ERR_OR_ZERO(pcf2127->rtc);
+       return ret;
 }
 
 #ifdef CONFIG_OF
@@ -309,11 +364,11 @@ static int pcf2127_i2c_probe(struct i2c_client *client,
        }
 
        return pcf2127_probe(&client->dev, regmap,
-                               pcf2127_i2c_driver.driver.name);
+                            pcf2127_i2c_driver.driver.name, id->driver_data);
 }
 
 static const struct i2c_device_id pcf2127_i2c_id[] = {
-       { "pcf2127", 0 },
+       { "pcf2127", 1 },
        { "pcf2129", 0 },
        { }
 };
@@ -372,11 +427,12 @@ static int pcf2127_spi_probe(struct spi_device *spi)
                return PTR_ERR(regmap);
        }
 
-       return pcf2127_probe(&spi->dev, regmap, pcf2127_spi_driver.driver.name);
+       return pcf2127_probe(&spi->dev, regmap, pcf2127_spi_driver.driver.name,
+                            spi_get_device_id(spi)->driver_data);
 }
 
 static const struct spi_device_id pcf2127_spi_id[] = {
-       { "pcf2127", 0 },
+       { "pcf2127", 1 },
        { "pcf2129", 0 },
        { }
 };
index 49bcbb3..283c233 100644 (file)
@@ -43,37 +43,38 @@ static struct i2c_driver pcf85063_driver;
 
 static int pcf85063_stop_clock(struct i2c_client *client, u8 *ctrl1)
 {
-       s32 ret;
+       int rc;
+       u8 reg;
 
-       ret = i2c_smbus_read_byte_data(client, PCF85063_REG_CTRL1);
-       if (ret < 0) {
+       rc = i2c_smbus_read_byte_data(client, PCF85063_REG_CTRL1);
+       if (rc < 0) {
                dev_err(&client->dev, "Failing to stop the clock\n");
                return -EIO;
        }
 
        /* stop the clock */
-       ret |= PCF85063_REG_CTRL1_STOP;
+       reg = rc | PCF85063_REG_CTRL1_STOP;
 
-       ret = i2c_smbus_write_byte_data(client, PCF85063_REG_CTRL1, ret);
-       if (ret < 0) {
+       rc = i2c_smbus_write_byte_data(client, PCF85063_REG_CTRL1, reg);
+       if (rc < 0) {
                dev_err(&client->dev, "Failing to stop the clock\n");
                return -EIO;
        }
 
-       *ctrl1 = ret;
+       *ctrl1 = reg;
 
        return 0;
 }
 
 static int pcf85063_start_clock(struct i2c_client *client, u8 ctrl1)
 {
-       s32 ret;
+       int rc;
 
        /* start the clock */
        ctrl1 &= ~PCF85063_REG_CTRL1_STOP;
 
-       ret = i2c_smbus_write_byte_data(client, PCF85063_REG_CTRL1, ctrl1);
-       if (ret < 0) {
+       rc = i2c_smbus_write_byte_data(client, PCF85063_REG_CTRL1, ctrl1);
+       if (rc < 0) {
                dev_err(&client->dev, "Failing to start the clock\n");
                return -EIO;
        }
index 8428455..6495f84 100644 (file)
@@ -1,19 +1,9 @@
-/*
- * Copyright (c) 2013-2014 Samsung Electronics Co., Ltd
- *     http://www.samsung.com
- *
- *  Copyright (C) 2013 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.
- *
- *  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.
- */
+// SPDX-License-Identifier: GPL-2.0+
+//
+// Copyright (c) 2013-2014 Samsung Electronics Co., Ltd
+//     http://www.samsung.com
+//
+//  Copyright (C) 2013 Google, Inc
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
index ed71d11..304d905 100644 (file)
@@ -224,7 +224,6 @@ int sa1100_rtc_init(struct platform_device *pdev, struct sa1100_rtc *info)
        info->rtc = rtc;
 
        rtc->max_user_freq = RTC_FREQ;
-       rtc_irq_set_freq(rtc, NULL, RTC_FREQ);
 
        /* Fix for a nasty initialization problem the in SA11xx RTSR register.
         * See also the comments in sa1100_rtc_interrupt().
index 776b70a..51ba414 100644 (file)
@@ -143,8 +143,6 @@ static int __sh_rtc_alarm(struct sh_rtc *rtc)
 
 static int __sh_rtc_periodic(struct sh_rtc *rtc)
 {
-       struct rtc_device *rtc_dev = rtc->rtc_dev;
-       struct rtc_task *irq_task;
        unsigned int tmp, pending;
 
        tmp = readb(rtc->regbase + RCR2);
@@ -161,14 +159,7 @@ static int __sh_rtc_periodic(struct sh_rtc *rtc)
        else {
                if (rtc->periodic_freq & PF_HP)
                        rtc->periodic_freq |= PF_COUNT;
-               if (rtc->periodic_freq & PF_KOU) {
-                       spin_lock(&rtc_dev->irq_task_lock);
-                       irq_task = rtc_dev->irq_task;
-                       if (irq_task)
-                               irq_task->func(irq_task->private_data);
-                       spin_unlock(&rtc_dev->irq_task_lock);
-               } else
-                       rtc_update_irq(rtc->rtc_dev, 1, RTC_PF | RTC_IRQF);
+               rtc_update_irq(rtc->rtc_dev, 1, RTC_PF | RTC_IRQF);
        }
 
        return pending;
@@ -224,81 +215,6 @@ static irqreturn_t sh_rtc_shared(int irq, void *dev_id)
        return IRQ_RETVAL(ret);
 }
 
-static int sh_rtc_irq_set_state(struct device *dev, int enable)
-{
-       struct sh_rtc *rtc = dev_get_drvdata(dev);
-       unsigned int tmp;
-
-       spin_lock_irq(&rtc->lock);
-
-       tmp = readb(rtc->regbase + RCR2);
-
-       if (enable) {
-               rtc->periodic_freq |= PF_KOU;
-               tmp &= ~RCR2_PEF;       /* Clear PES bit */
-               tmp |= (rtc->periodic_freq & ~PF_HP);   /* Set PES2-0 */
-       } else {
-               rtc->periodic_freq &= ~PF_KOU;
-               tmp &= ~(RCR2_PESMASK | RCR2_PEF);
-       }
-
-       writeb(tmp, rtc->regbase + RCR2);
-
-       spin_unlock_irq(&rtc->lock);
-
-       return 0;
-}
-
-static int sh_rtc_irq_set_freq(struct device *dev, int freq)
-{
-       struct sh_rtc *rtc = dev_get_drvdata(dev);
-       int tmp, ret = 0;
-
-       spin_lock_irq(&rtc->lock);
-       tmp = rtc->periodic_freq & PF_MASK;
-
-       switch (freq) {
-       case 0:
-               rtc->periodic_freq = 0x00;
-               break;
-       case 1:
-               rtc->periodic_freq = 0x60;
-               break;
-       case 2:
-               rtc->periodic_freq = 0x50;
-               break;
-       case 4:
-               rtc->periodic_freq = 0x40;
-               break;
-       case 8:
-               rtc->periodic_freq = 0x30 | PF_HP;
-               break;
-       case 16:
-               rtc->periodic_freq = 0x30;
-               break;
-       case 32:
-               rtc->periodic_freq = 0x20 | PF_HP;
-               break;
-       case 64:
-               rtc->periodic_freq = 0x20;
-               break;
-       case 128:
-               rtc->periodic_freq = 0x10 | PF_HP;
-               break;
-       case 256:
-               rtc->periodic_freq = 0x10;
-               break;
-       default:
-               ret = -ENOTSUPP;
-       }
-
-       if (ret == 0)
-               rtc->periodic_freq |= tmp;
-
-       spin_unlock_irq(&rtc->lock);
-       return ret;
-}
-
 static inline void sh_rtc_setaie(struct device *dev, unsigned int enable)
 {
        struct sh_rtc *rtc = dev_get_drvdata(dev);
@@ -675,8 +591,6 @@ static int __init sh_rtc_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, rtc);
 
        /* everything disabled by default */
-       sh_rtc_irq_set_freq(&pdev->dev, 0);
-       sh_rtc_irq_set_state(&pdev->dev, 0);
        sh_rtc_setaie(&pdev->dev, 0);
        sh_rtc_setcie(&pdev->dev, 0);
 
@@ -708,8 +622,6 @@ static int __exit sh_rtc_remove(struct platform_device *pdev)
 {
        struct sh_rtc *rtc = platform_get_drvdata(pdev);
 
-       sh_rtc_irq_set_state(&pdev->dev, 0);
-
        sh_rtc_setaie(&pdev->dev, 0);
        sh_rtc_setcie(&pdev->dev, 0);
 
index 8a75cc3..b2483a7 100644 (file)
@@ -40,49 +40,83 @@ struct snvs_rtc_data {
        struct clk *clk;
 };
 
+/* Read 64 bit timer register, which could be in inconsistent state */
+static u64 rtc_read_lpsrt(struct snvs_rtc_data *data)
+{
+       u32 msb, lsb;
+
+       regmap_read(data->regmap, data->offset + SNVS_LPSRTCMR, &msb);
+       regmap_read(data->regmap, data->offset + SNVS_LPSRTCLR, &lsb);
+       return (u64)msb << 32 | lsb;
+}
+
+/* Read the secure real time counter, taking care to deal with the cases of the
+ * counter updating while being read.
+ */
 static u32 rtc_read_lp_counter(struct snvs_rtc_data *data)
 {
        u64 read1, read2;
-       u32 val;
+       unsigned int timeout = 100;
 
+       /* As expected, the registers might update between the read of the LSB
+        * reg and the MSB reg.  It's also possible that one register might be
+        * in partially modified state as well.
+        */
+       read1 = rtc_read_lpsrt(data);
        do {
-               regmap_read(data->regmap, data->offset + SNVS_LPSRTCMR, &val);
-               read1 = val;
-               read1 <<= 32;
-               regmap_read(data->regmap, data->offset + SNVS_LPSRTCLR, &val);
-               read1 |= val;
-
-               regmap_read(data->regmap, data->offset + SNVS_LPSRTCMR, &val);
-               read2 = val;
-               read2 <<= 32;
-               regmap_read(data->regmap, data->offset + SNVS_LPSRTCLR, &val);
-               read2 |= val;
-       } while (read1 != read2);
+               read2 = read1;
+               read1 = rtc_read_lpsrt(data);
+       } while (read1 != read2 && --timeout);
+       if (!timeout)
+               dev_err(&data->rtc->dev, "Timeout trying to get valid LPSRT Counter read\n");
 
        /* Convert 47-bit counter to 32-bit raw second count */
        return (u32) (read1 >> CNTR_TO_SECS_SH);
 }
 
-static void rtc_write_sync_lp(struct snvs_rtc_data *data)
+/* Just read the lsb from the counter, dealing with inconsistent state */
+static int rtc_read_lp_counter_lsb(struct snvs_rtc_data *data, u32 *lsb)
+{
+       u32 count1, count2;
+       unsigned int timeout = 100;
+
+       regmap_read(data->regmap, data->offset + SNVS_LPSRTCLR, &count1);
+       do {
+               count2 = count1;
+               regmap_read(data->regmap, data->offset + SNVS_LPSRTCLR, &count1);
+       } while (count1 != count2 && --timeout);
+       if (!timeout) {
+               dev_err(&data->rtc->dev, "Timeout trying to get valid LPSRT Counter read\n");
+               return -ETIMEDOUT;
+       }
+
+       *lsb = count1;
+       return 0;
+}
+
+static int rtc_write_sync_lp(struct snvs_rtc_data *data)
 {
-       u32 count1, count2, count3;
-       int i;
-
-       /* Wait for 3 CKIL cycles */
-       for (i = 0; i < 3; i++) {
-               do {
-                       regmap_read(data->regmap, data->offset + SNVS_LPSRTCLR, &count1);
-                       regmap_read(data->regmap, data->offset + SNVS_LPSRTCLR, &count2);
-               } while (count1 != count2);
-
-               /* Now wait until counter value changes */
-               do {
-                       do {
-                               regmap_read(data->regmap, data->offset + SNVS_LPSRTCLR, &count2);
-                               regmap_read(data->regmap, data->offset + SNVS_LPSRTCLR, &count3);
-                       } while (count2 != count3);
-               } while (count3 == count1);
+       u32 count1, count2;
+       u32 elapsed;
+       unsigned int timeout = 1000;
+       int ret;
+
+       ret = rtc_read_lp_counter_lsb(data, &count1);
+       if (ret)
+               return ret;
+
+       /* Wait for 3 CKIL cycles, about 61.0-91.5 µs */
+       do {
+               ret = rtc_read_lp_counter_lsb(data, &count2);
+               if (ret)
+                       return ret;
+               elapsed = count2 - count1; /* wrap around _is_ handled! */
+       } while (elapsed < 3 && --timeout);
+       if (!timeout) {
+               dev_err(&data->rtc->dev, "Timeout waiting for LPSRT Counter to change\n");
+               return -ETIMEDOUT;
        }
+       return 0;
 }
 
 static int snvs_rtc_enable(struct snvs_rtc_data *data, bool enable)
@@ -166,9 +200,7 @@ static int snvs_rtc_alarm_irq_enable(struct device *dev, unsigned int enable)
                           (SNVS_LPCR_LPTA_EN | SNVS_LPCR_LPWUI_EN),
                           enable ? (SNVS_LPCR_LPTA_EN | SNVS_LPCR_LPWUI_EN) : 0);
 
-       rtc_write_sync_lp(data);
-
-       return 0;
+       return rtc_write_sync_lp(data);
 }
 
 static int snvs_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
@@ -176,11 +208,14 @@ static int snvs_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
        struct snvs_rtc_data *data = dev_get_drvdata(dev);
        struct rtc_time *alrm_tm = &alrm->time;
        unsigned long time;
+       int ret;
 
        rtc_tm_to_time(alrm_tm, &time);
 
        regmap_update_bits(data->regmap, data->offset + SNVS_LPCR, SNVS_LPCR_LPTA_EN, 0);
-       rtc_write_sync_lp(data);
+       ret = rtc_write_sync_lp(data);
+       if (ret)
+               return ret;
        regmap_write(data->regmap, data->offset + SNVS_LPTAR, time);
 
        /* Clear alarm interrupt status bit */
index d578e40..b76318f 100644 (file)
@@ -288,10 +288,22 @@ static int stmp3xxx_rtc_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, rtc_data);
 
-       err = stmp_reset_block(rtc_data->io);
-       if (err) {
-               dev_err(&pdev->dev, "stmp_reset_block failed: %d\n", err);
-               return err;
+       /*
+        * Resetting the rtc stops the watchdog timer that is potentially
+        * running. So (assuming it is running on purpose) don't reset if the
+        * watchdog is enabled.
+        */
+       if (readl(rtc_data->io + STMP3XXX_RTC_CTRL) &
+           STMP3XXX_RTC_CTRL_WATCHDOGEN) {
+               dev_info(&pdev->dev,
+                        "Watchdog is running, skip resetting rtc\n");
+       } else {
+               err = stmp_reset_block(rtc_data->io);
+               if (err) {
+                       dev_err(&pdev->dev, "stmp_reset_block failed: %d\n",
+                               err);
+                       return err;
+               }
        }
 
        /*
index 454da38..f1ff30a 100644 (file)
@@ -317,3 +317,46 @@ const struct attribute_group **rtc_get_dev_attribute_groups(void)
 {
        return rtc_attr_groups;
 }
+
+int rtc_add_groups(struct rtc_device *rtc, const struct attribute_group **grps)
+{
+       size_t old_cnt = 0, add_cnt = 0, new_cnt;
+       const struct attribute_group **groups, **old;
+
+       if (rtc->registered)
+               return -EINVAL;
+       if (!grps)
+               return -EINVAL;
+
+       groups = rtc->dev.groups;
+       if (groups)
+               for (; *groups; groups++)
+                       old_cnt++;
+
+       for (groups = grps; *groups; groups++)
+               add_cnt++;
+
+       new_cnt = old_cnt + add_cnt + 1;
+       groups = devm_kcalloc(&rtc->dev, new_cnt, sizeof(*groups), GFP_KERNEL);
+       if (IS_ERR_OR_NULL(groups))
+               return PTR_ERR(groups);
+       memcpy(groups, rtc->dev.groups, old_cnt * sizeof(*groups));
+       memcpy(groups + old_cnt, grps, add_cnt * sizeof(*groups));
+       groups[old_cnt + add_cnt] = NULL;
+
+       old = rtc->dev.groups;
+       rtc->dev.groups = groups;
+       if (old && old != rtc_attr_groups)
+               devm_kfree(&rtc->dev, old);
+
+       return 0;
+}
+EXPORT_SYMBOL(rtc_add_groups);
+
+int rtc_add_group(struct rtc_device *rtc, const struct attribute_group *grp)
+{
+       const struct attribute_group *groups[] = { grp, NULL };
+
+       return rtc_add_groups(rtc, groups);
+}
+EXPORT_SYMBOL(rtc_add_group);
index 8469256..ade6a82 100644 (file)
@@ -22,7 +22,7 @@ struct rtc_test_data {
        bool alarm_en;
 };
 
-struct platform_device *pdev[MAX_RTC_TEST];
+static struct platform_device *pdev[MAX_RTC_TEST];
 
 static int test_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
 {
index ed60728..23e526c 100644 (file)
@@ -922,9 +922,11 @@ __dcssblk_direct_access(struct dcssblk_dev_info *dev_info, pgoff_t pgoff,
        unsigned long dev_sz;
 
        dev_sz = dev_info->end - dev_info->start + 1;
-       *kaddr = (void *) dev_info->start + offset;
-       *pfn = __pfn_to_pfn_t(PFN_DOWN(dev_info->start + offset),
-                       PFN_DEV|PFN_SPECIAL);
+       if (kaddr)
+               *kaddr = (void *) dev_info->start + offset;
+       if (pfn)
+               *pfn = __pfn_to_pfn_t(PFN_DOWN(dev_info->start + offset),
+                               PFN_DEV|PFN_SPECIAL);
 
        return (dev_sz - offset) / PAGE_SIZE;
 }
index bf27fc4..ec891bc 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/crypto.h>
 #include <linux/mod_devicetable.h>
 #include <linux/debugfs.h>
+#include <linux/ctype.h>
 
 #include "ap_bus.h"
 #include "ap_debug.h"
  */
 int ap_domain_index = -1;      /* Adjunct Processor Domain Index */
 static DEFINE_SPINLOCK(ap_domain_lock);
-module_param_named(domain, ap_domain_index, int, S_IRUSR|S_IRGRP);
+module_param_named(domain, ap_domain_index, int, 0440);
 MODULE_PARM_DESC(domain, "domain index for ap devices");
 EXPORT_SYMBOL(ap_domain_index);
 
-static int ap_thread_flag = 0;
-module_param_named(poll_thread, ap_thread_flag, int, S_IRUSR|S_IRGRP);
+static int ap_thread_flag;
+module_param_named(poll_thread, ap_thread_flag, int, 0440);
 MODULE_PARM_DESC(poll_thread, "Turn on/off poll thread, default is 0 (off).");
 
+static char *apm_str;
+module_param_named(apmask, apm_str, charp, 0440);
+MODULE_PARM_DESC(apmask, "AP bus adapter mask.");
+
+static char *aqm_str;
+module_param_named(aqmask, aqm_str, charp, 0440);
+MODULE_PARM_DESC(aqmask, "AP bus domain mask.");
+
 static struct device *ap_root_device;
 
 DEFINE_SPINLOCK(ap_list_lock);
 LIST_HEAD(ap_card_list);
 
+/* Default permissions (card and domain masking) */
+static struct ap_perms {
+       DECLARE_BITMAP(apm, AP_DEVICES);
+       DECLARE_BITMAP(aqm, AP_DOMAINS);
+} ap_perms;
+static DEFINE_MUTEX(ap_perms_mutex);
+
 static struct ap_config_info *ap_configuration;
 static bool initialised;
 
@@ -78,22 +94,26 @@ static DECLARE_WORK(ap_scan_work, ap_scan_bus);
 static void ap_tasklet_fn(unsigned long);
 static DECLARE_TASKLET(ap_tasklet, ap_tasklet_fn, 0);
 static DECLARE_WAIT_QUEUE_HEAD(ap_poll_wait);
-static struct task_struct *ap_poll_kthread = NULL;
+static struct task_struct *ap_poll_kthread;
 static DEFINE_MUTEX(ap_poll_thread_mutex);
 static DEFINE_SPINLOCK(ap_poll_timer_lock);
 static struct hrtimer ap_poll_timer;
-/* In LPAR poll with 4kHz frequency. Poll every 250000 nanoseconds.
- * If z/VM change to 1500000 nanoseconds to adjust to z/VM polling.*/
+/*
+ * In LPAR poll with 4kHz frequency. Poll every 250000 nanoseconds.
+ * If z/VM change to 1500000 nanoseconds to adjust to z/VM polling.
+ */
 static unsigned long long poll_timeout = 250000;
 
 /* Suspend flag */
 static int ap_suspend_flag;
 /* Maximum domain id */
 static int ap_max_domain_id;
-/* Flag to check if domain was set through module parameter domain=. This is
+/*
+ * Flag to check if domain was set through module parameter domain=. This is
  * important when supsend and resume is done in a z/VM environment where the
- * domain might change. */
-static int user_set_domain = 0;
+ * domain might change.
+ */
+static int user_set_domain;
 static struct bus_type ap_bus_type;
 
 /* Adapter interrupt definitions */
@@ -531,7 +551,7 @@ static int ap_bus_match(struct device *dev, struct device_driver *drv)
  * It sets up a single environment variable DEV_TYPE which contains the
  * hardware device type.
  */
-static int ap_uevent (struct device *dev, struct kobj_uevent_env *env)
+static int ap_uevent(struct device *dev, struct kobj_uevent_env *env)
 {
        struct ap_device *ap_dev = to_ap_dev(dev);
        int retval = 0;
@@ -570,7 +590,7 @@ static int ap_dev_resume(struct device *dev)
 
 static void ap_bus_suspend(void)
 {
-       AP_DBF(DBF_DEBUG, "ap_bus_suspend running\n");
+       AP_DBF(DBF_DEBUG, "%s running\n", __func__);
 
        ap_suspend_flag = 1;
        /*
@@ -607,7 +627,7 @@ static void ap_bus_resume(void)
 {
        int rc;
 
-       AP_DBF(DBF_DEBUG, "ap_bus_resume running\n");
+       AP_DBF(DBF_DEBUG, "%s running\n", __func__);
 
        /* remove all queue devices */
        bus_for_each_dev(&ap_bus_type, NULL, NULL,
@@ -666,11 +686,97 @@ static struct bus_type ap_bus_type = {
        .pm = &ap_bus_pm_ops,
 };
 
+static int __ap_revise_reserved(struct device *dev, void *dummy)
+{
+       int rc, card, queue, devres, drvres;
+
+       if (is_queue_dev(dev)) {
+               card = AP_QID_CARD(to_ap_queue(dev)->qid);
+               queue = AP_QID_QUEUE(to_ap_queue(dev)->qid);
+               mutex_lock(&ap_perms_mutex);
+               devres = test_bit_inv(card, ap_perms.apm)
+                       && test_bit_inv(queue, ap_perms.aqm);
+               mutex_unlock(&ap_perms_mutex);
+               drvres = to_ap_drv(dev->driver)->flags
+                       & AP_DRIVER_FLAG_DEFAULT;
+               if (!!devres != !!drvres) {
+                       AP_DBF(DBF_DEBUG, "reprobing queue=%02x.%04x\n",
+                              card, queue);
+                       rc = device_reprobe(dev);
+               }
+       }
+
+       return 0;
+}
+
+static void ap_bus_revise_bindings(void)
+{
+       bus_for_each_dev(&ap_bus_type, NULL, NULL, __ap_revise_reserved);
+}
+
+int ap_owned_by_def_drv(int card, int queue)
+{
+       int rc = 0;
+
+       if (card < 0 || card >= AP_DEVICES || queue < 0 || queue >= AP_DOMAINS)
+               return -EINVAL;
+
+       mutex_lock(&ap_perms_mutex);
+
+       if (test_bit_inv(card, ap_perms.apm)
+           && test_bit_inv(queue, ap_perms.aqm))
+               rc = 1;
+
+       mutex_unlock(&ap_perms_mutex);
+
+       return rc;
+}
+EXPORT_SYMBOL(ap_owned_by_def_drv);
+
+int ap_apqn_in_matrix_owned_by_def_drv(unsigned long *apm,
+                                      unsigned long *aqm)
+{
+       int card, queue, rc = 0;
+
+       mutex_lock(&ap_perms_mutex);
+
+       for (card = 0; !rc && card < AP_DEVICES; card++)
+               if (test_bit_inv(card, apm) &&
+                   test_bit_inv(card, ap_perms.apm))
+                       for (queue = 0; !rc && queue < AP_DOMAINS; queue++)
+                               if (test_bit_inv(queue, aqm) &&
+                                   test_bit_inv(queue, ap_perms.aqm))
+                                       rc = 1;
+
+       mutex_unlock(&ap_perms_mutex);
+
+       return rc;
+}
+EXPORT_SYMBOL(ap_apqn_in_matrix_owned_by_def_drv);
+
 static int ap_device_probe(struct device *dev)
 {
        struct ap_device *ap_dev = to_ap_dev(dev);
        struct ap_driver *ap_drv = to_ap_drv(dev->driver);
-       int rc;
+       int card, queue, devres, drvres, rc;
+
+       if (is_queue_dev(dev)) {
+               /*
+                * If the apqn is marked as reserved/used by ap bus and
+                * default drivers, only probe with drivers with the default
+                * flag set. If it is not marked, only probe with drivers
+                * with the default flag not set.
+                */
+               card = AP_QID_CARD(to_ap_queue(dev)->qid);
+               queue = AP_QID_QUEUE(to_ap_queue(dev)->qid);
+               mutex_lock(&ap_perms_mutex);
+               devres = test_bit_inv(card, ap_perms.apm)
+                       && test_bit_inv(queue, ap_perms.aqm);
+               mutex_unlock(&ap_perms_mutex);
+               drvres = ap_drv->flags & AP_DRIVER_FLAG_DEFAULT;
+               if (!!devres != !!drvres)
+                       return -ENODEV;
+       }
 
        /* Add queue/card to list of active queues/cards */
        spin_lock_bh(&ap_list_lock);
@@ -751,8 +857,163 @@ void ap_bus_force_rescan(void)
 EXPORT_SYMBOL(ap_bus_force_rescan);
 
 /*
+ * hex2bitmap() - parse hex mask string and set bitmap.
+ * Valid strings are "0x012345678" with at least one valid hex number.
+ * Rest of the bitmap to the right is padded with 0. No spaces allowed
+ * within the string, the leading 0x may be omitted.
+ * Returns the bitmask with exactly the bits set as given by the hex
+ * string (both in big endian order).
+ */
+static int hex2bitmap(const char *str, unsigned long *bitmap, int bits)
+{
+       int i, n, b;
+
+       /* bits needs to be a multiple of 8 */
+       if (bits & 0x07)
+               return -EINVAL;
+
+       memset(bitmap, 0, bits / 8);
+
+       if (str[0] == '0' && str[1] == 'x')
+               str++;
+       if (*str == 'x')
+               str++;
+
+       for (i = 0; isxdigit(*str) && i < bits; str++) {
+               b = hex_to_bin(*str);
+               for (n = 0; n < 4; n++)
+                       if (b & (0x08 >> n))
+                               set_bit_inv(i + n, bitmap);
+               i += 4;
+       }
+
+       if (*str == '\n')
+               str++;
+       if (*str)
+               return -EINVAL;
+       return 0;
+}
+
+/*
+ * str2clrsetmasks() - parse bitmask argument and set the clear and
+ * the set bitmap mask. A concatenation (done with ',') of these terms
+ * is recognized:
+ *   +<bitnr>[-<bitnr>] or -<bitnr>[-<bitnr>]
+ * <bitnr> may be any valid number (hex, decimal or octal) in the range
+ * 0...bits-1; the leading + or - is required. Here are some examples:
+ *   +0-15,+32,-128,-0xFF
+ *   -0-255,+1-16,+0x128
+ *   +1,+2,+3,+4,-5,-7-10
+ * Returns a clear and a set bitmask. Every positive value in the string
+ * results in a bit set in the set mask and every negative value in the
+ * string results in a bit SET in the clear mask. As a bit may be touched
+ * more than once, the last 'operation' wins: +0-255,-128 = all but bit
+ * 128 set in the set mask, only bit 128 set in the clear mask.
+ */
+static int str2clrsetmasks(const char *str,
+                          unsigned long *clrmap,
+                          unsigned long *setmap,
+                          int bits)
+{
+       int a, i, z;
+       char *np, sign;
+
+       /* bits needs to be a multiple of 8 */
+       if (bits & 0x07)
+               return -EINVAL;
+
+       memset(clrmap, 0, bits / 8);
+       memset(setmap, 0, bits / 8);
+
+       while (*str) {
+               sign = *str++;
+               if (sign != '+' && sign != '-')
+                       return -EINVAL;
+               a = z = simple_strtoul(str, &np, 0);
+               if (str == np || a >= bits)
+                       return -EINVAL;
+               str = np;
+               if (*str == '-') {
+                       z = simple_strtoul(++str, &np, 0);
+                       if (str == np || a > z || z >= bits)
+                               return -EINVAL;
+                       str = np;
+               }
+               for (i = a; i <= z; i++)
+                       if (sign == '+') {
+                               set_bit_inv(i, setmap);
+                               clear_bit_inv(i, clrmap);
+                       } else {
+                               clear_bit_inv(i, setmap);
+                               set_bit_inv(i, clrmap);
+                       }
+               while (*str == ',' || *str == '\n')
+                       str++;
+       }
+
+       return 0;
+}
+
+/*
+ * process_mask_arg() - parse a bitmap string and clear/set the
+ * bits in the bitmap accordingly. The string may be given as
+ * absolute value, a hex string like 0x1F2E3D4C5B6A" simple over-
+ * writing the current content of the bitmap. Or as relative string
+ * like "+1-16,-32,-0x40,+128" where only single bits or ranges of
+ * bits are cleared or set. Distinction is done based on the very
+ * first character which may be '+' or '-' for the relative string
+ * and othewise assume to be an absolute value string. If parsing fails
+ * a negative errno value is returned. All arguments and bitmaps are
+ * big endian order.
+ */
+static int process_mask_arg(const char *str,
+                           unsigned long *bitmap, int bits,
+                           struct mutex *lock)
+{
+       int i;
+
+       /* bits needs to be a multiple of 8 */
+       if (bits & 0x07)
+               return -EINVAL;
+
+       if (*str == '+' || *str == '-') {
+               DECLARE_BITMAP(clrm, bits);
+               DECLARE_BITMAP(setm, bits);
+
+               i = str2clrsetmasks(str, clrm, setm, bits);
+               if (i)
+                       return i;
+               if (mutex_lock_interruptible(lock))
+                       return -ERESTARTSYS;
+               for (i = 0; i < bits; i++) {
+                       if (test_bit_inv(i, clrm))
+                               clear_bit_inv(i, bitmap);
+                       if (test_bit_inv(i, setm))
+                               set_bit_inv(i, bitmap);
+               }
+       } else {
+               DECLARE_BITMAP(setm, bits);
+
+               i = hex2bitmap(str, setm, bits);
+               if (i)
+                       return i;
+               if (mutex_lock_interruptible(lock))
+                       return -ERESTARTSYS;
+               for (i = 0; i < bits; i++)
+                       if (test_bit_inv(i, setm))
+                               set_bit_inv(i, bitmap);
+                       else
+                               clear_bit_inv(i, bitmap);
+       }
+       mutex_unlock(lock);
+
+       return 0;
+}
+
+/*
  * AP bus attributes.
  */
+
 static ssize_t ap_domain_show(struct bus_type *bus, char *buf)
 {
        return snprintf(buf, PAGE_SIZE, "%d\n", ap_domain_index);
@@ -764,7 +1025,8 @@ static ssize_t ap_domain_store(struct bus_type *bus,
        int domain;
 
        if (sscanf(buf, "%i\n", &domain) != 1 ||
-           domain < 0 || domain > ap_max_domain_id)
+           domain < 0 || domain > ap_max_domain_id ||
+           !test_bit_inv(domain, ap_perms.aqm))
                return -EINVAL;
        spin_lock_bh(&ap_domain_lock);
        ap_domain_index = domain;
@@ -775,7 +1037,7 @@ static ssize_t ap_domain_store(struct bus_type *bus,
        return count;
 }
 
-static BUS_ATTR(ap_domain, 0644, ap_domain_show, ap_domain_store);
+static BUS_ATTR_RW(ap_domain);
 
 static ssize_t ap_control_domain_mask_show(struct bus_type *bus, char *buf)
 {
@@ -790,8 +1052,7 @@ static ssize_t ap_control_domain_mask_show(struct bus_type *bus, char *buf)
                        ap_configuration->adm[6], ap_configuration->adm[7]);
 }
 
-static BUS_ATTR(ap_control_domain_mask, 0444,
-               ap_control_domain_mask_show, NULL);
+static BUS_ATTR_RO(ap_control_domain_mask);
 
 static ssize_t ap_usage_domain_mask_show(struct bus_type *bus, char *buf)
 {
@@ -806,13 +1067,7 @@ static ssize_t ap_usage_domain_mask_show(struct bus_type *bus, char *buf)
                        ap_configuration->aqm[6], ap_configuration->aqm[7]);
 }
 
-static BUS_ATTR(ap_usage_domain_mask, 0444,
-               ap_usage_domain_mask_show, NULL);
-
-static ssize_t ap_config_time_show(struct bus_type *bus, char *buf)
-{
-       return snprintf(buf, PAGE_SIZE, "%d\n", ap_config_time);
-}
+static BUS_ATTR_RO(ap_usage_domain_mask);
 
 static ssize_t ap_interrupts_show(struct bus_type *bus, char *buf)
 {
@@ -820,10 +1075,15 @@ static ssize_t ap_interrupts_show(struct bus_type *bus, char *buf)
                        ap_using_interrupts() ? 1 : 0);
 }
 
-static BUS_ATTR(ap_interrupts, 0444, ap_interrupts_show, NULL);
+static BUS_ATTR_RO(ap_interrupts);
+
+static ssize_t config_time_show(struct bus_type *bus, char *buf)
+{
+       return snprintf(buf, PAGE_SIZE, "%d\n", ap_config_time);
+}
 
-static ssize_t ap_config_time_store(struct bus_type *bus,
-                                   const char *buf, size_t count)
+static ssize_t config_time_store(struct bus_type *bus,
+                                const char *buf, size_t count)
 {
        int time;
 
@@ -834,15 +1094,15 @@ static ssize_t ap_config_time_store(struct bus_type *bus,
        return count;
 }
 
-static BUS_ATTR(config_time, 0644, ap_config_time_show, ap_config_time_store);
+static BUS_ATTR_RW(config_time);
 
-static ssize_t ap_poll_thread_show(struct bus_type *bus, char *buf)
+static ssize_t poll_thread_show(struct bus_type *bus, char *buf)
 {
        return snprintf(buf, PAGE_SIZE, "%d\n", ap_poll_kthread ? 1 : 0);
 }
 
-static ssize_t ap_poll_thread_store(struct bus_type *bus,
-                                   const char *buf, size_t count)
+static ssize_t poll_thread_store(struct bus_type *bus,
+                                const char *buf, size_t count)
 {
        int flag, rc;
 
@@ -857,7 +1117,7 @@ static ssize_t ap_poll_thread_store(struct bus_type *bus,
        return count;
 }
 
-static BUS_ATTR(poll_thread, 0644, ap_poll_thread_show, ap_poll_thread_store);
+static BUS_ATTR_RW(poll_thread);
 
 static ssize_t poll_timeout_show(struct bus_type *bus, char *buf)
 {
@@ -886,7 +1146,7 @@ static ssize_t poll_timeout_store(struct bus_type *bus, const char *buf,
        return count;
 }
 
-static BUS_ATTR(poll_timeout, 0644, poll_timeout_show, poll_timeout_store);
+static BUS_ATTR_RW(poll_timeout);
 
 static ssize_t ap_max_domain_id_show(struct bus_type *bus, char *buf)
 {
@@ -899,7 +1159,69 @@ static ssize_t ap_max_domain_id_show(struct bus_type *bus, char *buf)
        return snprintf(buf, PAGE_SIZE, "%d\n", max_domain_id);
 }
 
-static BUS_ATTR(ap_max_domain_id, 0444, ap_max_domain_id_show, NULL);
+static BUS_ATTR_RO(ap_max_domain_id);
+
+static ssize_t apmask_show(struct bus_type *bus, char *buf)
+{
+       int rc;
+
+       if (mutex_lock_interruptible(&ap_perms_mutex))
+               return -ERESTARTSYS;
+       rc = snprintf(buf, PAGE_SIZE,
+                     "0x%016lx%016lx%016lx%016lx\n",
+                     ap_perms.apm[0], ap_perms.apm[1],
+                     ap_perms.apm[2], ap_perms.apm[3]);
+       mutex_unlock(&ap_perms_mutex);
+
+       return rc;
+}
+
+static ssize_t apmask_store(struct bus_type *bus, const char *buf,
+                           size_t count)
+{
+       int rc;
+
+       rc = process_mask_arg(buf, ap_perms.apm, AP_DEVICES, &ap_perms_mutex);
+       if (rc)
+               return rc;
+
+       ap_bus_revise_bindings();
+
+       return count;
+}
+
+static BUS_ATTR_RW(apmask);
+
+static ssize_t aqmask_show(struct bus_type *bus, char *buf)
+{
+       int rc;
+
+       if (mutex_lock_interruptible(&ap_perms_mutex))
+               return -ERESTARTSYS;
+       rc = snprintf(buf, PAGE_SIZE,
+                     "0x%016lx%016lx%016lx%016lx\n",
+                     ap_perms.aqm[0], ap_perms.aqm[1],
+                     ap_perms.aqm[2], ap_perms.aqm[3]);
+       mutex_unlock(&ap_perms_mutex);
+
+       return rc;
+}
+
+static ssize_t aqmask_store(struct bus_type *bus, const char *buf,
+                           size_t count)
+{
+       int rc;
+
+       rc = process_mask_arg(buf, ap_perms.aqm, AP_DOMAINS, &ap_perms_mutex);
+       if (rc)
+               return rc;
+
+       ap_bus_revise_bindings();
+
+       return count;
+}
+
+static BUS_ATTR_RW(aqmask);
 
 static struct bus_attribute *const ap_bus_attrs[] = {
        &bus_attr_ap_domain,
@@ -910,6 +1232,8 @@ static struct bus_attribute *const ap_bus_attrs[] = {
        &bus_attr_ap_interrupts,
        &bus_attr_poll_timeout,
        &bus_attr_ap_max_domain_id,
+       &bus_attr_apmask,
+       &bus_attr_aqmask,
        NULL,
 };
 
@@ -938,7 +1262,8 @@ static int ap_select_domain(void)
        best_domain = -1;
        max_count = 0;
        for (i = 0; i < AP_DOMAINS; i++) {
-               if (!ap_test_config_domain(i))
+               if (!ap_test_config_domain(i) ||
+                   !test_bit_inv(i, ap_perms.aqm))
                        continue;
                count = 0;
                for (j = 0; j < AP_DEVICES; j++) {
@@ -956,7 +1281,7 @@ static int ap_select_domain(void)
                        best_domain = i;
                }
        }
-       if (best_domain >= 0){
+       if (best_domain >= 0) {
                ap_domain_index = best_domain;
                AP_DBF(DBF_DEBUG, "new ap_domain_index=%d\n", ap_domain_index);
                spin_unlock_bh(&ap_domain_lock);
@@ -1038,7 +1363,7 @@ static void ap_scan_bus(struct work_struct *unused)
        unsigned int func = 0;
        int rc, id, dom, borked, domains, defdomdevs = 0;
 
-       AP_DBF(DBF_DEBUG, "ap_scan_bus running\n");
+       AP_DBF(DBF_DEBUG, "%s running\n", __func__);
 
        ap_query_configuration(ap_configuration);
        if (ap_select_domain() != 0)
@@ -1163,7 +1488,8 @@ static void ap_scan_bus(struct work_struct *unused)
        } /* end device loop */
 
        if (defdomdevs < 1)
-               AP_DBF(DBF_INFO, "no queue device with default domain %d available\n",
+               AP_DBF(DBF_INFO,
+                      "no queue device with default domain %d available\n",
                       ap_domain_index);
 
 out:
@@ -1187,6 +1513,27 @@ static int __init ap_debug_init(void)
        return 0;
 }
 
+static void __init ap_perms_init(void)
+{
+       /* all resources useable if no kernel parameter string given */
+       memset(&ap_perms.apm, 0xFF, sizeof(ap_perms.apm));
+       memset(&ap_perms.aqm, 0xFF, sizeof(ap_perms.aqm));
+
+       /* apm kernel parameter string */
+       if (apm_str) {
+               memset(&ap_perms.apm, 0, sizeof(ap_perms.apm));
+               process_mask_arg(apm_str, ap_perms.apm, AP_DEVICES,
+                                &ap_perms_mutex);
+       }
+
+       /* aqm kernel parameter string */
+       if (aqm_str) {
+               memset(&ap_perms.aqm, 0, sizeof(ap_perms.aqm));
+               process_mask_arg(aqm_str, ap_perms.aqm, AP_DOMAINS,
+                                &ap_perms_mutex);
+       }
+}
+
 /**
  * ap_module_init(): The module initialization code.
  *
@@ -1201,11 +1548,14 @@ static int __init ap_module_init(void)
        if (rc)
                return rc;
 
-       if (ap_instructions_available() != 0) {
+       if (!ap_instructions_available()) {
                pr_warn("The hardware system does not support AP instructions\n");
                return -ENODEV;
        }
 
+       /* set up the AP permissions (ap and aq masks) */
+       ap_perms_init();
+
        /* Get AP configuration data if available */
        ap_init_configuration();
 
@@ -1214,7 +1564,9 @@ static int __init ap_module_init(void)
                        ap_max_domain_id ? ap_max_domain_id : AP_DOMAINS - 1;
        else
                max_domain_id = 15;
-       if (ap_domain_index < -1 || ap_domain_index > max_domain_id) {
+       if (ap_domain_index < -1 || ap_domain_index > max_domain_id ||
+           (ap_domain_index >= 0 &&
+            !test_bit_inv(ap_domain_index, ap_perms.aqm))) {
                pr_warn("%d is not a valid cryptographic domain\n",
                        ap_domain_index);
                ap_domain_index = -1;
index 9365419..5246cd8 100644 (file)
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0+
+/* SPDX-License-Identifier: GPL-2.0+ */
 /*
  * Copyright IBM Corp. 2006, 2012
  * Author(s): Cornelia Huck <cornelia.huck@de.ibm.com>
@@ -117,9 +117,18 @@ enum ap_wait {
 struct ap_device;
 struct ap_message;
 
+/*
+ * The ap driver struct includes a flags field which holds some info for
+ * the ap bus about the driver. Currently only one flag is supported and
+ * used: The DEFAULT flag marks an ap driver as a default driver which is
+ * used together with the apmask and aqmask whitelisting of the ap bus.
+ */
+#define AP_DRIVER_FLAG_DEFAULT 0x0001
+
 struct ap_driver {
        struct device_driver driver;
        struct ap_device_id *ids;
+       unsigned int flags;
 
        int (*probe)(struct ap_device *);
        void (*remove)(struct ap_device *);
@@ -167,7 +176,7 @@ struct ap_queue {
        int pendingq_count;             /* # requests on pendingq list. */
        int requestq_count;             /* # requests on requestq list. */
        int total_request_count;        /* # requests ever for this AP device.*/
-       int request_timeout;            /* Request timout in jiffies. */
+       int request_timeout;            /* Request timeout in jiffies. */
        struct timer_list timeout;      /* Timer for request timeouts. */
        struct list_head pendingq;      /* List of message sent to AP queue. */
        struct list_head requestq;      /* List of message yet to be sent. */
@@ -248,4 +257,27 @@ void ap_queue_resume(struct ap_device *ap_dev);
 struct ap_card *ap_card_create(int id, int queue_depth, int raw_device_type,
                               int comp_device_type, unsigned int functions);
 
+/*
+ * check APQN for owned/reserved by ap bus and default driver(s).
+ * Checks if this APQN is or will be in use by the ap bus
+ * and the default set of drivers.
+ * If yes, returns 1, if not returns 0. On error a negative
+ * errno value is returned.
+ */
+int ap_owned_by_def_drv(int card, int queue);
+
+/*
+ * check 'matrix' of APQNs for owned/reserved by ap bus and
+ * default driver(s).
+ * Checks if there is at least one APQN in the given 'matrix'
+ * marked as owned/reserved by the ap bus and default driver(s).
+ * If such an APQN is found the return value is 1, otherwise
+ * 0 is returned. On error a negative errno value is returned.
+ * The parameter apm is a bitmask which should be declared
+ * as DECLARE_BITMAP(apm, AP_DEVICES), the aqm parameter is
+ * similar, should be declared as DECLARE_BITMAP(aqm, AP_DOMAINS).
+ */
+int ap_apqn_in_matrix_owned_by_def_drv(unsigned long *apm,
+                                      unsigned long *aqm);
+
 #endif /* _AP_BUS_H_ */
index c13e432..63b4cc6 100644 (file)
 /*
  * AP card related attributes.
  */
-static ssize_t ap_hwtype_show(struct device *dev,
-                             struct device_attribute *attr, char *buf)
+static ssize_t hwtype_show(struct device *dev,
+                          struct device_attribute *attr, char *buf)
 {
        struct ap_card *ac = to_ap_card(dev);
 
        return snprintf(buf, PAGE_SIZE, "%d\n", ac->ap_dev.device_type);
 }
 
-static DEVICE_ATTR(hwtype, 0444, ap_hwtype_show, NULL);
+static DEVICE_ATTR_RO(hwtype);
 
-static ssize_t ap_raw_hwtype_show(struct device *dev,
-                                 struct device_attribute *attr, char *buf)
+static ssize_t raw_hwtype_show(struct device *dev,
+                              struct device_attribute *attr, char *buf)
 {
        struct ap_card *ac = to_ap_card(dev);
 
        return snprintf(buf, PAGE_SIZE, "%d\n", ac->raw_hwtype);
 }
 
-static DEVICE_ATTR(raw_hwtype, 0444, ap_raw_hwtype_show, NULL);
+static DEVICE_ATTR_RO(raw_hwtype);
 
-static ssize_t ap_depth_show(struct device *dev, struct device_attribute *attr,
-                            char *buf)
+static ssize_t depth_show(struct device *dev, struct device_attribute *attr,
+                         char *buf)
 {
        struct ap_card *ac = to_ap_card(dev);
 
        return snprintf(buf, PAGE_SIZE, "%d\n", ac->queue_depth);
 }
 
-static DEVICE_ATTR(depth, 0444, ap_depth_show, NULL);
+static DEVICE_ATTR_RO(depth);
 
 static ssize_t ap_functions_show(struct device *dev,
                                 struct device_attribute *attr, char *buf)
@@ -58,9 +58,9 @@ static ssize_t ap_functions_show(struct device *dev,
 
 static DEVICE_ATTR_RO(ap_functions);
 
-static ssize_t ap_req_count_show(struct device *dev,
-                                struct device_attribute *attr,
-                                char *buf)
+static ssize_t request_count_show(struct device *dev,
+                                 struct device_attribute *attr,
+                                 char *buf)
 {
        struct ap_card *ac = to_ap_card(dev);
        unsigned int req_cnt;
@@ -72,9 +72,9 @@ static ssize_t ap_req_count_show(struct device *dev,
        return snprintf(buf, PAGE_SIZE, "%d\n", req_cnt);
 }
 
-static ssize_t ap_req_count_store(struct device *dev,
-                                 struct device_attribute *attr,
-                                 const char *buf, size_t count)
+static ssize_t request_count_store(struct device *dev,
+                                  struct device_attribute *attr,
+                                  const char *buf, size_t count)
 {
        struct ap_card *ac = to_ap_card(dev);
        struct ap_queue *aq;
@@ -88,10 +88,10 @@ static ssize_t ap_req_count_store(struct device *dev,
        return count;
 }
 
-static DEVICE_ATTR(request_count, 0644, ap_req_count_show, ap_req_count_store);
+static DEVICE_ATTR_RW(request_count);
 
-static ssize_t ap_requestq_count_show(struct device *dev,
-                                     struct device_attribute *attr, char *buf)
+static ssize_t requestq_count_show(struct device *dev,
+                                  struct device_attribute *attr, char *buf)
 {
        struct ap_card *ac = to_ap_card(dev);
        struct ap_queue *aq;
@@ -105,10 +105,10 @@ static ssize_t ap_requestq_count_show(struct device *dev,
        return snprintf(buf, PAGE_SIZE, "%d\n", reqq_cnt);
 }
 
-static DEVICE_ATTR(requestq_count, 0444, ap_requestq_count_show, NULL);
+static DEVICE_ATTR_RO(requestq_count);
 
-static ssize_t ap_pendingq_count_show(struct device *dev,
-                                     struct device_attribute *attr, char *buf)
+static ssize_t pendingq_count_show(struct device *dev,
+                                  struct device_attribute *attr, char *buf)
 {
        struct ap_card *ac = to_ap_card(dev);
        struct ap_queue *aq;
@@ -122,15 +122,15 @@ static ssize_t ap_pendingq_count_show(struct device *dev,
        return snprintf(buf, PAGE_SIZE, "%d\n", penq_cnt);
 }
 
-static DEVICE_ATTR(pendingq_count, 0444, ap_pendingq_count_show, NULL);
+static DEVICE_ATTR_RO(pendingq_count);
 
-static ssize_t ap_modalias_show(struct device *dev,
-                               struct device_attribute *attr, char *buf)
+static ssize_t modalias_show(struct device *dev,
+                            struct device_attribute *attr, char *buf)
 {
        return sprintf(buf, "ap:t%02X\n", to_ap_dev(dev)->device_type);
 }
 
-static DEVICE_ATTR(modalias, 0444, ap_modalias_show, NULL);
+static DEVICE_ATTR_RO(modalias);
 
 static struct attribute *ap_card_dev_attrs[] = {
        &dev_attr_hwtype.attr,
index e365171..66f7334 100644 (file)
@@ -462,9 +462,9 @@ EXPORT_SYMBOL(ap_queue_resume);
 /*
  * AP queue related attributes.
  */
-static ssize_t ap_req_count_show(struct device *dev,
-                                struct device_attribute *attr,
-                                char *buf)
+static ssize_t request_count_show(struct device *dev,
+                                 struct device_attribute *attr,
+                                 char *buf)
 {
        struct ap_queue *aq = to_ap_queue(dev);
        unsigned int req_cnt;
@@ -475,9 +475,9 @@ static ssize_t ap_req_count_show(struct device *dev,
        return snprintf(buf, PAGE_SIZE, "%d\n", req_cnt);
 }
 
-static ssize_t ap_req_count_store(struct device *dev,
-                                 struct device_attribute *attr,
-                                 const char *buf, size_t count)
+static ssize_t request_count_store(struct device *dev,
+                                  struct device_attribute *attr,
+                                  const char *buf, size_t count)
 {
        struct ap_queue *aq = to_ap_queue(dev);
 
@@ -488,10 +488,10 @@ static ssize_t ap_req_count_store(struct device *dev,
        return count;
 }
 
-static DEVICE_ATTR(request_count, 0644, ap_req_count_show, ap_req_count_store);
+static DEVICE_ATTR_RW(request_count);
 
-static ssize_t ap_requestq_count_show(struct device *dev,
-                                     struct device_attribute *attr, char *buf)
+static ssize_t requestq_count_show(struct device *dev,
+                                  struct device_attribute *attr, char *buf)
 {
        struct ap_queue *aq = to_ap_queue(dev);
        unsigned int reqq_cnt = 0;
@@ -502,10 +502,10 @@ static ssize_t ap_requestq_count_show(struct device *dev,
        return snprintf(buf, PAGE_SIZE, "%d\n", reqq_cnt);
 }
 
-static DEVICE_ATTR(requestq_count, 0444, ap_requestq_count_show, NULL);
+static DEVICE_ATTR_RO(requestq_count);
 
-static ssize_t ap_pendingq_count_show(struct device *dev,
-                                     struct device_attribute *attr, char *buf)
+static ssize_t pendingq_count_show(struct device *dev,
+                                  struct device_attribute *attr, char *buf)
 {
        struct ap_queue *aq = to_ap_queue(dev);
        unsigned int penq_cnt = 0;
@@ -516,10 +516,10 @@ static ssize_t ap_pendingq_count_show(struct device *dev,
        return snprintf(buf, PAGE_SIZE, "%d\n", penq_cnt);
 }
 
-static DEVICE_ATTR(pendingq_count, 0444, ap_pendingq_count_show, NULL);
+static DEVICE_ATTR_RO(pendingq_count);
 
-static ssize_t ap_reset_show(struct device *dev,
-                                     struct device_attribute *attr, char *buf)
+static ssize_t reset_show(struct device *dev,
+                         struct device_attribute *attr, char *buf)
 {
        struct ap_queue *aq = to_ap_queue(dev);
        int rc = 0;
@@ -541,10 +541,10 @@ static ssize_t ap_reset_show(struct device *dev,
        return rc;
 }
 
-static DEVICE_ATTR(reset, 0444, ap_reset_show, NULL);
+static DEVICE_ATTR_RO(reset);
 
-static ssize_t ap_interrupt_show(struct device *dev,
-                                struct device_attribute *attr, char *buf)
+static ssize_t interrupt_show(struct device *dev,
+                             struct device_attribute *attr, char *buf)
 {
        struct ap_queue *aq = to_ap_queue(dev);
        int rc = 0;
@@ -560,7 +560,7 @@ static ssize_t ap_interrupt_show(struct device *dev,
        return rc;
 }
 
-static DEVICE_ATTR(interrupt, 0444, ap_interrupt_show, NULL);
+static DEVICE_ATTR_RO(interrupt);
 
 static struct attribute *ap_queue_dev_attrs[] = {
        &dev_attr_request_count.attr,
index e663432..1b4001e 100644 (file)
@@ -82,20 +82,20 @@ static int check_secaeskeytoken(const u8 *token, int keybitsize)
 
        if (t->type != 0x01) {
                DEBUG_ERR(
-                       "check_secaeskeytoken secure token check failed, type mismatch 0x%02x != 0x01\n",
-                       (int) t->type);
+                       "%s secure token check failed, type mismatch 0x%02x != 0x01\n",
+                       __func__, (int) t->type);
                return -EINVAL;
        }
        if (t->version != 0x04) {
                DEBUG_ERR(
-                       "check_secaeskeytoken secure token check failed, version mismatch 0x%02x != 0x04\n",
-                       (int) t->version);
+                       "%s secure token check failed, version mismatch 0x%02x != 0x04\n",
+                       __func__, (int) t->version);
                return -EINVAL;
        }
        if (keybitsize > 0 && t->bitsize != keybitsize) {
                DEBUG_ERR(
-                       "check_secaeskeytoken secure token check failed, bitsize mismatch %d != %d\n",
-                       (int) t->bitsize, keybitsize);
+                       "%s secure token check failed, bitsize mismatch %d != %d\n",
+                       __func__, (int) t->bitsize, keybitsize);
                return -EINVAL;
        }
 
@@ -270,8 +270,8 @@ int pkey_genseckey(u16 cardnr, u16 domain,
                break;
        default:
                DEBUG_ERR(
-                       "pkey_genseckey unknown/unsupported keytype %d\n",
-                       keytype);
+                       "%s unknown/unsupported keytype %d\n",
+                       __func__, keytype);
                rc = -EINVAL;
                goto out;
        }
@@ -290,15 +290,16 @@ int pkey_genseckey(u16 cardnr, u16 domain,
        rc = _zcrypt_send_cprb(&xcrb);
        if (rc) {
                DEBUG_ERR(
-                       "pkey_genseckey zcrypt_send_cprb (cardnr=%d domain=%d) failed with errno %d\n",
-                       (int) cardnr, (int) domain, rc);
+                       "%s zcrypt_send_cprb (cardnr=%d domain=%d) failed with errno %d\n",
+                       __func__, (int) cardnr, (int) domain, rc);
                goto out;
        }
 
        /* check response returncode and reasoncode */
        if (prepcblk->ccp_rtcode != 0) {
                DEBUG_ERR(
-                       "pkey_genseckey secure key generate failure, card response %d/%d\n",
+                       "%s secure key generate failure, card response %d/%d\n",
+                       __func__,
                        (int) prepcblk->ccp_rtcode,
                        (int) prepcblk->ccp_rscode);
                rc = -EIO;
@@ -315,8 +316,8 @@ int pkey_genseckey(u16 cardnr, u16 domain,
                - sizeof(prepparm->lv3.keyblock.tokattr);
        if (seckeysize != SECKEYBLOBSIZE) {
                DEBUG_ERR(
-                       "pkey_genseckey secure token size mismatch %d != %d bytes\n",
-                       seckeysize, SECKEYBLOBSIZE);
+                       "%s secure token size mismatch %d != %d bytes\n",
+                       __func__, seckeysize, SECKEYBLOBSIZE);
                rc = -EIO;
                goto out;
        }
@@ -407,8 +408,8 @@ int pkey_clr2seckey(u16 cardnr, u16 domain, u32 keytype,
                break;
        default:
                DEBUG_ERR(
-                       "pkey_clr2seckey unknown/unsupported keytype %d\n",
-                       keytype);
+                       "%s unknown/unsupported keytype %d\n",
+                       __func__, keytype);
                rc = -EINVAL;
                goto out;
        }
@@ -427,15 +428,16 @@ int pkey_clr2seckey(u16 cardnr, u16 domain, u32 keytype,
        rc = _zcrypt_send_cprb(&xcrb);
        if (rc) {
                DEBUG_ERR(
-                       "pkey_clr2seckey zcrypt_send_cprb (cardnr=%d domain=%d) failed with errno %d\n",
-                       (int) cardnr, (int) domain, rc);
+                       "%s zcrypt_send_cprb (cardnr=%d domain=%d) failed with errno %d\n",
+                       __func__, (int) cardnr, (int) domain, rc);
                goto out;
        }
 
        /* check response returncode and reasoncode */
        if (prepcblk->ccp_rtcode != 0) {
                DEBUG_ERR(
-                       "pkey_clr2seckey clear key import failure, card response %d/%d\n",
+                       "%s clear key import failure, card response %d/%d\n",
+                       __func__,
                        (int) prepcblk->ccp_rtcode,
                        (int) prepcblk->ccp_rscode);
                rc = -EIO;
@@ -452,8 +454,8 @@ int pkey_clr2seckey(u16 cardnr, u16 domain, u32 keytype,
                - sizeof(prepparm->lv3.keyblock.tokattr);
        if (seckeysize != SECKEYBLOBSIZE) {
                DEBUG_ERR(
-                       "pkey_clr2seckey secure token size mismatch %d != %d bytes\n",
-                       seckeysize, SECKEYBLOBSIZE);
+                       "%s secure token size mismatch %d != %d bytes\n",
+                       __func__, seckeysize, SECKEYBLOBSIZE);
                rc = -EIO;
                goto out;
        }
@@ -553,15 +555,16 @@ int pkey_sec2protkey(u16 cardnr, u16 domain,
        rc = _zcrypt_send_cprb(&xcrb);
        if (rc) {
                DEBUG_ERR(
-                       "pkey_sec2protkey zcrypt_send_cprb (cardnr=%d domain=%d) failed with errno %d\n",
-                       (int) cardnr, (int) domain, rc);
+                       "%s zcrypt_send_cprb (cardnr=%d domain=%d) failed with errno %d\n",
+                       __func__, (int) cardnr, (int) domain, rc);
                goto out;
        }
 
        /* check response returncode and reasoncode */
        if (prepcblk->ccp_rtcode != 0) {
                DEBUG_ERR(
-                       "pkey_sec2protkey unwrap secure key failure, card response %d/%d\n",
+                       "%s unwrap secure key failure, card response %d/%d\n",
+                       __func__,
                        (int) prepcblk->ccp_rtcode,
                        (int) prepcblk->ccp_rscode);
                rc = -EIO;
@@ -569,7 +572,8 @@ int pkey_sec2protkey(u16 cardnr, u16 domain,
        }
        if (prepcblk->ccp_rscode != 0) {
                DEBUG_WARN(
-                       "pkey_sec2protkey unwrap secure key warning, card response %d/%d\n",
+                       "%s unwrap secure key warning, card response %d/%d\n",
+                       __func__,
                        (int) prepcblk->ccp_rtcode,
                        (int) prepcblk->ccp_rscode);
        }
@@ -581,8 +585,8 @@ int pkey_sec2protkey(u16 cardnr, u16 domain,
        /* check the returned keyblock */
        if (prepparm->lv3.keyblock.version != 0x01) {
                DEBUG_ERR(
-                       "pkey_sec2protkey reply param keyblock version mismatch 0x%02x != 0x01\n",
-                       (int) prepparm->lv3.keyblock.version);
+                       "%s reply param keyblock version mismatch 0x%02x != 0x01\n",
+                       __func__, (int) prepparm->lv3.keyblock.version);
                rc = -EIO;
                goto out;
        }
@@ -599,8 +603,8 @@ int pkey_sec2protkey(u16 cardnr, u16 domain,
                protkey->type = PKEY_KEYTYPE_AES_256;
                break;
        default:
-               DEBUG_ERR("pkey_sec2protkey unknown/unsupported keytype %d\n",
-                         prepparm->lv3.keyblock.keylen);
+               DEBUG_ERR("%s unknown/unsupported keytype %d\n",
+                         __func__, prepparm->lv3.keyblock.keylen);
                rc = -EIO;
                goto out;
        }
@@ -638,8 +642,8 @@ int pkey_clr2protkey(u32 keytype,
                fc = CPACF_PCKMO_ENC_AES_256_KEY;
                break;
        default:
-               DEBUG_ERR("pkey_clr2protkey unknown/unsupported keytype %d\n",
-                         keytype);
+               DEBUG_ERR("%s unknown/unsupported keytype %d\n",
+                         __func__, keytype);
                return -EINVAL;
        }
 
@@ -713,15 +717,16 @@ static int query_crypto_facility(u16 cardnr, u16 domain,
        rc = _zcrypt_send_cprb(&xcrb);
        if (rc) {
                DEBUG_ERR(
-                       "query_crypto_facility zcrypt_send_cprb (cardnr=%d domain=%d) failed with errno %d\n",
-                       (int) cardnr, (int) domain, rc);
+                       "%s zcrypt_send_cprb (cardnr=%d domain=%d) failed with errno %d\n",
+                       __func__, (int) cardnr, (int) domain, rc);
                goto out;
        }
 
        /* check response returncode and reasoncode */
        if (prepcblk->ccp_rtcode != 0) {
                DEBUG_ERR(
-                       "query_crypto_facility unwrap secure key failure, card response %d/%d\n",
+                       "%s unwrap secure key failure, card response %d/%d\n",
+                       __func__,
                        (int) prepcblk->ccp_rtcode,
                        (int) prepcblk->ccp_rscode);
                rc = -EIO;
@@ -993,7 +998,7 @@ int pkey_skey2pkey(const struct pkey_seckey *seckey,
        }
 
        if (rc)
-               DEBUG_DBG("pkey_skey2pkey failed rc=%d\n", rc);
+               DEBUG_DBG("%s failed rc=%d\n", __func__, rc);
 
        return rc;
 }
@@ -1030,7 +1035,7 @@ int pkey_verifykey(const struct pkey_seckey *seckey,
        if (rc)
                goto out;
        if (t->mkvp == mkvp[1]) {
-               DEBUG_DBG("pkey_verifykey secure key has old mkvp\n");
+               DEBUG_DBG("%s secure key has old mkvp\n", __func__);
                if (pattributes)
                        *pattributes |= PKEY_VERIFY_ATTR_OLD_MKVP;
        }
@@ -1041,7 +1046,7 @@ int pkey_verifykey(const struct pkey_seckey *seckey,
                *pdomain = domain;
 
 out:
-       DEBUG_DBG("pkey_verifykey rc=%d\n", rc);
+       DEBUG_DBG("%s rc=%d\n", __func__, rc);
        return rc;
 }
 EXPORT_SYMBOL(pkey_verifykey);
@@ -1064,7 +1069,7 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd,
                        return -EFAULT;
                rc = pkey_genseckey(kgs.cardnr, kgs.domain,
                                    kgs.keytype, &kgs.seckey);
-               DEBUG_DBG("pkey_ioctl pkey_genseckey()=%d\n", rc);
+               DEBUG_DBG("%s pkey_genseckey()=%d\n", __func__, rc);
                if (rc)
                        break;
                if (copy_to_user(ugs, &kgs, sizeof(kgs)))
@@ -1079,7 +1084,7 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd,
                        return -EFAULT;
                rc = pkey_clr2seckey(kcs.cardnr, kcs.domain, kcs.keytype,
                                     &kcs.clrkey, &kcs.seckey);
-               DEBUG_DBG("pkey_ioctl pkey_clr2seckey()=%d\n", rc);
+               DEBUG_DBG("%s pkey_clr2seckey()=%d\n", __func__, rc);
                if (rc)
                        break;
                if (copy_to_user(ucs, &kcs, sizeof(kcs)))
@@ -1095,7 +1100,7 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd,
                        return -EFAULT;
                rc = pkey_sec2protkey(ksp.cardnr, ksp.domain,
                                      &ksp.seckey, &ksp.protkey);
-               DEBUG_DBG("pkey_ioctl pkey_sec2protkey()=%d\n", rc);
+               DEBUG_DBG("%s pkey_sec2protkey()=%d\n", __func__, rc);
                if (rc)
                        break;
                if (copy_to_user(usp, &ksp, sizeof(ksp)))
@@ -1110,7 +1115,7 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd,
                        return -EFAULT;
                rc = pkey_clr2protkey(kcp.keytype,
                                      &kcp.clrkey, &kcp.protkey);
-               DEBUG_DBG("pkey_ioctl pkey_clr2protkey()=%d\n", rc);
+               DEBUG_DBG("%s pkey_clr2protkey()=%d\n", __func__, rc);
                if (rc)
                        break;
                if (copy_to_user(ucp, &kcp, sizeof(kcp)))
@@ -1126,7 +1131,7 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd,
                        return -EFAULT;
                rc = pkey_findcard(&kfc.seckey,
                                   &kfc.cardnr, &kfc.domain, 1);
-               DEBUG_DBG("pkey_ioctl pkey_findcard()=%d\n", rc);
+               DEBUG_DBG("%s pkey_findcard()=%d\n", __func__, rc);
                if (rc)
                        break;
                if (copy_to_user(ufc, &kfc, sizeof(kfc)))
@@ -1140,7 +1145,7 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd,
                if (copy_from_user(&ksp, usp, sizeof(ksp)))
                        return -EFAULT;
                rc = pkey_skey2pkey(&ksp.seckey, &ksp.protkey);
-               DEBUG_DBG("pkey_ioctl pkey_skey2pkey()=%d\n", rc);
+               DEBUG_DBG("%s pkey_skey2pkey()=%d\n", __func__, rc);
                if (rc)
                        break;
                if (copy_to_user(usp, &ksp, sizeof(ksp)))
@@ -1155,7 +1160,7 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd,
                        return -EFAULT;
                rc = pkey_verifykey(&kvk.seckey, &kvk.cardnr, &kvk.domain,
                                    &kvk.keysize, &kvk.attributes);
-               DEBUG_DBG("pkey_ioctl pkey_verifykey()=%d\n", rc);
+               DEBUG_DBG("%s pkey_verifykey()=%d\n", __func__, rc);
                if (rc)
                        break;
                if (copy_to_user(uvk, &kvk, sizeof(kvk)))
index febcdb5..e685412 100644 (file)
@@ -50,7 +50,7 @@ EXPORT_TRACEPOINT_SYMBOL(s390_zcrypt_req);
 EXPORT_TRACEPOINT_SYMBOL(s390_zcrypt_rep);
 
 static int zcrypt_hwrng_seed = 1;
-module_param_named(hwrng_seed, zcrypt_hwrng_seed, int, S_IRUSR|S_IRGRP);
+module_param_named(hwrng_seed, zcrypt_hwrng_seed, int, 0440);
 MODULE_PARM_DESC(hwrng_seed, "Turn on/off hwrng auto seed, default is 1 (on).");
 
 DEFINE_SPINLOCK(zcrypt_list_lock);
@@ -182,7 +182,8 @@ static inline void zcrypt_drop_queue(struct zcrypt_card *zc,
 
 static inline bool zcrypt_card_compare(struct zcrypt_card *zc,
                                       struct zcrypt_card *pref_zc,
-                                      unsigned weight, unsigned pref_weight)
+                                      unsigned int weight,
+                                      unsigned int pref_weight)
 {
        if (!pref_zc)
                return false;
@@ -196,7 +197,8 @@ static inline bool zcrypt_card_compare(struct zcrypt_card *zc,
 
 static inline bool zcrypt_queue_compare(struct zcrypt_queue *zq,
                                        struct zcrypt_queue *pref_zq,
-                                       unsigned weight, unsigned pref_weight)
+                                       unsigned int weight,
+                                       unsigned int pref_weight)
 {
        if (!pref_zq)
                return false;
@@ -792,6 +794,7 @@ static long zcrypt_unlocked_ioctl(struct file *filp, unsigned int cmd,
        case ICARSAMODEXPO: {
                struct ica_rsa_modexpo __user *umex = (void __user *) arg;
                struct ica_rsa_modexpo mex;
+
                if (copy_from_user(&mex, umex, sizeof(mex)))
                        return -EFAULT;
                do {
@@ -811,6 +814,7 @@ static long zcrypt_unlocked_ioctl(struct file *filp, unsigned int cmd,
        case ICARSACRT: {
                struct ica_rsa_modexpo_crt __user *ucrt = (void __user *) arg;
                struct ica_rsa_modexpo_crt crt;
+
                if (copy_from_user(&crt, ucrt, sizeof(crt)))
                        return -EFAULT;
                do {
@@ -830,6 +834,7 @@ static long zcrypt_unlocked_ioctl(struct file *filp, unsigned int cmd,
        case ZSECSENDCPRB: {
                struct ica_xcRB __user *uxcRB = (void __user *) arg;
                struct ica_xcRB xcRB;
+
                if (copy_from_user(&xcRB, uxcRB, sizeof(xcRB)))
                        return -EFAULT;
                do {
@@ -849,6 +854,7 @@ static long zcrypt_unlocked_ioctl(struct file *filp, unsigned int cmd,
        case ZSENDEP11CPRB: {
                struct ep11_urb __user *uxcrb = (void __user *)arg;
                struct ep11_urb xcrb;
+
                if (copy_from_user(&xcrb, uxcrb, sizeof(xcrb)))
                        return -EFAULT;
                do {
@@ -1037,7 +1043,7 @@ static long trans_modexpo_crt32(struct file *filp, unsigned int cmd,
                return -EFAULT;
        crt64.inputdata = compat_ptr(crt32.inputdata);
        crt64.inputdatalength = crt32.inputdatalength;
-       crt64.outputdata compat_ptr(crt32.outputdata);
+       crt64.outputdata = compat_ptr(crt32.outputdata);
        crt64.outputdatalength = crt32.outputdatalength;
        crt64.bp_key = compat_ptr(crt32.bp_key);
        crt64.bq_key = compat_ptr(crt32.bq_key);
@@ -1063,20 +1069,20 @@ struct compat_ica_xcRB {
        unsigned int    user_defined;
        unsigned short  request_ID;
        unsigned int    request_control_blk_length;
-       unsigned char   padding1[16 - sizeof (compat_uptr_t)];
+       unsigned char   padding1[16 - sizeof(compat_uptr_t)];
        compat_uptr_t   request_control_blk_addr;
        unsigned int    request_data_length;
-       char            padding2[16 - sizeof (compat_uptr_t)];
+       char            padding2[16 - sizeof(compat_uptr_t)];
        compat_uptr_t   request_data_address;
        unsigned int    reply_control_blk_length;
-       char            padding3[16 - sizeof (compat_uptr_t)];
+       char            padding3[16 - sizeof(compat_uptr_t)];
        compat_uptr_t   reply_control_blk_addr;
        unsigned int    reply_data_length;
-       char            padding4[16 - sizeof (compat_uptr_t)];
+       char            padding4[16 - sizeof(compat_uptr_t)];
        compat_uptr_t   reply_data_addr;
        unsigned short  priority_window;
        unsigned int    status;
-} __attribute__((packed));
+} __packed;
 
 static long trans_xcRB32(struct file *filp, unsigned int cmd,
                         unsigned long arg)
@@ -1120,7 +1126,7 @@ static long trans_xcRB32(struct file *filp, unsigned int cmd,
        xcRB32.reply_data_length = xcRB64.reply_data_length;
        xcRB32.status = xcRB64.status;
        if (copy_to_user(uxcRB32, &xcRB32, sizeof(xcRB32)))
-                       return -EFAULT;
+               return -EFAULT;
        return rc;
 }
 
@@ -1182,10 +1188,10 @@ static int zcrypt_rng_data_read(struct hwrng *rng, u32 *data)
                        rc = zcrypt_rng((char *) zcrypt_rng_buffer);
                if (rc < 0)
                        return -EIO;
-               zcrypt_rng_buffer_index = rc / sizeof *data;
+               zcrypt_rng_buffer_index = rc / sizeof(*data);
        }
        *data = zcrypt_rng_buffer[--zcrypt_rng_buffer_index];
-       return sizeof *data;
+       return sizeof(*data);
 }
 
 static struct hwrng zcrypt_rng_dev = {
index f149a8f..a848625 100644 (file)
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0+
+/* SPDX-License-Identifier: GPL-2.0+ */
 /*
  *  zcrypt 2.1.0
  *
index da2c8df..40cd4c1 100644 (file)
  * Device attributes common for all crypto card devices.
  */
 
-static ssize_t zcrypt_card_type_show(struct device *dev,
-                                    struct device_attribute *attr, char *buf)
+static ssize_t type_show(struct device *dev,
+                        struct device_attribute *attr, char *buf)
 {
        struct zcrypt_card *zc = to_ap_card(dev)->private;
 
        return snprintf(buf, PAGE_SIZE, "%s\n", zc->type_string);
 }
 
-static DEVICE_ATTR(type, 0444, zcrypt_card_type_show, NULL);
+static DEVICE_ATTR_RO(type);
 
-static ssize_t zcrypt_card_online_show(struct device *dev,
-                                      struct device_attribute *attr,
-                                      char *buf)
+static ssize_t online_show(struct device *dev,
+                          struct device_attribute *attr,
+                          char *buf)
 {
        struct zcrypt_card *zc = to_ap_card(dev)->private;
 
        return snprintf(buf, PAGE_SIZE, "%d\n", zc->online);
 }
 
-static ssize_t zcrypt_card_online_store(struct device *dev,
-                                       struct device_attribute *attr,
-                                       const char *buf, size_t count)
+static ssize_t online_store(struct device *dev,
+                           struct device_attribute *attr,
+                           const char *buf, size_t count)
 {
        struct zcrypt_card *zc = to_ap_card(dev)->private;
        struct zcrypt_queue *zq;
@@ -80,19 +80,18 @@ static ssize_t zcrypt_card_online_store(struct device *dev,
        return count;
 }
 
-static DEVICE_ATTR(online, 0644, zcrypt_card_online_show,
-                  zcrypt_card_online_store);
+static DEVICE_ATTR_RW(online);
 
-static ssize_t zcrypt_card_load_show(struct device *dev,
-                                    struct device_attribute *attr,
-                                    char *buf)
+static ssize_t load_show(struct device *dev,
+                        struct device_attribute *attr,
+                        char *buf)
 {
        struct zcrypt_card *zc = to_ap_card(dev)->private;
 
        return snprintf(buf, PAGE_SIZE, "%d\n", atomic_read(&zc->load));
 }
 
-static DEVICE_ATTR(load, 0444, zcrypt_card_load_show, NULL);
+static DEVICE_ATTR_RO(load);
 
 static struct attribute *zcrypt_card_attrs[] = {
        &dev_attr_type.attr,
index 1752622..e5b5c02 100644 (file)
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0+
+/* SPDX-License-Identifier: GPL-2.0+ */
 /*
  *  zcrypt 2.1.0
  *
@@ -31,7 +31,7 @@ struct cca_token_hdr {
        unsigned char  version;
        unsigned short token_length;
        unsigned char  reserved[4];
-} __attribute__((packed));
+} __packed;
 
 #define CCA_TKN_HDR_ID_EXT 0x1E
 
@@ -51,7 +51,7 @@ struct cca_public_sec {
        unsigned short exponent_len;
        unsigned short modulus_bit_len;
        unsigned short modulus_byte_len;    /* In a private key, this is 0 */
-} __attribute__((packed));
+} __packed;
 
 /**
  * mapping for the cca private CRT key 'token'
@@ -85,7 +85,7 @@ struct cca_pvt_ext_CRT_sec {
        unsigned short pad_len;
        unsigned char  reserved4[52];
        unsigned char  confounder[8];
-} __attribute__((packed));
+} __packed;
 
 #define CCA_PVT_EXT_CRT_SEC_ID_PVT 0x08
 #define CCA_PVT_EXT_CRT_SEC_FMT_CL 0x40
@@ -114,7 +114,7 @@ static inline int zcrypt_type6_mex_key_en(struct ica_rsa_modexpo *mex, void *p)
                struct cca_token_hdr pubHdr;
                struct cca_public_sec pubSec;
                char exponent[0];
-       } __attribute__((packed)) *key = p;
+       } __packed *key = p;
        unsigned char *temp;
        int i;
 
@@ -183,7 +183,7 @@ static inline int zcrypt_type6_crt_key(struct ica_rsa_modexpo_crt *crt, void *p)
                struct cca_token_hdr token;
                struct cca_pvt_ext_CRT_sec pvt;
                char key_parts[0];
-       } __attribute__((packed)) *key = p;
+       } __packed *key = p;
        struct cca_public_sec *pub;
        int short_len, long_len, pad_len, key_len, size;
 
index e701194..f4ae5fa 100644 (file)
@@ -145,6 +145,7 @@ static struct ap_driver zcrypt_cex2a_card_driver = {
        .probe = zcrypt_cex2a_card_probe,
        .remove = zcrypt_cex2a_card_remove,
        .ids = zcrypt_cex2a_card_ids,
+       .flags = AP_DRIVER_FLAG_DEFAULT,
 };
 
 /**
@@ -208,6 +209,7 @@ static struct ap_driver zcrypt_cex2a_queue_driver = {
        .suspend = ap_queue_suspend,
        .resume = ap_queue_resume,
        .ids = zcrypt_cex2a_queue_ids,
+       .flags = AP_DRIVER_FLAG_DEFAULT,
 };
 
 int __init zcrypt_cex2a_init(void)
index c3c1167..66d58bc 100644 (file)
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0+
+/* SPDX-License-Identifier: GPL-2.0+ */
 /*
  *  zcrypt 2.1.0
  *
@@ -30,7 +30,7 @@ struct type50_hdr {
        unsigned char   reserved2;
        unsigned char   ignored;
        unsigned short  reserved3;
-} __attribute__((packed));
+} __packed;
 
 #define TYPE50_TYPE_CODE       0x50
 
@@ -49,7 +49,7 @@ struct type50_meb1_msg {
        unsigned char   exponent[128];
        unsigned char   modulus[128];
        unsigned char   message[128];
-} __attribute__((packed));
+} __packed;
 
 /* Mod-Exp, with a large modulus */
 struct type50_meb2_msg {
@@ -59,7 +59,7 @@ struct type50_meb2_msg {
        unsigned char   exponent[256];
        unsigned char   modulus[256];
        unsigned char   message[256];
-} __attribute__((packed));
+} __packed;
 
 /* Mod-Exp, with a larger modulus */
 struct type50_meb3_msg {
@@ -69,7 +69,7 @@ struct type50_meb3_msg {
        unsigned char   exponent[512];
        unsigned char   modulus[512];
        unsigned char   message[512];
-} __attribute__((packed));
+} __packed;
 
 /* CRT, with a small modulus */
 struct type50_crb1_msg {
@@ -82,7 +82,7 @@ struct type50_crb1_msg {
        unsigned char   dq[64];
        unsigned char   u[64];
        unsigned char   message[128];
-} __attribute__((packed));
+} __packed;
 
 /* CRT, with a large modulus */
 struct type50_crb2_msg {
@@ -95,7 +95,7 @@ struct type50_crb2_msg {
        unsigned char   dq[128];
        unsigned char   u[128];
        unsigned char   message[256];
-} __attribute__((packed));
+} __packed;
 
 /* CRT, with a larger modulus */
 struct type50_crb3_msg {
@@ -108,7 +108,7 @@ struct type50_crb3_msg {
        unsigned char   dq[256];
        unsigned char   u[256];
        unsigned char   message[512];
-} __attribute__((packed));
+} __packed;
 
 /**
  * The type 80 response family is associated with a CEX2A card.
@@ -128,7 +128,7 @@ struct type80_hdr {
        unsigned char   code;           /* 0x00 */
        unsigned char   reserved2[3];
        unsigned char   reserved3[8];
-} __attribute__((packed));
+} __packed;
 
 int zcrypt_cex2a_init(void);
 void zcrypt_cex2a_exit(void);
index f305538..35d58db 100644 (file)
@@ -214,6 +214,7 @@ static struct ap_driver zcrypt_cex4_card_driver = {
        .probe = zcrypt_cex4_card_probe,
        .remove = zcrypt_cex4_card_remove,
        .ids = zcrypt_cex4_card_ids,
+       .flags = AP_DRIVER_FLAG_DEFAULT,
 };
 
 /**
@@ -283,6 +284,7 @@ static struct ap_driver zcrypt_cex4_queue_driver = {
        .suspend = ap_queue_suspend,
        .resume = ap_queue_resume,
        .ids = zcrypt_cex4_queue_ids,
+       .flags = AP_DRIVER_FLAG_DEFAULT,
 };
 
 int __init zcrypt_cex4_init(void)
index 01598d8..6f7ebc1 100644 (file)
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0+
+/* SPDX-License-Identifier: GPL-2.0+ */
 /*
  *  zcrypt 2.1.0
  *
index afe1b2b..f159662 100644 (file)
 #include "zcrypt_error.h"
 #include "zcrypt_msgtype50.h"
 
-#define CEX3A_MAX_MOD_SIZE     512     /* 4096 bits    */
+/* 4096 bits */
+#define CEX3A_MAX_MOD_SIZE 512
 
-#define CEX2A_MAX_RESPONSE_SIZE 0x110  /* max outputdatalength + type80_hdr */
+/* max outputdatalength + type80_hdr */
+#define CEX2A_MAX_RESPONSE_SIZE 0x110
 
-#define CEX3A_MAX_RESPONSE_SIZE        0x210   /* 512 bit modulus
-                                        * (max outputdatalength) +
-                                        * type80_hdr*/
+/* 512 bit modulus, (max outputdatalength) + type80_hdr */
+#define CEX3A_MAX_RESPONSE_SIZE 0x210
 
 MODULE_AUTHOR("IBM Corporation");
 MODULE_DESCRIPTION("Cryptographic Accelerator (message type 50), " \
@@ -209,6 +210,7 @@ static int ICAMEX_msg_to_type50MEX_msg(struct zcrypt_queue *zq,
 
        if (mod_len <= 128) {
                struct type50_meb1_msg *meb1 = ap_msg->message;
+
                memset(meb1, 0, sizeof(*meb1));
                ap_msg->length = sizeof(*meb1);
                meb1->header.msg_type_code = TYPE50_TYPE_CODE;
@@ -219,6 +221,7 @@ static int ICAMEX_msg_to_type50MEX_msg(struct zcrypt_queue *zq,
                inp = meb1->message + sizeof(meb1->message) - mod_len;
        } else if (mod_len <= 256) {
                struct type50_meb2_msg *meb2 = ap_msg->message;
+
                memset(meb2, 0, sizeof(*meb2));
                ap_msg->length = sizeof(*meb2);
                meb2->header.msg_type_code = TYPE50_TYPE_CODE;
@@ -229,6 +232,7 @@ static int ICAMEX_msg_to_type50MEX_msg(struct zcrypt_queue *zq,
                inp = meb2->message + sizeof(meb2->message) - mod_len;
        } else if (mod_len <= 512) {
                struct type50_meb3_msg *meb3 = ap_msg->message;
+
                memset(meb3, 0, sizeof(*meb3));
                ap_msg->length = sizeof(*meb3);
                meb3->header.msg_type_code = TYPE50_TYPE_CODE;
@@ -274,6 +278,7 @@ static int ICACRT_msg_to_type50CRT_msg(struct zcrypt_queue *zq,
         */
        if (mod_len <= 128) {           /* up to 1024 bit key size */
                struct type50_crb1_msg *crb1 = ap_msg->message;
+
                memset(crb1, 0, sizeof(*crb1));
                ap_msg->length = sizeof(*crb1);
                crb1->header.msg_type_code = TYPE50_TYPE_CODE;
@@ -287,6 +292,7 @@ static int ICACRT_msg_to_type50CRT_msg(struct zcrypt_queue *zq,
                inp = crb1->message + sizeof(crb1->message) - mod_len;
        } else if (mod_len <= 256) {    /* up to 2048 bit key size */
                struct type50_crb2_msg *crb2 = ap_msg->message;
+
                memset(crb2, 0, sizeof(*crb2));
                ap_msg->length = sizeof(*crb2);
                crb2->header.msg_type_code = TYPE50_TYPE_CODE;
@@ -301,6 +307,7 @@ static int ICACRT_msg_to_type50CRT_msg(struct zcrypt_queue *zq,
        } else if ((mod_len <= 512) &&  /* up to 4096 bit key size */
                   (zq->zcard->max_mod_size == CEX3A_MAX_MOD_SIZE)) {
                struct type50_crb3_msg *crb3 = ap_msg->message;
+
                memset(crb3, 0, sizeof(*crb3));
                ap_msg->length = sizeof(*crb3);
                crb3->header.msg_type_code = TYPE50_TYPE_CODE;
index 0a36545..8530f65 100644 (file)
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0+
+/* SPDX-License-Identifier: GPL-2.0+ */
 /*
  *  zcrypt 2.1.0
  *
 #define MSGTYPE50_NAME                 "zcrypt_msgtype50"
 #define MSGTYPE50_VARIANT_DEFAULT      0
 
-#define MSGTYPE50_CRB2_MAX_MSG_SIZE    0x390 /*sizeof(struct type50_crb2_msg)*/
-#define MSGTYPE50_CRB3_MAX_MSG_SIZE    0x710 /*sizeof(struct type50_crb3_msg)*/
+#define MSGTYPE50_CRB2_MAX_MSG_SIZE 0x390 /* sizeof(struct type50_crb2_msg) */
+#define MSGTYPE50_CRB3_MAX_MSG_SIZE 0x710 /* sizeof(struct type50_crb3_msg) */
 
-#define MSGTYPE_ADJUSTMENT             0x08  /*type04 extension (not needed in type50)*/
+#define MSGTYPE_ADJUSTMENT 0x08  /* type04 extension (not needed in type50) */
 
 unsigned int get_rsa_modex_fc(struct ica_rsa_modexpo *, int *);
 unsigned int get_rsa_crt_fc(struct ica_rsa_modexpo_crt *, int *);
index e70ae07..2101776 100644 (file)
@@ -421,8 +421,10 @@ static int XCRB_msg_to_type6CPRB_msgX(struct ap_message *ap_msg,
        if (ap_msg->length > MSGTYPE06_MAX_MSG_SIZE)
                return -EINVAL;
 
-       /* Overflow check
-          sum must be greater (or equal) than the largest operand */
+       /*
+        * Overflow check
+        * sum must be greater (or equal) than the largest operand
+        */
        req_sumlen = CEIL4(xcRB->request_control_blk_length) +
                        xcRB->request_data_length;
        if ((CEIL4(xcRB->request_control_blk_length) <=
@@ -442,8 +444,10 @@ static int XCRB_msg_to_type6CPRB_msgX(struct ap_message *ap_msg,
        if (replylen > MSGTYPE06_MAX_MSG_SIZE)
                return -EINVAL;
 
-       /* Overflow check
-          sum must be greater (or equal) than the largest operand */
+       /*
+        * Overflow check
+        * sum must be greater (or equal) than the largest operand
+        */
        resp_sumlen = CEIL4(xcRB->reply_control_blk_length) +
                        xcRB->reply_data_length;
        if ((CEIL4(xcRB->reply_control_blk_length) <= xcRB->reply_data_length) ?
@@ -454,7 +458,7 @@ static int XCRB_msg_to_type6CPRB_msgX(struct ap_message *ap_msg,
 
        /* prepare type6 header */
        msg->hdr = static_type6_hdrX;
-       memcpy(msg->hdr.agent_id , &(xcRB->agent_ID), sizeof(xcRB->agent_ID));
+       memcpy(msg->hdr.agent_id, &(xcRB->agent_ID), sizeof(xcRB->agent_ID));
        msg->hdr.ToCardLen1 = xcRB->request_control_blk_length;
        if (xcRB->request_data_length) {
                msg->hdr.offset2 = msg->hdr.offset1 + rcblen;
@@ -806,8 +810,10 @@ static int convert_response_ica(struct zcrypt_queue *zq,
                if (msg->cprbx.cprb_ver_id == 0x02)
                        return convert_type86_ica(zq, reply,
                                                  outputdata, outputdatalength);
-               /* Fall through, no break, incorrect cprb version is an unknown
-                * response */
+               /*
+                * Fall through, no break, incorrect cprb version is an unknown
+                * response
+                */
        default: /* Unknown response type, this should NEVER EVER happen */
                zq->online = 0;
                pr_err("Cryptographic device %02x.%04x failed and was set offline\n",
@@ -840,8 +846,10 @@ static int convert_response_xcrb(struct zcrypt_queue *zq,
                }
                if (msg->cprbx.cprb_ver_id == 0x02)
                        return convert_type86_xcrb(zq, reply, xcRB);
-               /* Fall through, no break, incorrect cprb version is an unknown
-                * response */
+               /*
+                * Fall through, no break, incorrect cprb version is an unknown
+                * response
+                */
        default: /* Unknown response type, this should NEVER EVER happen */
                xcRB->status = 0x0008044DL; /* HDD_InvalidParm */
                zq->online = 0;
@@ -901,8 +909,10 @@ static int convert_response_rng(struct zcrypt_queue *zq,
                        return -EINVAL;
                if (msg->cprbx.cprb_ver_id == 0x02)
                        return convert_type86_rng(zq, reply, data);
-               /* Fall through, no break, incorrect cprb version is an unknown
-                * response */
+               /*
+                * Fall through, no break, incorrect cprb version is an unknown
+                * response
+                */
        default: /* Unknown response type, this should NEVER EVER happen */
                zq->online = 0;
                pr_err("Cryptographic device %02x.%04x failed and was set offline\n",
@@ -1004,7 +1014,7 @@ static void zcrypt_msgtype6_receive_ep11(struct ap_queue *aq,
                }
        } else {
                memcpy(msg->message, reply->message, sizeof(error_reply));
-         }
+       }
 out:
        complete(&(resp_type->work));
 }
index d314f45..e4c2f37 100644 (file)
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0+
+/* SPDX-License-Identifier: GPL-2.0+ */
 /*
  *  zcrypt 2.1.0
  *
index 159b0a0..94d9f72 100644 (file)
@@ -95,7 +95,7 @@ static int zcrypt_pcixcc_rng_supported(struct ap_queue *aq)
                struct type86_hdr hdr;
                struct type86_fmt2_ext fmt2;
                struct CPRBX cprbx;
-       } __attribute__((packed)) *reply;
+       } __packed *reply;
        struct {
                struct type6_hdr hdr;
                struct CPRBX cprbx;
@@ -104,7 +104,7 @@ static int zcrypt_pcixcc_rng_supported(struct ap_queue *aq)
                char rule[8];
                short int verb_length;
                short int key_length;
-       } __packed * msg;
+       } __packed *msg;
        int rc, i;
 
        ap_init_message(&ap_msg);
@@ -223,6 +223,7 @@ static struct ap_driver zcrypt_pcixcc_card_driver = {
        .probe = zcrypt_pcixcc_card_probe,
        .remove = zcrypt_pcixcc_card_remove,
        .ids = zcrypt_pcixcc_card_ids,
+       .flags = AP_DRIVER_FLAG_DEFAULT,
 };
 
 /**
@@ -286,6 +287,7 @@ static struct ap_driver zcrypt_pcixcc_queue_driver = {
        .suspend = ap_queue_suspend,
        .resume = ap_queue_resume,
        .ids = zcrypt_pcixcc_queue_ids,
+       .flags = AP_DRIVER_FLAG_DEFAULT,
 };
 
 int __init zcrypt_pcixcc_init(void)
index d678a3a..cf73a0f 100644 (file)
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0+
+/* SPDX-License-Identifier: GPL-2.0+ */
 /*
  *  zcrypt 2.1.0
  *
index 91a52f2..8df82c6 100644 (file)
  * Device attributes common for all crypto queue devices.
  */
 
-static ssize_t zcrypt_queue_online_show(struct device *dev,
-                                       struct device_attribute *attr,
-                                       char *buf)
+static ssize_t online_show(struct device *dev,
+                          struct device_attribute *attr,
+                          char *buf)
 {
        struct zcrypt_queue *zq = to_ap_queue(dev)->private;
 
        return snprintf(buf, PAGE_SIZE, "%d\n", zq->online);
 }
 
-static ssize_t zcrypt_queue_online_store(struct device *dev,
-                                        struct device_attribute *attr,
-                                        const char *buf, size_t count)
+static ssize_t online_store(struct device *dev,
+                           struct device_attribute *attr,
+                           const char *buf, size_t count)
 {
        struct zcrypt_queue *zq = to_ap_queue(dev)->private;
        struct zcrypt_card *zc = zq->zcard;
@@ -72,19 +72,18 @@ static ssize_t zcrypt_queue_online_store(struct device *dev,
        return count;
 }
 
-static DEVICE_ATTR(online, 0644, zcrypt_queue_online_show,
-                  zcrypt_queue_online_store);
+static DEVICE_ATTR_RW(online);
 
-static ssize_t zcrypt_queue_load_show(struct device *dev,
-                                     struct device_attribute *attr,
-                                     char *buf)
+static ssize_t load_show(struct device *dev,
+                        struct device_attribute *attr,
+                        char *buf)
 {
        struct zcrypt_queue *zq = to_ap_queue(dev)->private;
 
        return snprintf(buf, PAGE_SIZE, "%d\n", atomic_read(&zq->load));
 }
 
-static DEVICE_ATTR(load, 0444, zcrypt_queue_load_show, NULL);
+static DEVICE_ATTR_RO(load);
 
 static struct attribute *zcrypt_queue_attrs[] = {
        &dev_attr_online.attr,
index 0e56f1e..eaf36cc 100644 (file)
@@ -423,19 +423,11 @@ static int osd_probe(struct device *dev)
        if (scsi_device->type != TYPE_OSD)
                return -ENODEV;
 
-       do {
-               if (!ida_pre_get(&osd_minor_ida, GFP_KERNEL))
-                       return -ENODEV;
-
-               error = ida_get_new(&osd_minor_ida, &minor);
-       } while (error == -EAGAIN);
-
-       if (error)
-               return error;
-       if (minor >= SCSI_OSD_MAX_MINOR) {
-               error = -EBUSY;
-               goto err_retract_minor;
-       }
+       minor = ida_alloc_max(&osd_minor_ida, SCSI_OSD_MAX_MINOR, GFP_KERNEL);
+       if (minor == -ENOSPC)
+               return -EBUSY;
+       if (minor < 0)
+               return -ENODEV;
 
        error = -ENOMEM;
        oud = kzalloc(sizeof(*oud), GFP_KERNEL);
@@ -499,7 +491,7 @@ static int osd_probe(struct device *dev)
 err_free_osd:
        put_device(&oud->class_dev);
 err_retract_minor:
-       ida_remove(&osd_minor_ida, minor);
+       ida_free(&osd_minor_ida, minor);
        return error;
 }
 
@@ -514,7 +506,7 @@ static int osd_remove(struct device *dev)
        }
 
        cdev_device_del(&oud->cdev, &oud->class_dev);
-       ida_remove(&osd_minor_ida, oud->minor);
+       ida_free(&osd_minor_ida, oud->minor);
        put_device(&oud->class_dev);
 
        return 0;
index a58cee7..b79b366 100644 (file)
@@ -123,7 +123,6 @@ static void scsi_disk_release(struct device *cdev);
 static void sd_print_sense_hdr(struct scsi_disk *, struct scsi_sense_hdr *);
 static void sd_print_result(const struct scsi_disk *, const char *, int);
 
-static DEFINE_SPINLOCK(sd_index_lock);
 static DEFINE_IDA(sd_index_ida);
 
 /* This semaphore is used to mediate the 0->1 reference get in the
@@ -3340,16 +3339,8 @@ static int sd_probe(struct device *dev)
        if (!gd)
                goto out_free;
 
-       do {
-               if (!ida_pre_get(&sd_index_ida, GFP_KERNEL))
-                       goto out_put;
-
-               spin_lock(&sd_index_lock);
-               error = ida_get_new(&sd_index_ida, &index);
-               spin_unlock(&sd_index_lock);
-       } while (error == -EAGAIN);
-
-       if (error) {
+       index = ida_alloc(&sd_index_ida, GFP_KERNEL);
+       if (index < 0) {
                sdev_printk(KERN_WARNING, sdp, "sd_probe: memory exhausted.\n");
                goto out_put;
        }
@@ -3393,9 +3384,7 @@ static int sd_probe(struct device *dev)
        return 0;
 
  out_free_index:
-       spin_lock(&sd_index_lock);
-       ida_remove(&sd_index_ida, index);
-       spin_unlock(&sd_index_lock);
+       ida_free(&sd_index_ida, index);
  out_put:
        put_disk(gd);
  out_free:
@@ -3460,9 +3449,7 @@ static void scsi_disk_release(struct device *dev)
        struct scsi_disk *sdkp = to_scsi_disk(dev);
        struct gendisk *disk = sdkp->disk;
        
-       spin_lock(&sd_index_lock);
-       ida_remove(&sd_index_ida, sdkp->index);
-       spin_unlock(&sd_index_lock);
+       ida_free(&sd_index_ida, sdkp->index);
 
        disk->private_data = NULL;
        put_disk(disk);
index dcf8c80..a5577dd 100644 (file)
@@ -628,10 +628,26 @@ static const struct of_device_id ddr_shimphy_dt_ids[] = {
 
 static const struct of_device_id brcmstb_memc_of_match[] = {
        {
+               .compatible = "brcm,brcmstb-memc-ddr-rev-b.2.1",
+               .data = &ddr_seq,
+       },
+       {
                .compatible = "brcm,brcmstb-memc-ddr-rev-b.2.2",
                .data = &ddr_seq_b22,
        },
        {
+               .compatible = "brcm,brcmstb-memc-ddr-rev-b.2.3",
+               .data = &ddr_seq_b22,
+       },
+       {
+               .compatible = "brcm,brcmstb-memc-ddr-rev-b.3.0",
+               .data = &ddr_seq_b22,
+       },
+       {
+               .compatible = "brcm,brcmstb-memc-ddr-rev-b.3.1",
+               .data = &ddr_seq_b22,
+       },
+       {
                .compatible = "brcm,brcmstb-memc-ddr",
                .data = &ddr_seq,
        },
index 7a9fb9b..8f80e8b 100644 (file)
@@ -1,7 +1,9 @@
 #
-# Freescale SOC drivers
+# NXP/Freescale QorIQ series SOC drivers
 #
 
+menu "NXP/Freescale QorIQ SoC drivers"
+
 source "drivers/soc/fsl/qbman/Kconfig"
 source "drivers/soc/fsl/qe/Kconfig"
 
@@ -16,3 +18,14 @@ config FSL_GUTS
          Initially only reading SVR and registering soc device are supported.
          Other guts accesses, such as reading RCW, should eventually be moved
          into this driver as well.
+
+config FSL_MC_DPIO
+        tristate "QorIQ DPAA2 DPIO driver"
+        depends on FSL_MC_BUS
+        help
+         Driver for the DPAA2 DPIO object.  A DPIO provides queue and
+         buffer management facilities for software to interact with
+         other DPAA2 objects. This driver does not expose the DPIO
+         objects individually, but groups them under a service layer
+         API.
+endmenu
index 44b3beb..803ef1b 100644 (file)
@@ -6,3 +6,4 @@ obj-$(CONFIG_FSL_DPAA)                 += qbman/
 obj-$(CONFIG_QUICC_ENGINE)             += qe/
 obj-$(CONFIG_CPM)                      += qe/
 obj-$(CONFIG_FSL_GUTS)                 += guts.o
+obj-$(CONFIG_FSL_MC_DPIO)              += dpio/
similarity index 99%
rename from drivers/staging/fsl-mc/bus/dpio/dpio-driver.c
rename to drivers/soc/fsl/dpio/dpio-driver.c
index 11a90a9..b60b77b 100644 (file)
@@ -16,7 +16,7 @@
 #include <linux/io.h>
 
 #include <linux/fsl/mc.h>
-#include "../../include/dpaa2-io.h"
+#include <soc/fsl/dpaa2-io.h>
 
 #include "qbman-portal.h"
 #include "dpio.h"
similarity index 99%
rename from drivers/staging/fsl-mc/bus/dpio/dpio-service.c
rename to drivers/soc/fsl/dpio/dpio-service.c
index 14ed2be..9b17f72 100644 (file)
@@ -6,7 +6,7 @@
  */
 #include <linux/types.h>
 #include <linux/fsl/mc.h>
-#include "../../include/dpaa2-io.h"
+#include <soc/fsl/dpaa2-io.h>
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
similarity index 99%
rename from drivers/staging/fsl-mc/bus/dpio/qbman-portal.c
rename to drivers/soc/fsl/dpio/qbman-portal.c
index 116fafb..cf1d448 100644 (file)
@@ -8,7 +8,7 @@
 #include <asm/cacheflush.h>
 #include <linux/io.h>
 #include <linux/slab.h>
-#include "../../include/dpaa2-global.h"
+#include <soc/fsl/dpaa2-global.h>
 
 #include "qbman-portal.h"
 
similarity index 99%
rename from drivers/staging/fsl-mc/bus/dpio/qbman-portal.h
rename to drivers/soc/fsl/dpio/qbman-portal.h
index 69db3c8..89d1dd9 100644 (file)
@@ -7,7 +7,7 @@
 #ifndef __FSL_QBMAN_PORTAL_H
 #define __FSL_QBMAN_PORTAL_H
 
-#include "../../include/dpaa2-fd.h"
+#include <soc/fsl/dpaa2-fd.h>
 
 struct dpaa2_dq;
 struct qbman_swp;
index fb4e6bf..d570cb5 100644 (file)
@@ -1,5 +1,5 @@
 menuconfig FSL_DPAA
-       bool "Freescale DPAA 1.x support"
+       bool "QorIQ DPAA1 framework support"
        depends on (FSL_SOC_BOOKE || ARCH_LAYERSCAPE)
        select GENERIC_ALLOCATOR
        help
index 73a2e08..fabba17 100644 (file)
@@ -3,7 +3,7 @@
 #
 
 config QUICC_ENGINE
-       bool "Freescale QUICC Engine (QE) Support"
+       bool "QUICC Engine (QE) framework support"
        depends on FSL_SOC && PPC32
        select GENERIC_ALLOCATOR
        select CRC32
index 3b27075..819bed0 100644 (file)
@@ -83,6 +83,33 @@ static void qe_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
        spin_unlock_irqrestore(&qe_gc->lock, flags);
 }
 
+static void qe_gpio_set_multiple(struct gpio_chip *gc,
+                                unsigned long *mask, unsigned long *bits)
+{
+       struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
+       struct qe_gpio_chip *qe_gc = gpiochip_get_data(gc);
+       struct qe_pio_regs __iomem *regs = mm_gc->regs;
+       unsigned long flags;
+       int i;
+
+       spin_lock_irqsave(&qe_gc->lock, flags);
+
+       for (i = 0; i < gc->ngpio; i++) {
+               if (*mask == 0)
+                       break;
+               if (__test_and_clear_bit(i, mask)) {
+                       if (test_bit(i, bits))
+                               qe_gc->cpdata |= (1U << (QE_PIO_PINS - 1 - i));
+                       else
+                               qe_gc->cpdata &= ~(1U << (QE_PIO_PINS - 1 - i));
+               }
+       }
+
+       out_be32(&regs->cpdata, qe_gc->cpdata);
+
+       spin_unlock_irqrestore(&qe_gc->lock, flags);
+}
+
 static int qe_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio)
 {
        struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
@@ -298,6 +325,7 @@ static int __init qe_add_gpiochips(void)
                gc->direction_output = qe_gpio_dir_out;
                gc->get = qe_gpio_get;
                gc->set = qe_gpio_set;
+               gc->set_multiple = qe_gpio_set_multiple;
 
                ret = of_mm_gpiochip_add_data(np, mm_gc, qe_gc);
                if (ret)
index 546960a..b3da635 100644 (file)
@@ -54,7 +54,6 @@ struct imx_pm_domain {
        unsigned int reg_offs;
        signed char cntr_pdn_bit;
        unsigned int ipg_rate_mhz;
-       unsigned int flags;
 };
 
 static inline struct imx_pm_domain *
@@ -69,9 +68,6 @@ static int imx6_pm_domain_power_off(struct generic_pm_domain *genpd)
        int iso, iso2sw;
        u32 val;
 
-       if (pd->flags & PGC_DOMAIN_FLAG_NO_PD)
-               return -EBUSY;
-
        /* Read ISO and ISO2SW power down delays */
        regmap_read(pd->regmap, pd->reg_offs + GPC_PGC_PUPSCR_OFFS, &val);
        iso = val & 0x3f;
@@ -295,26 +291,31 @@ static struct imx_pm_domain imx_gpc_domains[] = {
 struct imx_gpc_dt_data {
        int num_domains;
        bool err009619_present;
+       bool err006287_present;
 };
 
 static const struct imx_gpc_dt_data imx6q_dt_data = {
        .num_domains = 2,
        .err009619_present = false,
+       .err006287_present = false,
 };
 
 static const struct imx_gpc_dt_data imx6qp_dt_data = {
        .num_domains = 2,
        .err009619_present = true,
+       .err006287_present = false,
 };
 
 static const struct imx_gpc_dt_data imx6sl_dt_data = {
        .num_domains = 3,
        .err009619_present = false,
+       .err006287_present = true,
 };
 
 static const struct imx_gpc_dt_data imx6sx_dt_data = {
        .num_domains = 4,
        .err009619_present = false,
+       .err006287_present = false,
 };
 
 static const struct of_device_id imx_gpc_dt_ids[] = {
@@ -434,8 +435,13 @@ static int imx_gpc_probe(struct platform_device *pdev)
 
        /* Disable PU power down in normal operation if ERR009619 is present */
        if (of_id_data->err009619_present)
-               imx_gpc_domains[GPC_PGC_DOMAIN_PU].flags |=
-                               PGC_DOMAIN_FLAG_NO_PD;
+               imx_gpc_domains[GPC_PGC_DOMAIN_PU].base.flags |=
+                               GENPD_FLAG_ALWAYS_ON;
+
+       /* Keep DISP always on if ERR006287 is present */
+       if (of_id_data->err006287_present)
+               imx_gpc_domains[GPC_PGC_DOMAIN_DISPLAY].base.flags |=
+                               GENPD_FLAG_ALWAYS_ON;
 
        if (!pgc_node) {
                ret = imx_gpc_old_dt_init(&pdev->dev, regmap,
index 2afae64..4e931fd 100644 (file)
@@ -146,6 +146,21 @@ static const u32 mt6397_regs[] = {
        [PWRAP_DEW_CIPHER_SWRST] =      0xbc24,
 };
 
+static const u32 mt6351_regs[] = {
+       [PWRAP_DEW_DIO_EN] =            0x02F2,
+       [PWRAP_DEW_READ_TEST] =         0x02F4,
+       [PWRAP_DEW_WRITE_TEST] =        0x02F6,
+       [PWRAP_DEW_CRC_EN] =            0x02FA,
+       [PWRAP_DEW_CRC_VAL] =           0x02FC,
+       [PWRAP_DEW_CIPHER_KEY_SEL] =    0x0300,
+       [PWRAP_DEW_CIPHER_IV_SEL] =     0x0302,
+       [PWRAP_DEW_CIPHER_EN] =         0x0304,
+       [PWRAP_DEW_CIPHER_RDY] =        0x0306,
+       [PWRAP_DEW_CIPHER_MODE] =       0x0308,
+       [PWRAP_DEW_CIPHER_SWRST] =      0x030A,
+       [PWRAP_DEW_RDDMY_NO] =          0x030C,
+};
+
 enum pwrap_regs {
        PWRAP_MUX_SEL,
        PWRAP_WRAP_EN,
@@ -366,6 +381,39 @@ static int mt2701_regs[] = {
        [PWRAP_ADC_RDATA_ADDR2] =       0x154,
 };
 
+static int mt6797_regs[] = {
+       [PWRAP_MUX_SEL] =               0x0,
+       [PWRAP_WRAP_EN] =               0x4,
+       [PWRAP_DIO_EN] =                0x8,
+       [PWRAP_SIDLY] =                 0xC,
+       [PWRAP_RDDMY] =                 0x10,
+       [PWRAP_CSHEXT_WRITE] =          0x18,
+       [PWRAP_CSHEXT_READ] =           0x1C,
+       [PWRAP_CSLEXT_START] =          0x20,
+       [PWRAP_CSLEXT_END] =            0x24,
+       [PWRAP_STAUPD_PRD] =            0x28,
+       [PWRAP_HARB_HPRIO] =            0x50,
+       [PWRAP_HIPRIO_ARB_EN] =         0x54,
+       [PWRAP_MAN_EN] =                0x60,
+       [PWRAP_MAN_CMD] =               0x64,
+       [PWRAP_WACS0_EN] =              0x70,
+       [PWRAP_WACS1_EN] =              0x84,
+       [PWRAP_WACS2_EN] =              0x98,
+       [PWRAP_INIT_DONE2] =            0x9C,
+       [PWRAP_WACS2_CMD] =             0xA0,
+       [PWRAP_WACS2_RDATA] =           0xA4,
+       [PWRAP_WACS2_VLDCLR] =          0xA8,
+       [PWRAP_INT_EN] =                0xC0,
+       [PWRAP_INT_FLG_RAW] =           0xC4,
+       [PWRAP_INT_FLG] =               0xC8,
+       [PWRAP_INT_CLR] =               0xCC,
+       [PWRAP_TIMER_EN] =              0xF4,
+       [PWRAP_WDT_UNIT] =              0xFC,
+       [PWRAP_WDT_SRC_EN] =            0x100,
+       [PWRAP_DCM_EN] =                0x1CC,
+       [PWRAP_DCM_DBC_PRD] =           0x1D4,
+};
+
 static int mt7622_regs[] = {
        [PWRAP_MUX_SEL] =               0x0,
        [PWRAP_WRAP_EN] =               0x4,
@@ -635,12 +683,14 @@ static int mt8135_regs[] = {
 
 enum pmic_type {
        PMIC_MT6323,
+       PMIC_MT6351,
        PMIC_MT6380,
        PMIC_MT6397,
 };
 
 enum pwrap_type {
        PWRAP_MT2701,
+       PWRAP_MT6797,
        PWRAP_MT7622,
        PWRAP_MT8135,
        PWRAP_MT8173,
@@ -1067,6 +1117,7 @@ static int pwrap_init_cipher(struct pmic_wrapper *wrp)
                pwrap_writel(wrp, 1, PWRAP_CIPHER_START);
                break;
        case PWRAP_MT2701:
+       case PWRAP_MT6797:
        case PWRAP_MT8173:
                pwrap_writel(wrp, 1, PWRAP_CIPHER_EN);
                break;
@@ -1080,8 +1131,6 @@ static int pwrap_init_cipher(struct pmic_wrapper *wrp)
        pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_SWRST], 0x0);
        pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_KEY_SEL], 0x1);
        pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_IV_SEL], 0x2);
-       pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_LOAD], 0x1);
-       pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_START], 0x1);
 
        switch (wrp->slave->type) {
        case PMIC_MT6397:
@@ -1091,6 +1140,7 @@ static int pwrap_init_cipher(struct pmic_wrapper *wrp)
                            0x1);
                break;
        case PMIC_MT6323:
+       case PMIC_MT6351:
                pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_EN],
                            0x1);
                break;
@@ -1367,6 +1417,15 @@ static const struct pwrap_slv_type pmic_mt6397 = {
        .pwrap_write = pwrap_write16,
 };
 
+static const struct pwrap_slv_type pmic_mt6351 = {
+       .dew_regs = mt6351_regs,
+       .type = PMIC_MT6351,
+       .regmap = &pwrap_regmap_config16,
+       .caps = 0,
+       .pwrap_read = pwrap_read16,
+       .pwrap_write = pwrap_write16,
+};
+
 static const struct of_device_id of_slave_match_tbl[] = {
        {
                .compatible = "mediatek,mt6323",
@@ -1381,6 +1440,9 @@ static const struct of_device_id of_slave_match_tbl[] = {
                .compatible = "mediatek,mt6397",
                .data = &pmic_mt6397,
        }, {
+               .compatible = "mediatek,mt6351",
+               .data = &pmic_mt6351,
+       }, {
                /* sentinel */
        }
 };
@@ -1398,6 +1460,18 @@ static const struct pmic_wrapper_type pwrap_mt2701 = {
        .init_soc_specific = pwrap_mt2701_init_soc_specific,
 };
 
+static const struct pmic_wrapper_type pwrap_mt6797 = {
+       .regs = mt6797_regs,
+       .type = PWRAP_MT6797,
+       .arb_en_all = 0x01fff,
+       .int_en_all = 0xffffffc6,
+       .spi_w = PWRAP_MAN_CMD_SPI_WRITE,
+       .wdt_src = PWRAP_WDT_SRC_MASK_ALL,
+       .has_bridge = 0,
+       .init_reg_clock = pwrap_common_init_reg_clock,
+       .init_soc_specific = NULL,
+};
+
 static const struct pmic_wrapper_type pwrap_mt7622 = {
        .regs = mt7622_regs,
        .type = PWRAP_MT7622,
@@ -1439,6 +1513,9 @@ static const struct of_device_id of_pwrap_match_tbl[] = {
                .compatible = "mediatek,mt2701-pwrap",
                .data = &pwrap_mt2701,
        }, {
+               .compatible = "mediatek,mt6797-pwrap",
+               .data = &pwrap_mt6797,
+       }, {
                .compatible = "mediatek,mt7622-pwrap",
                .data = &pwrap_mt7622,
        }, {
index 7dc0f20..c37b080 100644 (file)
@@ -18,6 +18,9 @@ obj-$(CONFIG_SYSC_R8A77970)   += r8a77970-sysc.o
 obj-$(CONFIG_SYSC_R8A77980)    += r8a77980-sysc.o
 obj-$(CONFIG_SYSC_R8A77990)    += r8a77990-sysc.o
 obj-$(CONFIG_SYSC_R8A77995)    += r8a77995-sysc.o
+ifdef CONFIG_SMP
+obj-$(CONFIG_ARCH_R9A06G032)   += r9a06g032-smp.o
+endif
 
 # Family
 obj-$(CONFIG_RST_RCAR)         += rcar-rst.o
diff --git a/drivers/soc/renesas/r9a06g032-smp.c b/drivers/soc/renesas/r9a06g032-smp.c
new file mode 100644 (file)
index 0000000..a1926e8
--- /dev/null
@@ -0,0 +1,96 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * R9A06G032 Second CA7 enabler.
+ *
+ * Copyright (C) 2018 Renesas Electronics Europe Limited
+ *
+ * Michel Pollet <michel.pollet@bp.renesas.com>, <buserror@gmail.com>
+ * Derived from actions,s500-smp
+ */
+
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/smp.h>
+
+/*
+ * The second CPU is parked in ROM at boot time. It requires waking it after
+ * writing an address into the BOOTADDR register of sysctrl.
+ *
+ * So the default value of the "cpu-release-addr" corresponds to BOOTADDR...
+ *
+ * *However* the BOOTADDR register is not available when the kernel
+ * starts in NONSEC mode.
+ *
+ * So for NONSEC mode, the bootloader re-parks the second CPU into a pen
+ * in SRAM, and changes the "cpu-release-addr" of linux's DT to a SRAM address,
+ * which is not restricted.
+ */
+
+static void __iomem *cpu_bootaddr;
+
+static DEFINE_SPINLOCK(cpu_lock);
+
+static int
+r9a06g032_smp_boot_secondary(unsigned int cpu,
+                            struct task_struct *idle)
+{
+       if (!cpu_bootaddr)
+               return -ENODEV;
+
+       spin_lock(&cpu_lock);
+
+       writel(__pa_symbol(secondary_startup), cpu_bootaddr);
+       arch_send_wakeup_ipi_mask(cpumask_of(cpu));
+
+       spin_unlock(&cpu_lock);
+
+       return 0;
+}
+
+static void __init r9a06g032_smp_prepare_cpus(unsigned int max_cpus)
+{
+       struct device_node *dn;
+       int ret = -EINVAL, dns;
+       u32 bootaddr;
+
+       dn = of_get_cpu_node(1, NULL);
+       if (!dn) {
+               pr_err("CPU#1: missing device tree node\n");
+               return;
+       }
+       /*
+        * Determine the address from which the CPU is polling.
+        * The bootloader *does* change this property.
+        * Note: The property can be either 64 or 32 bits, so handle both cases
+        */
+       if (of_find_property(dn, "cpu-release-addr", &dns)) {
+               if (dns == sizeof(u64)) {
+                       u64 temp;
+
+                       ret = of_property_read_u64(dn,
+                                                  "cpu-release-addr", &temp);
+                       bootaddr = temp;
+               } else {
+                       ret = of_property_read_u32(dn,
+                                                  "cpu-release-addr",
+                                                  &bootaddr);
+               }
+       }
+       of_node_put(dn);
+       if (ret) {
+               pr_err("CPU#1: invalid cpu-release-addr property\n");
+               return;
+       }
+       pr_info("CPU#1: cpu-release-addr %08x\n", bootaddr);
+
+       cpu_bootaddr = ioremap(bootaddr, sizeof(bootaddr));
+}
+
+static const struct smp_operations r9a06g032_smp_ops __initconst = {
+       .smp_prepare_cpus = r9a06g032_smp_prepare_cpus,
+       .smp_boot_secondary = r9a06g032_smp_boot_secondary,
+};
+
+CPU_METHOD_OF_DECLARE(r9a06g032_smp,
+                     "renesas,r9a06g032-smp", &r9a06g032_smp_ops);
index 50d03d8..029188e 100644 (file)
 
 #define RCAR_PD_ALWAYS_ON      32      /* Always-on power area */
 
+struct rcar_sysc_ch {
+       u16 chan_offs;
+       u8 chan_bit;
+       u8 isr_bit;
+};
+
 static void __iomem *rcar_sysc_base;
 static DEFINE_SPINLOCK(rcar_sysc_lock); /* SMP CPUs + I/O devices */
 
@@ -143,12 +149,12 @@ static int rcar_sysc_power(const struct rcar_sysc_ch *sysc_ch, bool on)
        return ret;
 }
 
-int rcar_sysc_power_down(const struct rcar_sysc_ch *sysc_ch)
+static int rcar_sysc_power_down(const struct rcar_sysc_ch *sysc_ch)
 {
        return rcar_sysc_power(sysc_ch, false);
 }
 
-int rcar_sysc_power_up(const struct rcar_sysc_ch *sysc_ch)
+static int rcar_sysc_power_up(const struct rcar_sysc_ch *sysc_ch)
 {
        return rcar_sysc_power(sysc_ch, true);
 }
@@ -315,6 +321,8 @@ struct rcar_pm_domains {
        struct generic_pm_domain *domains[RCAR_PD_ALWAYS_ON + 1];
 };
 
+static struct genpd_onecell_data *rcar_sysc_onecell_data;
+
 static int __init rcar_sysc_pd_init(void)
 {
        const struct rcar_sysc_info *info;
@@ -326,9 +334,6 @@ static int __init rcar_sysc_pd_init(void)
        unsigned int i;
        int error;
 
-       if (rcar_sysc_base)
-               return 0;
-
        np = of_find_matching_node_and_match(NULL, rcar_sysc_matches, &match);
        if (!np)
                return -ENODEV;
@@ -361,6 +366,7 @@ static int __init rcar_sysc_pd_init(void)
 
        domains->onecell_data.domains = domains->domains;
        domains->onecell_data.num_domains = ARRAY_SIZE(domains->domains);
+       rcar_sysc_onecell_data = &domains->onecell_data;
 
        for (i = 0, syscier = 0; i < info->num_areas; i++)
                syscier |= BIT(info->areas[i].isr_bit);
@@ -448,27 +454,39 @@ void __init rcar_sysc_nullify(struct rcar_sysc_area *areas,
                }
 }
 
-void __init rcar_sysc_init(phys_addr_t base, u32 syscier)
+#ifdef CONFIG_ARCH_R8A7779
+static int rcar_sysc_power_cpu(unsigned int idx, bool on)
 {
-       u32 syscimr;
+       struct generic_pm_domain *genpd;
+       struct rcar_sysc_pd *pd;
+       unsigned int i;
 
-       if (!rcar_sysc_pd_init())
-               return;
+       if (!rcar_sysc_onecell_data)
+               return -ENODEV;
 
-       rcar_sysc_base = ioremap_nocache(base, PAGE_SIZE);
+       for (i = 0; i < rcar_sysc_onecell_data->num_domains; i++) {
+               genpd = rcar_sysc_onecell_data->domains[i];
+               if (!genpd)
+                       continue;
 
-       /*
-        * Mask all interrupt sources to prevent the CPU from receiving them.
-        * Make sure not to clear reserved bits that were set before.
-        */
-       syscimr = ioread32(rcar_sysc_base + SYSCIMR);
-       syscimr |= syscier;
-       pr_debug("%s: syscimr = 0x%08x\n", __func__, syscimr);
-       iowrite32(syscimr, rcar_sysc_base + SYSCIMR);
+               pd = to_rcar_pd(genpd);
+               if (!(pd->flags & PD_CPU) || pd->ch.chan_bit != idx)
+                       continue;
 
-       /*
-        * SYSC needs all interrupt sources enabled to control power.
-        */
-       pr_debug("%s: syscier = 0x%08x\n", __func__, syscier);
-       iowrite32(syscier, rcar_sysc_base + SYSCIER);
+               return on ? rcar_sysc_power_up(&pd->ch)
+                         : rcar_sysc_power_down(&pd->ch);
+       }
+
+       return -ENOENT;
+}
+
+int rcar_sysc_power_down_cpu(unsigned int cpu)
+{
+       return rcar_sysc_power_cpu(cpu, false);
+}
+
+int rcar_sysc_power_up_cpu(unsigned int cpu)
+{
+       return rcar_sysc_power_cpu(cpu, true);
 }
+#endif /* CONFIG_ARCH_R8A7779 */
index 882be5e..b4b0f34 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/of_address.h>
 #include <linux/of_device.h>
 #include <linux/platform_device.h>
+#include <linux/regmap.h>
 
 #include <linux/soc/sunxi/sunxi_sram.h>
 
@@ -63,6 +64,12 @@ static struct sunxi_sram_desc sun4i_a10_sram_a3_a4 = {
                                  SUNXI_SRAM_MAP(1, 1, "emac")),
 };
 
+static struct sunxi_sram_desc sun4i_a10_sram_c1 = {
+       .data   = SUNXI_SRAM_DATA("C1", 0x0, 0x0, 31,
+                                 SUNXI_SRAM_MAP(0, 0, "cpu"),
+                                 SUNXI_SRAM_MAP(0x7fffffff, 1, "ve")),
+};
+
 static struct sunxi_sram_desc sun4i_a10_sram_d = {
        .data   = SUNXI_SRAM_DATA("D", 0x4, 0x0, 1,
                                  SUNXI_SRAM_MAP(0, 0, "cpu"),
@@ -81,6 +88,10 @@ static const struct of_device_id sunxi_sram_dt_ids[] = {
                .data           = &sun4i_a10_sram_a3_a4.data,
        },
        {
+               .compatible     = "allwinner,sun4i-a10-sram-c1",
+               .data           = &sun4i_a10_sram_c1.data,
+       },
+       {
                .compatible     = "allwinner,sun4i-a10-sram-d",
                .data           = &sun4i_a10_sram_d.data,
        },
@@ -281,13 +292,51 @@ int sunxi_sram_release(struct device *dev)
 }
 EXPORT_SYMBOL(sunxi_sram_release);
 
+struct sunxi_sramc_variant {
+       bool has_emac_clock;
+};
+
+static const struct sunxi_sramc_variant sun4i_a10_sramc_variant = {
+       /* Nothing special */
+};
+
+static const struct sunxi_sramc_variant sun50i_a64_sramc_variant = {
+       .has_emac_clock = true,
+};
+
+#define SUNXI_SRAM_EMAC_CLOCK_REG      0x30
+static bool sunxi_sram_regmap_accessible_reg(struct device *dev,
+                                            unsigned int reg)
+{
+       if (reg == SUNXI_SRAM_EMAC_CLOCK_REG)
+               return true;
+       return false;
+}
+
+static struct regmap_config sunxi_sram_emac_clock_regmap = {
+       .reg_bits       = 32,
+       .val_bits       = 32,
+       .reg_stride     = 4,
+       /* last defined register */
+       .max_register   = SUNXI_SRAM_EMAC_CLOCK_REG,
+       /* other devices have no business accessing other registers */
+       .readable_reg   = sunxi_sram_regmap_accessible_reg,
+       .writeable_reg  = sunxi_sram_regmap_accessible_reg,
+};
+
 static int sunxi_sram_probe(struct platform_device *pdev)
 {
        struct resource *res;
        struct dentry *d;
+       struct regmap *emac_clock;
+       const struct sunxi_sramc_variant *variant;
 
        sram_dev = &pdev->dev;
 
+       variant = of_device_get_match_data(&pdev->dev);
+       if (!variant)
+               return -EINVAL;
+
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        base = devm_ioremap_resource(&pdev->dev, res);
        if (IS_ERR(base))
@@ -300,12 +349,46 @@ static int sunxi_sram_probe(struct platform_device *pdev)
        if (!d)
                return -ENOMEM;
 
+       if (variant->has_emac_clock) {
+               emac_clock = devm_regmap_init_mmio(&pdev->dev, base,
+                                                  &sunxi_sram_emac_clock_regmap);
+
+               if (IS_ERR(emac_clock))
+                       return PTR_ERR(emac_clock);
+       }
+
        return 0;
 }
 
 static const struct of_device_id sunxi_sram_dt_match[] = {
-       { .compatible = "allwinner,sun4i-a10-sram-controller" },
-       { .compatible = "allwinner,sun50i-a64-sram-controller" },
+       {
+               .compatible = "allwinner,sun4i-a10-sram-controller",
+               .data = &sun4i_a10_sramc_variant,
+       },
+       {
+               .compatible = "allwinner,sun4i-a10-system-control",
+               .data = &sun4i_a10_sramc_variant,
+       },
+       {
+               .compatible = "allwinner,sun5i-a13-system-control",
+               .data = &sun4i_a10_sramc_variant,
+       },
+       {
+               .compatible = "allwinner,sun8i-a23-system-control",
+               .data = &sun4i_a10_sramc_variant,
+       },
+       {
+               .compatible = "allwinner,sun8i-h3-system-control",
+               .data = &sun4i_a10_sramc_variant,
+       },
+       {
+               .compatible = "allwinner,sun50i-a64-sram-controller",
+               .data = &sun50i_a64_sramc_variant,
+       },
+       {
+               .compatible = "allwinner,sun50i-a64-system-control",
+               .data = &sun50i_a64_sramc_variant,
+       },
        { },
 };
 MODULE_DEVICE_TABLE(of, sunxi_sram_dt_match);
index 92770d8..be4570b 100644 (file)
@@ -1,3 +1,17 @@
+# 64-bit ARM SoCs from TI
+if ARM64
+
+if ARCH_K3
+
+config ARCH_K3_AM6_SOC
+       bool "K3 AM6 SoC"
+       help
+         Enable support for TI's AM6 SoC Family support
+
+endif
+
+endif
+
 #
 # TI SOC drivers
 #
index 652739c..d0dab32 100644 (file)
@@ -41,6 +41,8 @@ static struct am33xx_pm_sram_addr *pm_sram;
 static struct device *pm33xx_dev;
 static struct wkup_m3_ipc *m3_ipc;
 
+static unsigned long suspend_wfi_flags;
+
 static u32 sram_suspend_address(unsigned long addr)
 {
        return ((unsigned long)am33xx_do_wfi_sram +
@@ -53,7 +55,7 @@ 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);
+                                 am33xx_do_wfi_sram, suspend_wfi_flags);
 
        if (ret) {
                dev_err(pm33xx_dev, "PM: Kernel suspend failure\n");
@@ -227,6 +229,7 @@ static int am33xx_push_sram_idle(void)
        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,
@@ -310,6 +313,17 @@ static int am33xx_pm_probe(struct platform_device *pdev)
        suspend_set_ops(&am33xx_pm_ops);
 #endif /* CONFIG_SUSPEND */
 
+       /*
+        * For a system suspend we must flush the caches, we want
+        * the DDR in self-refresh, we want to save the context
+        * of the EMIF, and we want the wkup_m3 to handle low-power
+        * transition.
+        */
+       suspend_wfi_flags |= WFI_FLAG_FLUSH_CACHE;
+       suspend_wfi_flags |= WFI_FLAG_SELF_REFRESH;
+       suspend_wfi_flags |= WFI_FLAG_SAVE_EMIF;
+       suspend_wfi_flags |= WFI_FLAG_WAKE_M3;
+
        ret = pm_ops->init();
        if (ret) {
                dev_err(dev, "Unable to call core pm init!\n");
index 369aef5..f5cb8c0 100644 (file)
@@ -46,6 +46,7 @@
 #define M3_BASELINE_VERSION            0x191
 #define M3_STATUS_RESP_MASK            (0xffff << 16)
 #define M3_FW_VERSION_MASK             0xffff
+#define M3_WAKE_SRC_MASK               0xff
 
 #define M3_STATE_UNKNOWN               0
 #define M3_STATE_RESET                 1
 
 static struct wkup_m3_ipc *m3_ipc_state;
 
+static const struct wkup_m3_wakeup_src wakeups[] = {
+       {.irq_nr = 35,  .src = "USB0_PHY"},
+       {.irq_nr = 36,  .src = "USB1_PHY"},
+       {.irq_nr = 40,  .src = "I2C0"},
+       {.irq_nr = 41,  .src = "RTC Timer"},
+       {.irq_nr = 42,  .src = "RTC Alarm"},
+       {.irq_nr = 43,  .src = "Timer0"},
+       {.irq_nr = 44,  .src = "Timer1"},
+       {.irq_nr = 45,  .src = "UART"},
+       {.irq_nr = 46,  .src = "GPIO0"},
+       {.irq_nr = 48,  .src = "MPU_WAKE"},
+       {.irq_nr = 49,  .src = "WDT0"},
+       {.irq_nr = 50,  .src = "WDT1"},
+       {.irq_nr = 51,  .src = "ADC_TSC"},
+       {.irq_nr = 0,   .src = "Unknown"},
+};
+
 static void am33xx_txev_eoi(struct wkup_m3_ipc *m3_ipc)
 {
        writel(AM33XX_M3_TXEV_ACK,
@@ -329,12 +347,45 @@ static int wkup_m3_finish_low_power(struct wkup_m3_ipc *m3_ipc)
        return 0;
 }
 
+/**
+ * wkup_m3_request_wake_src - Get the wakeup source info passed from wkup_m3
+ * @m3_ipc: Pointer to wkup_m3_ipc context
+ */
+static const char *wkup_m3_request_wake_src(struct wkup_m3_ipc *m3_ipc)
+{
+       unsigned int wakeup_src_idx;
+       int j, val;
+
+       val = wkup_m3_ctrl_ipc_read(m3_ipc, 6);
+
+       wakeup_src_idx = val & M3_WAKE_SRC_MASK;
+
+       for (j = 0; j < ARRAY_SIZE(wakeups) - 1; j++) {
+               if (wakeups[j].irq_nr == wakeup_src_idx)
+                       return wakeups[j].src;
+       }
+       return wakeups[j].src;
+}
+
+/**
+ * wkup_m3_set_rtc_only - Set the rtc_only flag
+ * @wkup_m3_wakeup: struct wkup_m3_wakeup_src * gets assigned the
+ *                  wakeup src value
+ */
+static void wkup_m3_set_rtc_only(struct wkup_m3_ipc *m3_ipc)
+{
+       if (m3_ipc_state)
+               m3_ipc_state->is_rtc_only = true;
+}
+
 static struct wkup_m3_ipc_ops ipc_ops = {
        .set_mem_type = wkup_m3_set_mem_type,
        .set_resume_address = wkup_m3_set_resume_address,
        .prepare_low_power = wkup_m3_prepare_low_power,
        .finish_low_power = wkup_m3_finish_low_power,
        .request_pm_status = wkup_m3_request_pm_status,
+       .request_wake_src = wkup_m3_request_wake_src,
+       .set_rtc_only = wkup_m3_set_rtc_only,
 };
 
 /**
@@ -484,6 +535,30 @@ static int wkup_m3_ipc_remove(struct platform_device *pdev)
        return 0;
 }
 
+static int __maybe_unused wkup_m3_ipc_suspend(struct device *dev)
+{
+       /*
+        * Nothing needs to be done on suspend even with rtc_only flag set
+        */
+       return 0;
+}
+
+static int __maybe_unused wkup_m3_ipc_resume(struct device *dev)
+{
+       if (m3_ipc_state->is_rtc_only) {
+               rproc_shutdown(m3_ipc_state->rproc);
+               rproc_boot(m3_ipc_state->rproc);
+       }
+
+       m3_ipc_state->is_rtc_only = false;
+
+       return 0;
+}
+
+static const struct dev_pm_ops wkup_m3_ipc_pm_ops = {
+       SET_SYSTEM_SLEEP_PM_OPS(wkup_m3_ipc_suspend, wkup_m3_ipc_resume)
+};
+
 static const struct of_device_id wkup_m3_ipc_of_match[] = {
        { .compatible = "ti,am3352-wkup-m3-ipc", },
        { .compatible = "ti,am4372-wkup-m3-ipc", },
@@ -497,6 +572,7 @@ static struct platform_driver wkup_m3_ipc_driver = {
        .driver = {
                .name = "wkup_m3_ipc",
                .of_match_table = wkup_m3_ipc_of_match,
+               .pm = &wkup_m3_ipc_pm_ops,
        },
 };
 
index 396fb3d..1abf76b 100644 (file)
@@ -90,8 +90,6 @@ source "drivers/staging/clocking-wizard/Kconfig"
 
 source "drivers/staging/fbtft/Kconfig"
 
-source "drivers/staging/fsl-mc/Kconfig"
-
 source "drivers/staging/fsl-dpaa2/Kconfig"
 
 source "drivers/staging/wilc1000/Kconfig"
index ad7b4ca..ab0cbe8 100644 (file)
@@ -35,7 +35,6 @@ obj-$(CONFIG_GS_FPGABOOT)     += gs_fpgaboot/
 obj-$(CONFIG_UNISYSSPAR)       += unisys/
 obj-$(CONFIG_COMMON_CLK_XLNX_CLKWZRD)  += clocking-wizard/
 obj-$(CONFIG_FB_TFT)           += fbtft/
-obj-$(CONFIG_FSL_MC_BUS)       += fsl-mc/
 obj-$(CONFIG_FSL_DPAA2)                += fsl-dpaa2/
 obj-$(CONFIG_WILC1000)         += wilc1000/
 obj-$(CONFIG_MOST)             += most/
index e2dac44..9329fca 100644 (file)
@@ -426,7 +426,7 @@ static int build_sg_fd(struct dpaa2_eth_priv *priv,
        dpaa2_fd_set_format(fd, dpaa2_fd_sg);
        dpaa2_fd_set_addr(fd, addr);
        dpaa2_fd_set_len(fd, skb->len);
-       dpaa2_fd_set_ctrl(fd, DPAA2_FD_CTRL_PTA | DPAA2_FD_CTRL_PTV1);
+       dpaa2_fd_set_ctrl(fd, FD_CTRL_PTA | FD_CTRL_PTV1);
 
        if (priv->tx_tstamp && skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)
                enable_tx_tstamp(fd, sgt_buf);
@@ -479,7 +479,7 @@ static int build_single_fd(struct dpaa2_eth_priv *priv,
        dpaa2_fd_set_offset(fd, (u16)(skb->data - buffer_start));
        dpaa2_fd_set_len(fd, skb->len);
        dpaa2_fd_set_format(fd, dpaa2_fd_single);
-       dpaa2_fd_set_ctrl(fd, DPAA2_FD_CTRL_PTA | DPAA2_FD_CTRL_PTV1);
+       dpaa2_fd_set_ctrl(fd, FD_CTRL_PTA | FD_CTRL_PTV1);
 
        if (priv->tx_tstamp && skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)
                enable_tx_tstamp(fd, buffer_start);
index 5064667..d54cb0b 100644 (file)
@@ -10,8 +10,8 @@
 #include <linux/if_vlan.h>
 #include <linux/fsl/mc.h>
 
-#include "../../fsl-mc/include/dpaa2-io.h"
-#include "../../fsl-mc/include/dpaa2-fd.h"
+#include <soc/fsl/dpaa2-io.h>
+#include <soc/fsl/dpaa2-fd.h>
 #include "dpni.h"
 #include "dpni-cmd.h"
 
@@ -97,21 +97,13 @@ struct dpaa2_eth_swa {
 #define DPAA2_FD_FRC_FAICFDV           0x0400
 
 /* Error bits in FD CTRL */
-#define DPAA2_FD_CTRL_UFD              0x00000004
-#define DPAA2_FD_CTRL_SBE              0x00000008
-#define DPAA2_FD_CTRL_FSE              0x00000020
-#define DPAA2_FD_CTRL_FAERR            0x00000040
-
-#define DPAA2_FD_RX_ERR_MASK           (DPAA2_FD_CTRL_SBE      | \
-                                        DPAA2_FD_CTRL_FAERR)
-#define DPAA2_FD_TX_ERR_MASK           (DPAA2_FD_CTRL_UFD      | \
-                                        DPAA2_FD_CTRL_SBE      | \
-                                        DPAA2_FD_CTRL_FSE      | \
-                                        DPAA2_FD_CTRL_FAERR)
+#define DPAA2_FD_RX_ERR_MASK           (FD_CTRL_SBE | FD_CTRL_FAERR)
+#define DPAA2_FD_TX_ERR_MASK           (FD_CTRL_UFD    | \
+                                        FD_CTRL_SBE    | \
+                                        FD_CTRL_FSE    | \
+                                        FD_CTRL_FAERR)
 
 /* Annotation bits in FD CTRL */
-#define DPAA2_FD_CTRL_PTA              0x00800000
-#define DPAA2_FD_CTRL_PTV1             0x00400000
 #define DPAA2_FD_CTRL_ASAL             0x00020000      /* ASAL = 128B */
 
 /* Frame annotation status */
diff --git a/drivers/staging/fsl-mc/Kconfig b/drivers/staging/fsl-mc/Kconfig
deleted file mode 100644 (file)
index 3002229..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-source "drivers/staging/fsl-mc/bus/Kconfig"
diff --git a/drivers/staging/fsl-mc/Makefile b/drivers/staging/fsl-mc/Makefile
deleted file mode 100644 (file)
index 1468388..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-# Freescale Management Complex (MC) bus drivers
-obj-$(CONFIG_FSL_MC_BUS)       += bus/
diff --git a/drivers/staging/fsl-mc/bus/Kconfig b/drivers/staging/fsl-mc/bus/Kconfig
deleted file mode 100644 (file)
index 3424530..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-#
-# DPAA2 fsl-mc bus
-#
-# Copyright (C) 2014-2016 Freescale Semiconductor, Inc.
-#
-
-config FSL_MC_DPIO
-        tristate "QorIQ DPAA2 DPIO driver"
-        depends on FSL_MC_BUS
-        help
-         Driver for the DPAA2 DPIO object.  A DPIO provides queue and
-         buffer management facilities for software to interact with
-         other DPAA2 objects. This driver does not expose the DPIO
-         objects individually, but groups them under a service layer
-         API.
diff --git a/drivers/staging/fsl-mc/bus/Makefile b/drivers/staging/fsl-mc/bus/Makefile
deleted file mode 100644 (file)
index 21d8ebc..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-#
-# Freescale Management Complex (MC) bus drivers
-#
-# Copyright (C) 2014 Freescale Semiconductor, Inc.
-#
-
-# MC DPIO driver
-obj-$(CONFIG_FSL_MC_DPIO) += dpio/
index 8e22379..94bad43 100644 (file)
@@ -57,9 +57,8 @@ static DEFINE_SPINLOCK(tiqn_lock);
 static DEFINE_MUTEX(np_lock);
 
 static struct idr tiqn_idr;
-struct idr sess_idr;
+DEFINE_IDA(sess_ida);
 struct mutex auth_id_lock;
-spinlock_t sess_idr_lock;
 
 struct iscsit_global *iscsit_global;
 
@@ -700,9 +699,7 @@ static int __init iscsi_target_init_module(void)
 
        spin_lock_init(&iscsit_global->ts_bitmap_lock);
        mutex_init(&auth_id_lock);
-       spin_lock_init(&sess_idr_lock);
        idr_init(&tiqn_idr);
-       idr_init(&sess_idr);
 
        ret = target_register_template(&iscsi_ops);
        if (ret)
@@ -4375,10 +4372,7 @@ int iscsit_close_session(struct iscsi_session *sess)
        pr_debug("Decremented number of active iSCSI Sessions on"
                " iSCSI TPG: %hu to %u\n", tpg->tpgt, tpg->nsessions);
 
-       spin_lock(&sess_idr_lock);
-       idr_remove(&sess_idr, sess->session_index);
-       spin_unlock(&sess_idr_lock);
-
+       ida_free(&sess_ida, sess->session_index);
        kfree(sess->sess_ops);
        sess->sess_ops = NULL;
        spin_unlock_bh(&se_tpg->session_lock);
index 42de184..48bac0a 100644 (file)
@@ -55,9 +55,7 @@ extern struct kmem_cache *lio_ooo_cache;
 extern struct kmem_cache *lio_qr_cache;
 extern struct kmem_cache *lio_r2t_cache;
 
-extern struct idr sess_idr;
+extern struct ida sess_ida;
 extern struct mutex auth_id_lock;
-extern spinlock_t sess_idr_lock;
-
 
 #endif   /*** ISCSI_TARGET_H ***/
index 923b1a9..9e74f8b 100644 (file)
@@ -336,22 +336,15 @@ static int iscsi_login_zero_tsih_s1(
        timer_setup(&sess->time2retain_timer,
                    iscsit_handle_time2retain_timeout, 0);
 
-       idr_preload(GFP_KERNEL);
-       spin_lock_bh(&sess_idr_lock);
-       ret = idr_alloc(&sess_idr, NULL, 0, 0, GFP_NOWAIT);
-       if (ret >= 0)
-               sess->session_index = ret;
-       spin_unlock_bh(&sess_idr_lock);
-       idr_preload_end();
-
+       ret = ida_alloc(&sess_ida, GFP_KERNEL);
        if (ret < 0) {
-               pr_err("idr_alloc() for sess_idr failed\n");
+               pr_err("Session ID allocation failed %d\n", ret);
                iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
                                ISCSI_LOGIN_STATUS_NO_RESOURCES);
-               kfree(sess);
-               return -ENOMEM;
+               goto free_sess;
        }
 
+       sess->session_index = ret;
        sess->creation_time = get_jiffies_64();
        /*
         * The FFP CmdSN window values will be allocated from the TPG's
@@ -365,20 +358,26 @@ static int iscsi_login_zero_tsih_s1(
                                ISCSI_LOGIN_STATUS_NO_RESOURCES);
                pr_err("Unable to allocate memory for"
                                " struct iscsi_sess_ops.\n");
-               kfree(sess);
-               return -ENOMEM;
+               goto free_id;
        }
 
        sess->se_sess = transport_alloc_session(TARGET_PROT_NORMAL);
        if (IS_ERR(sess->se_sess)) {
                iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
                                ISCSI_LOGIN_STATUS_NO_RESOURCES);
-               kfree(sess->sess_ops);
-               kfree(sess);
-               return -ENOMEM;
+               goto free_ops;
        }
 
        return 0;
+
+free_ops:
+       kfree(sess->sess_ops);
+free_id:
+       ida_free(&sess_ida, sess->session_index);
+free_sess:
+       kfree(sess);
+       conn->sess = NULL;
+       return -ENOMEM;
 }
 
 static int iscsi_login_zero_tsih_s2(
@@ -1161,13 +1160,9 @@ void iscsi_target_login_sess_out(struct iscsi_conn *conn,
                                   ISCSI_LOGIN_STATUS_INIT_ERR);
        if (!zero_tsih || !conn->sess)
                goto old_sess_out;
-       if (conn->sess->se_sess)
-               transport_free_session(conn->sess->se_sess);
-       if (conn->sess->session_index != 0) {
-               spin_lock_bh(&sess_idr_lock);
-               idr_remove(&sess_idr, conn->sess->session_index);
-               spin_unlock_bh(&sess_idr_lock);
-       }
+
+       transport_free_session(conn->sess->se_sess);
+       ida_free(&sess_ida, conn->sess->session_index);
        kfree(conn->sess->sess_ops);
        kfree(conn->sess);
        conn->sess = NULL;
index 0126de8..3c59e19 100644 (file)
@@ -5,3 +5,11 @@ config OPTEE
        help
          This implements the OP-TEE Trusted Execution Environment (TEE)
          driver.
+
+config OPTEE_SHM_NUM_PRIV_PAGES
+       int "Private Shared Memory Pages"
+       default 1
+       depends on OPTEE
+       help
+         This sets the number of private shared memory pages to be
+         used by OP-TEE TEE driver.
index e5fd5ed..e1aafe8 100644 (file)
@@ -32,7 +32,7 @@
 
 #define DRIVER_NAME "optee"
 
-#define OPTEE_SHM_NUM_PRIV_PAGES       1
+#define OPTEE_SHM_NUM_PRIV_PAGES       CONFIG_OPTEE_SHM_NUM_PRIV_PAGES
 
 /**
  * optee_from_msg_param() - convert from OPTEE_MSG parameters to
index 41aea12..b45c73d 100644 (file)
@@ -48,7 +48,7 @@ static void handle_rpc_func_cmd_get_time(struct optee_msg_arg *arg)
                        OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT)
                goto bad;
 
-       getnstimeofday64(&ts);
+       ktime_get_real_ts64(&ts);
        arg->params[0].u.value.a = ts.tv_sec;
        arg->params[0].u.value.b = ts.tv_nsec;
 
index 8297988..0e69edc 100644 (file)
@@ -360,7 +360,7 @@ config INTEL_SOC_DTS_IOSF_CORE
 
 config INTEL_SOC_DTS_THERMAL
        tristate "Intel SoCs DTS thermal driver"
-       depends on X86 && PCI
+       depends on X86 && PCI && ACPI
        select INTEL_SOC_DTS_IOSF_CORE
        select THERMAL_WRITABLE_TRIPS
        help
index 4540e89..cde891c 100644 (file)
@@ -28,7 +28,7 @@
  *              case of external interrupts without need for ack, clamping down
  *              cpu in non-irq context does not reduce irq. for majority of the
  *              cases, clamping down cpu does help reduce irq as well, we should
- *              be able to differenciate the two cases and give a quantitative
+ *              be able to differentiate the two cases and give a quantitative
  *              solution for the irqs that we can control. perhaps based on
  *              get_cpu_iowait_time_us()
  *
index c27868b..1e47511 100644 (file)
@@ -15,6 +15,7 @@
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
+#include <linux/acpi.h>
 #include <linux/module.h>
 #include <linux/interrupt.h>
 #include <asm/cpu_device_id.h>
@@ -31,6 +32,7 @@ MODULE_PARM_DESC(crit_offset,
 /* IRQ 86 is a fixed APIC interrupt for BYT DTS Aux threshold notifications */
 #define BYT_SOC_DTS_APIC_IRQ   86
 
+static int soc_dts_thres_gsi;
 static int soc_dts_thres_irq;
 static struct intel_soc_dts_sensors *soc_dts;
 
@@ -65,7 +67,21 @@ static int __init intel_soc_thermal_init(void)
                return err;
        }
 
-       soc_dts_thres_irq = (int)match_cpu->driver_data;
+       soc_dts_thres_gsi = (int)match_cpu->driver_data;
+       if (soc_dts_thres_gsi) {
+               /*
+                * Note the flags here MUST match the firmware defaults, rather
+                * then the request_irq flags, otherwise we get an EBUSY error.
+                */
+               soc_dts_thres_irq = acpi_register_gsi(NULL, soc_dts_thres_gsi,
+                                                     ACPI_LEVEL_SENSITIVE,
+                                                     ACPI_ACTIVE_LOW);
+               if (soc_dts_thres_irq < 0) {
+                       pr_warn("intel_soc_dts: Could not get IRQ for GSI %d, err %d\n",
+                               soc_dts_thres_gsi, soc_dts_thres_irq);
+                       soc_dts_thres_irq = 0;
+               }
+       }
 
        if (soc_dts_thres_irq) {
                err = request_threaded_irq(soc_dts_thres_irq, NULL,
@@ -90,8 +106,10 @@ static int __init intel_soc_thermal_init(void)
        return 0;
 
 error_trips:
-       if (soc_dts_thres_irq)
+       if (soc_dts_thres_irq) {
                free_irq(soc_dts_thres_irq, soc_dts);
+               acpi_unregister_gsi(soc_dts_thres_gsi);
+       }
        intel_soc_dts_iosf_exit(soc_dts);
 
        return err;
@@ -99,8 +117,10 @@ error_trips:
 
 static void __exit intel_soc_thermal_exit(void)
 {
-       if (soc_dts_thres_irq)
+       if (soc_dts_thres_irq) {
                free_irq(soc_dts_thres_irq, soc_dts);
+               acpi_unregister_gsi(soc_dts_thres_gsi);
+       }
        intel_soc_dts_iosf_exit(soc_dts);
 }
 
index f631f8b..77baf89 100644 (file)
@@ -52,6 +52,7 @@ static u32 hvc_opal_boot_termno;
 static const struct hv_ops hvc_opal_raw_ops = {
        .get_chars = opal_get_chars,
        .put_chars = opal_put_chars,
+       .flush = opal_flush_chars,
        .notifier_add = notifier_add_irq,
        .notifier_del = notifier_del_irq,
        .notifier_hangup = notifier_hangup_irq,
@@ -141,6 +142,7 @@ static int hvc_opal_hvsi_tiocmset(struct hvc_struct *hp, unsigned int set,
 static const struct hv_ops hvc_opal_hvsi_ops = {
        .get_chars = hvc_opal_hvsi_get_chars,
        .put_chars = hvc_opal_hvsi_put_chars,
+       .flush = opal_flush_chars,
        .notifier_add = hvc_opal_hvsi_open,
        .notifier_del = hvc_opal_hvsi_close,
        .notifier_hangup = hvc_opal_hvsi_hangup,
index 6364890..06ed20d 100644 (file)
@@ -348,7 +348,7 @@ static void send_sig_all(int sig)
                if (is_global_init(p))
                        continue;
 
-               do_send_sig_info(sig, SEND_SIG_FORCED, p, true);
+               do_send_sig_info(sig, SEND_SIG_FORCED, p, PIDTYPE_MAX);
        }
        read_unlock(&tasklist_lock);
 }
index 11c2df9..32bc3e3 100644 (file)
@@ -2113,7 +2113,7 @@ static int __tty_fasync(int fd, struct file *filp, int on)
                        type = PIDTYPE_PGID;
                } else {
                        pid = task_pid(current);
-                       type = PIDTYPE_PID;
+                       type = PIDTYPE_TGID;
                }
                get_pid(pid);
                spin_unlock_irqrestore(&tty->ctrl_lock, flags);
index d9145a8..8e3bab1 100644 (file)
@@ -161,16 +161,10 @@ static int exynos_ehci_probe(struct platform_device *pdev)
        }
        exynos_ehci = to_exynos_ehci(hcd);
 
-       if (of_device_is_compatible(pdev->dev.of_node,
-                                       "samsung,exynos5440-ehci"))
-               goto skip_phy;
-
        err = exynos_ehci_get_phy(&pdev->dev, exynos_ehci);
        if (err)
                goto fail_clk;
 
-skip_phy:
-
        exynos_ehci->clk = devm_clk_get(&pdev->dev, "usbhost");
 
        if (IS_ERR(exynos_ehci->clk)) {
@@ -304,7 +298,6 @@ static const struct dev_pm_ops exynos_ehci_pm_ops = {
 #ifdef CONFIG_OF
 static const struct of_device_id exynos_ehci_match[] = {
        { .compatible = "samsung,exynos4210-ehci" },
-       { .compatible = "samsung,exynos5440-ehci" },
        {},
 };
 MODULE_DEVICE_TABLE(of, exynos_ehci_match);
index a39fae4..c0c4dcc 100644 (file)
@@ -130,15 +130,10 @@ static int exynos_ohci_probe(struct platform_device *pdev)
 
        exynos_ohci = to_exynos_ohci(hcd);
 
-       if (of_device_is_compatible(pdev->dev.of_node,
-                                       "samsung,exynos5440-ohci"))
-               goto skip_phy;
-
        err = exynos_ohci_get_phy(&pdev->dev, exynos_ohci);
        if (err)
                goto fail_clk;
 
-skip_phy:
        exynos_ohci->clk = devm_clk_get(&pdev->dev, "usbhost");
 
        if (IS_ERR(exynos_ohci->clk)) {
@@ -270,7 +265,6 @@ static const struct dev_pm_ops exynos_ohci_pm_ops = {
 #ifdef CONFIG_OF
 static const struct of_device_id exynos_ohci_match[] = {
        { .compatible = "samsung,exynos4210-ohci" },
-       { .compatible = "samsung,exynos5440-ohci" },
        {},
 };
 MODULE_DEVICE_TABLE(of, exynos_ohci_match);
index cfdecea..b580885 100644 (file)
@@ -12,7 +12,7 @@ config VHOST_NET
 
 config VHOST_SCSI
        tristate "VHOST_SCSI TCM fabric driver"
-       depends on TARGET_CORE && EVENTFD && m
+       depends on TARGET_CORE && EVENTFD
        select VHOST
        default n
        ---help---
index 76f8d64..c24bb69 100644 (file)
@@ -55,7 +55,7 @@
 #define VHOST_SCSI_DEFAULT_TAGS 256
 #define VHOST_SCSI_PREALLOC_SGLS 2048
 #define VHOST_SCSI_PREALLOC_UPAGES 2048
-#define VHOST_SCSI_PREALLOC_PROT_SGLS 512
+#define VHOST_SCSI_PREALLOC_PROT_SGLS 2048
 
 struct vhost_scsi_inflight {
        /* Wait for the flush operation to finish */
index 16119bd..f1dc41c 100644 (file)
@@ -690,6 +690,7 @@ static int adp8860_probe(struct i2c_client *client,
        switch (ADP8860_MANID(reg_val)) {
        case ADP8863_MANUFID:
                data->gdwn_dis = !!pdata->gdwn_dis;
+               /* fall through */
        case ADP8860_MANUFID:
                data->en_ambl_sens = !!pdata->en_ambl_sens;
                break;
index 44ac5bd..bdfcc0a 100644 (file)
@@ -143,11 +143,116 @@ 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.
+ *
+ * The CIE 1931 lightness formula is what actually describes how we perceive
+ * light:
+ *          Y = (L* / 902.3)           if L* ≤ 0.08856
+ *          Y = ((L* + 16) / 116)^3    if L* > 0.08856
+ *
+ * Where Y is the luminance, the amount of light coming out of the screen, and
+ * is a number between 0.0 and 1.0; and L* is the lightness, how bright a human
+ * perceives the screen to be, and is a number between 0 and 100.
+ *
+ * The following function does the fixed point maths needed to implement the
+ * above formula.
+ */
+static u64 cie1931(unsigned int lightness, unsigned int scale)
+{
+       u64 retval;
+
+       lightness *= 100;
+       if (lightness <= (8 * scale)) {
+               retval = DIV_ROUND_CLOSEST_ULL(lightness * 10, 9023);
+       } else {
+               retval = int_pow((lightness + (16 * scale)) / 116, 3);
+               retval = DIV_ROUND_CLOSEST_ULL(retval, (scale * scale));
+       }
+
+       return retval;
+}
+
+/*
+ * Create a default correction table for PWM values to create linear brightness
+ * for LED based backlights using the CIE1931 algorithm.
+ */
+static
+int pwm_backlight_brightness_default(struct device *dev,
+                                    struct platform_pwm_backlight_data *data,
+                                    unsigned int period)
+{
+       unsigned int counter = 0;
+       unsigned int i, n;
+       u64 retval;
+
+       /*
+        * Count the number of bits needed to represent the period number. The
+        * number of bits is used to calculate the number of levels used for the
+        * brightness-levels table, the purpose of this calculation is have a
+        * pre-computed table with enough levels to get linear brightness
+        * perception. The period is divided by the number of bits so for a
+        * 8-bit PWM we have 255 / 8 = 32 brightness levels or for a 16-bit PWM
+        * we have 65535 / 16 = 4096 brightness levels.
+        *
+        * Note that this method is based on empirical testing on different
+        * devices with PWM of 8 and 16 bits of resolution.
+        */
+       n = period;
+       while (n) {
+               counter += n % 2;
+               n >>= 1;
+       }
+
+       data->max_brightness = DIV_ROUND_UP(period, counter);
+       data->levels = devm_kcalloc(dev, data->max_brightness,
+                                   sizeof(*data->levels), GFP_KERNEL);
+       if (!data->levels)
+               return -ENOMEM;
+
+       /* Fill the table using the cie1931 algorithm */
+       for (i = 0; i < data->max_brightness; i++) {
+               retval = cie1931((i * PWM_LUMINANCE_SCALE) /
+                                data->max_brightness, PWM_LUMINANCE_SCALE) *
+                                period;
+               retval = DIV_ROUND_CLOSEST_ULL(retval, PWM_LUMINANCE_SCALE);
+               if (retval > UINT_MAX)
+                       return -EINVAL;
+               data->levels[i] = (unsigned int)retval;
+       }
+
+       data->dft_brightness = data->max_brightness / 2;
+       data->max_brightness--;
+
+       return 0;
+}
+
 static int pwm_backlight_parse_dt(struct device *dev,
                                  struct platform_pwm_backlight_data *data)
 {
        struct device_node *node = dev->of_node;
+       unsigned int num_levels = 0;
+       unsigned int levels_count;
+       unsigned int num_steps = 0;
        struct property *prop;
+       unsigned int *table;
        int length;
        u32 value;
        int ret;
@@ -157,16 +262,20 @@ static int pwm_backlight_parse_dt(struct device *dev,
 
        memset(data, 0, sizeof(*data));
 
-       /* determine the number of brightness levels */
+       /*
+        * Determine the number of brightness levels, if this property is not
+        * set a default table of brightness levels will be used.
+        */
        prop = of_find_property(node, "brightness-levels", &length);
        if (!prop)
-               return -EINVAL;
+               return 0;
 
        data->max_brightness = length / sizeof(u32);
 
        /* read brightness levels from DT property */
        if (data->max_brightness > 0) {
                size_t size = sizeof(*data->levels) * data->max_brightness;
+               unsigned int i, j, n = 0;
 
                data->levels = devm_kzalloc(dev, size, GFP_KERNEL);
                if (!data->levels)
@@ -184,6 +293,84 @@ static int pwm_backlight_parse_dt(struct device *dev,
                        return ret;
 
                data->dft_brightness = value;
+
+               /*
+                * This property is optional, if is set enables linear
+                * interpolation between each of the values of brightness levels
+                * and creates a new pre-computed table.
+                */
+               of_property_read_u32(node, "num-interpolated-steps",
+                                    &num_steps);
+
+               /*
+                * Make sure that there is at least two entries in the
+                * brightness-levels table, otherwise we can't interpolate
+                * between two points.
+                */
+               if (num_steps) {
+                       if (data->max_brightness < 2) {
+                               dev_err(dev, "can't interpolate\n");
+                               return -EINVAL;
+                       }
+
+                       /*
+                        * Recalculate the number of brightness levels, now
+                        * taking in consideration the number of interpolated
+                        * steps between two levels.
+                        */
+                       for (i = 0; i < data->max_brightness - 1; i++) {
+                               if ((data->levels[i + 1] - data->levels[i]) /
+                                  num_steps)
+                                       num_levels += num_steps;
+                               else
+                                       num_levels++;
+                       }
+                       num_levels++;
+                       dev_dbg(dev, "new number of brightness levels: %d\n",
+                               num_levels);
+
+                       /*
+                        * Create a new table of brightness levels with all the
+                        * interpolated steps.
+                        */
+                       size = sizeof(*table) * num_levels;
+                       table = devm_kzalloc(dev, size, GFP_KERNEL);
+                       if (!table)
+                               return -ENOMEM;
+
+                       /* Fill the interpolated table. */
+                       levels_count = 0;
+                       for (i = 0; i < data->max_brightness - 1; i++) {
+                               value = data->levels[i];
+                               n = (data->levels[i + 1] - value) / num_steps;
+                               if (n > 0) {
+                                       for (j = 0; j < num_steps; j++) {
+                                               table[levels_count] = value;
+                                               value += n;
+                                               levels_count++;
+                                       }
+                               } else {
+                                       table[levels_count] = data->levels[i];
+                                       levels_count++;
+                               }
+                       }
+                       table[levels_count] = data->levels[i];
+
+                       /*
+                        * As we use interpolation lets remove current
+                        * brightness levels table and replace for the
+                        * new interpolated table.
+                        */
+                       devm_kfree(dev, data->levels);
+                       data->levels = table;
+
+                       /*
+                        * Reassign max_brightness value to the new total number
+                        * of brightness levels.
+                        */
+                       data->max_brightness = num_levels;
+               }
+
                data->max_brightness--;
        }
 
@@ -211,6 +398,14 @@ static int pwm_backlight_parse_dt(struct device *dev,
 {
        return -ENODEV;
 }
+
+static
+int pwm_backlight_brightness_default(struct device *dev,
+                                    struct platform_pwm_backlight_data *data,
+                                    unsigned int period)
+{
+       return -ENODEV;
+}
 #endif
 
 static int pwm_backlight_initial_power_state(const struct pwm_bl_data *pb)
@@ -251,7 +446,9 @@ static int pwm_backlight_probe(struct platform_device *pdev)
        struct backlight_device *bl;
        struct device_node *node = pdev->dev.of_node;
        struct pwm_bl_data *pb;
+       struct pwm_state state;
        struct pwm_args pargs;
+       unsigned int i;
        int ret;
 
        if (!data) {
@@ -276,17 +473,6 @@ static int pwm_backlight_probe(struct platform_device *pdev)
                goto err_alloc;
        }
 
-       if (data->levels) {
-               unsigned int i;
-
-               for (i = 0; i <= data->max_brightness; i++)
-                       if (data->levels[i] > pb->scale)
-                               pb->scale = data->levels[i];
-
-               pb->levels = data->levels;
-       } else
-               pb->scale = data->max_brightness;
-
        pb->notify = data->notify;
        pb->notify_after = data->notify_after;
        pb->check_fb = data->check_fb;
@@ -353,6 +539,26 @@ static int pwm_backlight_probe(struct platform_device *pdev)
 
        dev_dbg(&pdev->dev, "got pwm for backlight\n");
 
+       if (!data->levels) {
+               /* Get the PWM period (in nanoseconds) */
+               pwm_get_state(pb->pwm, &state);
+
+               ret = pwm_backlight_brightness_default(&pdev->dev, data,
+                                                      state.period);
+               if (ret < 0) {
+                       dev_err(&pdev->dev,
+                               "failed to setup default brightness table\n");
+                       goto err_alloc;
+               }
+       }
+
+       for (i = 0; i <= data->max_brightness; i++) {
+               if (data->levels[i] > pb->scale)
+                       pb->scale = data->levels[i];
+
+               pb->levels = data->levels;
+       }
+
        /*
         * FIXME: pwm_apply_args() should be removed when switching to
         * the atomic PWM API.
index e91edef..787792c 100644 (file)
@@ -152,7 +152,7 @@ config FRAMEBUFFER_CONSOLE_ROTATION
 
 config FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER
        bool "Framebuffer Console Deferred Takeover"
-       depends on FRAMEBUFFER_CONSOLE=y && DUMMY_CONSOLE=y
+       depends on FB=y && FRAMEBUFFER_CONSOLE && DUMMY_CONSOLE
        help
          If enabled this defers the framebuffer console taking over the
          console from the dummy console until the first text is displayed on
index 0254251..45ad925 100644 (file)
@@ -38,13 +38,11 @@ void dummycon_register_output_notifier(struct notifier_block *nb)
        if (dummycon_putc_called)
                nb->notifier_call(nb, 0, NULL);
 }
-EXPORT_SYMBOL_GPL(dummycon_register_output_notifier);
 
 void dummycon_unregister_output_notifier(struct notifier_block *nb)
 {
        raw_notifier_chain_unregister(&dummycon_output_nh, nb);
 }
-EXPORT_SYMBOL_GPL(dummycon_unregister_output_notifier);
 
 static void dummycon_putc(struct vc_data *vc, int c, int ypos, int xpos)
 {
index f09e17b..09731b2 100644 (file)
@@ -112,6 +112,11 @@ EXPORT_SYMBOL(vgacon_text_force);
 static int __init text_mode(char *str)
 {
        vgacon_text_mode_force = true;
+
+       pr_warning("You have booted with nomodeset. This means your GPU drivers are DISABLED\n");
+       pr_warning("Any video related functionality will be severely degraded, and you may not even be able to suspend the system properly\n");
+       pr_warning("Unless you actually understand what nomodeset does, you should reboot without enabling it\n");
+
        return 1;
 }
 
index cc11c60..0777aff 100644 (file)
@@ -2303,7 +2303,7 @@ static void ami_build_copper(struct fb_info *info)
        ami_rebuild_copper(info->par);
 }
 
-
+#ifndef MODULE
 static void __init amifb_setup_mcap(char *spec)
 {
        char *p;
@@ -2368,7 +2368,7 @@ static int __init amifb_setup(char *options)
 
        return 0;
 }
-
+#endif
 
 static int amifb_check_var(struct fb_var_screeninfo *var,
                           struct fb_info *info)
index 5fb156b..75ebbbf 100644 (file)
@@ -2234,8 +2234,8 @@ static int fbcon_switch(struct vc_data *vc)
         *
         * info->currcon = vc->vc_num;
         */
-       for (i = 0; i < FB_MAX; i++) {
-               if (registered_fb[i] != NULL && registered_fb[i]->fbcon_par) {
+       for_each_registered_fb(i) {
+               if (registered_fb[i]->fbcon_par) {
                        struct fbcon_ops *o = registered_fb[i]->fbcon_par;
 
                        o->currcon = vc->vc_num;
@@ -3124,11 +3124,9 @@ static int fbcon_fb_unregistered(struct fb_info *info)
        if (idx == info_idx) {
                info_idx = -1;
 
-               for (i = 0; i < FB_MAX; i++) {
-                       if (registered_fb[i] != NULL) {
-                               info_idx = i;
-                               break;
-                       }
+               for_each_registered_fb(i) {
+                       info_idx = i;
+                       break;
                }
        }
 
@@ -3594,13 +3592,24 @@ static int fbcon_init_device(void)
 }
 
 #ifdef CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER
+static void fbcon_register_existing_fbs(struct work_struct *work)
+{
+       int i;
+
+       console_lock();
+
+       for_each_registered_fb(i)
+               fbcon_fb_registered(registered_fb[i]);
+
+       console_unlock();
+}
+
 static struct notifier_block fbcon_output_nb;
+static DECLARE_WORK(fbcon_deferred_takeover_work, fbcon_register_existing_fbs);
 
 static int fbcon_output_notifier(struct notifier_block *nb,
                                 unsigned long action, void *data)
 {
-       int i;
-
        WARN_CONSOLE_UNLOCKED();
 
        pr_info("fbcon: Taking over console\n");
@@ -3609,45 +3618,37 @@ static int fbcon_output_notifier(struct notifier_block *nb,
        deferred_takeover = false;
        logo_shown = FBCON_LOGO_DONTSHOW;
 
-       for (i = 0; i < FB_MAX; i++) {
-               if (registered_fb[i])
-                       fbcon_fb_registered(registered_fb[i]);
-       }
+       /* We may get called in atomic context */
+       schedule_work(&fbcon_deferred_takeover_work);
 
        return NOTIFY_OK;
 }
-
-static void fbcon_register_output_notifier(void)
-{
-       fbcon_output_nb.notifier_call = fbcon_output_notifier;
-       dummycon_register_output_notifier(&fbcon_output_nb);
-}
-#else
-static inline void fbcon_register_output_notifier(void) {}
 #endif
 
 static void fbcon_start(void)
 {
+       WARN_CONSOLE_UNLOCKED();
+
+#ifdef CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER
+       if (conswitchp != &dummy_con)
+               deferred_takeover = false;
+
        if (deferred_takeover) {
-               fbcon_register_output_notifier();
+               fbcon_output_nb.notifier_call = fbcon_output_notifier;
+               dummycon_register_output_notifier(&fbcon_output_nb);
                return;
        }
+#endif
 
        if (num_registered_fb) {
                int i;
 
-               console_lock();
-
-               for (i = 0; i < FB_MAX; i++) {
-                       if (registered_fb[i] != NULL) {
-                               info_idx = i;
-                               break;
-                       }
+               for_each_registered_fb(i) {
+                       info_idx = i;
+                       break;
                }
 
                do_fbcon_takeover(0);
-               console_unlock();
-
        }
 }
 
@@ -3669,15 +3670,12 @@ static void fbcon_exit(void)
        kfree((void *)softback_buf);
        softback_buf = 0UL;
 
-       for (i = 0; i < FB_MAX; i++) {
+       for_each_registered_fb(i) {
                int pending = 0;
 
                mapped = 0;
                info = registered_fb[i];
 
-               if (info == NULL)
-                       continue;
-
                if (info->queue.func)
                        pending = cancel_work_sync(&info->queue);
                DPRINTK("fbcon: %s pending work\n", (pending ? "canceled" :
@@ -3733,8 +3731,8 @@ void __init fb_console_init(void)
        for (i = 0; i < MAX_NR_CONSOLES; i++)
                con2fb_map[i] = -1;
 
-       console_unlock();
        fbcon_start();
+       console_unlock();
 }
 
 #ifdef MODULE
index 609438d..2040542 100644 (file)
@@ -1347,6 +1347,7 @@ static long fb_compat_ioctl(struct file *file, unsigned int cmd,
        case FBIOGET_CON2FBMAP:
        case FBIOPUT_CON2FBMAP:
                arg = (unsigned long) compat_ptr(arg);
+               /* fall through */
        case FBIOBLANK:
                ret = do_fb_ioctl(info, cmd, arg);
                break;
@@ -1593,10 +1594,8 @@ static int do_remove_conflicting_framebuffers(struct apertures_struct *a,
        int i, ret;
 
        /* check all firmware fbs and kick off if the base addr overlaps */
-       for (i = 0 ; i < FB_MAX; i++) {
+       for_each_registered_fb(i) {
                struct apertures_struct *gen_aper;
-               if (!registered_fb[i])
-                       continue;
 
                if (!(registered_fb[i]->flags & FBINFO_MISC_FIRMWARE))
                        continue;
@@ -1691,25 +1690,30 @@ static int do_register_framebuffer(struct fb_info *fb_info)
        event.info = fb_info;
        if (!lockless_register_fb)
                console_lock();
+       else
+               atomic_inc(&ignore_console_lock_warning);
        if (!lock_fb_info(fb_info)) {
-               if (!lockless_register_fb)
-                       console_unlock();
-               return -ENODEV;
+               ret = -ENODEV;
+               goto unlock_console;
        }
+       ret = 0;
 
        fb_notifier_call_chain(FB_EVENT_FB_REGISTERED, &event);
        unlock_fb_info(fb_info);
+unlock_console:
        if (!lockless_register_fb)
                console_unlock();
-       return 0;
+       else
+               atomic_dec(&ignore_console_lock_warning);
+       return ret;
 }
 
-static int do_unregister_framebuffer(struct fb_info *fb_info)
+static int unbind_console(struct fb_info *fb_info)
 {
        struct fb_event event;
-       int i, ret = 0;
+       int ret;
+       int i = fb_info->node;
 
-       i = fb_info->node;
        if (i < 0 || i >= FB_MAX || registered_fb[i] != fb_info)
                return -EINVAL;
 
@@ -1724,17 +1728,29 @@ static int do_unregister_framebuffer(struct fb_info *fb_info)
        unlock_fb_info(fb_info);
        console_unlock();
 
+       return ret;
+}
+
+static int __unlink_framebuffer(struct fb_info *fb_info);
+
+static int do_unregister_framebuffer(struct fb_info *fb_info)
+{
+       struct fb_event event;
+       int ret;
+
+       ret = unbind_console(fb_info);
+
        if (ret)
                return -EINVAL;
 
        pm_vt_switch_unregister(fb_info->dev);
 
-       unlink_framebuffer(fb_info);
+       __unlink_framebuffer(fb_info);
        if (fb_info->pixmap.addr &&
            (fb_info->pixmap.flags & FB_PIXMAP_DEFAULT))
                kfree(fb_info->pixmap.addr);
        fb_destroy_modelist(&fb_info->modelist);
-       registered_fb[i] = NULL;
+       registered_fb[fb_info->node] = NULL;
        num_registered_fb--;
        fb_cleanup_device(fb_info);
        event.info = fb_info;
@@ -1747,7 +1763,7 @@ static int do_unregister_framebuffer(struct fb_info *fb_info)
        return 0;
 }
 
-int unlink_framebuffer(struct fb_info *fb_info)
+static int __unlink_framebuffer(struct fb_info *fb_info)
 {
        int i;
 
@@ -1759,6 +1775,20 @@ int unlink_framebuffer(struct fb_info *fb_info)
                device_destroy(fb_class, MKDEV(FB_MAJOR, i));
                fb_info->dev = NULL;
        }
+
+       return 0;
+}
+
+int unlink_framebuffer(struct fb_info *fb_info)
+{
+       int ret;
+
+       ret = __unlink_framebuffer(fb_info);
+       if (ret)
+               return ret;
+
+       unbind_console(fb_info);
+
        return 0;
 }
 EXPORT_SYMBOL(unlink_framebuffer);
index 2510fa7..283d930 100644 (file)
@@ -628,45 +628,47 @@ static int fb_try_mode(struct fb_var_screeninfo *var, struct fb_info *info,
 }
 
 /**
- *     fb_find_mode - finds a valid video mode
- *     @var: frame buffer user defined part of display
- *     @info: frame buffer info structure
- *     @mode_option: string video mode to find
- *     @db: video mode database
- *     @dbsize: size of @db
- *     @default_mode: default video mode to fall back to
- *     @default_bpp: default color depth in bits per pixel
+ * fb_find_mode - finds a valid video mode
+ * @var: frame buffer user defined part of display
+ * @info: frame buffer info structure
+ * @mode_option: string video mode to find
+ * @db: video mode database
+ * @dbsize: size of @db
+ * @default_mode: default video mode to fall back to
+ * @default_bpp: default color depth in bits per pixel
  *
- *     Finds a suitable video mode, starting with the specified mode
- *     in @mode_option with fallback to @default_mode.  If
- *     @default_mode fails, all modes in the video mode database will
- *     be tried.
+ * Finds a suitable video mode, starting with the specified mode
+ * in @mode_option with fallback to @default_mode.  If
+ * @default_mode fails, all modes in the video mode database will
+ * be tried.
  *
- *     Valid mode specifiers for @mode_option:
+ * Valid mode specifiers for @mode_option::
  *
- *     <xres>x<yres>[M][R][-<bpp>][@<refresh>][i][m] or
- *     <name>[-<bpp>][@<refresh>]
+ *     <xres>x<yres>[M][R][-<bpp>][@<refresh>][i][p][m]
+ *
+ * or ::
  *
- *     with <xres>, <yres>, <bpp> and <refresh> decimal numbers and
- *     <name> a string.
+ *     <name>[-<bpp>][@<refresh>]
  *
- *      If 'M' is present after yres (and before refresh/bpp if present),
- *      the function will compute the timings using VESA(tm) Coordinated
- *      Video Timings (CVT).  If 'R' is present after 'M', will compute with
- *      reduced blanking (for flatpanels).  If 'i' is present, compute
- *      interlaced mode.  If 'm' is present, add margins equal to 1.8%
- *      of xres rounded down to 8 pixels, and 1.8% of yres. The char
- *      'i' and 'm' must be after 'M' and 'R'. Example:
+ * with <xres>, <yres>, <bpp> and <refresh> decimal numbers and
+ * <name> a string.
  *
- *      1024x768MR-8@60m - Reduced blank with margins at 60Hz.
+ * If 'M' is present after yres (and before refresh/bpp if present),
+ * the function will compute the timings using VESA(tm) Coordinated
+ * Video Timings (CVT).  If 'R' is present after 'M', will compute with
+ * reduced blanking (for flatpanels).  If 'i' or 'p' are present, compute
+ * interlaced or progressive mode.  If 'm' is present, add margins equal
+ * to 1.8% of xres rounded down to 8 pixels, and 1.8% of yres. The char
+ * 'i', 'p' and 'm' must be after 'M' and 'R'. Example::
  *
- *     NOTE: The passed struct @var is _not_ cleared!  This allows you
- *     to supply values for e.g. the grayscale and accel_flags fields.
+ *     1024x768MR-8@60m - Reduced blank with margins at 60Hz.
  *
- *     Returns zero for failure, 1 if using specified @mode_option,
- *     2 if using specified @mode_option with an ignored refresh rate,
- *     3 if default mode is used, 4 if fall back to any valid mode.
+ * NOTE: The passed struct @var is _not_ cleared!  This allows you
+ * to supply values for e.g. the grayscale and accel_flags fields.
  *
+ * Returns zero for failure, 1 if using specified @mode_option,
+ * 2 if using specified @mode_option with an ignored refresh rate,
+ * 3 if default mode is used, 4 if fall back to any valid mode.
  */
 
 int fb_find_mode(struct fb_var_screeninfo *var,
@@ -697,7 +699,8 @@ int fb_find_mode(struct fb_var_screeninfo *var,
                unsigned int namelen = strlen(name);
                int res_specified = 0, bpp_specified = 0, refresh_specified = 0;
                unsigned int xres = 0, yres = 0, bpp = default_bpp, refresh = 0;
-               int yres_specified = 0, cvt = 0, rb = 0, interlace = 0;
+               int yres_specified = 0, cvt = 0, rb = 0;
+               int interlace_specified = 0, interlace = 0;
                int margins = 0;
                u32 best, diff, tdiff;
 
@@ -748,9 +751,17 @@ int fb_find_mode(struct fb_var_screeninfo *var,
                                if (!cvt)
                                        margins = 1;
                                break;
+                       case 'p':
+                               if (!cvt) {
+                                       interlace = 0;
+                                       interlace_specified = 1;
+                               }
+                               break;
                        case 'i':
-                               if (!cvt)
+                               if (!cvt) {
                                        interlace = 1;
+                                       interlace_specified = 1;
+                               }
                                break;
                        default:
                                goto done;
@@ -819,11 +830,21 @@ done:
                        if ((name_matches(db[i], name, namelen) ||
                             (res_specified && res_matches(db[i], xres, yres))) &&
                            !fb_try_mode(var, info, &db[i], bpp)) {
-                               if (refresh_specified && db[i].refresh == refresh)
-                                       return 1;
+                               const int db_interlace = (db[i].vmode &
+                                       FB_VMODE_INTERLACED ? 1 : 0);
+                               int score = abs(db[i].refresh - refresh);
+
+                               if (interlace_specified)
+                                       score += abs(db_interlace - interlace);
+
+                               if (!interlace_specified ||
+                                   db_interlace == interlace)
+                                       if (refresh_specified &&
+                                           db[i].refresh == refresh)
+                                               return 1;
 
-                               if (abs(db[i].refresh - refresh) < diff) {
-                                       diff = abs(db[i].refresh - refresh);
+                               if (score < diff) {
+                                       diff = score;
                                        best = i;
                                }
                        }
index c6f78d2..3946649 100644 (file)
@@ -9,16 +9,39 @@
 
 #include <linux/kernel.h>
 #include <linux/efi.h>
+#include <linux/efi-bgrt.h>
 #include <linux/errno.h>
 #include <linux/fb.h>
 #include <linux/pci.h>
 #include <linux/platform_device.h>
+#include <linux/printk.h>
 #include <linux/screen_info.h>
 #include <video/vga.h>
 #include <asm/efi.h>
 #include <drm/drm_utils.h> /* For drm_get_panel_orientation_quirk */
 #include <drm/drm_connector.h>  /* For DRM_MODE_PANEL_ORIENTATION_* */
 
+struct bmp_file_header {
+       u16 id;
+       u32 file_size;
+       u32 reserved;
+       u32 bitmap_offset;
+} __packed;
+
+struct bmp_dib_header {
+       u32 dib_header_size;
+       s32 width;
+       s32 height;
+       u16 planes;
+       u16 bpp;
+       u32 compression;
+       u32 bitmap_size;
+       u32 horz_resolution;
+       u32 vert_resolution;
+       u32 colors_used;
+       u32 colors_important;
+} __packed;
+
 static bool request_mem_succeeded = false;
 static u64 mem_flags = EFI_MEMORY_WC | EFI_MEMORY_UC;
 
@@ -66,6 +89,164 @@ static int efifb_setcolreg(unsigned regno, unsigned red, unsigned green,
        return 0;
 }
 
+/*
+ * If fbcon deffered console takeover is configured, the intent is for the
+ * framebuffer to show the boot graphics (e.g. vendor logo) until there is some
+ * (error) message to display. But the boot graphics may have been destroyed by
+ * e.g. option ROM output, detect this and restore the boot graphics.
+ */
+#if defined CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER && \
+    defined CONFIG_ACPI_BGRT
+static void efifb_copy_bmp(u8 *src, u32 *dst, int width, struct screen_info *si)
+{
+       u8 r, g, b;
+
+       while (width--) {
+               b = *src++;
+               g = *src++;
+               r = *src++;
+               *dst++ = (r << si->red_pos)   |
+                        (g << si->green_pos) |
+                        (b << si->blue_pos);
+       }
+}
+
+#ifdef CONFIG_X86
+/*
+ * On x86 some firmwares use a low non native resolution for the display when
+ * they have shown some text messages. While keeping the bgrt filled with info
+ * for the native resolution. If the bgrt image intended for the native
+ * resolution still fits, it will be displayed very close to the right edge of
+ * the display looking quite bad. This function checks for this.
+ */
+static bool efifb_bgrt_sanity_check(struct screen_info *si, u32 bmp_width)
+{
+       static const int default_resolutions[][2] = {
+               {  800,  600 },
+               { 1024,  768 },
+               { 1280, 1024 },
+       };
+       u32 i, right_margin;
+
+       for (i = 0; i < ARRAY_SIZE(default_resolutions); i++) {
+               if (default_resolutions[i][0] == si->lfb_width &&
+                   default_resolutions[i][1] == si->lfb_height)
+                       break;
+       }
+       /* If not a default resolution used for textmode, this should be fine */
+       if (i >= ARRAY_SIZE(default_resolutions))
+               return true;
+
+       /* If the right margin is 5 times smaller then the left one, reject */
+       right_margin = si->lfb_width - (bgrt_tab.image_offset_x + bmp_width);
+       if (right_margin < (bgrt_tab.image_offset_x / 5))
+               return false;
+
+       return true;
+}
+#else
+static bool efifb_bgrt_sanity_check(struct screen_info *si, u32 bmp_width)
+{
+       return true;
+}
+#endif
+
+static void efifb_show_boot_graphics(struct fb_info *info)
+{
+       u32 bmp_width, bmp_height, bmp_pitch, screen_pitch, dst_x, y, src_y;
+       struct screen_info *si = &screen_info;
+       struct bmp_file_header *file_header;
+       struct bmp_dib_header *dib_header;
+       void *bgrt_image = NULL;
+       u8 *dst = info->screen_base;
+
+       if (!bgrt_tab.image_address) {
+               pr_info("efifb: No BGRT, not showing boot graphics\n");
+               return;
+       }
+
+       /* Avoid flashing the logo if we're going to print std probe messages */
+       if (console_loglevel > CONSOLE_LOGLEVEL_QUIET)
+               return;
+
+       /* bgrt_tab.status is unreliable, so we don't check it */
+
+       if (si->lfb_depth != 32) {
+               pr_info("efifb: not 32 bits, not showing boot graphics\n");
+               return;
+       }
+
+       bgrt_image = memremap(bgrt_tab.image_address, bgrt_image_size,
+                             MEMREMAP_WB);
+       if (!bgrt_image) {
+               pr_warn("efifb: Ignoring BGRT: failed to map image memory\n");
+               return;
+       }
+
+       if (bgrt_image_size < (sizeof(*file_header) + sizeof(*dib_header)))
+               goto error;
+
+       file_header = bgrt_image;
+       if (file_header->id != 0x4d42 || file_header->reserved != 0)
+               goto error;
+
+       dib_header = bgrt_image + sizeof(*file_header);
+       if (dib_header->dib_header_size != 40 || dib_header->width < 0 ||
+           dib_header->planes != 1 || dib_header->bpp != 24 ||
+           dib_header->compression != 0)
+               goto error;
+
+       bmp_width = dib_header->width;
+       bmp_height = abs(dib_header->height);
+       bmp_pitch = round_up(3 * bmp_width, 4);
+       screen_pitch = si->lfb_linelength;
+
+       if ((file_header->bitmap_offset + bmp_pitch * bmp_height) >
+                               bgrt_image_size)
+               goto error;
+
+       if ((bgrt_tab.image_offset_x + bmp_width) > si->lfb_width ||
+           (bgrt_tab.image_offset_y + bmp_height) > si->lfb_height)
+               goto error;
+
+       if (!efifb_bgrt_sanity_check(si, bmp_width))
+               goto error;
+
+       pr_info("efifb: showing boot graphics\n");
+
+       for (y = 0; y < si->lfb_height; y++, dst += si->lfb_linelength) {
+               /* Only background? */
+               if (y < bgrt_tab.image_offset_y ||
+                   y >= (bgrt_tab.image_offset_y + bmp_height)) {
+                       memset(dst, 0, 4 * si->lfb_width);
+                       continue;
+               }
+
+               src_y = y - bgrt_tab.image_offset_y;
+               /* Positive header height means upside down row order */
+               if (dib_header->height > 0)
+                       src_y = (bmp_height - 1) - src_y;
+
+               memset(dst, 0, bgrt_tab.image_offset_x * 4);
+               dst_x = bgrt_tab.image_offset_x;
+               efifb_copy_bmp(bgrt_image + file_header->bitmap_offset +
+                                           src_y * bmp_pitch,
+                              (u32 *)dst + dst_x, bmp_width, si);
+               dst_x += bmp_width;
+               memset((u32 *)dst + dst_x, 0, (si->lfb_width - dst_x) * 4);
+       }
+
+       memunmap(bgrt_image);
+       return;
+
+error:
+       memunmap(bgrt_image);
+       pr_warn("efifb: Ignoring BGRT: unexpected or invalid BMP data\n");
+}
+#else
+static inline void efifb_show_boot_graphics(struct fb_info *info) {}
+#endif
+
 static void efifb_destroy(struct fb_info *info)
 {
        if (info->screen_base) {
@@ -311,6 +492,8 @@ static int efifb_probe(struct platform_device *dev)
                goto err_release_fb;
        }
 
+       efifb_show_boot_graphics(info);
+
        pr_info("efifb: framebuffer at 0x%lx, using %dk, total %dk\n",
               efifb_fix.smem_start, size_remap/1024, size_total/1024);
        pr_info("efifb: mode is %dx%dx%d, linelength=%d, pages=%d\n",
index 1bfd13c..bc9eb8a 100644 (file)
@@ -360,6 +360,10 @@ struct mfb_info {
  * @ad[]: Area Descriptors for each real AOI
  * @gamma: gamma color table
  * @cursor: hardware cursor data
+ * @blank_cursor: blank cursor for hiding cursor
+ * @next_cursor: scratch space to build load cursor
+ * @edid_data: EDID information buffer
+ * @has_edid: whether or not the EDID buffer is valid
  *
  * This data structure must be allocated with 32-byte alignment, so that the
  * internal fields can be aligned properly.
@@ -381,6 +385,8 @@ struct fsl_diu_data {
        __le16 cursor[MAX_CURS * MAX_CURS] __aligned(32);
        /* Blank cursor data -- used to hide the cursor */
        __le16 blank_cursor[MAX_CURS * MAX_CURS] __aligned(32);
+       /* Scratch cursor data -- used to build new cursor */
+       __le16 next_cursor[MAX_CURS * MAX_CURS] __aligned(32);
        uint8_t edid_data[EDID_LENGTH];
        bool has_edid;
 } __aligned(32);
@@ -1056,13 +1062,17 @@ static int fsl_diu_cursor(struct fb_info *info, struct fb_cursor *cursor)
         * FB_CUR_SETSHAPE - the cursor bitmask has changed
         */
        if (cursor->set & (FB_CUR_SETSHAPE | FB_CUR_SETCMAP | FB_CUR_SETIMAGE)) {
+               /*
+                * Determine the size of the cursor image data.  Normally,
+                * it's 8x16.
+                */
                unsigned int image_size =
-                       DIV_ROUND_UP(cursor->image.width, 8) * cursor->image.height;
+                       DIV_ROUND_UP(cursor->image.width, 8) *
+                       cursor->image.height;
                unsigned int image_words =
                        DIV_ROUND_UP(image_size, sizeof(uint32_t));
                unsigned int bg_idx = cursor->image.bg_color;
                unsigned int fg_idx = cursor->image.fg_color;
-               uint8_t buffer[image_size];
                uint32_t *image, *source, *mask;
                uint16_t fg, bg;
                unsigned int i;
@@ -1070,13 +1080,6 @@ static int fsl_diu_cursor(struct fb_info *info, struct fb_cursor *cursor)
                if (info->state != FBINFO_STATE_RUNNING)
                        return 0;
 
-               /*
-                * Determine the size of the cursor image data.  Normally,
-                * it's 8x16.
-                */
-               image_size = DIV_ROUND_UP(cursor->image.width, 8) *
-                       cursor->image.height;
-
                bg = ((info->cmap.red[bg_idx] & 0xf8) << 7) |
                     ((info->cmap.green[bg_idx] & 0xf8) << 2) |
                     ((info->cmap.blue[bg_idx] & 0xf8) >> 3) |
@@ -1088,7 +1091,7 @@ static int fsl_diu_cursor(struct fb_info *info, struct fb_cursor *cursor)
                     1 << 15;
 
                /* Use 32-bit operations on the data to improve performance */
-               image = (uint32_t *)buffer;
+               image = (uint32_t *)data->next_cursor;
                source = (uint32_t *)cursor->image.data;
                mask = (uint32_t *)cursor->mask;
 
index 3b70044..4377e34 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
 #include <linux/platform_device.h>
+#include <linux/acpi.h>
 
 enum {
        FB_GET_WIDTH        = 0x00,
@@ -124,6 +125,7 @@ static int goldfish_fb_check_var(struct fb_var_screeninfo *var,
 static int goldfish_fb_set_par(struct fb_info *info)
 {
        struct goldfish_fb *fb = container_of(info, struct goldfish_fb, fb);
+
        if (fb->rotation != fb->fb.var.rotate) {
                info->fix.line_length = info->var.xres * 2;
                fb->rotation = fb->fb.var.rotate;
@@ -148,13 +150,14 @@ static int goldfish_fb_pan_display(struct fb_var_screeninfo *var,
        wait_event_timeout(fb->wait,
                        fb->base_update_count != base_update_count, HZ / 15);
        if (fb->base_update_count == base_update_count)
-               pr_err("goldfish_fb_pan_display: timeout waiting for base update\n");
+               pr_err("%s: timeout waiting for base update\n", __func__);
        return 0;
 }
 
 static int goldfish_fb_blank(int blank, struct fb_info *info)
 {
        struct goldfish_fb *fb = container_of(info, struct goldfish_fb, fb);
+
        switch (blank) {
        case FB_BLANK_NORMAL:
                writel(1, fb->reg_base + FB_SET_BLANK);
@@ -234,7 +237,7 @@ static int goldfish_fb_probe(struct platform_device *pdev)
        fb->fb.var.activate     = FB_ACTIVATE_NOW;
        fb->fb.var.height       = readl(fb->reg_base + FB_GET_PHYS_HEIGHT);
        fb->fb.var.width        = readl(fb->reg_base + FB_GET_PHYS_WIDTH);
-       fb->fb.var.pixclock     = 10000;
+       fb->fb.var.pixclock     = 0;
 
        fb->fb.var.red.offset = 11;
        fb->fb.var.red.length = 5;
@@ -301,6 +304,7 @@ static int goldfish_fb_remove(struct platform_device *pdev)
        dma_free_coherent(&pdev->dev, framesize, (void *)fb->fb.screen_base,
                                                fb->fb.fix.smem_start);
        iounmap(fb->reg_base);
+       kfree(fb);
        return 0;
 }
 
@@ -310,12 +314,19 @@ static const struct of_device_id goldfish_fb_of_match[] = {
 };
 MODULE_DEVICE_TABLE(of, goldfish_fb_of_match);
 
+static const struct acpi_device_id goldfish_fb_acpi_match[] = {
+       { "GFSH0004", 0 },
+       { },
+};
+MODULE_DEVICE_TABLE(acpi, goldfish_fb_acpi_match);
+
 static struct platform_driver goldfish_fb_driver = {
        .probe          = goldfish_fb_probe,
        .remove         = goldfish_fb_remove,
        .driver = {
                .name = "goldfish_fb",
                .of_match_table = goldfish_fb_of_match,
+               .acpi_match_table = ACPI_PTR(goldfish_fb_acpi_match),
        }
 };
 
index 7bc5f60..f6d7b04 100644 (file)
@@ -429,6 +429,7 @@ static int i740fb_decode_var(const struct fb_var_screeninfo *var,
                break;
        case 9 ... 15:
                bpp = 15;
+               /* fall through */
        case 16:
                if ((1000000 / var->pixclock) > DACSPEED16) {
                        dev_err(info->device, "requested pixclock %i MHz out of range (max. %i MHz at 15/16bpp)\n",
index 9085e95..bb4fee5 100644 (file)
@@ -233,7 +233,7 @@ static int load_waveform(u8 *mem, size_t size, int m, int t,
 
        /* check temperature range table checksum */
        cksum_idx = sizeof(*wfm_hdr) + wfm_hdr->trc + 1;
-       if (cksum_idx > size)
+       if (cksum_idx >= size)
                return -EINVAL;
        cksum = calc_cksum(sizeof(*wfm_hdr), cksum_idx, mem);
        if (cksum != mem[cksum_idx]) {
@@ -245,7 +245,7 @@ static int load_waveform(u8 *mem, size_t size, int m, int t,
        /* check waveform mode table address checksum */
        wmta = get_unaligned_le32(wfm_hdr->wmta) & 0x00FFFFFF;
        cksum_idx = wmta + m*4 + 3;
-       if (cksum_idx > size)
+       if (cksum_idx >= size)
                return -EINVAL;
        cksum = calc_cksum(cksum_idx - 3, cksum_idx, mem);
        if (cksum != mem[cksum_idx]) {
@@ -257,7 +257,7 @@ static int load_waveform(u8 *mem, size_t size, int m, int t,
        /* check waveform temperature table address checksum */
        tta = get_unaligned_le32(mem + wmta + m * 4) & 0x00FFFFFF;
        cksum_idx = tta + trn*4 + 3;
-       if (cksum_idx > size)
+       if (cksum_idx >= size)
                return -EINVAL;
        cksum = calc_cksum(cksum_idx - 3, cksum_idx, mem);
        if (cksum != mem[cksum_idx]) {
@@ -270,7 +270,7 @@ static int load_waveform(u8 *mem, size_t size, int m, int t,
        metromem buffer. this does runlength decoding of the waveform */
        wfm_idx = get_unaligned_le32(mem + tta + trn * 4) & 0x00FFFFFF;
        owfm_idx = wfm_idx;
-       if (wfm_idx > size)
+       if (wfm_idx >= size)
                return -EINVAL;
        while (wfm_idx < size) {
                unsigned char rl;
@@ -292,7 +292,7 @@ static int load_waveform(u8 *mem, size_t size, int m, int t,
        }
 
        cksum_idx = wfm_idx;
-       if (cksum_idx > size)
+       if (cksum_idx >= size)
                return -EINVAL;
        cksum = calc_cksum(owfm_idx, cksum_idx, mem);
        if (cksum != mem[cksum_idx]) {
index 585f39e..1c75f48 100644 (file)
@@ -958,7 +958,7 @@ int omapfb_register_client(struct omapfb_notifier_block *omapfb_nb,
 {
        int r;
 
-       if ((unsigned)omapfb_nb->plane_idx > OMAPFB_PLANE_NUM)
+       if ((unsigned)omapfb_nb->plane_idx >= OMAPFB_PLANE_NUM)
                return -EINVAL;
 
        if (!notifier_inited) {
index 602edfe..f54c3f5 100644 (file)
@@ -2,5 +2,5 @@
 obj-$(CONFIG_OMAP2_VRFB) += vrfb.o
 obj-y += dss/
 obj-y += displays/
-obj-$(CONFIG_FB_OMAP2) += omapfb.o
-omapfb-y := omapfb-main.o omapfb-sysfs.o omapfb-ioctl.o
+obj-$(CONFIG_FB_OMAP2) += omap2fb.o
+omap2fb-y := omapfb-main.o omapfb-sysfs.o omapfb-ioctl.o
index 3079a3d..47f0459 100644 (file)
@@ -219,7 +219,7 @@ static int tpd_probe_of(struct platform_device *pdev)
 
 static int tpd_probe(struct platform_device *pdev)
 {
-       struct omap_dss_device *in, *dssdev;
+       struct omap_dss_device *dssdev;
        struct panel_drv_data *ddata;
        int r;
        struct gpio_desc *gpio;
@@ -238,25 +238,30 @@ static int tpd_probe(struct platform_device *pdev)
                return -ENODEV;
        }
 
-
        gpio = devm_gpiod_get_index_optional(&pdev->dev, NULL, 0,
                GPIOD_OUT_LOW);
-       if (IS_ERR(gpio))
+       if (IS_ERR(gpio)) {
+               r = PTR_ERR(gpio);
                goto err_gpio;
+       }
 
        ddata->ct_cp_hpd_gpio = gpio;
 
        gpio = devm_gpiod_get_index_optional(&pdev->dev, NULL, 1,
                GPIOD_OUT_LOW);
-       if (IS_ERR(gpio))
+       if (IS_ERR(gpio)) {
+               r = PTR_ERR(gpio);
                goto err_gpio;
+       }
 
        ddata->ls_oe_gpio = gpio;
 
        gpio = devm_gpiod_get_index(&pdev->dev, NULL, 2,
                GPIOD_IN);
-       if (IS_ERR(gpio))
+       if (IS_ERR(gpio)) {
+               r = PTR_ERR(gpio);
                goto err_gpio;
+       }
 
        ddata->hpd_gpio = gpio;
 
@@ -268,8 +273,6 @@ static int tpd_probe(struct platform_device *pdev)
        dssdev->owner = THIS_MODULE;
        dssdev->port_num = 1;
 
-       in = ddata->in;
-
        r = omapdss_register_output(dssdev);
        if (r) {
                dev_err(&pdev->dev, "Failed to register output\n");
index fb605ae..a06d9c2 100644 (file)
@@ -1858,7 +1858,7 @@ static s32 pixinc(int pixels, u8 ps)
                return 1 - (-pixels + 1) * ps;
        else
                BUG();
-               return 0;
+       return 0;
 }
 
 static void calc_vrfb_rotation_offset(u8 rotation, bool mirror,
@@ -1905,6 +1905,7 @@ static void calc_vrfb_rotation_offset(u8 rotation, bool mirror,
                if (color_mode == OMAP_DSS_COLOR_YUV2 ||
                        color_mode == OMAP_DSS_COLOR_UYVY)
                        width = width >> 1;
+               /* fall through */
        case OMAP_DSS_ROT_90:
        case OMAP_DSS_ROT_270:
                *offset1 = 0;
@@ -1927,6 +1928,7 @@ static void calc_vrfb_rotation_offset(u8 rotation, bool mirror,
                if (color_mode == OMAP_DSS_COLOR_YUV2 ||
                        color_mode == OMAP_DSS_COLOR_UYVY)
                        width = width >> 1;
+               /* fall through */
        case OMAP_DSS_ROT_90 + 4:
        case OMAP_DSS_ROT_270 + 4:
                *offset1 = 0;
index 3e7887c..b8b5b4a 100644 (file)
@@ -893,6 +893,7 @@ int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
                                / (var->bits_per_pixel >> 2);
                        break;
                }
+               /* fall through */
        default:
                screen_width = fix->line_length / (var->bits_per_pixel >> 3);
                break;
index bd6c2f5..1dcf02e 100644 (file)
@@ -233,8 +233,10 @@ static u32 to3264(u32 timing, int bpp, int is64)
        switch (bpp) {
        case 24:
                timing *= 3;
+               /* fall through */
        case 8:
                timing >>= 1;
+               /* fall through */
        case 16:
                timing >>= 1;
        case 32:
index 0955622..69cfb33 100644 (file)
@@ -44,6 +44,7 @@
 #include <linux/clk.h>
 #include <linux/fs.h>
 #include <linux/io.h>
+#include <linux/of.h>
 
 #include "pxa3xx-gcu.h"
 
@@ -703,11 +704,20 @@ static int pxa3xx_gcu_remove(struct platform_device *pdev)
        return 0;
 }
 
+#ifdef CONFIG_OF
+static const struct of_device_id pxa3xx_gcu_of_match[] = {
+       { .compatible = "marvell,pxa300-gcu", },
+       { }
+};
+MODULE_DEVICE_TABLE(of, pxa3xx_gcu_of_match);
+#endif
+
 static struct platform_driver pxa3xx_gcu_driver = {
        .probe    = pxa3xx_gcu_probe,
        .remove  = pxa3xx_gcu_remove,
        .driver  = {
                .name   = DRV_NAME,
+               .of_match_table = of_match_ptr(pxa3xx_gcu_of_match),
        },
 };
 
index 76722a5..bbed039 100644 (file)
@@ -56,6 +56,7 @@
 #include <linux/freezer.h>
 #include <linux/console.h>
 #include <linux/of_graph.h>
+#include <linux/regulator/consumer.h>
 #include <video/of_display_timing.h>
 #include <video/videomode.h>
 
@@ -1423,6 +1424,21 @@ static inline void __pxafb_lcd_power(struct pxafb_info *fbi, int on)
 
        if (fbi->lcd_power)
                fbi->lcd_power(on, &fbi->fb.var);
+
+       if (fbi->lcd_supply && fbi->lcd_supply_enabled != on) {
+               int ret;
+
+               if (on)
+                       ret = regulator_enable(fbi->lcd_supply);
+               else
+                       ret = regulator_disable(fbi->lcd_supply);
+
+               if (ret < 0)
+                       pr_warn("Unable to %s LCD supply regulator: %d\n",
+                               on ? "enable" : "disable", ret);
+               else
+                       fbi->lcd_supply_enabled = on;
+       }
 }
 
 static void pxafb_enable_controller(struct pxafb_info *fbi)
@@ -1799,19 +1815,17 @@ static struct pxafb_info *pxafb_init_fbinfo(struct device *dev,
        void *addr;
 
        /* Alloc the pxafb_info and pseudo_palette in one step */
-       fbi = kmalloc(sizeof(struct pxafb_info) + sizeof(u32) * 16, GFP_KERNEL);
+       fbi = devm_kzalloc(dev, sizeof(struct pxafb_info) + sizeof(u32) * 16,
+                          GFP_KERNEL);
        if (!fbi)
-               return NULL;
+               return ERR_PTR(-ENOMEM);
 
-       memset(fbi, 0, sizeof(struct pxafb_info));
        fbi->dev = dev;
        fbi->inf = inf;
 
-       fbi->clk = clk_get(dev, NULL);
-       if (IS_ERR(fbi->clk)) {
-               kfree(fbi);
-               return NULL;
-       }
+       fbi->clk = devm_clk_get(dev, NULL);
+       if (IS_ERR(fbi->clk))
+               return ERR_CAST(fbi->clk);
 
        strcpy(fbi->fb.fix.id, PXA_NAME);
 
@@ -2128,8 +2142,9 @@ static int of_get_pxafb_display(struct device *dev, struct device_node *disp,
                return -EINVAL;
 
        ret = -ENOMEM;
-       info->modes = kmalloc_array(timings->num_timings,
-                                   sizeof(info->modes[0]), GFP_KERNEL);
+       info->modes = devm_kcalloc(dev, timings->num_timings,
+                                  sizeof(info->modes[0]),
+                                  GFP_KERNEL);
        if (!info->modes)
                goto out;
        info->num_modes = timings->num_timings;
@@ -2288,10 +2303,9 @@ static int pxafb_probe(struct platform_device *dev)
        }
 
        fbi = pxafb_init_fbinfo(&dev->dev, inf);
-       if (!fbi) {
-               /* only reason for pxafb_init_fbinfo to fail is kmalloc */
+       if (IS_ERR(fbi)) {
                dev_err(&dev->dev, "Failed to initialize framebuffer device\n");
-               ret = -ENOMEM;
+               ret = PTR_ERR(fbi);
                goto failed;
        }
 
@@ -2301,25 +2315,26 @@ static int pxafb_probe(struct platform_device *dev)
        fbi->backlight_power = inf->pxafb_backlight_power;
        fbi->lcd_power = inf->pxafb_lcd_power;
 
+       fbi->lcd_supply = devm_regulator_get_optional(&dev->dev, "lcd");
+       if (IS_ERR(fbi->lcd_supply)) {
+               if (PTR_ERR(fbi->lcd_supply) == -EPROBE_DEFER)
+                       return -EPROBE_DEFER;
+
+               fbi->lcd_supply = NULL;
+       }
+
        r = platform_get_resource(dev, IORESOURCE_MEM, 0);
        if (r == NULL) {
                dev_err(&dev->dev, "no I/O memory resource defined\n");
                ret = -ENODEV;
-               goto failed_fbi;
-       }
-
-       r = request_mem_region(r->start, resource_size(r), dev->name);
-       if (r == NULL) {
-               dev_err(&dev->dev, "failed to request I/O memory\n");
-               ret = -EBUSY;
-               goto failed_fbi;
+               goto failed;
        }
 
-       fbi->mmio_base = ioremap(r->start, resource_size(r));
-       if (fbi->mmio_base == NULL) {
-               dev_err(&dev->dev, "failed to map I/O memory\n");
+       fbi->mmio_base = devm_ioremap_resource(&dev->dev, r);
+       if (IS_ERR(fbi->mmio_base)) {
+               dev_err(&dev->dev, "failed to get I/O memory\n");
                ret = -EBUSY;
-               goto failed_free_res;
+               goto failed;
        }
 
        fbi->dma_buff_size = PAGE_ALIGN(sizeof(struct pxafb_dma_buff));
@@ -2328,7 +2343,7 @@ static int pxafb_probe(struct platform_device *dev)
        if (fbi->dma_buff == NULL) {
                dev_err(&dev->dev, "failed to allocate memory for DMA\n");
                ret = -ENOMEM;
-               goto failed_free_io;
+               goto failed;
        }
 
        ret = pxafb_init_video_memory(fbi);
@@ -2345,7 +2360,7 @@ static int pxafb_probe(struct platform_device *dev)
                goto failed_free_mem;
        }
 
-       ret = request_irq(irq, pxafb_handle_irq, 0, "LCD", fbi);
+       ret = devm_request_irq(&dev->dev, irq, pxafb_handle_irq, 0, "LCD", fbi);
        if (ret) {
                dev_err(&dev->dev, "request_irq failed: %d\n", ret);
                ret = -EBUSY;
@@ -2355,7 +2370,7 @@ static int pxafb_probe(struct platform_device *dev)
        ret = pxafb_smart_init(fbi);
        if (ret) {
                dev_err(&dev->dev, "failed to initialize smartpanel\n");
-               goto failed_free_irq;
+               goto failed_free_mem;
        }
 
        /*
@@ -2365,13 +2380,13 @@ static int pxafb_probe(struct platform_device *dev)
        ret = pxafb_check_var(&fbi->fb.var, &fbi->fb);
        if (ret) {
                dev_err(&dev->dev, "failed to get suitable mode\n");
-               goto failed_free_irq;
+               goto failed_free_mem;
        }
 
        ret = pxafb_set_par(&fbi->fb);
        if (ret) {
                dev_err(&dev->dev, "Failed to set parameters\n");
-               goto failed_free_irq;
+               goto failed_free_mem;
        }
 
        platform_set_drvdata(dev, fbi);
@@ -2404,20 +2419,11 @@ static int pxafb_probe(struct platform_device *dev)
 failed_free_cmap:
        if (fbi->fb.cmap.len)
                fb_dealloc_cmap(&fbi->fb.cmap);
-failed_free_irq:
-       free_irq(irq, fbi);
 failed_free_mem:
        free_pages_exact(fbi->video_mem, fbi->video_mem_size);
 failed_free_dma:
        dma_free_coherent(&dev->dev, fbi->dma_buff_size,
                        fbi->dma_buff, fbi->dma_buff_phys);
-failed_free_io:
-       iounmap(fbi->mmio_base);
-failed_free_res:
-       release_mem_region(r->start, resource_size(r));
-failed_fbi:
-       clk_put(fbi->clk);
-       kfree(fbi);
 failed:
        return ret;
 }
@@ -2425,8 +2431,6 @@ failed:
 static int pxafb_remove(struct platform_device *dev)
 {
        struct pxafb_info *fbi = platform_get_drvdata(dev);
-       struct resource *r;
-       int irq;
        struct fb_info *info;
 
        if (!fbi)
@@ -2442,22 +2446,11 @@ static int pxafb_remove(struct platform_device *dev)
        if (fbi->fb.cmap.len)
                fb_dealloc_cmap(&fbi->fb.cmap);
 
-       irq = platform_get_irq(dev, 0);
-       free_irq(irq, fbi);
-
        free_pages_exact(fbi->video_mem, fbi->video_mem_size);
 
        dma_free_wc(&dev->dev, fbi->dma_buff_size, fbi->dma_buff,
                    fbi->dma_buff_phys);
 
-       iounmap(fbi->mmio_base);
-
-       r = platform_get_resource(dev, IORESOURCE_MEM, 0);
-       release_mem_region(r->start, resource_size(r));
-
-       clk_put(fbi->clk);
-       kfree(fbi);
-
        return 0;
 }
 
index 5dc414e..b641289 100644 (file)
@@ -165,6 +165,9 @@ struct pxafb_info {
        struct notifier_block   freq_policy;
 #endif
 
+       struct regulator *lcd_supply;
+       bool lcd_supply_enabled;
+
        void (*lcd_power)(int, struct fb_var_screeninfo *);
        void (*backlight_power)(int);
 
index a3c44ec..9a9d748 100644 (file)
@@ -27,8 +27,8 @@
 #include <linux/platform_data/simplefb.h>
 #include <linux/platform_device.h>
 #include <linux/clk.h>
-#include <linux/clk-provider.h>
 #include <linux/of.h>
+#include <linux/of_clk.h>
 #include <linux/of_platform.h>
 #include <linux/parser.h>
 #include <linux/regulator/consumer.h>
index dec1fed..fbbf26b 100644 (file)
@@ -522,6 +522,7 @@ static int tdfxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
        case 32:
                var->transp.offset = 24;
                var->transp.length = 8;
+               /* fall through */
        case 24:
                var->red.offset = 16;
                var->green.offset = 8;
index 2847061..f4b7455 100644 (file)
@@ -777,9 +777,6 @@ static int get_nativex(struct tridentfb_par *par)
        case 3:
                x = 800; y = 600;
                break;
-       case 4:
-               x = 1400; y = 1050;
-               break;
        case 1:
        default:
                x = 640;  y = 480;
index f365d48..afbd610 100644 (file)
@@ -25,8 +25,8 @@
 #include <linux/fb.h>
 #include <linux/vmalloc.h>
 #include <linux/slab.h>
-#include <linux/prefetch.h>
 #include <linux/delay.h>
+#include <asm/unaligned.h>
 #include <video/udlfb.h>
 #include "edid.h"
 
@@ -72,6 +72,13 @@ static bool fb_defio = 1;  /* Detect mmap writes using page faults */
 static bool shadow = 1; /* Optionally disable shadow framebuffer */
 static int pixel_limit; /* Optionally force a pixel resolution limit */
 
+struct dlfb_deferred_free {
+       struct list_head list;
+       void *mem;
+};
+
+static int dlfb_realloc_framebuffer(struct dlfb_data *dlfb, struct fb_info *info, u32 new_len);
+
 /* dlfb keeps a list of urbs for efficient bulk transfers */
 static void dlfb_urb_completion(struct urb *urb);
 static struct urb *dlfb_get_urb(struct dlfb_data *dlfb);
@@ -367,9 +374,6 @@ static int dlfb_trim_hline(const u8 *bback, const u8 **bfront, int *width_bytes)
        int start = width;
        int end = width;
 
-       prefetch((void *) front);
-       prefetch((void *) back);
-
        for (j = 0; j < width; j++) {
                if (back[j] != front[j]) {
                        start = j;
@@ -423,7 +427,9 @@ static void dlfb_compress_hline(
        const uint16_t *const pixel_end,
        uint32_t *device_address_ptr,
        uint8_t **command_buffer_ptr,
-       const uint8_t *const cmd_buffer_end)
+       const uint8_t *const cmd_buffer_end,
+       unsigned long back_buffer_offset,
+       int *ident_ptr)
 {
        const uint16_t *pixel = *pixel_start_ptr;
        uint32_t dev_addr  = *device_address_ptr;
@@ -436,7 +442,13 @@ static void dlfb_compress_hline(
                const uint16_t *raw_pixel_start = NULL;
                const uint16_t *cmd_pixel_start, *cmd_pixel_end = NULL;
 
-               prefetchw((void *) cmd); /* pull in one cache line at least */
+               if (back_buffer_offset &&
+                   *pixel == *(u16 *)((u8 *)pixel + back_buffer_offset)) {
+                       pixel++;
+                       dev_addr += BPP;
+                       (*ident_ptr)++;
+                       continue;
+               }
 
                *cmd++ = 0xAF;
                *cmd++ = 0x6B;
@@ -450,29 +462,39 @@ static void dlfb_compress_hline(
                raw_pixels_count_byte = cmd++; /*  we'll know this later */
                raw_pixel_start = pixel;
 
-               cmd_pixel_end = pixel + min(MAX_CMD_PIXELS + 1,
-                       min((int)(pixel_end - pixel),
-                           (int)(cmd_buffer_end - cmd) / BPP));
+               cmd_pixel_end = pixel + min3(MAX_CMD_PIXELS + 1UL,
+                                       (unsigned long)(pixel_end - pixel),
+                                       (unsigned long)(cmd_buffer_end - 1 - cmd) / BPP);
 
-               prefetch_range((void *) pixel, (cmd_pixel_end - pixel) * BPP);
+               if (back_buffer_offset) {
+                       /* note: the framebuffer may change under us, so we must test for underflow */
+                       while (cmd_pixel_end - 1 > pixel &&
+                              *(cmd_pixel_end - 1) == *(u16 *)((u8 *)(cmd_pixel_end - 1) + back_buffer_offset))
+                               cmd_pixel_end--;
+               }
 
                while (pixel < cmd_pixel_end) {
                        const uint16_t * const repeating_pixel = pixel;
+                       u16 pixel_value = *pixel;
 
-                       *cmd++ = *pixel >> 8;
-                       *cmd++ = *pixel;
+                       put_unaligned_be16(pixel_value, cmd);
+                       if (back_buffer_offset)
+                               *(u16 *)((u8 *)pixel + back_buffer_offset) = pixel_value;
+                       cmd += 2;
                        pixel++;
 
                        if (unlikely((pixel < cmd_pixel_end) &&
-                                    (*pixel == *repeating_pixel))) {
+                                    (*pixel == pixel_value))) {
                                /* go back and fill in raw pixel count */
                                *raw_pixels_count_byte = ((repeating_pixel -
                                                raw_pixel_start) + 1) & 0xFF;
 
-                               while ((pixel < cmd_pixel_end)
-                                      && (*pixel == *repeating_pixel)) {
+                               do {
+                                       if (back_buffer_offset)
+                                               *(u16 *)((u8 *)pixel + back_buffer_offset) = pixel_value;
                                        pixel++;
-                               }
+                               } while ((pixel < cmd_pixel_end) &&
+                                        (*pixel == pixel_value));
 
                                /* immediately after raw data is repeat byte */
                                *cmd++ = ((pixel - repeating_pixel) - 1) & 0xFF;
@@ -486,13 +508,16 @@ static void dlfb_compress_hline(
                if (pixel > raw_pixel_start) {
                        /* finalize last RAW span */
                        *raw_pixels_count_byte = (pixel-raw_pixel_start) & 0xFF;
+               } else {
+                       /* undo unused byte */
+                       cmd--;
                }
 
                *cmd_pixels_count_byte = (pixel - cmd_pixel_start) & 0xFF;
-               dev_addr += (pixel - cmd_pixel_start) * BPP;
+               dev_addr += (u8 *)pixel - (u8 *)cmd_pixel_start;
        }
 
-       if (cmd_buffer_end <= MIN_RLX_CMD_BYTES + cmd) {
+       if (cmd_buffer_end - MIN_RLX_CMD_BYTES <= cmd) {
                /* Fill leftover bytes with no-ops */
                if (cmd_buffer_end > cmd)
                        memset(cmd, 0xAF, cmd_buffer_end - cmd);
@@ -520,6 +545,7 @@ static int dlfb_render_hline(struct dlfb_data *dlfb, struct urb **urb_ptr,
        struct urb *urb = *urb_ptr;
        u8 *cmd = *urb_buf_ptr;
        u8 *cmd_end = (u8 *) urb->transfer_buffer + urb->transfer_buffer_length;
+       unsigned long back_buffer_offset = 0;
 
        line_start = (u8 *) (front + byte_offset);
        next_pixel = line_start;
@@ -530,6 +556,8 @@ static int dlfb_render_hline(struct dlfb_data *dlfb, struct urb **urb_ptr,
                const u8 *back_start = (u8 *) (dlfb->backing_buffer
                                                + byte_offset);
 
+               back_buffer_offset = (unsigned long)back_start - (unsigned long)line_start;
+
                *ident_ptr += dlfb_trim_hline(back_start, &next_pixel,
                        &byte_width);
 
@@ -538,16 +566,14 @@ static int dlfb_render_hline(struct dlfb_data *dlfb, struct urb **urb_ptr,
                dev_addr += offset;
                back_start += offset;
                line_start += offset;
-
-               memcpy((char *)back_start, (char *) line_start,
-                      byte_width);
        }
 
        while (next_pixel < line_end) {
 
                dlfb_compress_hline((const uint16_t **) &next_pixel,
                             (const uint16_t *) line_end, &dev_addr,
-                       (u8 **) &cmd, (u8 *) cmd_end);
+                       (u8 **) &cmd, (u8 *) cmd_end, back_buffer_offset,
+                       ident_ptr);
 
                if (cmd >= cmd_end) {
                        int len = cmd - (u8 *) urb->transfer_buffer;
@@ -610,8 +636,11 @@ static int dlfb_handle_damage(struct dlfb_data *dlfb, int x, int y,
        }
 
        if (cmd > (char *) urb->transfer_buffer) {
+               int len;
+               if (cmd < (char *) urb->transfer_buffer + urb->transfer_buffer_length)
+                       *cmd++ = 0xAF;
                /* Send partial buffer remaining before exiting */
-               int len = cmd - (char *) urb->transfer_buffer;
+               len = cmd - (char *) urb->transfer_buffer;
                ret = dlfb_submit_urb(dlfb, urb, len);
                bytes_sent += len;
        } else
@@ -735,8 +764,11 @@ static void dlfb_dpy_deferred_io(struct fb_info *info,
        }
 
        if (cmd > (char *) urb->transfer_buffer) {
+               int len;
+               if (cmd < (char *) urb->transfer_buffer + urb->transfer_buffer_length)
+                       *cmd++ = 0xAF;
                /* Send partial buffer remaining before exiting */
-               int len = cmd - (char *) urb->transfer_buffer;
+               len = cmd - (char *) urb->transfer_buffer;
                dlfb_submit_urb(dlfb, urb, len);
                bytes_sent += len;
        } else
@@ -917,19 +949,17 @@ static void dlfb_free(struct kref *kref)
 {
        struct dlfb_data *dlfb = container_of(kref, struct dlfb_data, kref);
 
+       while (!list_empty(&dlfb->deferred_free)) {
+               struct dlfb_deferred_free *d = list_entry(dlfb->deferred_free.next, struct dlfb_deferred_free, list);
+               list_del(&d->list);
+               vfree(d->mem);
+               kfree(d);
+       }
        vfree(dlfb->backing_buffer);
        kfree(dlfb->edid);
        kfree(dlfb);
 }
 
-static void dlfb_release_urb_work(struct work_struct *work)
-{
-       struct urb_node *unode = container_of(work, struct urb_node,
-                                             release_urb_work.work);
-
-       up(&unode->dlfb->urbs.limit_sem);
-}
-
 static void dlfb_free_framebuffer(struct dlfb_data *dlfb)
 {
        struct fb_info *info = dlfb->info;
@@ -1018,10 +1048,6 @@ static int dlfb_ops_check_var(struct fb_var_screeninfo *var,
        struct fb_videomode mode;
        struct dlfb_data *dlfb = info->par;
 
-       /* TODO: support dynamically changing framebuffer size */
-       if ((var->xres * var->yres * 2) > info->fix.smem_len)
-               return -EINVAL;
-
        /* set device-specific elements of var unrelated to mode */
        dlfb_var_color_format(var);
 
@@ -1039,22 +1065,42 @@ static int dlfb_ops_set_par(struct fb_info *info)
        int result;
        u16 *pix_framebuffer;
        int i;
+       struct fb_var_screeninfo fvs;
+       u32 line_length = info->var.xres * (info->var.bits_per_pixel / 8);
+
+       /* clear the activate field because it causes spurious miscompares */
+       fvs = info->var;
+       fvs.activate = 0;
+       fvs.vmode &= ~FB_VMODE_SMOOTH_XPAN;
+
+       if (!memcmp(&dlfb->current_mode, &fvs, sizeof(struct fb_var_screeninfo)))
+               return 0;
+
+       result = dlfb_realloc_framebuffer(dlfb, info, info->var.yres * line_length);
+       if (result)
+               return result;
 
        result = dlfb_set_video_mode(dlfb, &info->var);
 
-       if ((result == 0) && (dlfb->fb_count == 0)) {
+       if (result)
+               return result;
+
+       dlfb->current_mode = fvs;
+       info->fix.line_length = line_length;
+
+       if (dlfb->fb_count == 0) {
 
                /* paint greenscreen */
 
                pix_framebuffer = (u16 *) info->screen_base;
                for (i = 0; i < info->fix.smem_len / 2; i++)
                        pix_framebuffer[i] = 0x37e6;
-
-               dlfb_handle_damage(dlfb, 0, 0, info->var.xres, info->var.yres,
-                                  info->screen_base);
        }
 
-       return result;
+       dlfb_handle_damage(dlfb, 0, 0, info->var.xres, info->var.yres,
+                          info->screen_base);
+
+       return 0;
 }
 
 /* To fonzi the jukebox (e.g. make blanking changes take effect) */
@@ -1129,21 +1175,29 @@ static struct fb_ops dlfb_ops = {
 };
 
 
+static void dlfb_deferred_vfree(struct dlfb_data *dlfb, void *mem)
+{
+       struct dlfb_deferred_free *d = kmalloc(sizeof(struct dlfb_deferred_free), GFP_KERNEL);
+       if (!d)
+               return;
+       d->mem = mem;
+       list_add(&d->list, &dlfb->deferred_free);
+}
+
 /*
  * Assumes &info->lock held by caller
  * Assumes no active clients have framebuffer open
  */
-static int dlfb_realloc_framebuffer(struct dlfb_data *dlfb, struct fb_info *info)
+static int dlfb_realloc_framebuffer(struct dlfb_data *dlfb, struct fb_info *info, u32 new_len)
 {
-       int old_len = info->fix.smem_len;
-       int new_len;
-       unsigned char *old_fb = info->screen_base;
+       u32 old_len = info->fix.smem_len;
+       const void *old_fb = (const void __force *)info->screen_base;
        unsigned char *new_fb;
        unsigned char *new_back = NULL;
 
-       new_len = info->fix.line_length * info->var.yres;
+       new_len = PAGE_ALIGN(new_len);
 
-       if (PAGE_ALIGN(new_len) > old_len) {
+       if (new_len > old_len) {
                /*
                 * Alloc system memory for virtual framebuffer
                 */
@@ -1152,14 +1206,15 @@ static int dlfb_realloc_framebuffer(struct dlfb_data *dlfb, struct fb_info *info
                        dev_err(info->dev, "Virtual framebuffer alloc failed\n");
                        return -ENOMEM;
                }
+               memset(new_fb, 0xff, new_len);
 
                if (info->screen_base) {
                        memcpy(new_fb, old_fb, old_len);
-                       vfree(info->screen_base);
+                       dlfb_deferred_vfree(dlfb, (void __force *)info->screen_base);
                }
 
-               info->screen_base = new_fb;
-               info->fix.smem_len = PAGE_ALIGN(new_len);
+               info->screen_base = (char __iomem *)new_fb;
+               info->fix.smem_len = new_len;
                info->fix.smem_start = (unsigned long) new_fb;
                info->flags = udlfb_info_flags;
 
@@ -1175,7 +1230,7 @@ static int dlfb_realloc_framebuffer(struct dlfb_data *dlfb, struct fb_info *info
                        dev_info(info->dev,
                                 "No shadow/backing buffer allocated\n");
                else {
-                       vfree(dlfb->backing_buffer);
+                       dlfb_deferred_vfree(dlfb, dlfb->backing_buffer);
                        dlfb->backing_buffer = new_back;
                }
        }
@@ -1327,11 +1382,6 @@ static int dlfb_setup_modes(struct dlfb_data *dlfb,
                 * with mode size info, we can now alloc our framebuffer.
                 */
                memcpy(&info->fix, &dlfb_fix, sizeof(dlfb_fix));
-               info->fix.line_length = info->var.xres *
-                       (info->var.bits_per_pixel / 8);
-
-               result = dlfb_realloc_framebuffer(dlfb, info);
-
        } else
                result = -EINVAL;
 
@@ -1419,7 +1469,10 @@ static ssize_t edid_store(
        if (!dlfb->edid || memcmp(src, dlfb->edid, src_size))
                return -EINVAL;
 
-       dlfb_ops_set_par(fb_info);
+       ret = dlfb_ops_set_par(fb_info);
+       if (ret)
+               return ret;
+
        return src_size;
 }
 
@@ -1579,6 +1632,7 @@ static int dlfb_usb_probe(struct usb_interface *intf,
        }
 
        kref_init(&dlfb->kref); /* matching kref_put in usb .disconnect fn */
+       INIT_LIST_HEAD(&dlfb->deferred_free);
 
        dlfb->udev = usbdev;
        usb_set_intfdata(intf, dlfb);
@@ -1649,7 +1703,8 @@ static void dlfb_init_framebuffer_work(struct work_struct *work)
        dlfb->info = info;
        info->par = dlfb;
        info->pseudo_palette = dlfb->pseudo_palette;
-       info->fbops = &dlfb_ops;
+       dlfb->ops = dlfb_ops;
+       info->fbops = &dlfb->ops;
 
        retval = fb_alloc_cmap(&info->cmap, 256, 0);
        if (retval < 0) {
@@ -1675,7 +1730,9 @@ static void dlfb_init_framebuffer_work(struct work_struct *work)
        dlfb_select_std_channel(dlfb);
 
        dlfb_ops_check_var(&info->var, info);
-       dlfb_ops_set_par(info);
+       retval = dlfb_ops_set_par(info);
+       if (retval)
+               goto error;
 
        retval = register_framebuffer(info);
        if (retval < 0) {
@@ -1789,14 +1846,7 @@ static void dlfb_urb_completion(struct urb *urb)
        dlfb->urbs.available++;
        spin_unlock_irqrestore(&dlfb->urbs.lock, flags);
 
-       /*
-        * When using fb_defio, we deadlock if up() is called
-        * while another is waiting. So queue to another process.
-        */
-       if (fb_defio)
-               schedule_delayed_work(&unode->release_urb_work, 0);
-       else
-               up(&dlfb->urbs.limit_sem);
+       up(&dlfb->urbs.limit_sem);
 }
 
 static void dlfb_free_urb_list(struct dlfb_data *dlfb)
@@ -1805,23 +1855,17 @@ static void dlfb_free_urb_list(struct dlfb_data *dlfb)
        struct list_head *node;
        struct urb_node *unode;
        struct urb *urb;
-       int ret;
-       unsigned long flags;
 
        /* keep waiting and freeing, until we've got 'em all */
        while (count--) {
+               down(&dlfb->urbs.limit_sem);
 
-               /* Getting interrupted means a leak, but ok at disconnect */
-               ret = down_interruptible(&dlfb->urbs.limit_sem);
-               if (ret)
-                       break;
-
-               spin_lock_irqsave(&dlfb->urbs.lock, flags);
+               spin_lock_irq(&dlfb->urbs.lock);
 
                node = dlfb->urbs.list.next; /* have reserved one with sem */
                list_del_init(node);
 
-               spin_unlock_irqrestore(&dlfb->urbs.lock, flags);
+               spin_unlock_irq(&dlfb->urbs.lock);
 
                unode = list_entry(node, struct urb_node, entry);
                urb = unode->urb;
@@ -1838,25 +1882,27 @@ static void dlfb_free_urb_list(struct dlfb_data *dlfb)
 
 static int dlfb_alloc_urb_list(struct dlfb_data *dlfb, int count, size_t size)
 {
-       int i = 0;
        struct urb *urb;
        struct urb_node *unode;
        char *buf;
+       size_t wanted_size = count * size;
 
        spin_lock_init(&dlfb->urbs.lock);
 
+retry:
        dlfb->urbs.size = size;
        INIT_LIST_HEAD(&dlfb->urbs.list);
 
-       while (i < count) {
+       sema_init(&dlfb->urbs.limit_sem, 0);
+       dlfb->urbs.count = 0;
+       dlfb->urbs.available = 0;
+
+       while (dlfb->urbs.count * size < wanted_size) {
                unode = kzalloc(sizeof(*unode), GFP_KERNEL);
                if (!unode)
                        break;
                unode->dlfb = dlfb;
 
-               INIT_DELAYED_WORK(&unode->release_urb_work,
-                         dlfb_release_urb_work);
-
                urb = usb_alloc_urb(0, GFP_KERNEL);
                if (!urb) {
                        kfree(unode);
@@ -1864,11 +1910,16 @@ static int dlfb_alloc_urb_list(struct dlfb_data *dlfb, int count, size_t size)
                }
                unode->urb = urb;
 
-               buf = usb_alloc_coherent(dlfb->udev, MAX_TRANSFER, GFP_KERNEL,
+               buf = usb_alloc_coherent(dlfb->udev, size, GFP_KERNEL,
                                         &urb->transfer_dma);
                if (!buf) {
                        kfree(unode);
                        usb_free_urb(urb);
+                       if (size > PAGE_SIZE) {
+                               size /= 2;
+                               dlfb_free_urb_list(dlfb);
+                               goto retry;
+                       }
                        break;
                }
 
@@ -1879,14 +1930,12 @@ static int dlfb_alloc_urb_list(struct dlfb_data *dlfb, int count, size_t size)
 
                list_add_tail(&unode->entry, &dlfb->urbs.list);
 
-               i++;
+               up(&dlfb->urbs.limit_sem);
+               dlfb->urbs.count++;
+               dlfb->urbs.available++;
        }
 
-       sema_init(&dlfb->urbs.limit_sem, i);
-       dlfb->urbs.count = i;
-       dlfb->urbs.available = i;
-
-       return i;
+       return dlfb->urbs.count;
 }
 
 static struct urb *dlfb_get_urb(struct dlfb_data *dlfb)
@@ -1894,7 +1943,6 @@ static struct urb *dlfb_get_urb(struct dlfb_data *dlfb)
        int ret;
        struct list_head *entry;
        struct urb_node *unode;
-       unsigned long flags;
 
        /* Wait for an in-flight buffer to complete and get re-queued */
        ret = down_timeout(&dlfb->urbs.limit_sem, GET_URB_TIMEOUT);
@@ -1906,14 +1954,14 @@ static struct urb *dlfb_get_urb(struct dlfb_data *dlfb)
                return NULL;
        }
 
-       spin_lock_irqsave(&dlfb->urbs.lock, flags);
+       spin_lock_irq(&dlfb->urbs.lock);
 
        BUG_ON(list_empty(&dlfb->urbs.list)); /* reserved one with limit_sem */
        entry = dlfb->urbs.list.next;
        list_del_init(entry);
        dlfb->urbs.available--;
 
-       spin_unlock_irqrestore(&dlfb->urbs.lock, flags);
+       spin_unlock_irq(&dlfb->urbs.lock);
 
        unode = list_entry(entry, struct urb_node, entry);
        return unode->urb;
index 5d21ff4..b9305d7 100644 (file)
@@ -758,6 +758,7 @@ static void set_lcd_output_path(int set_iga, int output_interface)
                    viaparinfo->chip_info->gfx_chip_name))
                        viafb_write_reg_mask(CR97, VIACR, 0x84,
                                       BIT7 + BIT2 + BIT1 + BIT0);
+               /* fall through */
        case INTERFACE_DVP0:
        case INTERFACE_DVP1:
        case INTERFACE_DFP_HIGH:
index d2f7850..7bb7e90 100644 (file)
@@ -19,6 +19,7 @@
  * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  */
 
+#include <linux/compiler.h>
 #include <linux/module.h>
 #include <linux/seq_file.h>
 #include <linux/slab.h>
@@ -1468,7 +1469,7 @@ static const struct file_operations viafb_vt1636_proc_fops = {
 
 #endif /* CONFIG_FB_VIA_DIRECT_PROCFS */
 
-static int viafb_sup_odev_proc_show(struct seq_file *m, void *v)
+static int __maybe_unused viafb_sup_odev_proc_show(struct seq_file *m, void *v)
 {
        via_odev_to_seq(m, supported_odev_map[
                viaparinfo->shared->chip_info.gfx_chip_name]);
index 3988c09..d1c1f62 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/balloon_compaction.h>
-#include <linux/oom.h>
 #include <linux/wait.h>
 #include <linux/mm.h>
 #include <linux/mount.h>
  */
 #define VIRTIO_BALLOON_PAGES_PER_PAGE (unsigned)(PAGE_SIZE >> VIRTIO_BALLOON_PFN_SHIFT)
 #define VIRTIO_BALLOON_ARRAY_PFNS_MAX 256
-#define OOM_VBALLOON_DEFAULT_PAGES 256
 #define VIRTBALLOON_OOM_NOTIFY_PRIORITY 80
 
-static int oom_pages = OOM_VBALLOON_DEFAULT_PAGES;
-module_param(oom_pages, int, S_IRUSR | S_IWUSR);
-MODULE_PARM_DESC(oom_pages, "pages to free on OOM");
-
 #ifdef CONFIG_BALLOON_COMPACTION
 static struct vfsmount *balloon_mnt;
 #endif
@@ -86,8 +80,8 @@ struct virtio_balloon {
        /* Memory statistics */
        struct virtio_balloon_stat stats[VIRTIO_BALLOON_S_NR];
 
-       /* To register callback in oom notifier call chain */
-       struct notifier_block nb;
+       /* To register a shrinker to shrink memory upon memory pressure */
+       struct shrinker shrinker;
 };
 
 static struct virtio_device_id id_table[] = {
@@ -365,38 +359,6 @@ static void update_balloon_size(struct virtio_balloon *vb)
                      &actual);
 }
 
-/*
- * virtballoon_oom_notify - release pages when system is under severe
- *                         memory pressure (called from out_of_memory())
- * @self : notifier block struct
- * @dummy: not used
- * @parm : returned - number of freed pages
- *
- * The balancing of memory by use of the virtio balloon should not cause
- * the termination of processes while there are pages in the balloon.
- * If virtio balloon manages to release some memory, it will make the
- * system return and retry the allocation that forced the OOM killer
- * to run.
- */
-static int virtballoon_oom_notify(struct notifier_block *self,
-                                 unsigned long dummy, void *parm)
-{
-       struct virtio_balloon *vb;
-       unsigned long *freed;
-       unsigned num_freed_pages;
-
-       vb = container_of(self, struct virtio_balloon, nb);
-       if (!virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_DEFLATE_ON_OOM))
-               return NOTIFY_OK;
-
-       freed = parm;
-       num_freed_pages = leak_balloon(vb, oom_pages);
-       update_balloon_size(vb);
-       *freed += num_freed_pages;
-
-       return NOTIFY_OK;
-}
-
 static void update_balloon_stats_func(struct work_struct *work)
 {
        struct virtio_balloon *vb;
@@ -455,9 +417,13 @@ static int init_vqs(struct virtio_balloon *vb)
                num_stats = update_balloon_stats(vb);
 
                sg_init_one(&sg, vb->stats, sizeof(vb->stats[0]) * num_stats);
-               if (virtqueue_add_outbuf(vb->stats_vq, &sg, 1, vb, GFP_KERNEL)
-                   < 0)
-                       BUG();
+               err = virtqueue_add_outbuf(vb->stats_vq, &sg, 1, vb,
+                                          GFP_KERNEL);
+               if (err) {
+                       dev_warn(&vb->vdev->dev, "%s: add stat_vq failed\n",
+                                __func__);
+                       return err;
+               }
                virtqueue_kick(vb->stats_vq);
        }
        return 0;
@@ -546,6 +512,52 @@ static struct file_system_type balloon_fs = {
 
 #endif /* CONFIG_BALLOON_COMPACTION */
 
+static unsigned long virtio_balloon_shrinker_scan(struct shrinker *shrinker,
+                                                 struct shrink_control *sc)
+{
+       unsigned long pages_to_free, pages_freed = 0;
+       struct virtio_balloon *vb = container_of(shrinker,
+                                       struct virtio_balloon, shrinker);
+
+       pages_to_free = sc->nr_to_scan * VIRTIO_BALLOON_PAGES_PER_PAGE;
+
+       /*
+        * One invocation of leak_balloon can deflate at most
+        * VIRTIO_BALLOON_ARRAY_PFNS_MAX balloon pages, so we call it
+        * multiple times to deflate pages till reaching pages_to_free.
+        */
+       while (vb->num_pages && pages_to_free) {
+               pages_to_free -= pages_freed;
+               pages_freed += leak_balloon(vb, pages_to_free);
+       }
+       update_balloon_size(vb);
+
+       return pages_freed / VIRTIO_BALLOON_PAGES_PER_PAGE;
+}
+
+static unsigned long virtio_balloon_shrinker_count(struct shrinker *shrinker,
+                                                  struct shrink_control *sc)
+{
+       struct virtio_balloon *vb = container_of(shrinker,
+                                       struct virtio_balloon, shrinker);
+
+       return vb->num_pages / VIRTIO_BALLOON_PAGES_PER_PAGE;
+}
+
+static void virtio_balloon_unregister_shrinker(struct virtio_balloon *vb)
+{
+       unregister_shrinker(&vb->shrinker);
+}
+
+static int virtio_balloon_register_shrinker(struct virtio_balloon *vb)
+{
+       vb->shrinker.scan_objects = virtio_balloon_shrinker_scan;
+       vb->shrinker.count_objects = virtio_balloon_shrinker_count;
+       vb->shrinker.seeks = DEFAULT_SEEKS;
+
+       return register_shrinker(&vb->shrinker);
+}
+
 static int virtballoon_probe(struct virtio_device *vdev)
 {
        struct virtio_balloon *vb;
@@ -557,7 +569,7 @@ static int virtballoon_probe(struct virtio_device *vdev)
                return -EINVAL;
        }
 
-       vdev->priv = vb = kmalloc(sizeof(*vb), GFP_KERNEL);
+       vdev->priv = vb = kzalloc(sizeof(*vb), GFP_KERNEL);
        if (!vb) {
                err = -ENOMEM;
                goto out;
@@ -566,8 +578,6 @@ static int virtballoon_probe(struct virtio_device *vdev)
        INIT_WORK(&vb->update_balloon_stats_work, update_balloon_stats_func);
        INIT_WORK(&vb->update_balloon_size_work, update_balloon_size_func);
        spin_lock_init(&vb->stop_update_lock);
-       vb->stop_update = false;
-       vb->num_pages = 0;
        mutex_init(&vb->balloon_lock);
        init_waitqueue_head(&vb->acked);
        vb->vdev = vdev;
@@ -578,17 +588,10 @@ static int virtballoon_probe(struct virtio_device *vdev)
        if (err)
                goto out_free_vb;
 
-       vb->nb.notifier_call = virtballoon_oom_notify;
-       vb->nb.priority = VIRTBALLOON_OOM_NOTIFY_PRIORITY;
-       err = register_oom_notifier(&vb->nb);
-       if (err < 0)
-               goto out_del_vqs;
-
 #ifdef CONFIG_BALLOON_COMPACTION
        balloon_mnt = kern_mount(&balloon_fs);
        if (IS_ERR(balloon_mnt)) {
                err = PTR_ERR(balloon_mnt);
-               unregister_oom_notifier(&vb->nb);
                goto out_del_vqs;
        }
 
@@ -597,13 +600,19 @@ static int virtballoon_probe(struct virtio_device *vdev)
        if (IS_ERR(vb->vb_dev_info.inode)) {
                err = PTR_ERR(vb->vb_dev_info.inode);
                kern_unmount(balloon_mnt);
-               unregister_oom_notifier(&vb->nb);
-               vb->vb_dev_info.inode = NULL;
                goto out_del_vqs;
        }
        vb->vb_dev_info.inode->i_mapping->a_ops = &balloon_aops;
 #endif
-
+       /*
+        * We continue to use VIRTIO_BALLOON_F_DEFLATE_ON_OOM to decide if a
+        * shrinker needs to be registered to relieve memory pressure.
+        */
+       if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_DEFLATE_ON_OOM)) {
+               err = virtio_balloon_register_shrinker(vb);
+               if (err)
+                       goto out_del_vqs;
+       }
        virtio_device_ready(vdev);
 
        if (towards_target(vb))
@@ -635,8 +644,8 @@ static void virtballoon_remove(struct virtio_device *vdev)
 {
        struct virtio_balloon *vb = vdev->priv;
 
-       unregister_oom_notifier(&vb->nb);
-
+       if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_DEFLATE_ON_OOM))
+               virtio_balloon_unregister_shrinker(vb);
        spin_lock_irq(&vb->stop_update_lock);
        vb->stop_update = true;
        spin_unlock_irq(&vb->stop_update_lock);
index 67763d3..4cd9ea5 100644 (file)
@@ -397,9 +397,23 @@ static struct virtqueue *vm_setup_vq(struct virtio_device *vdev, unsigned index,
        /* Activate the queue */
        writel(virtqueue_get_vring_size(vq), vm_dev->base + VIRTIO_MMIO_QUEUE_NUM);
        if (vm_dev->version == 1) {
+               u64 q_pfn = virtqueue_get_desc_addr(vq) >> PAGE_SHIFT;
+
+               /*
+                * virtio-mmio v1 uses a 32bit QUEUE PFN. If we have something
+                * that doesn't fit in 32bit, fail the setup rather than
+                * pretending to be successful.
+                */
+               if (q_pfn >> 32) {
+                       dev_err(&vdev->dev,
+                               "platform bug: legacy virtio-mmio must not be used with RAM above 0x%llxGB\n",
+                               0x1ULL << (32 + PAGE_SHIFT - 30));
+                       err = -E2BIG;
+                       goto error_bad_pfn;
+               }
+
                writel(PAGE_SIZE, vm_dev->base + VIRTIO_MMIO_QUEUE_ALIGN);
-               writel(virtqueue_get_desc_addr(vq) >> PAGE_SHIFT,
-                               vm_dev->base + VIRTIO_MMIO_QUEUE_PFN);
+               writel(q_pfn, vm_dev->base + VIRTIO_MMIO_QUEUE_PFN);
        } else {
                u64 addr;
 
@@ -430,6 +444,8 @@ static struct virtqueue *vm_setup_vq(struct virtio_device *vdev, unsigned index,
 
        return vq;
 
+error_bad_pfn:
+       vring_del_virtqueue(vq);
 error_new_virtqueue:
        if (vm_dev->version == 1) {
                writel(0, vm_dev->base + VIRTIO_MMIO_QUEUE_PFN);
index 2780886..de062fb 100644 (file)
@@ -122,6 +122,7 @@ static struct virtqueue *setup_vq(struct virtio_pci_device *vp_dev,
        struct virtqueue *vq;
        u16 num;
        int err;
+       u64 q_pfn;
 
        /* Select the queue we're interested in */
        iowrite16(index, vp_dev->ioaddr + VIRTIO_PCI_QUEUE_SEL);
@@ -141,9 +142,17 @@ static struct virtqueue *setup_vq(struct virtio_pci_device *vp_dev,
        if (!vq)
                return ERR_PTR(-ENOMEM);
 
+       q_pfn = virtqueue_get_desc_addr(vq) >> VIRTIO_PCI_QUEUE_ADDR_SHIFT;
+       if (q_pfn >> 32) {
+               dev_err(&vp_dev->pci_dev->dev,
+                       "platform bug: legacy virtio-mmio must not be used with RAM above 0x%llxGB\n",
+                       0x1ULL << (32 + PAGE_SHIFT - 30));
+               err = -E2BIG;
+               goto out_del_vq;
+       }
+
        /* activate the queue */
-       iowrite32(virtqueue_get_desc_addr(vq) >> VIRTIO_PCI_QUEUE_ADDR_SHIFT,
-                 vp_dev->ioaddr + VIRTIO_PCI_QUEUE_PFN);
+       iowrite32(q_pfn, vp_dev->ioaddr + VIRTIO_PCI_QUEUE_PFN);
 
        vq->priv = (void __force *)vp_dev->ioaddr + VIRTIO_PCI_QUEUE_NOTIFY;
 
@@ -160,6 +169,7 @@ static struct virtqueue *setup_vq(struct virtio_pci_device *vp_dev,
 
 out_deactivate:
        iowrite32(0, vp_dev->ioaddr + VIRTIO_PCI_QUEUE_PFN);
+out_del_vq:
        vring_del_virtqueue(vq);
        return ERR_PTR(err);
 }
index 7931231..e22fded 100644 (file)
@@ -100,18 +100,6 @@ config W1_SLAVE_DS2438
          Say Y here if you want to use a 1-wire
          DS2438 Smart Battery Monitor device support
 
-config W1_SLAVE_DS2760
-       tristate "Dallas 2760 battery monitor chip (HP iPAQ & others)"
-       help
-         If you enable this you will have the DS2760 battery monitor
-         chip support.
-
-         The battery monitor chip is used in many batteries/devices
-         as the one who is responsible for charging/discharging/monitoring
-         Li+ batteries.
-
-         If you are unsure, say N.
-
 config W1_SLAVE_DS2780
        tristate "Dallas 2780 battery monitor chip"
        help
index d5f4f4d..eab29f1 100644 (file)
@@ -14,7 +14,6 @@ obj-$(CONFIG_W1_SLAVE_DS2431) += w1_ds2431.o
 obj-$(CONFIG_W1_SLAVE_DS2805)  += w1_ds2805.o
 obj-$(CONFIG_W1_SLAVE_DS2433)  += w1_ds2433.o
 obj-$(CONFIG_W1_SLAVE_DS2438)  += w1_ds2438.o
-obj-$(CONFIG_W1_SLAVE_DS2760)  += w1_ds2760.o
 obj-$(CONFIG_W1_SLAVE_DS2780)  += w1_ds2780.o
 obj-$(CONFIG_W1_SLAVE_DS2781)  += w1_ds2781.o
 obj-$(CONFIG_W1_SLAVE_DS28E04) += w1_ds28e04.o
diff --git a/drivers/w1/slaves/w1_ds2760.c b/drivers/w1/slaves/w1_ds2760.c
deleted file mode 100644 (file)
index 26168ab..0000000
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- * 1-Wire implementation for the ds2760 chip
- *
- * Copyright © 2004-2005, Szabolcs Gyurko <szabolcs.gyurko@tlt.hu>
- *
- * Use consistent with the GNU GPL is permitted,
- * provided that this copyright notice is
- * preserved in its entirety in all copies and derived works.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/device.h>
-#include <linux/types.h>
-#include <linux/platform_device.h>
-#include <linux/mutex.h>
-#include <linux/idr.h>
-#include <linux/gfp.h>
-
-#include <linux/w1.h>
-
-#include "w1_ds2760.h"
-
-#define W1_FAMILY_DS2760       0x30
-
-static int w1_ds2760_io(struct device *dev, char *buf, int addr, size_t count,
-                       int io)
-{
-       struct w1_slave *sl = container_of(dev, struct w1_slave, dev);
-
-       if (!dev)
-               return 0;
-
-       mutex_lock(&sl->master->bus_mutex);
-
-       if (addr > DS2760_DATA_SIZE || addr < 0) {
-               count = 0;
-               goto out;
-       }
-       if (addr + count > DS2760_DATA_SIZE)
-               count = DS2760_DATA_SIZE - addr;
-
-       if (!w1_reset_select_slave(sl)) {
-               if (!io) {
-                       w1_write_8(sl->master, W1_DS2760_READ_DATA);
-                       w1_write_8(sl->master, addr);
-                       count = w1_read_block(sl->master, buf, count);
-               } else {
-                       w1_write_8(sl->master, W1_DS2760_WRITE_DATA);
-                       w1_write_8(sl->master, addr);
-                       w1_write_block(sl->master, buf, count);
-                       /* XXX w1_write_block returns void, not n_written */
-               }
-       }
-
-out:
-       mutex_unlock(&sl->master->bus_mutex);
-
-       return count;
-}
-
-int w1_ds2760_read(struct device *dev, char *buf, int addr, size_t count)
-{
-       return w1_ds2760_io(dev, buf, addr, count, 0);
-}
-EXPORT_SYMBOL(w1_ds2760_read);
-
-int w1_ds2760_write(struct device *dev, char *buf, int addr, size_t count)
-{
-       return w1_ds2760_io(dev, buf, addr, count, 1);
-}
-EXPORT_SYMBOL(w1_ds2760_write);
-
-static int w1_ds2760_eeprom_cmd(struct device *dev, int addr, int cmd)
-{
-       struct w1_slave *sl = container_of(dev, struct w1_slave, dev);
-
-       if (!dev)
-               return -EINVAL;
-
-       mutex_lock(&sl->master->bus_mutex);
-
-       if (w1_reset_select_slave(sl) == 0) {
-               w1_write_8(sl->master, cmd);
-               w1_write_8(sl->master, addr);
-       }
-
-       mutex_unlock(&sl->master->bus_mutex);
-       return 0;
-}
-
-int w1_ds2760_store_eeprom(struct device *dev, int addr)
-{
-       return w1_ds2760_eeprom_cmd(dev, addr, W1_DS2760_COPY_DATA);
-}
-EXPORT_SYMBOL(w1_ds2760_store_eeprom);
-
-int w1_ds2760_recall_eeprom(struct device *dev, int addr)
-{
-       return w1_ds2760_eeprom_cmd(dev, addr, W1_DS2760_RECALL_DATA);
-}
-EXPORT_SYMBOL(w1_ds2760_recall_eeprom);
-
-static ssize_t w1_slave_read(struct file *filp, struct kobject *kobj,
-                            struct bin_attribute *bin_attr, char *buf,
-                            loff_t off, size_t count)
-{
-       struct device *dev = container_of(kobj, struct device, kobj);
-       return w1_ds2760_read(dev, buf, off, count);
-}
-
-static BIN_ATTR_RO(w1_slave, DS2760_DATA_SIZE);
-
-static struct bin_attribute *w1_ds2760_bin_attrs[] = {
-       &bin_attr_w1_slave,
-       NULL,
-};
-
-static const struct attribute_group w1_ds2760_group = {
-       .bin_attrs = w1_ds2760_bin_attrs,
-};
-
-static const struct attribute_group *w1_ds2760_groups[] = {
-       &w1_ds2760_group,
-       NULL,
-};
-
-static int w1_ds2760_add_slave(struct w1_slave *sl)
-{
-       int ret;
-       struct platform_device *pdev;
-
-       pdev = platform_device_alloc("ds2760-battery", PLATFORM_DEVID_AUTO);
-       if (!pdev)
-               return -ENOMEM;
-       pdev->dev.parent = &sl->dev;
-
-       ret = platform_device_add(pdev);
-       if (ret)
-               goto pdev_add_failed;
-
-       dev_set_drvdata(&sl->dev, pdev);
-
-       return 0;
-
-pdev_add_failed:
-       platform_device_put(pdev);
-
-       return ret;
-}
-
-static void w1_ds2760_remove_slave(struct w1_slave *sl)
-{
-       struct platform_device *pdev = dev_get_drvdata(&sl->dev);
-
-       platform_device_unregister(pdev);
-}
-
-static struct w1_family_ops w1_ds2760_fops = {
-       .add_slave    = w1_ds2760_add_slave,
-       .remove_slave = w1_ds2760_remove_slave,
-       .groups       = w1_ds2760_groups,
-};
-
-static struct w1_family w1_ds2760_family = {
-       .fid = W1_FAMILY_DS2760,
-       .fops = &w1_ds2760_fops,
-};
-module_w1_family(w1_ds2760_family);
-
-MODULE_AUTHOR("Szabolcs Gyurko <szabolcs.gyurko@tlt.hu>");
-MODULE_DESCRIPTION("1-wire Driver Dallas 2760 battery monitor chip");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("w1-family-" __stringify(W1_FAMILY_DS2760));
diff --git a/drivers/w1/slaves/w1_ds2760.h b/drivers/w1/slaves/w1_ds2760.h
deleted file mode 100644 (file)
index 24168c9..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * 1-Wire implementation for the ds2760 chip
- *
- * Copyright © 2004-2005, Szabolcs Gyurko <szabolcs.gyurko@tlt.hu>
- *
- * Use consistent with the GNU GPL is permitted,
- * provided that this copyright notice is
- * preserved in its entirety in all copies and derived works.
- *
- */
-
-#ifndef __w1_ds2760_h__
-#define __w1_ds2760_h__
-
-/* Known commands to the DS2760 chip */
-#define W1_DS2760_SWAP                 0xAA
-#define W1_DS2760_READ_DATA            0x69
-#define W1_DS2760_WRITE_DATA           0x6C
-#define W1_DS2760_COPY_DATA            0x48
-#define W1_DS2760_RECALL_DATA          0xB8
-#define W1_DS2760_LOCK                 0x6A
-
-/* Number of valid register addresses */
-#define DS2760_DATA_SIZE               0x40
-
-#define DS2760_PROTECTION_REG          0x00
-
-#define DS2760_STATUS_REG              0x01
-#define DS2760_STATUS_IE               (1 << 2)
-#define DS2760_STATUS_SWEN             (1 << 3)
-#define DS2760_STATUS_RNAOP            (1 << 4)
-#define DS2760_STATUS_PMOD             (1 << 5)
-
-#define DS2760_EEPROM_REG              0x07
-#define DS2760_SPECIAL_FEATURE_REG     0x08
-#define DS2760_VOLTAGE_MSB             0x0c
-#define DS2760_VOLTAGE_LSB             0x0d
-#define DS2760_CURRENT_MSB             0x0e
-#define DS2760_CURRENT_LSB             0x0f
-#define DS2760_CURRENT_ACCUM_MSB       0x10
-#define DS2760_CURRENT_ACCUM_LSB       0x11
-#define DS2760_TEMP_MSB                        0x18
-#define DS2760_TEMP_LSB                        0x19
-#define DS2760_EEPROM_BLOCK0           0x20
-#define DS2760_ACTIVE_FULL             0x20
-#define DS2760_EEPROM_BLOCK1           0x30
-#define DS2760_STATUS_WRITE_REG                0x31
-#define DS2760_RATED_CAPACITY          0x32
-#define DS2760_CURRENT_OFFSET_BIAS     0x33
-#define DS2760_ACTIVE_EMPTY            0x3b
-
-extern int w1_ds2760_read(struct device *dev, char *buf, int addr,
-                         size_t count);
-extern int w1_ds2760_write(struct device *dev, char *buf, int addr,
-                          size_t count);
-extern int w1_ds2760_store_eeprom(struct device *dev, int addr);
-extern int w1_ds2760_recall_eeprom(struct device *dev, int addr);
-
-#endif /* !__w1_ds2760_h__ */
index caef0e0..890c038 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/kthread.h>
 #include <linux/freezer.h>
 #include <linux/hwmon.h>
+#include <linux/of.h>
 
 #include <linux/atomic.h>
 
@@ -686,6 +687,8 @@ static int __w1_attach_slave_device(struct w1_slave *sl)
        sl->dev.bus = &w1_bus_type;
        sl->dev.release = &w1_slave_release;
        sl->dev.groups = w1_slave_groups;
+       sl->dev.of_node = of_find_matching_node(sl->master->dev.of_node,
+                                               sl->family->of_match_table);
 
        dev_set_name(&sl->dev, "%02x-%012llx",
                 (unsigned int) sl->reg_num.family,
index 2f3b049..e268add 100644 (file)
@@ -146,12 +146,7 @@ static int kempld_wdt_set_stage_timeout(struct kempld_wdt_data *wdt_data,
        u32 remainder;
        u8 stage_cfg;
 
-#if GCC_VERSION < 40400
-       /* work around a bug compiling do_div() */
-       prescaler = READ_ONCE(kempld_prescaler[PRESCALER_21]);
-#else
        prescaler = kempld_prescaler[PRESCALER_21];
-#endif
 
        if (!stage)
                return -EINVAL;
index c866a62..57390c7 100644 (file)
@@ -479,18 +479,25 @@ static const struct vm_operations_struct gntdev_vmops = {
 
 /* ------------------------------------------------------------------ */
 
+static bool in_range(struct gntdev_grant_map *map,
+                             unsigned long start, unsigned long end)
+{
+       if (!map->vma)
+               return false;
+       if (map->vma->vm_start >= end)
+               return false;
+       if (map->vma->vm_end <= start)
+               return false;
+
+       return true;
+}
+
 static void unmap_if_in_range(struct gntdev_grant_map *map,
                              unsigned long start, unsigned long end)
 {
        unsigned long mstart, mend;
        int err;
 
-       if (!map->vma)
-               return;
-       if (map->vma->vm_start >= end)
-               return;
-       if (map->vma->vm_end <= start)
-               return;
        mstart = max(start, map->vma->vm_start);
        mend   = min(end,   map->vma->vm_end);
        pr_debug("map %d+%d (%lx %lx), range %lx %lx, mrange %lx %lx\n",
@@ -503,21 +510,40 @@ static void unmap_if_in_range(struct gntdev_grant_map *map,
        WARN_ON(err);
 }
 
-static void mn_invl_range_start(struct mmu_notifier *mn,
+static int mn_invl_range_start(struct mmu_notifier *mn,
                                struct mm_struct *mm,
-                               unsigned long start, unsigned long end)
+                               unsigned long start, unsigned long end,
+                               bool blockable)
 {
        struct gntdev_priv *priv = container_of(mn, struct gntdev_priv, mn);
        struct gntdev_grant_map *map;
+       int ret = 0;
+
+       /* TODO do we really need a mutex here? */
+       if (blockable)
+               mutex_lock(&priv->lock);
+       else if (!mutex_trylock(&priv->lock))
+               return -EAGAIN;
 
-       mutex_lock(&priv->lock);
        list_for_each_entry(map, &priv->maps, next) {
+               if (in_range(map, start, end)) {
+                       ret = -EAGAIN;
+                       goto out_unlock;
+               }
                unmap_if_in_range(map, start, end);
        }
        list_for_each_entry(map, &priv->freeable_maps, next) {
+               if (in_range(map, start, end)) {
+                       ret = -EAGAIN;
+                       goto out_unlock;
+               }
                unmap_if_in_range(map, start, end);
        }
+
+out_unlock:
        mutex_unlock(&priv->lock);
+
+       return ret;
 }
 
 static void mn_release(struct mmu_notifier *mn,
index 262835a..b8bf61a 100644 (file)
@@ -288,7 +288,6 @@ static int mc_queue_handle(uint32_t flags)
        int ret = 0;
 
        mc_op.cmd = XEN_MC_fetch;
-       mc_op.interface_version = XEN_MCA_INTERFACE_VERSION;
        set_xen_guest_handle(mc_op.u.mc_fetch.data, &g_mi);
        do {
                mc_op.u.mc_fetch.flags = flags;
@@ -358,7 +357,6 @@ static int bind_virq_for_mce(void)
 
        /* Fetch physical CPU Numbers */
        mc_op.cmd = XEN_MC_physcpuinfo;
-       mc_op.interface_version = XEN_MCA_INTERFACE_VERSION;
        set_xen_guest_handle(mc_op.u.mc_physcpuinfo.info, g_physinfo);
        ret = HYPERVISOR_mca(&mc_op);
        if (ret) {
index b29f4e4..fbb9137 100644 (file)
@@ -362,6 +362,12 @@ read_acpi_id(acpi_handle handle, u32 lvl, void *context, void **rv)
        default:
                return AE_OK;
        }
+       if (invalid_phys_cpuid(acpi_get_phys_id(handle,
+                                               acpi_type == ACPI_TYPE_DEVICE,
+                                               acpi_id))) {
+               pr_debug("CPU with ACPI ID %u is unavailable\n", acpi_id);
+               return AE_OK;
+       }
        /* There are more ACPI Processor objects than in x2APIC or MADT.
         * This can happen with incorrect ACPI SSDT declerations. */
        if (acpi_id >= nr_acpi_bits) {
index e91028d..66621e9 100644 (file)
@@ -167,7 +167,7 @@ adfs_mode2atts(struct super_block *sb, struct inode *inode)
  * of time to convert from RISC OS epoch to Unix epoch.
  */
 static void
-adfs_adfs2unix_time(struct timespec *tv, struct inode *inode)
+adfs_adfs2unix_time(struct timespec64 *tv, struct inode *inode)
 {
        unsigned int high, low;
        /* 01 Jan 1970 00:00:00 (Unix epoch) as nanoseconds since
@@ -195,11 +195,11 @@ adfs_adfs2unix_time(struct timespec *tv, struct inode *inode)
        /* convert from RISC OS to Unix epoch */
        nsec -= nsec_unix_epoch_diff_risc_os_epoch;
 
-       *tv = ns_to_timespec(nsec);
+       *tv = ns_to_timespec64(nsec);
        return;
 
  cur_time:
-       *tv = timespec64_to_timespec(current_time(inode));
+       *tv = current_time(inode);
        return;
 
  too_early:
@@ -242,7 +242,6 @@ adfs_unix2adfs_time(struct inode *inode, unsigned int secs)
 struct inode *
 adfs_iget(struct super_block *sb, struct object_info *obj)
 {
-       struct timespec ts;
        struct inode *inode;
 
        inode = new_inode(sb);
@@ -271,9 +270,7 @@ adfs_iget(struct super_block *sb, struct object_info *obj)
        ADFS_I(inode)->stamped   = ((obj->loadaddr & 0xfff00000) == 0xfff00000);
 
        inode->i_mode    = adfs_atts2mode(sb, inode);
-       ts = timespec64_to_timespec(inode->i_mtime);
-       adfs_adfs2unix_time(&ts, inode);
-       inode->i_mtime = timespec_to_timespec64(ts);
+       adfs_adfs2unix_time(&inode->i_mtime, inode);
        inode->i_atime = inode->i_mtime;
        inode->i_ctime = inode->i_mtime;
 
index 9778df1..871a228 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/fscache.h>
 #include <linux/backing-dev.h>
 #include <linux/uuid.h>
+#include <linux/mm_types.h>
 #include <net/net_namespace.h>
 #include <net/netns/generic.h>
 #include <net/sock.h>
@@ -1076,7 +1077,7 @@ 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 int afs_page_mkwrite(struct vm_fault *);
+extern vm_fault_t afs_page_mkwrite(struct vm_fault *vmf);
 extern void afs_prune_wb_keys(struct afs_vnode *);
 extern int afs_launder_page(struct page *);
 
index 8b39e6e..19c04ca 100644 (file)
@@ -753,7 +753,7 @@ int afs_fsync(struct file *file, loff_t start, loff_t end, int datasync)
  * notification that a previously read-only page is about to become writable
  * - if it returns an error, the caller will deliver a bus error signal
  */
-int afs_page_mkwrite(struct vm_fault *vmf)
+vm_fault_t afs_page_mkwrite(struct vm_fault *vmf)
 {
        struct file *file = vmf->vma->vm_file;
        struct inode *inode = file_inode(file);
index 9400a9f..9f9cadb 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/string.h>
 #include <linux/wait.h>
 #include <linux/sched.h>
+#include <linux/sched/signal.h>
 #include <linux/mount.h>
 #include <linux/namei.h>
 #include <linux/uaccess.h>
@@ -26,6 +27,7 @@
 #include <linux/list.h>
 #include <linux/completion.h>
 #include <linux/file.h>
+#include <linux/magic.h>
 
 /* This is the range of ioctl() numbers we claim as ours */
 #define AUTOFS_IOC_FIRST     AUTOFS_IOC_READY
@@ -124,7 +126,8 @@ struct autofs_sb_info {
 
 static inline struct autofs_sb_info *autofs_sbi(struct super_block *sb)
 {
-       return (struct autofs_sb_info *)(sb->s_fs_info);
+       return sb->s_magic != AUTOFS_SUPER_MAGIC ?
+               NULL : (struct autofs_sb_info *)(sb->s_fs_info);
 }
 
 static inline struct autofs_info *autofs_dentry_ino(struct dentry *dentry)
@@ -151,15 +154,9 @@ int autofs_expire_run(struct super_block *, struct vfsmount *,
                      struct autofs_sb_info *,
                      struct autofs_packet_expire __user *);
 int autofs_do_expire_multi(struct super_block *sb, struct vfsmount *mnt,
-                          struct autofs_sb_info *sbi, int when);
+                          struct autofs_sb_info *sbi, unsigned int how);
 int autofs_expire_multi(struct super_block *, struct vfsmount *,
                        struct autofs_sb_info *, int __user *);
-struct dentry *autofs_expire_direct(struct super_block *sb,
-                                   struct vfsmount *mnt,
-                                   struct autofs_sb_info *sbi, int how);
-struct dentry *autofs_expire_indirect(struct super_block *sb,
-                                     struct vfsmount *mnt,
-                                     struct autofs_sb_info *sbi, int how);
 
 /* Device node initialization */
 
index b332d3f..d441244 100644 (file)
 
 #include "autofs_i.h"
 
-static unsigned long now;
-
 /* Check if a dentry can be expired */
 static inline int autofs_can_expire(struct dentry *dentry,
-                                   unsigned long timeout, int do_now)
+                                   unsigned long timeout, unsigned int how)
 {
        struct autofs_info *ino = autofs_dentry_ino(dentry);
 
@@ -22,16 +20,17 @@ static inline int autofs_can_expire(struct dentry *dentry,
        if (ino == NULL)
                return 0;
 
-       if (!do_now) {
+       if (!(how & AUTOFS_EXP_IMMEDIATE)) {
                /* Too young to die */
-               if (!timeout || time_after(ino->last_used + timeout, now))
+               if (!timeout || time_after(ino->last_used + timeout, jiffies))
                        return 0;
        }
        return 1;
 }
 
 /* Check a mount point for busyness */
-static int autofs_mount_busy(struct vfsmount *mnt, struct dentry *dentry)
+static int autofs_mount_busy(struct vfsmount *mnt,
+                            struct dentry *dentry, unsigned int how)
 {
        struct dentry *top = dentry;
        struct path path = {.mnt = mnt, .dentry = dentry};
@@ -52,6 +51,12 @@ static int autofs_mount_busy(struct vfsmount *mnt, struct dentry *dentry)
                        goto done;
        }
 
+       /* Not a submount, has a forced expire been requested */
+       if (how & AUTOFS_EXP_FORCED) {
+               status = 0;
+               goto done;
+       }
+
        /* Update the expiry counter if fs is busy */
        if (!may_umount_tree(path.mnt)) {
                struct autofs_info *ino;
@@ -187,10 +192,14 @@ again:
 static int autofs_direct_busy(struct vfsmount *mnt,
                              struct dentry *top,
                              unsigned long timeout,
-                             int do_now)
+                             unsigned int how)
 {
        pr_debug("top %p %pd\n", top, top);
 
+       /* Forced expire, user space handles busy mounts */
+       if (how & AUTOFS_EXP_FORCED)
+               return 0;
+
        /* If it's busy update the expiry counters */
        if (!may_umount_tree(mnt)) {
                struct autofs_info *ino;
@@ -202,7 +211,7 @@ static int autofs_direct_busy(struct vfsmount *mnt,
        }
 
        /* Timeout of a direct mount is determined by its top dentry */
-       if (!autofs_can_expire(top, timeout, do_now))
+       if (!autofs_can_expire(top, timeout, how))
                return 1;
 
        return 0;
@@ -215,7 +224,7 @@ static int autofs_direct_busy(struct vfsmount *mnt,
 static int autofs_tree_busy(struct vfsmount *mnt,
                            struct dentry *top,
                            unsigned long timeout,
-                           int do_now)
+                           unsigned int how)
 {
        struct autofs_info *top_ino = autofs_dentry_ino(top);
        struct dentry *p;
@@ -237,7 +246,7 @@ static int autofs_tree_busy(struct vfsmount *mnt,
                 * If the fs is busy update the expiry counter.
                 */
                if (d_mountpoint(p)) {
-                       if (autofs_mount_busy(mnt, p)) {
+                       if (autofs_mount_busy(mnt, p, how)) {
                                top_ino->last_used = jiffies;
                                dput(p);
                                return 1;
@@ -260,8 +269,12 @@ static int autofs_tree_busy(struct vfsmount *mnt,
                }
        }
 
+       /* Forced expire, user space handles busy mounts */
+       if (how & AUTOFS_EXP_FORCED)
+               return 0;
+
        /* Timeout of a tree mount is ultimately determined by its top dentry */
-       if (!autofs_can_expire(top, timeout, do_now))
+       if (!autofs_can_expire(top, timeout, how))
                return 1;
 
        return 0;
@@ -270,7 +283,7 @@ static int autofs_tree_busy(struct vfsmount *mnt,
 static struct dentry *autofs_check_leaves(struct vfsmount *mnt,
                                          struct dentry *parent,
                                          unsigned long timeout,
-                                         int do_now)
+                                         unsigned int how)
 {
        struct dentry *p;
 
@@ -282,11 +295,17 @@ static struct dentry *autofs_check_leaves(struct vfsmount *mnt,
 
                if (d_mountpoint(p)) {
                        /* Can we umount this guy */
-                       if (autofs_mount_busy(mnt, p))
+                       if (autofs_mount_busy(mnt, p, how))
                                continue;
 
+                       /* This isn't a submount so if a forced expire
+                        * has been requested, user space handles busy
+                        * mounts */
+                       if (how & AUTOFS_EXP_FORCED)
+                               return p;
+
                        /* Can we expire this guy */
-                       if (autofs_can_expire(p, timeout, do_now))
+                       if (autofs_can_expire(p, timeout, how))
                                return p;
                }
        }
@@ -294,23 +313,21 @@ static struct dentry *autofs_check_leaves(struct vfsmount *mnt,
 }
 
 /* Check if we can expire a direct mount (possibly a tree) */
-struct dentry *autofs_expire_direct(struct super_block *sb,
-                                   struct vfsmount *mnt,
-                                   struct autofs_sb_info *sbi,
-                                   int how)
+static struct dentry *autofs_expire_direct(struct super_block *sb,
+                                          struct vfsmount *mnt,
+                                          struct autofs_sb_info *sbi,
+                                          unsigned int how)
 {
-       unsigned long timeout;
        struct dentry *root = dget(sb->s_root);
-       int do_now = how & AUTOFS_EXP_IMMEDIATE;
        struct autofs_info *ino;
+       unsigned long timeout;
 
        if (!root)
                return NULL;
 
-       now = jiffies;
        timeout = sbi->exp_timeout;
 
-       if (!autofs_direct_busy(mnt, root, timeout, do_now)) {
+       if (!autofs_direct_busy(mnt, root, timeout, how)) {
                spin_lock(&sbi->fs_lock);
                ino = autofs_dentry_ino(root);
                /* No point expiring a pending mount */
@@ -321,7 +338,7 @@ struct dentry *autofs_expire_direct(struct super_block *sb,
                ino->flags |= AUTOFS_INF_WANT_EXPIRE;
                spin_unlock(&sbi->fs_lock);
                synchronize_rcu();
-               if (!autofs_direct_busy(mnt, root, timeout, do_now)) {
+               if (!autofs_direct_busy(mnt, root, timeout, how)) {
                        spin_lock(&sbi->fs_lock);
                        ino->flags |= AUTOFS_INF_EXPIRING;
                        init_completion(&ino->expire_complete);
@@ -346,10 +363,8 @@ out:
 static struct dentry *should_expire(struct dentry *dentry,
                                    struct vfsmount *mnt,
                                    unsigned long timeout,
-                                   int how)
+                                   unsigned int how)
 {
-       int do_now = how & AUTOFS_EXP_IMMEDIATE;
-       int exp_leaves = how & AUTOFS_EXP_LEAVES;
        struct autofs_info *ino = autofs_dentry_ino(dentry);
        unsigned int ino_count;
 
@@ -367,22 +382,33 @@ static struct dentry *should_expire(struct dentry *dentry,
                pr_debug("checking mountpoint %p %pd\n", dentry, dentry);
 
                /* Can we umount this guy */
-               if (autofs_mount_busy(mnt, dentry))
+               if (autofs_mount_busy(mnt, dentry, how))
                        return NULL;
 
+               /* This isn't a submount so if a forced expire
+                * has been requested, user space handles busy
+                * mounts */
+               if (how & AUTOFS_EXP_FORCED)
+                       return dentry;
+
                /* Can we expire this guy */
-               if (autofs_can_expire(dentry, timeout, do_now))
+               if (autofs_can_expire(dentry, timeout, how))
                        return dentry;
                return NULL;
        }
 
        if (d_really_is_positive(dentry) && d_is_symlink(dentry)) {
                pr_debug("checking symlink %p %pd\n", dentry, dentry);
+
+               /* Forced expire, user space handles busy mounts */
+               if (how & AUTOFS_EXP_FORCED)
+                       return dentry;
+
                /*
                 * A symlink can't be "busy" in the usual sense so
                 * just check last used for expire timeout.
                 */
-               if (autofs_can_expire(dentry, timeout, do_now))
+               if (autofs_can_expire(dentry, timeout, how))
                        return dentry;
                return NULL;
        }
@@ -391,27 +417,33 @@ static struct dentry *should_expire(struct dentry *dentry,
                return NULL;
 
        /* Case 2: tree mount, expire iff entire tree is not busy */
-       if (!exp_leaves) {
-               /* Path walk currently on this dentry? */
-               ino_count = atomic_read(&ino->count) + 1;
-               if (d_count(dentry) > ino_count)
-                       return NULL;
+       if (!(how & AUTOFS_EXP_LEAVES)) {
+               /* Not a forced expire? */
+               if (!(how & AUTOFS_EXP_FORCED)) {
+                       /* ref-walk currently on this dentry? */
+                       ino_count = atomic_read(&ino->count) + 1;
+                       if (d_count(dentry) > ino_count)
+                               return NULL;
+               }
 
-               if (!autofs_tree_busy(mnt, dentry, timeout, do_now))
+               if (!autofs_tree_busy(mnt, dentry, timeout, how))
                        return dentry;
        /*
         * Case 3: pseudo direct mount, expire individual leaves
         *         (autofs-4.1).
         */
        } else {
-               /* Path walk currently on this dentry? */
                struct dentry *expired;
 
-               ino_count = atomic_read(&ino->count) + 1;
-               if (d_count(dentry) > ino_count)
-                       return NULL;
+               /* Not a forced expire? */
+               if (!(how & AUTOFS_EXP_FORCED)) {
+                       /* ref-walk currently on this dentry? */
+                       ino_count = atomic_read(&ino->count) + 1;
+                       if (d_count(dentry) > ino_count)
+                               return NULL;
+               }
 
-               expired = autofs_check_leaves(mnt, dentry, timeout, do_now);
+               expired = autofs_check_leaves(mnt, dentry, timeout, how);
                if (expired) {
                        if (expired == dentry)
                                dput(dentry);
@@ -427,10 +459,10 @@ static struct dentry *should_expire(struct dentry *dentry,
  *  - it is unused by any user process
  *  - it has been unused for exp_timeout time
  */
-struct dentry *autofs_expire_indirect(struct super_block *sb,
-                                     struct vfsmount *mnt,
-                                     struct autofs_sb_info *sbi,
-                                     int how)
+static struct dentry *autofs_expire_indirect(struct super_block *sb,
+                                            struct vfsmount *mnt,
+                                            struct autofs_sb_info *sbi,
+                                            unsigned int how)
 {
        unsigned long timeout;
        struct dentry *root = sb->s_root;
@@ -442,13 +474,10 @@ struct dentry *autofs_expire_indirect(struct super_block *sb,
        if (!root)
                return NULL;
 
-       now = jiffies;
        timeout = sbi->exp_timeout;
 
        dentry = NULL;
        while ((dentry = get_next_positive_subdir(dentry, root))) {
-               int flags = how;
-
                spin_lock(&sbi->fs_lock);
                ino = autofs_dentry_ino(dentry);
                if (ino->flags & AUTOFS_INF_WANT_EXPIRE) {
@@ -457,7 +486,7 @@ struct dentry *autofs_expire_indirect(struct super_block *sb,
                }
                spin_unlock(&sbi->fs_lock);
 
-               expired = should_expire(dentry, mnt, timeout, flags);
+               expired = should_expire(dentry, mnt, timeout, how);
                if (!expired)
                        continue;
 
@@ -470,7 +499,7 @@ struct dentry *autofs_expire_indirect(struct super_block *sb,
                /* Make sure a reference is not taken on found if
                 * things have changed.
                 */
-               flags &= ~AUTOFS_EXP_LEAVES;
+               how &= ~AUTOFS_EXP_LEAVES;
                found = should_expire(expired, mnt, timeout, how);
                if (!found || found != expired)
                        /* Something has changed, continue */
@@ -575,7 +604,7 @@ int autofs_expire_run(struct super_block *sb,
        spin_lock(&sbi->fs_lock);
        ino = autofs_dentry_ino(dentry);
        /* avoid rapid-fire expire attempts if expiry fails */
-       ino->last_used = now;
+       ino->last_used = jiffies;
        ino->flags &= ~(AUTOFS_INF_EXPIRING|AUTOFS_INF_WANT_EXPIRE);
        complete_all(&ino->expire_complete);
        spin_unlock(&sbi->fs_lock);
@@ -584,15 +613,15 @@ int autofs_expire_run(struct super_block *sb,
 }
 
 int autofs_do_expire_multi(struct super_block *sb, struct vfsmount *mnt,
-                          struct autofs_sb_info *sbi, int when)
+                          struct autofs_sb_info *sbi, unsigned int how)
 {
        struct dentry *dentry;
        int ret = -EAGAIN;
 
        if (autofs_type_trigger(sbi->type))
-               dentry = autofs_expire_direct(sb, mnt, sbi, when);
+               dentry = autofs_expire_direct(sb, mnt, sbi, how);
        else
-               dentry = autofs_expire_indirect(sb, mnt, sbi, when);
+               dentry = autofs_expire_indirect(sb, mnt, sbi, how);
 
        if (dentry) {
                struct autofs_info *ino = autofs_dentry_ino(dentry);
@@ -605,7 +634,7 @@ int autofs_do_expire_multi(struct super_block *sb, struct vfsmount *mnt,
 
                spin_lock(&sbi->fs_lock);
                /* avoid rapid-fire expire attempts if expiry fails */
-               ino->last_used = now;
+               ino->last_used = jiffies;
                ino->flags &= ~(AUTOFS_INF_EXPIRING|AUTOFS_INF_WANT_EXPIRE);
                complete_all(&ino->expire_complete);
                spin_unlock(&sbi->fs_lock);
@@ -622,10 +651,10 @@ int autofs_do_expire_multi(struct super_block *sb, struct vfsmount *mnt,
 int autofs_expire_multi(struct super_block *sb, struct vfsmount *mnt,
                        struct autofs_sb_info *sbi, int __user *arg)
 {
-       int do_now = 0;
+       unsigned int how = 0;
 
-       if (arg && get_user(do_now, arg))
+       if (arg && get_user(how, arg))
                return -EFAULT;
 
-       return autofs_do_expire_multi(sb, mnt, sbi, do_now);
+       return autofs_do_expire_multi(sb, mnt, sbi, how);
 }
index b51980f..846c052 100644 (file)
@@ -10,7 +10,6 @@
 #include <linux/seq_file.h>
 #include <linux/pagemap.h>
 #include <linux/parser.h>
-#include <linux/magic.h>
 
 #include "autofs_i.h"
 
index a3d4141..782e57b 100644 (file)
@@ -559,6 +559,13 @@ static int autofs_dir_symlink(struct inode *dir,
        if (!autofs_oz_mode(sbi))
                return -EACCES;
 
+       /* autofs_oz_mode() needs to allow path walks when the
+        * autofs mount is catatonic but the state of an autofs
+        * file system needs to be preserved over restarts.
+        */
+       if (sbi->catatonic)
+               return -EACCES;
+
        BUG_ON(!ino);
 
        autofs_clean_ino(ino);
@@ -612,9 +619,15 @@ static int autofs_dir_unlink(struct inode *dir, struct dentry *dentry)
        struct autofs_info *ino = autofs_dentry_ino(dentry);
        struct autofs_info *p_ino;
 
-       /* This allows root to remove symlinks */
-       if (!autofs_oz_mode(sbi) && !capable(CAP_SYS_ADMIN))
-               return -EPERM;
+       if (!autofs_oz_mode(sbi))
+               return -EACCES;
+
+       /* autofs_oz_mode() needs to allow path walks when the
+        * autofs mount is catatonic but the state of an autofs
+        * file system needs to be preserved over restarts.
+        */
+       if (sbi->catatonic)
+               return -EACCES;
 
        if (atomic_dec_and_test(&ino->count)) {
                p_ino = autofs_dentry_ino(dentry->d_parent);
@@ -697,6 +710,13 @@ static int autofs_dir_rmdir(struct inode *dir, struct dentry *dentry)
        if (!autofs_oz_mode(sbi))
                return -EACCES;
 
+       /* autofs_oz_mode() needs to allow path walks when the
+        * autofs mount is catatonic but the state of an autofs
+        * file system needs to be preserved over restarts.
+        */
+       if (sbi->catatonic)
+               return -EACCES;
+
        spin_lock(&sbi->lookup_lock);
        if (!simple_empty(dentry)) {
                spin_unlock(&sbi->lookup_lock);
@@ -735,6 +755,13 @@ static int autofs_dir_mkdir(struct inode *dir,
        if (!autofs_oz_mode(sbi))
                return -EACCES;
 
+       /* autofs_oz_mode() needs to allow path walks when the
+        * autofs mount is catatonic but the state of an autofs
+        * file system needs to be preserved over restarts.
+        */
+       if (sbi->catatonic)
+               return -EACCES;
+
        pr_debug("dentry %p, creating %pd\n", dentry, dentry);
 
        BUG_ON(!ino);
index 318be78..53af9f5 100644 (file)
@@ -3217,8 +3217,9 @@ void btrfs_get_block_group_info(struct list_head *groups_list,
                                struct btrfs_ioctl_space_info *space);
 void btrfs_update_ioctl_balance_args(struct btrfs_fs_info *fs_info,
                               struct btrfs_ioctl_balance_args *bargs);
-ssize_t btrfs_dedupe_file_range(struct file *src_file, u64 loff, u64 olen,
-                          struct file *dst_file, u64 dst_loff);
+int btrfs_dedupe_file_range(struct file *src_file, loff_t src_loff,
+                           struct file *dst_file, loff_t dst_loff,
+                           u64 olen);
 
 /* file.c */
 int __init btrfs_auto_defrag_init(void);
index d3a5d2a..63600dc 100644 (file)
@@ -3592,13 +3592,13 @@ out_unlock:
        return ret;
 }
 
-ssize_t btrfs_dedupe_file_range(struct file *src_file, u64 loff, u64 olen,
-                               struct file *dst_file, u64 dst_loff)
+int btrfs_dedupe_file_range(struct file *src_file, loff_t src_loff,
+                           struct file *dst_file, loff_t dst_loff,
+                           u64 olen)
 {
        struct inode *src = file_inode(src_file);
        struct inode *dst = file_inode(dst_file);
        u64 bs = BTRFS_I(src)->root->fs_info->sb->s_blocksize;
-       ssize_t res;
 
        if (WARN_ON_ONCE(bs < PAGE_SIZE)) {
                /*
@@ -3609,10 +3609,7 @@ ssize_t btrfs_dedupe_file_range(struct file *src_file, u64 loff, u64 olen,
                return -EINVAL;
        }
 
-       res = btrfs_extent_same(src, loff, olen, dst, dst_loff);
-       if (res)
-               return res;
-       return olen;
+       return btrfs_extent_same(src, src_loff, olen, dst, dst_loff);
 }
 
 static int clone_finish_inode_update(struct btrfs_trans_handle *trans,
index 59cb307..027408d 100644 (file)
@@ -45,6 +45,7 @@ static inline void ceph_set_cached_acl(struct inode *inode,
 struct posix_acl *ceph_get_acl(struct inode *inode, int type)
 {
        int size;
+       unsigned int retry_cnt = 0;
        const char *name;
        char *value = NULL;
        struct posix_acl *acl;
@@ -60,6 +61,7 @@ struct posix_acl *ceph_get_acl(struct inode *inode, int type)
                BUG();
        }
 
+retry:
        size = __ceph_getxattr(inode, name, "", 0);
        if (size > 0) {
                value = kzalloc(size, GFP_NOFS);
@@ -68,12 +70,22 @@ struct posix_acl *ceph_get_acl(struct inode *inode, int type)
                size = __ceph_getxattr(inode, name, value, size);
        }
 
-       if (size > 0)
+       if (size == -ERANGE && retry_cnt < 10) {
+               retry_cnt++;
+               kfree(value);
+               value = NULL;
+               goto retry;
+       }
+
+       if (size > 0) {
                acl = posix_acl_from_xattr(&init_user_ns, value, size);
-       else if (size == -ERANGE || size == -ENODATA || size == 0)
+       } else if (size == -ENODATA || size == 0) {
                acl = NULL;
-       else
+       } else {
+               pr_err_ratelimited("get acl %llx.%llx failed, err=%d\n",
+                                  ceph_vinop(inode), size);
                acl = ERR_PTR(-EIO);
+       }
 
        kfree(value);
 
@@ -89,6 +101,7 @@ int ceph_set_acl(struct inode *inode, struct posix_acl *acl, int type)
        const char *name = NULL;
        char *value = NULL;
        struct iattr newattrs;
+       struct timespec64 old_ctime = inode->i_ctime;
        umode_t new_mode = inode->i_mode, old_mode = inode->i_mode;
 
        switch (type) {
@@ -133,7 +146,7 @@ int ceph_set_acl(struct inode *inode, struct posix_acl *acl, int type)
        if (new_mode != old_mode) {
                newattrs.ia_ctime = current_time(inode);
                newattrs.ia_mode = new_mode;
-               newattrs.ia_valid = ATTR_MODE;
+               newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
                ret = __ceph_setattr(inode, &newattrs);
                if (ret)
                        goto out_free;
@@ -142,8 +155,9 @@ int ceph_set_acl(struct inode *inode, struct posix_acl *acl, int type)
        ret = __ceph_setxattr(inode, name, value, size, 0);
        if (ret) {
                if (new_mode != old_mode) {
+                       newattrs.ia_ctime = old_ctime;
                        newattrs.ia_mode = old_mode;
-                       newattrs.ia_valid = ATTR_MODE;
+                       newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
                        __ceph_setattr(inode, &newattrs);
                }
                goto out_free;
@@ -171,10 +185,10 @@ int ceph_pre_init_acls(struct inode *dir, umode_t *mode,
                return err;
 
        if (acl) {
-               int ret = posix_acl_equiv_mode(acl, mode);
-               if (ret < 0)
+               err = posix_acl_equiv_mode(acl, mode);
+               if (err < 0)
                        goto out_err;
-               if (ret == 0) {
+               if (err == 0) {
                        posix_acl_release(acl);
                        acl = NULL;
                }
index 292b3d7..9c332a6 100644 (file)
@@ -574,7 +574,6 @@ static u64 get_writepages_data_length(struct inode *inode,
  */
 static int writepage_nounlock(struct page *page, struct writeback_control *wbc)
 {
-       struct timespec ts;
        struct inode *inode;
        struct ceph_inode_info *ci;
        struct ceph_fs_client *fsc;
@@ -625,12 +624,11 @@ static int writepage_nounlock(struct page *page, struct writeback_control *wbc)
                set_bdi_congested(inode_to_bdi(inode), BLK_RW_ASYNC);
 
        set_page_writeback(page);
-       ts = timespec64_to_timespec(inode->i_mtime);
        err = ceph_osdc_writepages(&fsc->client->osdc, ceph_vino(inode),
                                   &ci->i_layout, snapc, page_off, len,
                                   ceph_wbc.truncate_seq,
                                   ceph_wbc.truncate_size,
-                                  &ts, &page, 1);
+                                  &inode->i_mtime, &page, 1);
        if (err < 0) {
                struct writeback_control tmp_wbc;
                if (!wbc)
@@ -1134,7 +1132,7 @@ new_request:
                        pages = NULL;
                }
 
-               req->r_mtime = timespec64_to_timespec(inode->i_mtime);
+               req->r_mtime = inode->i_mtime;
                rc = ceph_osdc_start_request(&fsc->client->osdc, req, true);
                BUG_ON(rc);
                req = NULL;
@@ -1431,7 +1429,7 @@ static void ceph_restore_sigs(sigset_t *oldset)
 /*
  * vm ops
  */
-static int ceph_filemap_fault(struct vm_fault *vmf)
+static vm_fault_t ceph_filemap_fault(struct vm_fault *vmf)
 {
        struct vm_area_struct *vma = vmf->vma;
        struct inode *inode = file_inode(vma->vm_file);
@@ -1439,8 +1437,9 @@ static int ceph_filemap_fault(struct vm_fault *vmf)
        struct ceph_file_info *fi = vma->vm_file->private_data;
        struct page *pinned_page = NULL;
        loff_t off = vmf->pgoff << PAGE_SHIFT;
-       int want, got, ret;
+       int want, got, err;
        sigset_t oldset;
+       vm_fault_t ret = VM_FAULT_SIGBUS;
 
        ceph_block_sigs(&oldset);
 
@@ -1452,8 +1451,8 @@ static int ceph_filemap_fault(struct vm_fault *vmf)
                want = CEPH_CAP_FILE_CACHE;
 
        got = 0;
-       ret = ceph_get_caps(ci, CEPH_CAP_FILE_RD, want, -1, &got, &pinned_page);
-       if (ret < 0)
+       err = ceph_get_caps(ci, CEPH_CAP_FILE_RD, want, -1, &got, &pinned_page);
+       if (err < 0)
                goto out_restore;
 
        dout("filemap_fault %p %llu~%zd got cap refs on %s\n",
@@ -1465,16 +1464,17 @@ static int ceph_filemap_fault(struct vm_fault *vmf)
                ceph_add_rw_context(fi, &rw_ctx);
                ret = filemap_fault(vmf);
                ceph_del_rw_context(fi, &rw_ctx);
+               dout("filemap_fault %p %llu~%zd drop cap refs %s ret %x\n",
+                       inode, off, (size_t)PAGE_SIZE,
+                               ceph_cap_string(got), ret);
        } else
-               ret = -EAGAIN;
+               err = -EAGAIN;
 
-       dout("filemap_fault %p %llu~%zd dropping cap refs on %s ret %d\n",
-            inode, off, (size_t)PAGE_SIZE, ceph_cap_string(got), ret);
        if (pinned_page)
                put_page(pinned_page);
        ceph_put_cap_refs(ci, got);
 
-       if (ret != -EAGAIN)
+       if (err != -EAGAIN)
                goto out_restore;
 
        /* read inline data */
@@ -1482,7 +1482,6 @@ static int ceph_filemap_fault(struct vm_fault *vmf)
                /* does not support inline data > PAGE_SIZE */
                ret = VM_FAULT_SIGBUS;
        } else {
-               int ret1;
                struct address_space *mapping = inode->i_mapping;
                struct page *page = find_or_create_page(mapping, 0,
                                                mapping_gfp_constraint(mapping,
@@ -1491,32 +1490,32 @@ static int ceph_filemap_fault(struct vm_fault *vmf)
                        ret = VM_FAULT_OOM;
                        goto out_inline;
                }
-               ret1 = __ceph_do_getattr(inode, page,
+               err = __ceph_do_getattr(inode, page,
                                         CEPH_STAT_CAP_INLINE_DATA, true);
-               if (ret1 < 0 || off >= i_size_read(inode)) {
+               if (err < 0 || off >= i_size_read(inode)) {
                        unlock_page(page);
                        put_page(page);
-                       if (ret1 < 0)
-                               ret = ret1;
+                       if (err == -ENOMEM)
+                               ret = VM_FAULT_OOM;
                        else
                                ret = VM_FAULT_SIGBUS;
                        goto out_inline;
                }
-               if (ret1 < PAGE_SIZE)
-                       zero_user_segment(page, ret1, PAGE_SIZE);
+               if (err < PAGE_SIZE)
+                       zero_user_segment(page, err, PAGE_SIZE);
                else
                        flush_dcache_page(page);
                SetPageUptodate(page);
                vmf->page = page;
                ret = VM_FAULT_MAJOR | VM_FAULT_LOCKED;
 out_inline:
-               dout("filemap_fault %p %llu~%zd read inline data ret %d\n",
+               dout("filemap_fault %p %llu~%zd read inline data ret %x\n",
                     inode, off, (size_t)PAGE_SIZE, ret);
        }
 out_restore:
        ceph_restore_sigs(&oldset);
-       if (ret < 0)
-               ret = (ret == -ENOMEM) ? VM_FAULT_OOM : VM_FAULT_SIGBUS;
+       if (err < 0)
+               ret = vmf_error(err);
 
        return ret;
 }
@@ -1524,7 +1523,7 @@ out_restore:
 /*
  * Reuse write_begin here for simplicity.
  */
-static int ceph_page_mkwrite(struct vm_fault *vmf)
+static vm_fault_t ceph_page_mkwrite(struct vm_fault *vmf)
 {
        struct vm_area_struct *vma = vmf->vma;
        struct inode *inode = file_inode(vma->vm_file);
@@ -1535,8 +1534,9 @@ static int ceph_page_mkwrite(struct vm_fault *vmf)
        loff_t off = page_offset(page);
        loff_t size = i_size_read(inode);
        size_t len;
-       int want, got, ret;
+       int want, got, err;
        sigset_t oldset;
+       vm_fault_t ret = VM_FAULT_SIGBUS;
 
        prealloc_cf = ceph_alloc_cap_flush();
        if (!prealloc_cf)
@@ -1550,10 +1550,10 @@ static int ceph_page_mkwrite(struct vm_fault *vmf)
                        lock_page(page);
                        locked_page = page;
                }
-               ret = ceph_uninline_data(vma->vm_file, locked_page);
+               err = ceph_uninline_data(vma->vm_file, locked_page);
                if (locked_page)
                        unlock_page(locked_page);
-               if (ret < 0)
+               if (err < 0)
                        goto out_free;
        }
 
@@ -1570,9 +1570,9 @@ static int ceph_page_mkwrite(struct vm_fault *vmf)
                want = CEPH_CAP_FILE_BUFFER;
 
        got = 0;
-       ret = ceph_get_caps(ci, CEPH_CAP_FILE_WR, want, off + len,
+       err = ceph_get_caps(ci, CEPH_CAP_FILE_WR, want, off + len,
                            &got, NULL);
-       if (ret < 0)
+       if (err < 0)
                goto out_free;
 
        dout("page_mkwrite %p %llu~%zd got cap refs on %s\n",
@@ -1590,13 +1590,13 @@ static int ceph_page_mkwrite(struct vm_fault *vmf)
                        break;
                }
 
-               ret = ceph_update_writeable_page(vma->vm_file, off, len, page);
-               if (ret >= 0) {
+               err = ceph_update_writeable_page(vma->vm_file, off, len, page);
+               if (err >= 0) {
                        /* success.  we'll keep the page locked. */
                        set_page_dirty(page);
                        ret = VM_FAULT_LOCKED;
                }
-       } while (ret == -EAGAIN);
+       } while (err == -EAGAIN);
 
        if (ret == VM_FAULT_LOCKED ||
            ci->i_inline_version != CEPH_INLINE_NONE) {
@@ -1610,14 +1610,14 @@ static int ceph_page_mkwrite(struct vm_fault *vmf)
                        __mark_inode_dirty(inode, dirty);
        }
 
-       dout("page_mkwrite %p %llu~%zd dropping cap refs on %s ret %d\n",
+       dout("page_mkwrite %p %llu~%zd dropping cap refs on %s ret %x\n",
             inode, off, len, ceph_cap_string(got), ret);
        ceph_put_cap_refs(ci, got);
 out_free:
        ceph_restore_sigs(&oldset);
        ceph_free_cap_flush(prealloc_cf);
-       if (ret < 0)
-               ret = (ret == -ENOMEM) ? VM_FAULT_OOM : VM_FAULT_SIGBUS;
+       if (err < 0)
+               ret = vmf_error(err);
        return ret;
 }
 
@@ -1734,7 +1734,7 @@ int ceph_uninline_data(struct file *filp, struct page *locked_page)
                goto out;
        }
 
-       req->r_mtime = timespec64_to_timespec(inode->i_mtime);
+       req->r_mtime = inode->i_mtime;
        err = ceph_osdc_start_request(&fsc->client->osdc, req, false);
        if (!err)
                err = ceph_osdc_wait_request(&fsc->client->osdc, req);
@@ -1776,7 +1776,7 @@ int ceph_uninline_data(struct file *filp, struct page *locked_page)
                        goto out_put;
        }
 
-       req->r_mtime = timespec64_to_timespec(inode->i_mtime);
+       req->r_mtime = inode->i_mtime;
        err = ceph_osdc_start_request(&fsc->client->osdc, req, false);
        if (!err)
                err = ceph_osdc_wait_request(&fsc->client->osdc, req);
@@ -1937,7 +1937,7 @@ static int __ceph_pool_perm_get(struct ceph_inode_info *ci,
                                     0, false, true);
        err = ceph_osdc_start_request(&fsc->client->osdc, rd_req, false);
 
-       wr_req->r_mtime = timespec64_to_timespec(ci->vfs_inode.i_mtime);
+       wr_req->r_mtime = ci->vfs_inode.i_mtime;
        err2 = ceph_osdc_start_request(&fsc->client->osdc, wr_req, false);
 
        if (!err)
index 362900e..1bf3502 100644 (file)
@@ -25,8 +25,9 @@
 #include "cache.h"
 
 struct ceph_aux_inode {
-       u64             version;
-       struct timespec mtime;
+       u64     version;
+       u64     mtime_sec;
+       u64     mtime_nsec;
 };
 
 struct fscache_netfs ceph_cache_netfs = {
@@ -130,7 +131,8 @@ static enum fscache_checkaux ceph_fscache_inode_check_aux(
 
        memset(&aux, 0, sizeof(aux));
        aux.version = ci->i_version;
-       aux.mtime = timespec64_to_timespec(inode->i_mtime);
+       aux.mtime_sec = inode->i_mtime.tv_sec;
+       aux.mtime_nsec = inode->i_mtime.tv_nsec;
 
        if (memcmp(data, &aux, sizeof(aux)) != 0)
                return FSCACHE_CHECKAUX_OBSOLETE;
@@ -163,7 +165,8 @@ void ceph_fscache_register_inode_cookie(struct inode *inode)
        if (!ci->fscache) {
                memset(&aux, 0, sizeof(aux));
                aux.version = ci->i_version;
-               aux.mtime = timespec64_to_timespec(inode->i_mtime);
+               aux.mtime_sec = inode->i_mtime.tv_sec;
+               aux.mtime_nsec = inode->i_mtime.tv_nsec;
                ci->fscache = fscache_acquire_cookie(fsc->fscache,
                                                     &ceph_fscache_inode_object_def,
                                                     &ci->i_vino, sizeof(ci->i_vino),
index 990258c..dd7dfdd 100644 (file)
@@ -156,6 +156,37 @@ void ceph_adjust_min_caps(struct ceph_mds_client *mdsc, int delta)
        spin_unlock(&mdsc->caps_list_lock);
 }
 
+static void __ceph_unreserve_caps(struct ceph_mds_client *mdsc, int nr_caps)
+{
+       struct ceph_cap *cap;
+       int i;
+
+       if (nr_caps) {
+               BUG_ON(mdsc->caps_reserve_count < nr_caps);
+               mdsc->caps_reserve_count -= nr_caps;
+               if (mdsc->caps_avail_count >=
+                   mdsc->caps_reserve_count + mdsc->caps_min_count) {
+                       mdsc->caps_total_count -= nr_caps;
+                       for (i = 0; i < nr_caps; i++) {
+                               cap = list_first_entry(&mdsc->caps_list,
+                                       struct ceph_cap, caps_item);
+                               list_del(&cap->caps_item);
+                               kmem_cache_free(ceph_cap_cachep, cap);
+                       }
+               } else {
+                       mdsc->caps_avail_count += nr_caps;
+               }
+
+               dout("%s: caps %d = %d used + %d resv + %d avail\n",
+                    __func__,
+                    mdsc->caps_total_count, mdsc->caps_use_count,
+                    mdsc->caps_reserve_count, mdsc->caps_avail_count);
+               BUG_ON(mdsc->caps_total_count != mdsc->caps_use_count +
+                                                mdsc->caps_reserve_count +
+                                                mdsc->caps_avail_count);
+       }
+}
+
 /*
  * Called under mdsc->mutex.
  */
@@ -167,6 +198,7 @@ int ceph_reserve_caps(struct ceph_mds_client *mdsc,
        int have;
        int alloc = 0;
        int max_caps;
+       int err = 0;
        bool trimmed = false;
        struct ceph_mds_session *s;
        LIST_HEAD(newcaps);
@@ -233,9 +265,14 @@ int ceph_reserve_caps(struct ceph_mds_client *mdsc,
 
                pr_warn("reserve caps ctx=%p ENOMEM need=%d got=%d\n",
                        ctx, need, have + alloc);
-               goto out_nomem;
+               err = -ENOMEM;
+               break;
+       }
+
+       if (!err) {
+               BUG_ON(have + alloc != need);
+               ctx->count = need;
        }
-       BUG_ON(have + alloc != need);
 
        spin_lock(&mdsc->caps_list_lock);
        mdsc->caps_total_count += alloc;
@@ -245,77 +282,26 @@ int ceph_reserve_caps(struct ceph_mds_client *mdsc,
        BUG_ON(mdsc->caps_total_count != mdsc->caps_use_count +
                                         mdsc->caps_reserve_count +
                                         mdsc->caps_avail_count);
+
+       if (err)
+               __ceph_unreserve_caps(mdsc, have + alloc);
+
        spin_unlock(&mdsc->caps_list_lock);
 
-       ctx->count = need;
        dout("reserve caps ctx=%p %d = %d used + %d resv + %d avail\n",
             ctx, mdsc->caps_total_count, mdsc->caps_use_count,
             mdsc->caps_reserve_count, mdsc->caps_avail_count);
-       return 0;
-
-out_nomem:
-
-       spin_lock(&mdsc->caps_list_lock);
-       mdsc->caps_avail_count += have;
-       mdsc->caps_reserve_count -= have;
-
-       while (!list_empty(&newcaps)) {
-               cap = list_first_entry(&newcaps,
-                               struct ceph_cap, caps_item);
-               list_del(&cap->caps_item);
-
-               /* Keep some preallocated caps around (ceph_min_count), to
-                * avoid lots of free/alloc churn. */
-               if (mdsc->caps_avail_count >=
-                   mdsc->caps_reserve_count + mdsc->caps_min_count) {
-                       kmem_cache_free(ceph_cap_cachep, cap);
-               } else {
-                       mdsc->caps_avail_count++;
-                       mdsc->caps_total_count++;
-                       list_add(&cap->caps_item, &mdsc->caps_list);
-               }
-       }
-
-       BUG_ON(mdsc->caps_total_count != mdsc->caps_use_count +
-                                        mdsc->caps_reserve_count +
-                                        mdsc->caps_avail_count);
-       spin_unlock(&mdsc->caps_list_lock);
-       return -ENOMEM;
+       return err;
 }
 
-int ceph_unreserve_caps(struct ceph_mds_client *mdsc,
+void ceph_unreserve_caps(struct ceph_mds_client *mdsc,
                        struct ceph_cap_reservation *ctx)
 {
-       int i;
-       struct ceph_cap *cap;
-
        dout("unreserve caps ctx=%p count=%d\n", ctx, ctx->count);
-       if (ctx->count) {
-               spin_lock(&mdsc->caps_list_lock);
-               BUG_ON(mdsc->caps_reserve_count < ctx->count);
-               mdsc->caps_reserve_count -= ctx->count;
-               if (mdsc->caps_avail_count >=
-                   mdsc->caps_reserve_count + mdsc->caps_min_count) {
-                       mdsc->caps_total_count -= ctx->count;
-                       for (i = 0; i < ctx->count; i++) {
-                               cap = list_first_entry(&mdsc->caps_list,
-                                       struct ceph_cap, caps_item);
-                               list_del(&cap->caps_item);
-                               kmem_cache_free(ceph_cap_cachep, cap);
-                       }
-               } else {
-                       mdsc->caps_avail_count += ctx->count;
-               }
-               ctx->count = 0;
-               dout("unreserve caps %d = %d used + %d resv + %d avail\n",
-                    mdsc->caps_total_count, mdsc->caps_use_count,
-                    mdsc->caps_reserve_count, mdsc->caps_avail_count);
-               BUG_ON(mdsc->caps_total_count != mdsc->caps_use_count +
-                                                mdsc->caps_reserve_count +
-                                                mdsc->caps_avail_count);
-               spin_unlock(&mdsc->caps_list_lock);
-       }
-       return 0;
+       spin_lock(&mdsc->caps_list_lock);
+       __ceph_unreserve_caps(mdsc, ctx->count);
+       ctx->count = 0;
+       spin_unlock(&mdsc->caps_list_lock);
 }
 
 struct ceph_cap *ceph_get_cap(struct ceph_mds_client *mdsc,
@@ -1125,7 +1111,7 @@ struct cap_msg_args {
        u64                     flush_tid, oldest_flush_tid, size, max_size;
        u64                     xattr_version;
        struct ceph_buffer      *xattr_buf;
-       struct timespec         atime, mtime, ctime;
+       struct timespec64       atime, mtime, ctime;
        int                     op, caps, wanted, dirty;
        u32                     seq, issue_seq, mseq, time_warp_seq;
        u32                     flags;
@@ -1146,7 +1132,7 @@ static int send_cap_msg(struct cap_msg_args *arg)
        struct ceph_msg *msg;
        void *p;
        size_t extra_len;
-       struct timespec zerotime = {0};
+       struct timespec64 zerotime = {0};
        struct ceph_osd_client *osdc = &arg->session->s_mdsc->fsc->client->osdc;
 
        dout("send_cap_msg %s %llx %llx caps %s wanted %s dirty %s"
@@ -1186,9 +1172,9 @@ static int send_cap_msg(struct cap_msg_args *arg)
 
        fc->size = cpu_to_le64(arg->size);
        fc->max_size = cpu_to_le64(arg->max_size);
-       ceph_encode_timespec(&fc->mtime, &arg->mtime);
-       ceph_encode_timespec(&fc->atime, &arg->atime);
-       ceph_encode_timespec(&fc->ctime, &arg->ctime);
+       ceph_encode_timespec64(&fc->mtime, &arg->mtime);
+       ceph_encode_timespec64(&fc->atime, &arg->atime);
+       ceph_encode_timespec64(&fc->ctime, &arg->ctime);
        fc->time_warp_seq = cpu_to_le32(arg->time_warp_seq);
 
        fc->uid = cpu_to_le32(from_kuid(&init_user_ns, arg->uid));
@@ -1237,7 +1223,7 @@ static int send_cap_msg(struct cap_msg_args *arg)
         * We just zero these out for now, as the MDS ignores them unless
         * the requisite feature flags are set (which we don't do yet).
         */
-       ceph_encode_timespec(p, &zerotime);
+       ceph_encode_timespec64(p, &zerotime);
        p += sizeof(struct ceph_timespec);
        ceph_encode_64(&p, 0);
 
@@ -1360,9 +1346,9 @@ static int __send_cap(struct ceph_mds_client *mdsc, struct ceph_cap *cap,
                arg.xattr_buf = NULL;
        }
 
-       arg.mtime = timespec64_to_timespec(inode->i_mtime);
-       arg.atime = timespec64_to_timespec(inode->i_atime);
-       arg.ctime = timespec64_to_timespec(inode->i_ctime);
+       arg.mtime = inode->i_mtime;
+       arg.atime = inode->i_atime;
+       arg.ctime = inode->i_ctime;
 
        arg.op = op;
        arg.caps = cap->implemented;
@@ -3148,11 +3134,11 @@ static void handle_cap_grant(struct inode *inode,
        }
 
        if (newcaps & CEPH_CAP_ANY_RD) {
-               struct timespec mtime, atime, ctime;
+               struct timespec64 mtime, atime, ctime;
                /* ctime/mtime/atime? */
-               ceph_decode_timespec(&mtime, &grant->mtime);
-               ceph_decode_timespec(&atime, &grant->atime);
-               ceph_decode_timespec(&ctime, &grant->ctime);
+               ceph_decode_timespec64(&mtime, &grant->mtime);
+               ceph_decode_timespec64(&atime, &grant->atime);
+               ceph_decode_timespec64(&ctime, &grant->ctime);
                ceph_fill_file_time(inode, extra_info->issued,
                                    le32_to_cpu(grant->time_warp_seq),
                                    &ctime, &mtime, &atime);
index 036ac0f..82928ce 100644 (file)
@@ -827,12 +827,14 @@ static int ceph_mknod(struct inode *dir, struct dentry *dentry,
        if (ceph_snap(dir) != CEPH_NOSNAP)
                return -EROFS;
 
-       if (ceph_quota_is_max_files_exceeded(dir))
-               return -EDQUOT;
+       if (ceph_quota_is_max_files_exceeded(dir)) {
+               err = -EDQUOT;
+               goto out;
+       }
 
        err = ceph_pre_init_acls(dir, &mode, &acls);
        if (err < 0)
-               return err;
+               goto out;
 
        dout("mknod in dir %p dentry %p mode 0%ho rdev %d\n",
             dir, dentry, mode, rdev);
@@ -883,8 +885,10 @@ static int ceph_symlink(struct inode *dir, struct dentry *dentry,
        if (ceph_snap(dir) != CEPH_NOSNAP)
                return -EROFS;
 
-       if (ceph_quota_is_max_files_exceeded(dir))
-               return -EDQUOT;
+       if (ceph_quota_is_max_files_exceeded(dir)) {
+               err = -EDQUOT;
+               goto out;
+       }
 
        dout("symlink in dir %p dentry %p to '%s'\n", dir, dentry, dest);
        req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_SYMLINK, USE_AUTH_MDS);
@@ -1393,7 +1397,7 @@ static ssize_t ceph_read_dir(struct file *file, char __user *buf, size_t size,
                                " rfiles:   %20lld\n"
                                " rsubdirs: %20lld\n"
                                "rbytes:    %20lld\n"
-                               "rctime:    %10ld.%09ld\n",
+                               "rctime:    %10lld.%09ld\n",
                                ci->i_files + ci->i_subdirs,
                                ci->i_files,
                                ci->i_subdirs,
@@ -1401,8 +1405,8 @@ static ssize_t ceph_read_dir(struct file *file, char __user *buf, size_t size,
                                ci->i_rfiles,
                                ci->i_rsubdirs,
                                ci->i_rbytes,
-                               (long)ci->i_rctime.tv_sec,
-                               (long)ci->i_rctime.tv_nsec);
+                               ci->i_rctime.tv_sec,
+                               ci->i_rctime.tv_nsec);
        }
 
        if (*ppos >= dfi->dir_info_len)
index e2679e8..92ab204 100644 (file)
@@ -720,7 +720,7 @@ struct ceph_aio_request {
        struct list_head osd_reqs;
        unsigned num_reqs;
        atomic_t pending_reqs;
-       struct timespec mtime;
+       struct timespec64 mtime;
        struct ceph_cap_flush *prealloc_cf;
 };
 
@@ -922,7 +922,7 @@ ceph_direct_read_write(struct kiocb *iocb, struct iov_iter *iter,
        int num_pages = 0;
        int flags;
        int ret;
-       struct timespec mtime = timespec64_to_timespec(current_time(inode));
+       struct timespec64 mtime = current_time(inode);
        size_t count = iov_iter_count(iter);
        loff_t pos = iocb->ki_pos;
        bool write = iov_iter_rw(iter) == WRITE;
@@ -1130,7 +1130,7 @@ ceph_sync_write(struct kiocb *iocb, struct iov_iter *from, loff_t pos,
        int flags;
        int ret;
        bool check_caps = false;
-       struct timespec mtime = timespec64_to_timespec(current_time(inode));
+       struct timespec64 mtime = current_time(inode);
        size_t count = iov_iter_count(from);
 
        if (ceph_snap(file_inode(file)) != CEPH_NOSNAP)
@@ -1383,12 +1383,12 @@ static ssize_t ceph_write_iter(struct kiocb *iocb, struct iov_iter *from)
        struct ceph_file_info *fi = file->private_data;
        struct inode *inode = file_inode(file);
        struct ceph_inode_info *ci = ceph_inode(inode);
-       struct ceph_osd_client *osdc =
-               &ceph_sb_to_client(inode->i_sb)->client->osdc;
+       struct ceph_fs_client *fsc = ceph_inode_to_client(inode);
        struct ceph_cap_flush *prealloc_cf;
        ssize_t count, written = 0;
        int err, want, got;
        loff_t pos;
+       loff_t limit = max(i_size_read(inode), fsc->max_file_size);
 
        if (ceph_snap(inode) != CEPH_NOSNAP)
                return -EROFS;
@@ -1414,6 +1414,13 @@ retry_snap:
                goto out;
 
        pos = iocb->ki_pos;
+       if (unlikely(pos >= limit)) {
+               err = -EFBIG;
+               goto out;
+       } else {
+               iov_iter_truncate(from, limit - pos);
+       }
+
        count = iov_iter_count(from);
        if (ceph_quota_is_max_bytes_exceeded(inode, pos + count)) {
                err = -EDQUOT;
@@ -1435,7 +1442,7 @@ retry_snap:
        }
 
        /* FIXME: not complete since it doesn't account for being at quota */
-       if (ceph_osdmap_flag(osdc, CEPH_OSDMAP_FULL)) {
+       if (ceph_osdmap_flag(&fsc->client->osdc, CEPH_OSDMAP_FULL)) {
                err = -ENOSPC;
                goto out;
        }
@@ -1525,7 +1532,7 @@ retry_snap:
        }
 
        if (written >= 0) {
-               if (ceph_osdmap_flag(osdc, CEPH_OSDMAP_NEARFULL))
+               if (ceph_osdmap_flag(&fsc->client->osdc, CEPH_OSDMAP_NEARFULL))
                        iocb->ki_flags |= IOCB_DSYNC;
                written = generic_write_sync(iocb, written);
        }
@@ -1546,6 +1553,7 @@ out_unlocked:
 static loff_t ceph_llseek(struct file *file, loff_t offset, int whence)
 {
        struct inode *inode = file->f_mapping->host;
+       struct ceph_fs_client *fsc = ceph_inode_to_client(inode);
        loff_t i_size;
        loff_t ret;
 
@@ -1590,7 +1598,7 @@ static loff_t ceph_llseek(struct file *file, loff_t offset, int whence)
                break;
        }
 
-       ret = vfs_setpos(file, offset, inode->i_sb->s_maxbytes);
+       ret = vfs_setpos(file, offset, max(i_size, fsc->max_file_size));
 
 out:
        inode_unlock(inode);
@@ -1662,7 +1670,7 @@ static int ceph_zero_partial_object(struct inode *inode,
                goto out;
        }
 
-       req->r_mtime = timespec64_to_timespec(inode->i_mtime);
+       req->r_mtime = inode->i_mtime;
        ret = ceph_osdc_start_request(&fsc->client->osdc, req, false);
        if (!ret) {
                ret = ceph_osdc_wait_request(&fsc->client->osdc, req);
@@ -1727,8 +1735,7 @@ static long ceph_fallocate(struct file *file, int mode,
        struct ceph_file_info *fi = file->private_data;
        struct inode *inode = file_inode(file);
        struct ceph_inode_info *ci = ceph_inode(inode);
-       struct ceph_osd_client *osdc =
-               &ceph_inode_to_client(inode)->client->osdc;
+       struct ceph_fs_client *fsc = ceph_inode_to_client(inode);
        struct ceph_cap_flush *prealloc_cf;
        int want, got = 0;
        int dirty;
@@ -1736,6 +1743,9 @@ static long ceph_fallocate(struct file *file, int mode,
        loff_t endoff = 0;
        loff_t size;
 
+       if ((offset + length) > max(i_size_read(inode), fsc->max_file_size))
+               return -EFBIG;
+
        if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE))
                return -EOPNOTSUPP;
 
@@ -1759,7 +1769,7 @@ static long ceph_fallocate(struct file *file, int mode,
                goto unlock;
        }
 
-       if (ceph_osdmap_flag(osdc, CEPH_OSDMAP_FULL) &&
+       if (ceph_osdmap_flag(&fsc->client->osdc, CEPH_OSDMAP_FULL) &&
            !(mode & FALLOC_FL_PUNCH_HOLE)) {
                ret = -ENOSPC;
                goto unlock;
index a866be9..ebc7bda 100644 (file)
@@ -658,13 +658,10 @@ int ceph_fill_file_size(struct inode *inode, int issued,
 }
 
 void ceph_fill_file_time(struct inode *inode, int issued,
-                        u64 time_warp_seq, struct timespec *ctime,
-                        struct timespec *mtime, struct timespec *atime)
+                        u64 time_warp_seq, struct timespec64 *ctime,
+                        struct timespec64 *mtime, struct timespec64 *atime)
 {
        struct ceph_inode_info *ci = ceph_inode(inode);
-       struct timespec64 ctime64 = timespec_to_timespec64(*ctime);
-       struct timespec64 mtime64 = timespec_to_timespec64(*mtime);
-       struct timespec64 atime64 = timespec_to_timespec64(*atime);
        int warn = 0;
 
        if (issued & (CEPH_CAP_FILE_EXCL|
@@ -673,39 +670,39 @@ void ceph_fill_file_time(struct inode *inode, int issued,
                      CEPH_CAP_AUTH_EXCL|
                      CEPH_CAP_XATTR_EXCL)) {
                if (ci->i_version == 0 ||
-                   timespec64_compare(&ctime64, &inode->i_ctime) > 0) {
+                   timespec64_compare(ctime, &inode->i_ctime) > 0) {
                        dout("ctime %lld.%09ld -> %lld.%09ld inc w/ cap\n",
-                            (long long)inode->i_ctime.tv_sec, inode->i_ctime.tv_nsec,
-                            (long long)ctime->tv_sec, ctime->tv_nsec);
-                       inode->i_ctime = ctime64;
+                            inode->i_ctime.tv_sec, inode->i_ctime.tv_nsec,
+                            ctime->tv_sec, ctime->tv_nsec);
+                       inode->i_ctime = *ctime;
                }
                if (ci->i_version == 0 ||
                    ceph_seq_cmp(time_warp_seq, ci->i_time_warp_seq) > 0) {
                        /* the MDS did a utimes() */
                        dout("mtime %lld.%09ld -> %lld.%09ld "
                             "tw %d -> %d\n",
-                            (long long)inode->i_mtime.tv_sec, inode->i_mtime.tv_nsec,
-                            (long long)mtime->tv_sec, mtime->tv_nsec,
+                            inode->i_mtime.tv_sec, inode->i_mtime.tv_nsec,
+                            mtime->tv_sec, mtime->tv_nsec,
                             ci->i_time_warp_seq, (int)time_warp_seq);
 
-                       inode->i_mtime = mtime64;
-                       inode->i_atime = atime64;
+                       inode->i_mtime = *mtime;
+                       inode->i_atime = *atime;
                        ci->i_time_warp_seq = time_warp_seq;
                } else if (time_warp_seq == ci->i_time_warp_seq) {
                        /* nobody did utimes(); take the max */
-                       if (timespec64_compare(&mtime64, &inode->i_mtime) > 0) {
+                       if (timespec64_compare(mtime, &inode->i_mtime) > 0) {
                                dout("mtime %lld.%09ld -> %lld.%09ld inc\n",
-                                    (long long)inode->i_mtime.tv_sec,
+                                    inode->i_mtime.tv_sec,
                                     inode->i_mtime.tv_nsec,
-                                    (long long)mtime->tv_sec, mtime->tv_nsec);
-                               inode->i_mtime = mtime64;
+                                    mtime->tv_sec, mtime->tv_nsec);
+                               inode->i_mtime = *mtime;
                        }
-                       if (timespec64_compare(&atime64, &inode->i_atime) > 0) {
+                       if (timespec64_compare(atime, &inode->i_atime) > 0) {
                                dout("atime %lld.%09ld -> %lld.%09ld inc\n",
-                                    (long long)inode->i_atime.tv_sec,
+                                    inode->i_atime.tv_sec,
                                     inode->i_atime.tv_nsec,
-                                    (long long)atime->tv_sec, atime->tv_nsec);
-                               inode->i_atime = atime64;
+                                    atime->tv_sec, atime->tv_nsec);
+                               inode->i_atime = *atime;
                        }
                } else if (issued & CEPH_CAP_FILE_EXCL) {
                        /* we did a utimes(); ignore mds values */
@@ -715,9 +712,9 @@ void ceph_fill_file_time(struct inode *inode, int issued,
        } else {
                /* we have no write|excl caps; whatever the MDS says is true */
                if (ceph_seq_cmp(time_warp_seq, ci->i_time_warp_seq) >= 0) {
-                       inode->i_ctime = ctime64;
-                       inode->i_mtime = mtime64;
-                       inode->i_atime = atime64;
+                       inode->i_ctime = *ctime;
+                       inode->i_mtime = *mtime;
+                       inode->i_atime = *atime;
                        ci->i_time_warp_seq = time_warp_seq;
                } else {
                        warn = 1;
@@ -743,7 +740,7 @@ static int fill_inode(struct inode *inode, struct page *locked_page,
        struct ceph_mds_reply_inode *info = iinfo->in;
        struct ceph_inode_info *ci = ceph_inode(inode);
        int issued, new_issued, info_caps;
-       struct timespec mtime, atime, ctime;
+       struct timespec64 mtime, atime, ctime;
        struct ceph_buffer *xattr_blob = NULL;
        struct ceph_string *pool_ns = NULL;
        struct ceph_cap *new_cap = NULL;
@@ -823,9 +820,9 @@ static int fill_inode(struct inode *inode, struct page *locked_page,
 
        if (new_version || (new_issued & CEPH_CAP_ANY_RD)) {
                /* be careful with mtime, atime, size */
-               ceph_decode_timespec(&atime, &info->atime);
-               ceph_decode_timespec(&mtime, &info->mtime);
-               ceph_decode_timespec(&ctime, &info->ctime);
+               ceph_decode_timespec64(&atime, &info->atime);
+               ceph_decode_timespec64(&mtime, &info->mtime);
+               ceph_decode_timespec64(&ctime, &info->ctime);
                ceph_fill_file_time(inode, issued,
                                le32_to_cpu(info->time_warp_seq),
                                &ctime, &mtime, &atime);
@@ -872,7 +869,7 @@ static int fill_inode(struct inode *inode, struct page *locked_page,
                        ci->i_rbytes = le64_to_cpu(info->rbytes);
                        ci->i_rfiles = le64_to_cpu(info->rfiles);
                        ci->i_rsubdirs = le64_to_cpu(info->rsubdirs);
-                       ceph_decode_timespec(&ci->i_rctime, &info->rctime);
+                       ceph_decode_timespec64(&ci->i_rctime, &info->rctime);
                }
        }
 
@@ -1954,7 +1951,6 @@ int __ceph_setattr(struct inode *inode, struct iattr *attr)
        int err = 0;
        int inode_dirty_flags = 0;
        bool lock_snap_rwsem = false;
-       struct timespec ts;
 
        prealloc_cf = ceph_alloc_cap_flush();
        if (!prealloc_cf)
@@ -2030,8 +2026,8 @@ int __ceph_setattr(struct inode *inode, struct iattr *attr)
 
        if (ia_valid & ATTR_ATIME) {
                dout("setattr %p atime %lld.%ld -> %lld.%ld\n", inode,
-                    (long long)inode->i_atime.tv_sec, inode->i_atime.tv_nsec,
-                    (long long)attr->ia_atime.tv_sec, attr->ia_atime.tv_nsec);
+                    inode->i_atime.tv_sec, inode->i_atime.tv_nsec,
+                    attr->ia_atime.tv_sec, attr->ia_atime.tv_nsec);
                if (issued & CEPH_CAP_FILE_EXCL) {
                        ci->i_time_warp_seq++;
                        inode->i_atime = attr->ia_atime;
@@ -2043,8 +2039,8 @@ int __ceph_setattr(struct inode *inode, struct iattr *attr)
                        dirtied |= CEPH_CAP_FILE_WR;
                } else if ((issued & CEPH_CAP_FILE_SHARED) == 0 ||
                           !timespec64_equal(&inode->i_atime, &attr->ia_atime)) {
-                       ts = timespec64_to_timespec(attr->ia_atime);
-                       ceph_encode_timespec(&req->r_args.setattr.atime, &ts);
+                       ceph_encode_timespec64(&req->r_args.setattr.atime,
+                                              &attr->ia_atime);
                        mask |= CEPH_SETATTR_ATIME;
                        release |= CEPH_CAP_FILE_SHARED |
                                   CEPH_CAP_FILE_RD | CEPH_CAP_FILE_WR;
@@ -2052,8 +2048,8 @@ int __ceph_setattr(struct inode *inode, struct iattr *attr)
        }
        if (ia_valid & ATTR_MTIME) {
                dout("setattr %p mtime %lld.%ld -> %lld.%ld\n", inode,
-                    (long long)inode->i_mtime.tv_sec, inode->i_mtime.tv_nsec,
-                    (long long)attr->ia_mtime.tv_sec, attr->ia_mtime.tv_nsec);
+                    inode->i_mtime.tv_sec, inode->i_mtime.tv_nsec,
+                    attr->ia_mtime.tv_sec, attr->ia_mtime.tv_nsec);
                if (issued & CEPH_CAP_FILE_EXCL) {
                        ci->i_time_warp_seq++;
                        inode->i_mtime = attr->ia_mtime;
@@ -2065,8 +2061,8 @@ int __ceph_setattr(struct inode *inode, struct iattr *attr)
                        dirtied |= CEPH_CAP_FILE_WR;
                } else if ((issued & CEPH_CAP_FILE_SHARED) == 0 ||
                           !timespec64_equal(&inode->i_mtime, &attr->ia_mtime)) {
-                       ts = timespec64_to_timespec(attr->ia_mtime);
-                       ceph_encode_timespec(&req->r_args.setattr.mtime, &ts);
+                       ceph_encode_timespec64(&req->r_args.setattr.mtime,
+                                              &attr->ia_mtime);
                        mask |= CEPH_SETATTR_MTIME;
                        release |= CEPH_CAP_FILE_SHARED |
                                   CEPH_CAP_FILE_RD | CEPH_CAP_FILE_WR;
@@ -2097,8 +2093,8 @@ int __ceph_setattr(struct inode *inode, struct iattr *attr)
                bool only = (ia_valid & (ATTR_SIZE|ATTR_MTIME|ATTR_ATIME|
                                         ATTR_MODE|ATTR_UID|ATTR_GID)) == 0;
                dout("setattr %p ctime %lld.%ld -> %lld.%ld (%s)\n", inode,
-                    (long long)inode->i_ctime.tv_sec, inode->i_ctime.tv_nsec,
-                    (long long)attr->ia_ctime.tv_sec, attr->ia_ctime.tv_nsec,
+                    inode->i_ctime.tv_sec, inode->i_ctime.tv_nsec,
+                    attr->ia_ctime.tv_sec, attr->ia_ctime.tv_nsec,
                     only ? "ctime only" : "ignored");
                if (only) {
                        /*
@@ -2140,7 +2136,7 @@ int __ceph_setattr(struct inode *inode, struct iattr *attr)
                req->r_inode_drop = release;
                req->r_args.setattr.mask = cpu_to_le32(mask);
                req->r_num_caps = 1;
-               req->r_stamp = timespec64_to_timespec(attr->ia_ctime);
+               req->r_stamp = attr->ia_ctime;
                err = ceph_mdsc_do_request(mdsc, NULL, req);
        }
        dout("setattr %p result=%d (%s locally, %d remote)\n", inode, err,
@@ -2161,6 +2157,7 @@ int __ceph_setattr(struct inode *inode, struct iattr *attr)
 int ceph_setattr(struct dentry *dentry, struct iattr *attr)
 {
        struct inode *inode = d_inode(dentry);
+       struct ceph_fs_client *fsc = ceph_inode_to_client(inode);
        int err;
 
        if (ceph_snap(inode) != CEPH_NOSNAP)
@@ -2171,6 +2168,10 @@ int ceph_setattr(struct dentry *dentry, struct iattr *attr)
                return err;
 
        if ((attr->ia_valid & ATTR_SIZE) &&
+           attr->ia_size > max(inode->i_size, fsc->max_file_size))
+               return -EFBIG;
+
+       if ((attr->ia_valid & ATTR_SIZE) &&
            ceph_quota_is_max_bytes_exceeded(inode, attr->ia_size))
                return -EDQUOT;
 
index dc8bc66..bc43c82 100644 (file)
@@ -902,6 +902,27 @@ static struct ceph_msg *create_session_msg(u32 op, u64 seq)
        return msg;
 }
 
+static void encode_supported_features(void **p, void *end)
+{
+       static const unsigned char bits[] = CEPHFS_FEATURES_CLIENT_SUPPORTED;
+       static const size_t count = ARRAY_SIZE(bits);
+
+       if (count > 0) {
+               size_t i;
+               size_t size = ((size_t)bits[count - 1] + 64) / 64 * 8;
+
+               BUG_ON(*p + 4 + size > end);
+               ceph_encode_32(p, size);
+               memset(*p, 0, size);
+               for (i = 0; i < count; i++)
+                       ((unsigned char*)(*p))[i / 8] |= 1 << (bits[i] % 8);
+               *p += size;
+       } else {
+               BUG_ON(*p + 4 > end);
+               ceph_encode_32(p, 0);
+       }
+}
+
 /*
  * session message, specialization for CEPH_SESSION_REQUEST_OPEN
  * to include additional client metadata fields.
@@ -911,11 +932,11 @@ static struct ceph_msg *create_session_open_msg(struct ceph_mds_client *mdsc, u6
        struct ceph_msg *msg;
        struct ceph_mds_session_head *h;
        int i = -1;
-       int metadata_bytes = 0;
+       int extra_bytes = 0;
        int metadata_key_count = 0;
        struct ceph_options *opt = mdsc->fsc->client->options;
        struct ceph_mount_options *fsopt = mdsc->fsc->mount_options;
-       void *p;
+       void *p, *end;
 
        const char* metadata[][2] = {
                {"hostname", mdsc->nodename},
@@ -926,21 +947,26 @@ static struct ceph_msg *create_session_open_msg(struct ceph_mds_client *mdsc, u6
        };
 
        /* Calculate serialized length of metadata */
-       metadata_bytes = 4;  /* map length */
+       extra_bytes = 4;  /* map length */
        for (i = 0; metadata[i][0]; ++i) {
-               metadata_bytes += 8 + strlen(metadata[i][0]) +
+               extra_bytes += 8 + strlen(metadata[i][0]) +
                        strlen(metadata[i][1]);
                metadata_key_count++;
        }
+       /* supported feature */
+       extra_bytes += 4 + 8;
 
        /* Allocate the message */
-       msg = ceph_msg_new(CEPH_MSG_CLIENT_SESSION, sizeof(*h) + metadata_bytes,
+       msg = ceph_msg_new(CEPH_MSG_CLIENT_SESSION, sizeof(*h) + extra_bytes,
                           GFP_NOFS, false);
        if (!msg) {
                pr_err("create_session_msg ENOMEM creating msg\n");
                return NULL;
        }
-       h = msg->front.iov_base;
+       p = msg->front.iov_base;
+       end = p + msg->front.iov_len;
+
+       h = p;
        h->op = cpu_to_le32(CEPH_SESSION_REQUEST_OPEN);
        h->seq = cpu_to_le64(seq);
 
@@ -950,11 +976,11 @@ static struct ceph_msg *create_session_open_msg(struct ceph_mds_client *mdsc, u6
         *
         * ClientSession messages with metadata are v2
         */
-       msg->hdr.version = cpu_to_le16(2);
+       msg->hdr.version = cpu_to_le16(3);
        msg->hdr.compat_version = cpu_to_le16(1);
 
        /* The write pointer, following the session_head structure */
-       p = msg->front.iov_base + sizeof(*h);
+       p += sizeof(*h);
 
        /* Number of entries in the map */
        ceph_encode_32(&p, metadata_key_count);
@@ -972,6 +998,10 @@ static struct ceph_msg *create_session_open_msg(struct ceph_mds_client *mdsc, u6
                p += val_len;
        }
 
+       encode_supported_features(&p, end);
+       msg->front.iov_len = p - msg->front.iov_base;
+       msg->hdr.front_len = cpu_to_le32(msg->front.iov_len);
+
        return msg;
 }
 
@@ -1779,6 +1809,7 @@ struct ceph_mds_request *
 ceph_mdsc_create_request(struct ceph_mds_client *mdsc, int op, int mode)
 {
        struct ceph_mds_request *req = kzalloc(sizeof(*req), GFP_NOFS);
+       struct timespec64 ts;
 
        if (!req)
                return ERR_PTR(-ENOMEM);
@@ -1797,7 +1828,8 @@ ceph_mdsc_create_request(struct ceph_mds_client *mdsc, int op, int mode)
        init_completion(&req->r_safe_completion);
        INIT_LIST_HEAD(&req->r_unsafe_item);
 
-       req->r_stamp = timespec_trunc(current_kernel_time(), mdsc->fsc->sb->s_time_gran);
+       ktime_get_coarse_real_ts64(&ts);
+       req->r_stamp = timespec64_trunc(ts, mdsc->fsc->sb->s_time_gran);
 
        req->r_op = op;
        req->r_direct_mode = mode;
@@ -2094,7 +2126,7 @@ static struct ceph_msg *create_request_message(struct ceph_mds_client *mdsc,
        /* time stamp */
        {
                struct ceph_timespec ts;
-               ceph_encode_timespec(&ts, &req->r_stamp);
+               ceph_encode_timespec64(&ts, &req->r_stamp);
                ceph_encode_copy(&p, &ts, sizeof(ts));
        }
 
@@ -2187,7 +2219,7 @@ static int __prepare_send_request(struct ceph_mds_client *mdsc,
                p = msg->front.iov_base + req->r_request_release_offset;
                {
                        struct ceph_timespec ts;
-                       ceph_encode_timespec(&ts, &req->r_stamp);
+                       ceph_encode_timespec64(&ts, &req->r_stamp);
                        ceph_encode_copy(&p, &ts, sizeof(ts));
                }
 
@@ -2225,7 +2257,7 @@ static int __prepare_send_request(struct ceph_mds_client *mdsc,
 /*
  * send request, or put it on the appropriate wait list.
  */
-static int __do_request(struct ceph_mds_client *mdsc,
+static void __do_request(struct ceph_mds_client *mdsc,
                        struct ceph_mds_request *req)
 {
        struct ceph_mds_session *session = NULL;
@@ -2235,7 +2267,7 @@ static int __do_request(struct ceph_mds_client *mdsc,
        if (req->r_err || test_bit(CEPH_MDS_R_GOT_RESULT, &req->r_req_flags)) {
                if (test_bit(CEPH_MDS_R_ABORTED, &req->r_req_flags))
                        __unregister_request(mdsc, req);
-               goto out;
+               return;
        }
 
        if (req->r_timeout &&
@@ -2258,7 +2290,7 @@ static int __do_request(struct ceph_mds_client *mdsc,
                if (mdsc->mdsmap->m_epoch == 0) {
                        dout("do_request no mdsmap, waiting for map\n");
                        list_add(&req->r_wait, &mdsc->waiting_for_map);
-                       goto finish;
+                       return;
                }
                if (!(mdsc->fsc->mount_options->flags &
                      CEPH_MOUNT_OPT_MOUNTWAIT) &&
@@ -2276,7 +2308,7 @@ static int __do_request(struct ceph_mds_client *mdsc,
            ceph_mdsmap_get_state(mdsc->mdsmap, mds) < CEPH_MDS_STATE_ACTIVE) {
                dout("do_request no mds or not active, waiting for map\n");
                list_add(&req->r_wait, &mdsc->waiting_for_map);
-               goto out;
+               return;
        }
 
        /* get, open session */
@@ -2326,8 +2358,7 @@ finish:
                complete_request(mdsc, req);
                __unregister_request(mdsc, req);
        }
-out:
-       return err;
+       return;
 }
 
 /*
@@ -2748,7 +2779,7 @@ static void handle_session(struct ceph_mds_session *session,
        int wake = 0;
 
        /* decode */
-       if (msg->front.iov_len != sizeof(*h))
+       if (msg->front.iov_len < sizeof(*h))
                goto bad;
        op = le32_to_cpu(h->op);
        seq = le64_to_cpu(h->seq);
@@ -2958,15 +2989,12 @@ static int encode_caps_cb(struct inode *inode, struct ceph_cap *cap,
                rec.v2.flock_len = (__force __le32)
                        ((ci->i_ceph_flags & CEPH_I_ERROR_FILELOCK) ? 0 : 1);
        } else {
-               struct timespec ts;
                rec.v1.cap_id = cpu_to_le64(cap->cap_id);
                rec.v1.wanted = cpu_to_le32(__ceph_caps_wanted(ci));
                rec.v1.issued = cpu_to_le32(cap->issued);
                rec.v1.size = cpu_to_le64(inode->i_size);
-               ts = timespec64_to_timespec(inode->i_mtime);
-               ceph_encode_timespec(&rec.v1.mtime, &ts);
-               ts = timespec64_to_timespec(inode->i_atime);
-               ceph_encode_timespec(&rec.v1.atime, &ts);
+               ceph_encode_timespec64(&rec.v1.mtime, &inode->i_mtime);
+               ceph_encode_timespec64(&rec.v1.atime, &inode->i_atime);
                rec.v1.snaprealm = cpu_to_le64(ci->i_snap_realm->ino);
                rec.v1.pathbase = cpu_to_le64(pathbase);
        }
@@ -3378,10 +3406,10 @@ static void handle_lease(struct ceph_mds_client *mdsc,
        vino.ino = le64_to_cpu(h->ino);
        vino.snap = CEPH_NOSNAP;
        seq = le32_to_cpu(h->seq);
-       dname.name = (void *)h + sizeof(*h) + sizeof(u32);
-       dname.len = msg->front.iov_len - sizeof(*h) - sizeof(u32);
-       if (dname.len != get_unaligned_le32(h+1))
+       dname.len = get_unaligned_le32(h + 1);
+       if (msg->front.iov_len < sizeof(*h) + sizeof(u32) + dname.len)
                goto bad;
+       dname.name = (void *)(h + 1) + sizeof(u32);
 
        /* lookup inode */
        inode = ceph_find_inode(sb, vino);
@@ -3644,8 +3672,8 @@ int ceph_mdsc_init(struct ceph_fs_client *fsc)
        init_rwsem(&mdsc->pool_perm_rwsem);
        mdsc->pool_perm_tree = RB_ROOT;
 
-       strncpy(mdsc->nodename, utsname()->nodename,
-               sizeof(mdsc->nodename) - 1);
+       strscpy(mdsc->nodename, utsname()->nodename,
+               sizeof(mdsc->nodename));
        return 0;
 }
 
@@ -4019,7 +4047,8 @@ void ceph_mdsc_handle_mdsmap(struct ceph_mds_client *mdsc, struct ceph_msg *msg)
        } else {
                mdsc->mdsmap = newmap;  /* first mds map */
        }
-       mdsc->fsc->sb->s_maxbytes = mdsc->mdsmap->m_max_file_size;
+       mdsc->fsc->max_file_size = min((loff_t)mdsc->mdsmap->m_max_file_size,
+                                       MAX_LFS_FILESIZE);
 
        __wake_requests(mdsc, &mdsc->waiting_for_map);
        ceph_monc_got_map(&mdsc->fsc->client->monc, CEPH_SUB_MDSMAP,
@@ -4155,6 +4184,16 @@ static struct ceph_auth_handshake *get_authorizer(struct ceph_connection *con,
        return auth;
 }
 
+static int add_authorizer_challenge(struct ceph_connection *con,
+                                   void *challenge_buf, int challenge_buf_len)
+{
+       struct ceph_mds_session *s = con->private;
+       struct ceph_mds_client *mdsc = s->s_mdsc;
+       struct ceph_auth_client *ac = mdsc->fsc->client->monc.auth;
+
+       return ceph_auth_add_authorizer_challenge(ac, s->s_auth.authorizer,
+                                           challenge_buf, challenge_buf_len);
+}
 
 static int verify_authorizer_reply(struct ceph_connection *con)
 {
@@ -4218,6 +4257,7 @@ static const struct ceph_connection_operations mds_con_ops = {
        .put = con_put,
        .dispatch = dispatch,
        .get_authorizer = get_authorizer,
+       .add_authorizer_challenge = add_authorizer_challenge,
        .verify_authorizer_reply = verify_authorizer_reply,
        .invalidate_authorizer = invalidate_authorizer,
        .peer_reset = peer_reset,
index 2ec3b5b..32fcce0 100644 (file)
 #include <linux/ceph/mdsmap.h>
 #include <linux/ceph/auth.h>
 
+/* The first 8 bits are reserved for old ceph releases */
+#define CEPHFS_FEATURE_MIMIC    8
+
+#define CEPHFS_FEATURES_ALL {           \
+  0, 1, 2, 3, 4, 5, 6, 7,              \
+  CEPHFS_FEATURE_MIMIC,                 \
+}
+
+#define CEPHFS_FEATURES_CLIENT_SUPPORTED CEPHFS_FEATURES_ALL
+#define CEPHFS_FEATURES_CLIENT_REQUIRED {}
+
+
 /*
  * Some lock dependencies:
  *
@@ -229,7 +241,7 @@ struct ceph_mds_request {
        int r_fmode;        /* file mode, if expecting cap */
        kuid_t r_uid;
        kgid_t r_gid;
-       struct timespec r_stamp;
+       struct timespec64 r_stamp;
 
        /* for choosing which mds to send this request to */
        int r_direct_mode;
index 242bfa5..32d4f13 100644 (file)
@@ -48,7 +48,7 @@ void ceph_handle_quota(struct ceph_mds_client *mdsc,
        struct inode *inode;
        struct ceph_inode_info *ci;
 
-       if (msg->front.iov_len != sizeof(*h)) {
+       if (msg->front.iov_len < sizeof(*h)) {
                pr_err("%s corrupt message mds%d len %d\n", __func__,
                       session->s_mds, (int)msg->front.iov_len);
                ceph_msg_dump(msg);
index af81555..041c27e 100644 (file)
@@ -594,9 +594,9 @@ int __ceph_finish_cap_snap(struct ceph_inode_info *ci,
 
        BUG_ON(capsnap->writing);
        capsnap->size = inode->i_size;
-       capsnap->mtime = timespec64_to_timespec(inode->i_mtime);
-       capsnap->atime = timespec64_to_timespec(inode->i_atime);
-       capsnap->ctime = timespec64_to_timespec(inode->i_ctime);
+       capsnap->mtime = inode->i_mtime;
+       capsnap->atime = inode->i_atime;
+       capsnap->ctime = inode->i_ctime;
        capsnap->time_warp_seq = ci->i_time_warp_seq;
        capsnap->truncate_size = ci->i_truncate_size;
        capsnap->truncate_seq = ci->i_truncate_seq;
index 95a3b3a..43ca3b7 100644 (file)
@@ -219,8 +219,7 @@ static int parse_fsopt_token(char *c, void *private)
        if (token < Opt_last_int) {
                ret = match_int(&argstr[0], &intval);
                if (ret < 0) {
-                       pr_err("bad mount option arg (not int) "
-                              "at '%s'\n", c);
+                       pr_err("bad option arg (not int) at '%s'\n", c);
                        return ret;
                }
                dout("got int token %d val %d\n", token, intval);
@@ -941,11 +940,12 @@ static int ceph_set_super(struct super_block *s, void *data)
        dout("set_super %p data %p\n", s, data);
 
        s->s_flags = fsc->mount_options->sb_flags;
-       s->s_maxbytes = 1ULL << 40;  /* temp value until we get mdsmap */
+       s->s_maxbytes = MAX_LFS_FILESIZE;
 
        s->s_xattr = ceph_xattr_handlers;
        s->s_fs_info = fsc;
        fsc->sb = s;
+       fsc->max_file_size = 1ULL << 40; /* temp value until we get mdsmap */
 
        s->s_op = &ceph_super_ops;
        s->s_d_op = &ceph_dentry_ops;
index 971328b..582e28f 100644 (file)
@@ -98,6 +98,7 @@ struct ceph_fs_client {
 
        unsigned long mount_state;
        int min_caps;                  /* min caps i added */
+       loff_t max_file_size;
 
        struct ceph_mds_client *mdsc;
 
@@ -193,7 +194,7 @@ struct ceph_cap_snap {
        u64 xattr_version;
 
        u64 size;
-       struct timespec mtime, atime, ctime;
+       struct timespec64 mtime, atime, ctime;
        u64 time_warp_seq;
        u64 truncate_size;
        u32 truncate_seq;
@@ -307,7 +308,7 @@ struct ceph_inode_info {
        char *i_symlink;
 
        /* for dirs */
-       struct timespec i_rctime;
+       struct timespec64 i_rctime;
        u64 i_rbytes, i_rfiles, i_rsubdirs;
        u64 i_files, i_subdirs;
 
@@ -655,7 +656,7 @@ extern void ceph_caps_finalize(struct ceph_mds_client *mdsc);
 extern void ceph_adjust_min_caps(struct ceph_mds_client *mdsc, int delta);
 extern int ceph_reserve_caps(struct ceph_mds_client *mdsc,
                             struct ceph_cap_reservation *ctx, int need);
-extern int ceph_unreserve_caps(struct ceph_mds_client *mdsc,
+extern void ceph_unreserve_caps(struct ceph_mds_client *mdsc,
                               struct ceph_cap_reservation *ctx);
 extern void ceph_reservation_status(struct ceph_fs_client *client,
                                    int *total, int *avail, int *used,
@@ -857,8 +858,9 @@ extern struct inode *ceph_get_snapdir(struct inode *parent);
 extern int ceph_fill_file_size(struct inode *inode, int issued,
                               u32 truncate_seq, u64 truncate_size, u64 size);
 extern void ceph_fill_file_time(struct inode *inode, int issued,
-                               u64 time_warp_seq, struct timespec *ctime,
-                               struct timespec *mtime, struct timespec *atime);
+                               u64 time_warp_seq, struct timespec64 *ctime,
+                               struct timespec64 *mtime,
+                               struct timespec64 *atime);
 extern int ceph_fill_trace(struct super_block *sb,
                           struct ceph_mds_request *req);
 extern int ceph_readdir_prepopulate(struct ceph_mds_request *req,
index 5bc8edb..5cc8b94 100644 (file)
@@ -224,8 +224,8 @@ static size_t ceph_vxattrcb_dir_rbytes(struct ceph_inode_info *ci, char *val,
 static size_t ceph_vxattrcb_dir_rctime(struct ceph_inode_info *ci, char *val,
                                       size_t size)
 {
-       return snprintf(val, size, "%ld.09%ld", (long)ci->i_rctime.tv_sec,
-                       (long)ci->i_rctime.tv_nsec);
+       return snprintf(val, size, "%lld.09%ld", ci->i_rctime.tv_sec,
+                       ci->i_rctime.tv_nsec);
 }
 
 /* quotas */
index f3a78ef..f047e87 100644 (file)
@@ -148,5 +148,5 @@ extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg);
 extern const struct export_operations cifs_export_ops;
 #endif /* CONFIG_CIFS_NFSD_EXPORT */
 
-#define CIFS_VERSION   "2.12"
+#define CIFS_VERSION   "2.13"
 #endif                         /* _CIFSFS_H */
index 8b0502c..aa23c00 100644 (file)
@@ -398,6 +398,12 @@ int build_ntlmssp_auth_blob(unsigned char **pbuffer,
                goto setup_ntlmv2_ret;
        }
        *pbuffer = kmalloc(size_of_ntlmssp_blob(ses), GFP_KERNEL);
+       if (!*pbuffer) {
+               rc = -ENOMEM;
+               cifs_dbg(VFS, "Error %d during NTLMSSP allocation\n", rc);
+               *buflen = 0;
+               goto setup_ntlmv2_ret;
+       }
        sec_blob = (AUTHENTICATE_MESSAGE *)*pbuffer;
 
        memcpy(sec_blob->Signature, NTLMSSP_SIGNATURE, 8);
index 303d459..db04536 100644 (file)
@@ -238,6 +238,13 @@ smb2_check_message(char *buf, unsigned int len, struct TCP_Server_Info *srvr)
                        return 0;
 
                /*
+                * Some windows servers (win2016) will pad also the final
+                * PDU in a compound to 8 bytes.
+                */
+               if (((clc_len + 7) & ~7) == len)
+                       return 0;
+
+               /*
                 * MacOS server pads after SMB2.1 write response with 3 bytes
                 * of junk. Other servers match RFC1001 len to actual
                 * SMB2/SMB3 frame length (header + smb2 response specific data)
index 5412584..247a98e 100644 (file)
@@ -1582,7 +1582,7 @@ smb2_queryfs(const unsigned int xid, struct cifs_tcon *tcon,
        struct smb_rqst rqst[3];
        int resp_buftype[3];
        struct kvec rsp_iov[3];
-       struct kvec open_iov[5]; /* 4 + potential padding. */
+       struct kvec open_iov[SMB2_CREATE_IOV_SIZE];
        struct kvec qi_iov[1];
        struct kvec close_iov[1];
        struct cifs_ses *ses = tcon->ses;
@@ -1603,7 +1603,7 @@ smb2_queryfs(const unsigned int xid, struct cifs_tcon *tcon,
 
        memset(&open_iov, 0, sizeof(open_iov));
        rqst[0].rq_iov = open_iov;
-       rqst[0].rq_nvec = 4;
+       rqst[0].rq_nvec = SMB2_CREATE_IOV_SIZE;
 
        oparms.tcon = tcon;
        oparms.desired_access = FILE_READ_ATTRIBUTES;
index 2f19380..5740aa8 100644 (file)
@@ -2256,7 +2256,7 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
        struct TCP_Server_Info *server;
        struct cifs_tcon *tcon = oparms->tcon;
        struct cifs_ses *ses = tcon->ses;
-       struct kvec iov[5]; /* make sure at least one for each open context */
+       struct kvec iov[SMB2_CREATE_IOV_SIZE];
        struct kvec rsp_iov = {NULL, 0};
        int resp_buftype;
        int rc = 0;
@@ -2274,7 +2274,7 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
        memset(&rqst, 0, sizeof(struct smb_rqst));
        memset(&iov, 0, sizeof(iov));
        rqst.rq_iov = iov;
-       rqst.rq_nvec = 5;
+       rqst.rq_nvec = SMB2_CREATE_IOV_SIZE;
 
        rc = SMB2_open_init(tcon, &rqst, oplock, oparms, path);
        if (rc)
index a2eeae9..8fb7887 100644 (file)
@@ -614,6 +614,18 @@ struct smb2_tree_disconnect_rsp {
 #define SMB2_CREATE_TAG_POSIX          0x93AD25509CB411E7B42383DE968BCD7C
 
 
+/*
+ * Maximum number of iovs we need for an open/create request.
+ * [0] : struct smb2_create_req
+ * [1] : path
+ * [2] : lease context
+ * [3] : durable context
+ * [4] : posix context
+ * [5] : time warp context
+ * [6] : compound padding
+ */
+#define SMB2_CREATE_IOV_SIZE 7
+
 struct smb2_create_req {
        struct smb2_sync_hdr sync_hdr;
        __le16 StructureSize;   /* Must be 57 */
index 897b51e..f32d712 100644 (file)
--- a/fs/dax.c
+++ b/fs/dax.c
@@ -226,8 +226,8 @@ static inline void *unlock_slot(struct address_space *mapping, void **slot)
  *
  * Must be called with the i_pages lock held.
  */
-static void *get_unlocked_mapping_entry(struct address_space *mapping,
-                                       pgoff_t index, void ***slotp)
+static void *__get_unlocked_mapping_entry(struct address_space *mapping,
+               pgoff_t index, void ***slotp, bool (*wait_fn)(void))
 {
        void *entry, **slot;
        struct wait_exceptional_entry_queue ewait;
@@ -237,6 +237,8 @@ static void *get_unlocked_mapping_entry(struct address_space *mapping,
        ewait.wait.func = wake_exceptional_entry_func;
 
        for (;;) {
+               bool revalidate;
+
                entry = __radix_tree_lookup(&mapping->i_pages, index, NULL,
                                          &slot);
                if (!entry ||
@@ -251,14 +253,31 @@ static void *get_unlocked_mapping_entry(struct address_space *mapping,
                prepare_to_wait_exclusive(wq, &ewait.wait,
                                          TASK_UNINTERRUPTIBLE);
                xa_unlock_irq(&mapping->i_pages);
-               schedule();
+               revalidate = wait_fn();
                finish_wait(wq, &ewait.wait);
                xa_lock_irq(&mapping->i_pages);
+               if (revalidate)
+                       return ERR_PTR(-EAGAIN);
        }
 }
 
-static void dax_unlock_mapping_entry(struct address_space *mapping,
-                                    pgoff_t index)
+static bool entry_wait(void)
+{
+       schedule();
+       /*
+        * Never return an ERR_PTR() from
+        * __get_unlocked_mapping_entry(), just keep looping.
+        */
+       return false;
+}
+
+static void *get_unlocked_mapping_entry(struct address_space *mapping,
+               pgoff_t index, void ***slotp)
+{
+       return __get_unlocked_mapping_entry(mapping, index, slotp, entry_wait);
+}
+
+static void unlock_mapping_entry(struct address_space *mapping, pgoff_t index)
 {
        void *entry, **slot;
 
@@ -277,7 +296,7 @@ static void dax_unlock_mapping_entry(struct address_space *mapping,
 static void put_locked_mapping_entry(struct address_space *mapping,
                pgoff_t index)
 {
-       dax_unlock_mapping_entry(mapping, index);
+       unlock_mapping_entry(mapping, index);
 }
 
 /*
@@ -319,18 +338,27 @@ static unsigned long dax_radix_end_pfn(void *entry)
        for (pfn = dax_radix_pfn(entry); \
                        pfn < dax_radix_end_pfn(entry); pfn++)
 
-static void dax_associate_entry(void *entry, struct address_space *mapping)
+/*
+ * TODO: for reflink+dax we need a way to associate a single page with
+ * multiple address_space instances at different linear_page_index()
+ * offsets.
+ */
+static void dax_associate_entry(void *entry, struct address_space *mapping,
+               struct vm_area_struct *vma, unsigned long address)
 {
-       unsigned long pfn;
+       unsigned long size = dax_entry_size(entry), pfn, index;
+       int i = 0;
 
        if (IS_ENABLED(CONFIG_FS_DAX_LIMITED))
                return;
 
+       index = linear_page_index(vma, address & ~(size - 1));
        for_each_mapped_pfn(entry, pfn) {
                struct page *page = pfn_to_page(pfn);
 
                WARN_ON_ONCE(page->mapping);
                page->mapping = mapping;
+               page->index = index + i++;
        }
 }
 
@@ -348,6 +376,7 @@ static void dax_disassociate_entry(void *entry, struct address_space *mapping,
                WARN_ON_ONCE(trunc && page_ref_count(page) > 1);
                WARN_ON_ONCE(page->mapping && page->mapping != mapping);
                page->mapping = NULL;
+               page->index = 0;
        }
 }
 
@@ -364,6 +393,84 @@ static struct page *dax_busy_page(void *entry)
        return NULL;
 }
 
+static bool entry_wait_revalidate(void)
+{
+       rcu_read_unlock();
+       schedule();
+       rcu_read_lock();
+
+       /*
+        * Tell __get_unlocked_mapping_entry() to take a break, we need
+        * to revalidate page->mapping after dropping locks
+        */
+       return true;
+}
+
+bool dax_lock_mapping_entry(struct page *page)
+{
+       pgoff_t index;
+       struct inode *inode;
+       bool did_lock = false;
+       void *entry = NULL, **slot;
+       struct address_space *mapping;
+
+       rcu_read_lock();
+       for (;;) {
+               mapping = READ_ONCE(page->mapping);
+
+               if (!dax_mapping(mapping))
+                       break;
+
+               /*
+                * In the device-dax case there's no need to lock, a
+                * struct dev_pagemap pin is sufficient to keep the
+                * inode alive, and we assume we have dev_pagemap pin
+                * otherwise we would not have a valid pfn_to_page()
+                * translation.
+                */
+               inode = mapping->host;
+               if (S_ISCHR(inode->i_mode)) {
+                       did_lock = true;
+                       break;
+               }
+
+               xa_lock_irq(&mapping->i_pages);
+               if (mapping != page->mapping) {
+                       xa_unlock_irq(&mapping->i_pages);
+                       continue;
+               }
+               index = page->index;
+
+               entry = __get_unlocked_mapping_entry(mapping, index, &slot,
+                               entry_wait_revalidate);
+               if (!entry) {
+                       xa_unlock_irq(&mapping->i_pages);
+                       break;
+               } else if (IS_ERR(entry)) {
+                       WARN_ON_ONCE(PTR_ERR(entry) != -EAGAIN);
+                       continue;
+               }
+               lock_slot(mapping, slot);
+               did_lock = true;
+               xa_unlock_irq(&mapping->i_pages);
+               break;
+       }
+       rcu_read_unlock();
+
+       return did_lock;
+}
+
+void dax_unlock_mapping_entry(struct page *page)
+{
+       struct address_space *mapping = page->mapping;
+       struct inode *inode = mapping->host;
+
+       if (S_ISCHR(inode->i_mode))
+               return;
+
+       unlock_mapping_entry(mapping, page->index);
+}
+
 /*
  * Find radix tree entry at given index. If it points to an exceptional entry,
  * return it with the radix tree entry locked. If the radix tree doesn't
@@ -655,7 +762,6 @@ static int copy_user_dax(struct block_device *bdev, struct dax_device *dax_dev,
 {
        void *vto, *kaddr;
        pgoff_t pgoff;
-       pfn_t pfn;
        long rc;
        int id;
 
@@ -664,7 +770,7 @@ static int copy_user_dax(struct block_device *bdev, struct dax_device *dax_dev,
                return rc;
 
        id = dax_read_lock();
-       rc = dax_direct_access(dax_dev, pgoff, PHYS_PFN(size), &kaddr, &pfn);
+       rc = dax_direct_access(dax_dev, pgoff, PHYS_PFN(size), &kaddr, NULL);
        if (rc < 0) {
                dax_read_unlock(id);
                return rc;
@@ -709,7 +815,7 @@ static void *dax_insert_mapping_entry(struct address_space *mapping,
        new_entry = dax_radix_locked_entry(pfn, flags);
        if (dax_entry_size(entry) != dax_entry_size(new_entry)) {
                dax_disassociate_entry(entry, mapping, false);
-               dax_associate_entry(new_entry, mapping);
+               dax_associate_entry(new_entry, mapping, vmf->vma, vmf->address);
        }
 
        if (dax_is_zero_entry(entry) || dax_is_empty_entry(entry)) {
@@ -975,7 +1081,6 @@ static int dax_iomap_pfn(struct iomap *iomap, loff_t pos, size_t size,
 {
        const sector_t sector = dax_iomap_sector(iomap, pos);
        pgoff_t pgoff;
-       void *kaddr;
        int id, rc;
        long length;
 
@@ -984,7 +1089,7 @@ static int dax_iomap_pfn(struct iomap *iomap, loff_t pos, size_t size,
                return rc;
        id = dax_read_lock();
        length = dax_direct_access(iomap->dax_dev, pgoff, PHYS_PFN(size),
-                                  &kaddr, pfnp);
+                                  NULL, pfnp);
        if (length < 0) {
                rc = length;
                goto out;
@@ -1060,15 +1165,13 @@ int __dax_zero_page_range(struct block_device *bdev,
                pgoff_t pgoff;
                long rc, id;
                void *kaddr;
-               pfn_t pfn;
 
                rc = bdev_dax_pgoff(bdev, sector, PAGE_SIZE, &pgoff);
                if (rc)
                        return rc;
 
                id = dax_read_lock();
-               rc = dax_direct_access(dax_dev, pgoff, 1, &kaddr,
-                               &pfn);
+               rc = dax_direct_access(dax_dev, pgoff, 1, &kaddr, NULL);
                if (rc < 0) {
                        dax_read_unlock(id);
                        return rc;
@@ -1124,7 +1227,6 @@ dax_iomap_actor(struct inode *inode, loff_t pos, loff_t length, void *data,
                ssize_t map_len;
                pgoff_t pgoff;
                void *kaddr;
-               pfn_t pfn;
 
                if (fatal_signal_pending(current)) {
                        ret = -EINTR;
@@ -1136,7 +1238,7 @@ dax_iomap_actor(struct inode *inode, loff_t pos, loff_t length, void *data,
                        break;
 
                map_len = dax_direct_access(dax_dev, pgoff, PHYS_PFN(size),
-                               &kaddr, &pfn);
+                               &kaddr, NULL);
                if (map_len < 0) {
                        ret = map_len;
                        break;
index e072e95..c538145 100644 (file)
@@ -46,7 +46,7 @@ static int pty_limit = NR_UNIX98_PTY_DEFAULT;
 static int pty_reserve = NR_UNIX98_PTY_RESERVE;
 static int pty_limit_min;
 static int pty_limit_max = INT_MAX;
-static int pty_count;
+static atomic_t pty_count = ATOMIC_INIT(0);
 
 static struct ctl_table pty_table[] = {
        {
@@ -93,8 +93,6 @@ static struct ctl_table pty_root_table[] = {
        {}
 };
 
-static DEFINE_MUTEX(allocated_ptys_lock);
-
 struct pts_mount_opts {
        int setuid;
        int setgid;
@@ -533,44 +531,25 @@ static struct file_system_type devpts_fs_type = {
 
 int devpts_new_index(struct pts_fs_info *fsi)
 {
-       int index;
-       int ida_ret;
-
-retry:
-       if (!ida_pre_get(&fsi->allocated_ptys, GFP_KERNEL))
-               return -ENOMEM;
-
-       mutex_lock(&allocated_ptys_lock);
-       if (pty_count >= (pty_limit -
-                         (fsi->mount_opts.reserve ? 0 : pty_reserve))) {
-               mutex_unlock(&allocated_ptys_lock);
-               return -ENOSPC;
-       }
+       int index = -ENOSPC;
 
-       ida_ret = ida_get_new(&fsi->allocated_ptys, &index);
-       if (ida_ret < 0) {
-               mutex_unlock(&allocated_ptys_lock);
-               if (ida_ret == -EAGAIN)
-                       goto retry;
-               return -EIO;
-       }
+       if (atomic_inc_return(&pty_count) >= (pty_limit -
+                         (fsi->mount_opts.reserve ? 0 : pty_reserve)))
+               goto out;
 
-       if (index >= fsi->mount_opts.max) {
-               ida_remove(&fsi->allocated_ptys, index);
-               mutex_unlock(&allocated_ptys_lock);
-               return -ENOSPC;
-       }
-       pty_count++;
-       mutex_unlock(&allocated_ptys_lock);
+       index = ida_alloc_max(&fsi->allocated_ptys, fsi->mount_opts.max - 1,
+                       GFP_KERNEL);
+
+out:
+       if (index < 0)
+               atomic_dec(&pty_count);
        return index;
 }
 
 void devpts_kill_index(struct pts_fs_info *fsi, int idx)
 {
-       mutex_lock(&allocated_ptys_lock);
-       ida_remove(&fsi->allocated_ptys, idx);
-       pty_count--;
-       mutex_unlock(&allocated_ptys_lock);
+       ida_free(&fsi->allocated_ptys, idx);
+       atomic_dec(&pty_count);
 }
 
 /**
index 67db22f..42bbe68 100644 (file)
  *
  * 1) epmutex (mutex)
  * 2) ep->mtx (mutex)
- * 3) ep->lock (spinlock)
+ * 3) ep->wq.lock (spinlock)
  *
  * The acquire order is the one listed above, from 1 to 3.
- * We need a spinlock (ep->lock) because we manipulate objects
+ * We need a spinlock (ep->wq.lock) because we manipulate objects
  * from inside the poll callback, that might be triggered from
  * a wake_up() that in turn might be called from IRQ context.
  * So we can't sleep inside the poll callback and hence we need
@@ -85,7 +85,7 @@
  * of epoll file descriptors, we use the current recursion depth as
  * the lockdep subkey.
  * It is possible to drop the "ep->mtx" and to use the global
- * mutex "epmutex" (together with "ep->lock") to have it working,
+ * mutex "epmutex" (together with "ep->wq.lock") to have it working,
  * but having "ep->mtx" will make the interface more scalable.
  * Events that require holding "epmutex" are very rare, while for
  * normal operations the epoll private "ep->mtx" will guarantee
@@ -182,11 +182,10 @@ struct epitem {
  * This structure is stored inside the "private_data" member of the file
  * structure and represents the main data structure for the eventpoll
  * interface.
+ *
+ * Access to it is protected by the lock inside wq.
  */
 struct eventpoll {
-       /* Protect the access to this structure */
-       spinlock_t lock;
-
        /*
         * This mutex is used to ensure that files are not removed
         * while epoll is using them. This is held during the event
@@ -210,7 +209,7 @@ struct eventpoll {
        /*
         * This is a single linked list that chains all the "struct epitem" that
         * happened while transferring ready events to userspace w/out
-        * holding ->lock.
+        * holding ->wq.lock.
         */
        struct epitem *ovflist;
 
@@ -337,9 +336,9 @@ static inline int ep_cmp_ffd(struct epoll_filefd *p1,
 }
 
 /* Tells us if the item is currently linked */
-static inline int ep_is_linked(struct list_head *p)
+static inline int ep_is_linked(struct epitem *epi)
 {
-       return !list_empty(p);
+       return !list_empty(&epi->rdllink);
 }
 
 static inline struct eppoll_entry *ep_pwq_from_wait(wait_queue_entry_t *p)
@@ -392,7 +391,6 @@ static bool ep_busy_loop_end(void *p, unsigned long start_time)
 
        return ep_events_available(ep) || busy_loop_timeout(start_time);
 }
-#endif /* CONFIG_NET_RX_BUSY_POLL */
 
 /*
  * Busy poll if globally on and supporting sockets found && no events,
@@ -402,20 +400,16 @@ static bool ep_busy_loop_end(void *p, unsigned long start_time)
  */
 static void ep_busy_loop(struct eventpoll *ep, int nonblock)
 {
-#ifdef CONFIG_NET_RX_BUSY_POLL
        unsigned int napi_id = READ_ONCE(ep->napi_id);
 
        if ((napi_id >= MIN_NAPI_ID) && net_busy_loop_on())
                napi_busy_loop(napi_id, nonblock ? NULL : ep_busy_loop_end, ep);
-#endif
 }
 
 static inline void ep_reset_busy_poll_napi_id(struct eventpoll *ep)
 {
-#ifdef CONFIG_NET_RX_BUSY_POLL
        if (ep->napi_id)
                ep->napi_id = 0;
-#endif
 }
 
 /*
@@ -423,7 +417,6 @@ static inline void ep_reset_busy_poll_napi_id(struct eventpoll *ep)
  */
 static inline void ep_set_busy_poll_napi_id(struct epitem *epi)
 {
-#ifdef CONFIG_NET_RX_BUSY_POLL
        struct eventpoll *ep;
        unsigned int napi_id;
        struct socket *sock;
@@ -453,9 +446,24 @@ static inline void ep_set_busy_poll_napi_id(struct epitem *epi)
 
        /* record NAPI ID for use in next busy poll */
        ep->napi_id = napi_id;
-#endif
 }
 
+#else
+
+static inline void ep_busy_loop(struct eventpoll *ep, int nonblock)
+{
+}
+
+static inline void ep_reset_busy_poll_napi_id(struct eventpoll *ep)
+{
+}
+
+static inline void ep_set_busy_poll_napi_id(struct epitem *epi)
+{
+}
+
+#endif /* CONFIG_NET_RX_BUSY_POLL */
+
 /**
  * ep_call_nested - Perform a bound (possibly) nested call, by checking
  *                  that the recursion limit is not exceeded, and that
@@ -668,10 +676,11 @@ static __poll_t ep_scan_ready_list(struct eventpoll *ep,
 {
        __poll_t res;
        int pwake = 0;
-       unsigned long flags;
        struct epitem *epi, *nepi;
        LIST_HEAD(txlist);
 
+       lockdep_assert_irqs_enabled();
+
        /*
         * We need to lock this because we could be hit by
         * eventpoll_release_file() and epoll_ctl().
@@ -688,17 +697,17 @@ static __poll_t ep_scan_ready_list(struct eventpoll *ep,
         * because we want the "sproc" callback to be able to do it
         * in a lockless way.
         */
-       spin_lock_irqsave(&ep->lock, flags);
+       spin_lock_irq(&ep->wq.lock);
        list_splice_init(&ep->rdllist, &txlist);
        ep->ovflist = NULL;
-       spin_unlock_irqrestore(&ep->lock, flags);
+       spin_unlock_irq(&ep->wq.lock);
 
        /*
         * Now call the callback function.
         */
        res = (*sproc)(ep, &txlist, priv);
 
-       spin_lock_irqsave(&ep->lock, flags);
+       spin_lock_irq(&ep->wq.lock);
        /*
         * During the time we spent inside the "sproc" callback, some
         * other events might have been queued by the poll callback.
@@ -712,7 +721,7 @@ static __poll_t ep_scan_ready_list(struct eventpoll *ep,
                 * queued into ->ovflist but the "txlist" might already
                 * contain them, and the list_splice() below takes care of them.
                 */
-               if (!ep_is_linked(&epi->rdllink)) {
+               if (!ep_is_linked(epi)) {
                        list_add_tail(&epi->rdllink, &ep->rdllist);
                        ep_pm_stay_awake(epi);
                }
@@ -740,7 +749,7 @@ static __poll_t ep_scan_ready_list(struct eventpoll *ep,
                if (waitqueue_active(&ep->poll_wait))
                        pwake++;
        }
-       spin_unlock_irqrestore(&ep->lock, flags);
+       spin_unlock_irq(&ep->wq.lock);
 
        if (!ep_locked)
                mutex_unlock(&ep->mtx);
@@ -764,16 +773,12 @@ static void epi_rcu_free(struct rcu_head *head)
  */
 static int ep_remove(struct eventpoll *ep, struct epitem *epi)
 {
-       unsigned long flags;
        struct file *file = epi->ffd.file;
 
+       lockdep_assert_irqs_enabled();
+
        /*
-        * Removes poll wait queue hooks. We _have_ to do this without holding
-        * the "ep->lock" otherwise a deadlock might occur. This because of the
-        * sequence of the lock acquisition. Here we do "ep->lock" then the wait
-        * queue head lock when unregistering the wait queue. The wakeup callback
-        * will run by holding the wait queue head lock and will call our callback
-        * that will try to get "ep->lock".
+        * Removes poll wait queue hooks.
         */
        ep_unregister_pollwait(ep, epi);
 
@@ -784,10 +789,10 @@ static int ep_remove(struct eventpoll *ep, struct epitem *epi)
 
        rb_erase_cached(&epi->rbn, &ep->rbr);
 
-       spin_lock_irqsave(&ep->lock, flags);
-       if (ep_is_linked(&epi->rdllink))
+       spin_lock_irq(&ep->wq.lock);
+       if (ep_is_linked(epi))
                list_del_init(&epi->rdllink);
-       spin_unlock_irqrestore(&ep->lock, flags);
+       spin_unlock_irq(&ep->wq.lock);
 
        wakeup_source_unregister(ep_wakeup_source(epi));
        /*
@@ -837,7 +842,7 @@ static void ep_free(struct eventpoll *ep)
         * Walks through the whole tree by freeing each "struct epitem". At this
         * point we are sure no poll callbacks will be lingering around, and also by
         * holding "epmutex" we can be sure that no file cleanup code will hit
-        * us during this operation. So we can avoid the lock on "ep->lock".
+        * us during this operation. So we can avoid the lock on "ep->wq.lock".
         * We do not need to lock ep->mtx, either, we only do it to prevent
         * a lockdep warning.
         */
@@ -1017,7 +1022,6 @@ static int ep_alloc(struct eventpoll **pep)
        if (unlikely(!ep))
                goto free_uid;
 
-       spin_lock_init(&ep->lock);
        mutex_init(&ep->mtx);
        init_waitqueue_head(&ep->wq);
        init_waitqueue_head(&ep->poll_wait);
@@ -1122,7 +1126,7 @@ static int ep_poll_callback(wait_queue_entry_t *wait, unsigned mode, int sync, v
        __poll_t pollflags = key_to_poll(key);
        int ewake = 0;
 
-       spin_lock_irqsave(&ep->lock, flags);
+       spin_lock_irqsave(&ep->wq.lock, flags);
 
        ep_set_busy_poll_napi_id(epi);
 
@@ -1167,7 +1171,7 @@ static int ep_poll_callback(wait_queue_entry_t *wait, unsigned mode, int sync, v
        }
 
        /* If this file is already in the ready list we exit soon */
-       if (!ep_is_linked(&epi->rdllink)) {
+       if (!ep_is_linked(epi)) {
                list_add_tail(&epi->rdllink, &ep->rdllist);
                ep_pm_stay_awake_rcu(epi);
        }
@@ -1199,7 +1203,7 @@ static int ep_poll_callback(wait_queue_entry_t *wait, unsigned mode, int sync, v
                pwake++;
 
 out_unlock:
-       spin_unlock_irqrestore(&ep->lock, flags);
+       spin_unlock_irqrestore(&ep->wq.lock, flags);
 
        /* We have to call this outside the lock */
        if (pwake)
@@ -1417,11 +1421,12 @@ static int ep_insert(struct eventpoll *ep, const struct epoll_event *event,
 {
        int error, pwake = 0;
        __poll_t revents;
-       unsigned long flags;
        long user_watches;
        struct epitem *epi;
        struct ep_pqueue epq;
 
+       lockdep_assert_irqs_enabled();
+
        user_watches = atomic_long_read(&ep->user->epoll_watches);
        if (unlikely(user_watches >= max_user_watches))
                return -ENOSPC;
@@ -1484,13 +1489,13 @@ static int ep_insert(struct eventpoll *ep, const struct epoll_event *event,
                goto error_remove_epi;
 
        /* We have to drop the new item inside our item list to keep track of it */
-       spin_lock_irqsave(&ep->lock, flags);
+       spin_lock_irq(&ep->wq.lock);
 
        /* record NAPI ID of new item if present */
        ep_set_busy_poll_napi_id(epi);
 
        /* If the file is already "ready" we drop it inside the ready list */
-       if (revents && !ep_is_linked(&epi->rdllink)) {
+       if (revents && !ep_is_linked(epi)) {
                list_add_tail(&epi->rdllink, &ep->rdllist);
                ep_pm_stay_awake(epi);
 
@@ -1501,7 +1506,7 @@ static int ep_insert(struct eventpoll *ep, const struct epoll_event *event,
                        pwake++;
        }
 
-       spin_unlock_irqrestore(&ep->lock, flags);
+       spin_unlock_irq(&ep->wq.lock);
 
        atomic_long_inc(&ep->user->epoll_watches);
 
@@ -1527,10 +1532,10 @@ error_unregister:
         * list, since that is used/cleaned only inside a section bound by "mtx".
         * And ep_insert() is called with "mtx" held.
         */
-       spin_lock_irqsave(&ep->lock, flags);
-       if (ep_is_linked(&epi->rdllink))
+       spin_lock_irq(&ep->wq.lock);
+       if (ep_is_linked(epi))
                list_del_init(&epi->rdllink);
-       spin_unlock_irqrestore(&ep->lock, flags);
+       spin_unlock_irq(&ep->wq.lock);
 
        wakeup_source_unregister(ep_wakeup_source(epi));
 
@@ -1550,6 +1555,8 @@ static int ep_modify(struct eventpoll *ep, struct epitem *epi,
        int pwake = 0;
        poll_table pt;
 
+       lockdep_assert_irqs_enabled();
+
        init_poll_funcptr(&pt, NULL);
 
        /*
@@ -1572,9 +1579,9 @@ static int ep_modify(struct eventpoll *ep, struct epitem *epi,
         * 1) Flush epi changes above to other CPUs.  This ensures
         *    we do not miss events from ep_poll_callback if an
         *    event occurs immediately after we call f_op->poll().
-        *    We need this because we did not take ep->lock while
+        *    We need this because we did not take ep->wq.lock while
         *    changing epi above (but ep_poll_callback does take
-        *    ep->lock).
+        *    ep->wq.lock).
         *
         * 2) We also need to ensure we do not miss _past_ events
         *    when calling f_op->poll().  This barrier also
@@ -1593,8 +1600,8 @@ static int ep_modify(struct eventpoll *ep, struct epitem *epi,
         * list, push it inside.
         */
        if (ep_item_poll(epi, &pt, 1)) {
-               spin_lock_irq(&ep->lock);
-               if (!ep_is_linked(&epi->rdllink)) {
+               spin_lock_irq(&ep->wq.lock);
+               if (!ep_is_linked(epi)) {
                        list_add_tail(&epi->rdllink, &ep->rdllist);
                        ep_pm_stay_awake(epi);
 
@@ -1604,7 +1611,7 @@ static int ep_modify(struct eventpoll *ep, struct epitem *epi,
                        if (waitqueue_active(&ep->poll_wait))
                                pwake++;
                }
-               spin_unlock_irq(&ep->lock);
+               spin_unlock_irq(&ep->wq.lock);
        }
 
        /* We have to call this outside the lock */
@@ -1739,11 +1746,12 @@ static int ep_poll(struct eventpoll *ep, struct epoll_event __user *events,
                   int maxevents, long timeout)
 {
        int res = 0, eavail, timed_out = 0;
-       unsigned long flags;
        u64 slack = 0;
        wait_queue_entry_t wait;
        ktime_t expires, *to = NULL;
 
+       lockdep_assert_irqs_enabled();
+
        if (timeout > 0) {
                struct timespec64 end_time = ep_set_mstimeout(timeout);
 
@@ -1756,7 +1764,7 @@ static int ep_poll(struct eventpoll *ep, struct epoll_event __user *events,
                 * caller specified a non blocking operation.
                 */
                timed_out = 1;
-               spin_lock_irqsave(&ep->lock, flags);
+               spin_lock_irq(&ep->wq.lock);
                goto check_events;
        }
 
@@ -1765,7 +1773,7 @@ fetch_events:
        if (!ep_events_available(ep))
                ep_busy_loop(ep, timed_out);
 
-       spin_lock_irqsave(&ep->lock, flags);
+       spin_lock_irq(&ep->wq.lock);
 
        if (!ep_events_available(ep)) {
                /*
@@ -1807,11 +1815,11 @@ fetch_events:
                                break;
                        }
 
-                       spin_unlock_irqrestore(&ep->lock, flags);
+                       spin_unlock_irq(&ep->wq.lock);
                        if (!schedule_hrtimeout_range(to, slack, HRTIMER_MODE_ABS))
                                timed_out = 1;
 
-                       spin_lock_irqsave(&ep->lock, flags);
+                       spin_lock_irq(&ep->wq.lock);
                }
 
                __remove_wait_queue(&ep->wq, &wait);
@@ -1821,7 +1829,7 @@ check_events:
        /* Is it worth to try to dig for events ? */
        eavail = ep_events_available(ep);
 
-       spin_unlock_irqrestore(&ep->lock, flags);
+       spin_unlock_irq(&ep->wq.lock);
 
        /*
         * Try to transfer events to user space. In case we get 0 events and
index bdd0eac..1ebf6e5 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1145,6 +1145,7 @@ static int de_thread(struct task_struct *tsk)
                 */
                tsk->pid = leader->pid;
                change_pid(tsk, PIDTYPE_PID, task_pid(leader));
+               transfer_pid(leader, tsk, PIDTYPE_TGID);
                transfer_pid(leader, tsk, PIDTYPE_PGID);
                transfer_pid(leader, tsk, PIDTYPE_SID);
 
index 9f1c96c..e8b6b89 100644 (file)
@@ -28,6 +28,7 @@ struct kmem_cache *f2fs_inode_entry_slab;
 
 void f2fs_stop_checkpoint(struct f2fs_sb_info *sbi, bool end_io)
 {
+       f2fs_build_fault_attr(sbi, 0, 0);
        set_ckpt_flags(sbi, CP_ERROR_FLAG);
        if (!end_io)
                f2fs_flush_merged_writes(sbi);
@@ -70,6 +71,7 @@ static struct page *__get_meta_page(struct f2fs_sb_info *sbi, pgoff_t index,
                .encrypted_page = NULL,
                .is_meta = is_meta,
        };
+       int err;
 
        if (unlikely(!is_meta))
                fio.op_flags &= ~REQ_META;
@@ -84,9 +86,10 @@ repeat:
 
        fio.page = page;
 
-       if (f2fs_submit_page_bio(&fio)) {
+       err = f2fs_submit_page_bio(&fio);
+       if (err) {
                f2fs_put_page(page, 1);
-               goto repeat;
+               return ERR_PTR(err);
        }
 
        lock_page(page);
@@ -95,14 +98,9 @@ repeat:
                goto repeat;
        }
 
-       /*
-        * if there is any IO error when accessing device, make our filesystem
-        * readonly and make sure do not write checkpoint with non-uptodate
-        * meta page.
-        */
        if (unlikely(!PageUptodate(page))) {
-               memset(page_address(page), 0, PAGE_SIZE);
-               f2fs_stop_checkpoint(sbi, false);
+               f2fs_put_page(page, 1);
+               return ERR_PTR(-EIO);
        }
 out:
        return page;
@@ -113,13 +111,32 @@ struct page *f2fs_get_meta_page(struct f2fs_sb_info *sbi, pgoff_t index)
        return __get_meta_page(sbi, index, true);
 }
 
+struct page *f2fs_get_meta_page_nofail(struct f2fs_sb_info *sbi, pgoff_t index)
+{
+       struct page *page;
+       int count = 0;
+
+retry:
+       page = __get_meta_page(sbi, index, true);
+       if (IS_ERR(page)) {
+               if (PTR_ERR(page) == -EIO &&
+                               ++count <= DEFAULT_RETRY_IO_COUNT)
+                       goto retry;
+
+               f2fs_stop_checkpoint(sbi, false);
+               f2fs_bug_on(sbi, 1);
+       }
+
+       return page;
+}
+
 /* for POR only */
 struct page *f2fs_get_tmp_page(struct f2fs_sb_info *sbi, pgoff_t index)
 {
        return __get_meta_page(sbi, index, false);
 }
 
-bool f2fs_is_valid_meta_blkaddr(struct f2fs_sb_info *sbi,
+bool f2fs_is_valid_blkaddr(struct f2fs_sb_info *sbi,
                                        block_t blkaddr, int type)
 {
        switch (type) {
@@ -140,8 +157,20 @@ bool f2fs_is_valid_meta_blkaddr(struct f2fs_sb_info *sbi,
                        return false;
                break;
        case META_POR:
+       case DATA_GENERIC:
                if (unlikely(blkaddr >= MAX_BLKADDR(sbi) ||
-                       blkaddr < MAIN_BLKADDR(sbi)))
+                       blkaddr < MAIN_BLKADDR(sbi))) {
+                       if (type == DATA_GENERIC) {
+                               f2fs_msg(sbi->sb, KERN_WARNING,
+                                       "access invalid blkaddr:%u", blkaddr);
+                               WARN_ON(1);
+                       }
+                       return false;
+               }
+               break;
+       case META_GENERIC:
+               if (unlikely(blkaddr < SEG0_BLKADDR(sbi) ||
+                       blkaddr >= MAIN_BLKADDR(sbi)))
                        return false;
                break;
        default:
@@ -176,7 +205,7 @@ int f2fs_ra_meta_pages(struct f2fs_sb_info *sbi, block_t start, int nrpages,
        blk_start_plug(&plug);
        for (; nrpages-- > 0; blkno++) {
 
-               if (!f2fs_is_valid_meta_blkaddr(sbi, blkno, type))
+               if (!f2fs_is_valid_blkaddr(sbi, blkno, type))
                        goto out;
 
                switch (type) {
@@ -242,11 +271,8 @@ static int __f2fs_write_meta_page(struct page *page,
 
        trace_f2fs_writepage(page, META);
 
-       if (unlikely(f2fs_cp_error(sbi))) {
-               dec_page_count(sbi, F2FS_DIRTY_META);
-               unlock_page(page);
-               return 0;
-       }
+       if (unlikely(f2fs_cp_error(sbi)))
+               goto redirty_out;
        if (unlikely(is_sbi_flag_set(sbi, SBI_POR_DOING)))
                goto redirty_out;
        if (wbc->for_reclaim && page->index < GET_SUM_BLOCK(sbi, 0))
@@ -529,13 +555,12 @@ int f2fs_acquire_orphan_inode(struct f2fs_sb_info *sbi)
 
        spin_lock(&im->ino_lock);
 
-#ifdef CONFIG_F2FS_FAULT_INJECTION
        if (time_to_inject(sbi, FAULT_ORPHAN)) {
                spin_unlock(&im->ino_lock);
                f2fs_show_injection_info(FAULT_ORPHAN);
                return -ENOSPC;
        }
-#endif
+
        if (unlikely(im->ino_num >= sbi->max_orphans))
                err = -ENOSPC;
        else
@@ -572,12 +597,7 @@ static int recover_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino)
 {
        struct inode *inode;
        struct node_info ni;
-       int err = f2fs_acquire_orphan_inode(sbi);
-
-       if (err)
-               goto err_out;
-
-       __add_ino_entry(sbi, ino, 0, ORPHAN_INO);
+       int err;
 
        inode = f2fs_iget_retry(sbi->sb, ino);
        if (IS_ERR(inode)) {
@@ -600,14 +620,15 @@ static int recover_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino)
        /* truncate all the data during iput */
        iput(inode);
 
-       f2fs_get_node_info(sbi, ino, &ni);
+       err = f2fs_get_node_info(sbi, ino, &ni);
+       if (err)
+               goto err_out;
 
        /* ENOMEM was fully retried in f2fs_evict_inode. */
        if (ni.blk_addr != NULL_ADDR) {
                err = -EIO;
                goto err_out;
        }
-       __remove_ino_entry(sbi, ino, ORPHAN_INO);
        return 0;
 
 err_out:
@@ -639,7 +660,10 @@ int f2fs_recover_orphan_inodes(struct f2fs_sb_info *sbi)
        /* Needed for iput() to work correctly and not trash data */
        sbi->sb->s_flags |= SB_ACTIVE;
 
-       /* Turn on quotas so that they are updated correctly */
+       /*
+        * Turn on quotas which were not enabled for read-only mounts if
+        * filesystem has quota feature, so that they are updated correctly.
+        */
        quota_enabled = f2fs_enable_quota_files(sbi, s_flags & SB_RDONLY);
 #endif
 
@@ -649,9 +673,15 @@ int f2fs_recover_orphan_inodes(struct f2fs_sb_info *sbi)
        f2fs_ra_meta_pages(sbi, start_blk, orphan_blocks, META_CP, true);
 
        for (i = 0; i < orphan_blocks; i++) {
-               struct page *page = f2fs_get_meta_page(sbi, start_blk + i);
+               struct page *page;
                struct f2fs_orphan_block *orphan_blk;
 
+               page = f2fs_get_meta_page(sbi, start_blk + i);
+               if (IS_ERR(page)) {
+                       err = PTR_ERR(page);
+                       goto out;
+               }
+
                orphan_blk = (struct f2fs_orphan_block *)page_address(page);
                for (j = 0; j < le32_to_cpu(orphan_blk->entry_count); j++) {
                        nid_t ino = le32_to_cpu(orphan_blk->ino[j]);
@@ -742,10 +772,14 @@ static int get_checkpoint_version(struct f2fs_sb_info *sbi, block_t cp_addr,
        __u32 crc = 0;
 
        *cp_page = f2fs_get_meta_page(sbi, cp_addr);
+       if (IS_ERR(*cp_page))
+               return PTR_ERR(*cp_page);
+
        *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))) {
+               f2fs_put_page(*cp_page, 1);
                f2fs_msg(sbi->sb, KERN_WARNING,
                        "invalid crc_offset: %zu", crc_offset);
                return -EINVAL;
@@ -753,6 +787,7 @@ static int get_checkpoint_version(struct f2fs_sb_info *sbi, block_t cp_addr,
 
        crc = cur_cp_crc(*cp_block);
        if (!f2fs_crc_valid(sbi, crc, *cp_block, crc_offset)) {
+               f2fs_put_page(*cp_page, 1);
                f2fs_msg(sbi->sb, KERN_WARNING, "invalid crc value");
                return -EINVAL;
        }
@@ -772,14 +807,22 @@ static struct page *validate_checkpoint(struct f2fs_sb_info *sbi,
        err = get_checkpoint_version(sbi, cp_addr, &cp_block,
                                        &cp_page_1, version);
        if (err)
-               goto invalid_cp1;
+               return NULL;
+
+       if (le32_to_cpu(cp_block->cp_pack_total_block_count) >
+                                       sbi->blocks_per_seg) {
+               f2fs_msg(sbi->sb, KERN_WARNING,
+                       "invalid cp_pack_total_block_count:%u",
+                       le32_to_cpu(cp_block->cp_pack_total_block_count));
+               goto invalid_cp;
+       }
        pre_version = *version;
 
        cp_addr += le32_to_cpu(cp_block->cp_pack_total_block_count) - 1;
        err = get_checkpoint_version(sbi, cp_addr, &cp_block,
                                        &cp_page_2, version);
        if (err)
-               goto invalid_cp2;
+               goto invalid_cp;
        cur_version = *version;
 
        if (cur_version == pre_version) {
@@ -787,9 +830,8 @@ static struct page *validate_checkpoint(struct f2fs_sb_info *sbi,
                f2fs_put_page(cp_page_2, 1);
                return cp_page_1;
        }
-invalid_cp2:
        f2fs_put_page(cp_page_2, 1);
-invalid_cp1:
+invalid_cp:
        f2fs_put_page(cp_page_1, 1);
        return NULL;
 }
@@ -838,15 +880,15 @@ int f2fs_get_valid_checkpoint(struct f2fs_sb_info *sbi)
        cp_block = (struct f2fs_checkpoint *)page_address(cur_page);
        memcpy(sbi->ckpt, cp_block, blk_size);
 
-       /* Sanity checking of checkpoint */
-       if (f2fs_sanity_check_ckpt(sbi))
-               goto free_fail_no_cp;
-
        if (cur_page == cp1)
                sbi->cur_cp_pack = 1;
        else
                sbi->cur_cp_pack = 2;
 
+       /* Sanity checking of checkpoint */
+       if (f2fs_sanity_check_ckpt(sbi))
+               goto free_fail_no_cp;
+
        if (cp_blks <= 1)
                goto done;
 
@@ -859,6 +901,8 @@ int f2fs_get_valid_checkpoint(struct f2fs_sb_info *sbi)
                unsigned char *ckpt = (unsigned char *)sbi->ckpt;
 
                cur_page = f2fs_get_meta_page(sbi, cp_blk_no + i);
+               if (IS_ERR(cur_page))
+                       goto free_fail_no_cp;
                sit_bitmap_ptr = page_address(cur_page);
                memcpy(ckpt + i * blk_size, sit_bitmap_ptr, blk_size);
                f2fs_put_page(cur_page, 1);
@@ -980,12 +1024,10 @@ retry:
 
                iput(inode);
                /* We need to give cpu to another writers. */
-               if (ino == cur_ino) {
-                       congestion_wait(BLK_RW_ASYNC, HZ/50);
+               if (ino == cur_ino)
                        cond_resched();
-               } else {
+               else
                        ino = cur_ino;
-               }
        } else {
                /*
                 * We should submit bio, since it exists several
@@ -1119,7 +1161,7 @@ static void unblock_operations(struct f2fs_sb_info *sbi)
        f2fs_unlock_all(sbi);
 }
 
-static void wait_on_all_pages_writeback(struct f2fs_sb_info *sbi)
+void f2fs_wait_on_all_pages_writeback(struct f2fs_sb_info *sbi)
 {
        DEFINE_WAIT(wait);
 
@@ -1129,6 +1171,9 @@ static void wait_on_all_pages_writeback(struct f2fs_sb_info *sbi)
                if (!get_pages(sbi, F2FS_WB_CP_DATA))
                        break;
 
+               if (unlikely(f2fs_cp_error(sbi)))
+                       break;
+
                io_schedule_timeout(5*HZ);
        }
        finish_wait(&sbi->cp_wait, &wait);
@@ -1202,8 +1247,12 @@ static void commit_checkpoint(struct f2fs_sb_info *sbi,
 
        /* writeout cp pack 2 page */
        err = __f2fs_write_meta_page(page, &wbc, FS_CP_META_IO);
-       f2fs_bug_on(sbi, err);
+       if (unlikely(err && f2fs_cp_error(sbi))) {
+               f2fs_put_page(page, 1);
+               return;
+       }
 
+       f2fs_bug_on(sbi, err);
        f2fs_put_page(page, 0);
 
        /* submit checkpoint (with barrier if NOBARRIER is not set) */
@@ -1229,7 +1278,7 @@ static int do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)
        while (get_pages(sbi, F2FS_DIRTY_META)) {
                f2fs_sync_meta_pages(sbi, META, LONG_MAX, FS_CP_META_IO);
                if (unlikely(f2fs_cp_error(sbi)))
-                       return -EIO;
+                       break;
        }
 
        /*
@@ -1309,7 +1358,7 @@ static int do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)
                        f2fs_sync_meta_pages(sbi, META, LONG_MAX,
                                                        FS_CP_META_IO);
                        if (unlikely(f2fs_cp_error(sbi)))
-                               return -EIO;
+                               break;
                }
        }
 
@@ -1348,10 +1397,7 @@ static int do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)
        f2fs_sync_meta_pages(sbi, META, LONG_MAX, FS_CP_META_IO);
 
        /* wait for previous submitted meta pages writeback */
-       wait_on_all_pages_writeback(sbi);
-
-       if (unlikely(f2fs_cp_error(sbi)))
-               return -EIO;
+       f2fs_wait_on_all_pages_writeback(sbi);
 
        /* flush all device cache */
        err = f2fs_flush_device_cache(sbi);
@@ -1360,12 +1406,19 @@ static int do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)
 
        /* barrier and flush checkpoint cp pack 2 page if it can */
        commit_checkpoint(sbi, ckpt, start_blk);
-       wait_on_all_pages_writeback(sbi);
+       f2fs_wait_on_all_pages_writeback(sbi);
+
+       /*
+        * invalidate intermediate page cache borrowed from meta inode
+        * which are used for migration of encrypted inode's blocks.
+        */
+       if (f2fs_sb_has_encrypt(sbi->sb))
+               invalidate_mapping_pages(META_MAPPING(sbi),
+                               MAIN_BLKADDR(sbi), MAX_BLKADDR(sbi) - 1);
 
        f2fs_release_ino_entry(sbi, false);
 
-       if (unlikely(f2fs_cp_error(sbi)))
-               return -EIO;
+       f2fs_reset_fsync_node_info(sbi);
 
        clear_sbi_flag(sbi, SBI_IS_DIRTY);
        clear_sbi_flag(sbi, SBI_NEED_CP);
@@ -1381,7 +1434,7 @@ static int do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)
 
        f2fs_bug_on(sbi, get_pages(sbi, F2FS_DIRTY_DENTS));
 
-       return 0;
+       return unlikely(f2fs_cp_error(sbi)) ? -EIO : 0;
 }
 
 /*
index b7c9b58..382c1ef 100644 (file)
@@ -126,12 +126,10 @@ static bool f2fs_bio_post_read_required(struct bio *bio)
 
 static void f2fs_read_end_io(struct bio *bio)
 {
-#ifdef CONFIG_F2FS_FAULT_INJECTION
        if (time_to_inject(F2FS_P_SB(bio_first_page_all(bio)), FAULT_IO)) {
                f2fs_show_injection_info(FAULT_IO);
                bio->bi_status = BLK_STS_IOERR;
        }
-#endif
 
        if (f2fs_bio_post_read_required(bio)) {
                struct bio_post_read_ctx *ctx = bio->bi_private;
@@ -177,6 +175,8 @@ static void f2fs_write_end_io(struct bio *bio)
                                        page->index != nid_of_node(page));
 
                dec_page_count(sbi, type);
+               if (f2fs_in_warm_node_list(sbi, page))
+                       f2fs_del_fsync_node_entry(sbi, page);
                clear_cold_data(page);
                end_page_writeback(page);
        }
@@ -264,7 +264,7 @@ static inline void __submit_bio(struct f2fs_sb_info *sbi,
                if (type != DATA && type != NODE)
                        goto submit_io;
 
-               if (f2fs_sb_has_blkzoned(sbi->sb) && current->plug)
+               if (test_opt(sbi, LFS) && current->plug)
                        blk_finish_plug(current->plug);
 
                start = bio->bi_iter.bi_size >> F2FS_BLKSIZE_BITS;
@@ -441,7 +441,10 @@ int f2fs_submit_page_bio(struct f2fs_io_info *fio)
        struct page *page = fio->encrypted_page ?
                        fio->encrypted_page : fio->page;
 
-       verify_block_addr(fio, fio->new_blkaddr);
+       if (!f2fs_is_valid_blkaddr(fio->sbi, fio->new_blkaddr,
+                       __is_meta_io(fio) ? META_GENERIC : DATA_GENERIC))
+               return -EFAULT;
+
        trace_f2fs_submit_page_bio(page, fio);
        f2fs_trace_ios(fio, 0);
 
@@ -485,7 +488,7 @@ next:
                spin_unlock(&io->io_lock);
        }
 
-       if (is_valid_blkaddr(fio->old_blkaddr))
+       if (__is_valid_data_blkaddr(fio->old_blkaddr))
                verify_block_addr(fio, fio->old_blkaddr);
        verify_block_addr(fio, fio->new_blkaddr);
 
@@ -534,19 +537,22 @@ out:
 }
 
 static struct bio *f2fs_grab_read_bio(struct inode *inode, block_t blkaddr,
-                                                        unsigned nr_pages)
+                                       unsigned nr_pages, unsigned op_flag)
 {
        struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
        struct bio *bio;
        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);
        f2fs_target_device(sbi, blkaddr, bio);
        bio->bi_end_io = f2fs_read_end_io;
-       bio_set_op_attrs(bio, REQ_OP_READ, 0);
+       bio_set_op_attrs(bio, REQ_OP_READ, op_flag);
 
        if (f2fs_encrypted_file(inode))
                post_read_steps |= 1 << STEP_DECRYPT;
@@ -571,7 +577,7 @@ 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);
+       struct bio *bio = f2fs_grab_read_bio(inode, blkaddr, 1, 0);
 
        if (IS_ERR(bio))
                return PTR_ERR(bio);
@@ -869,6 +875,7 @@ static int __allocate_data_block(struct dnode_of_data *dn, int seg_type)
        struct f2fs_sb_info *sbi = F2FS_I_SB(dn->inode);
        struct f2fs_summary sum;
        struct node_info ni;
+       block_t old_blkaddr;
        pgoff_t fofs;
        blkcnt_t count = 1;
        int err;
@@ -876,6 +883,10 @@ static int __allocate_data_block(struct dnode_of_data *dn, int seg_type)
        if (unlikely(is_inode_flag_set(dn->inode, FI_NO_ALLOC)))
                return -EPERM;
 
+       err = f2fs_get_node_info(sbi, dn->nid, &ni);
+       if (err)
+               return err;
+
        dn->data_blkaddr = datablock_addr(dn->inode,
                                dn->node_page, dn->ofs_in_node);
        if (dn->data_blkaddr == NEW_ADDR)
@@ -885,11 +896,13 @@ static int __allocate_data_block(struct dnode_of_data *dn, int seg_type)
                return err;
 
 alloc:
-       f2fs_get_node_info(sbi, dn->nid, &ni);
        set_summary(&sum, dn->nid, dn->ofs_in_node, ni.version);
-
-       f2fs_allocate_data_block(sbi, NULL, dn->data_blkaddr, &dn->data_blkaddr,
+       old_blkaddr = dn->data_blkaddr;
+       f2fs_allocate_data_block(sbi, NULL, old_blkaddr, &dn->data_blkaddr,
                                        &sum, seg_type, NULL, false);
+       if (GET_SEGNO(sbi, old_blkaddr) != NULL_SEGNO)
+               invalidate_mapping_pages(META_MAPPING(sbi),
+                                       old_blkaddr, old_blkaddr);
        f2fs_set_data_blkaddr(dn);
 
        /* update i_size */
@@ -1045,7 +1058,13 @@ next_dnode:
 next_block:
        blkaddr = datablock_addr(dn.inode, dn.node_page, dn.ofs_in_node);
 
-       if (!is_valid_blkaddr(blkaddr)) {
+       if (__is_valid_data_blkaddr(blkaddr) &&
+               !f2fs_is_valid_blkaddr(sbi, blkaddr, DATA_GENERIC)) {
+               err = -EFAULT;
+               goto sync_out;
+       }
+
+       if (!is_valid_data_blkaddr(sbi, blkaddr)) {
                if (create) {
                        if (unlikely(f2fs_cp_error(sbi))) {
                                err = -EIO;
@@ -1282,7 +1301,11 @@ static int f2fs_xattr_fiemap(struct inode *inode,
                if (!page)
                        return -ENOMEM;
 
-               f2fs_get_node_info(sbi, inode->i_ino, &ni);
+               err = f2fs_get_node_info(sbi, inode->i_ino, &ni);
+               if (err) {
+                       f2fs_put_page(page, 1);
+                       return err;
+               }
 
                phys = (__u64)blk_to_logical(inode, ni.blk_addr);
                offset = offsetof(struct f2fs_inode, i_addr) +
@@ -1309,7 +1332,11 @@ static int f2fs_xattr_fiemap(struct inode *inode,
                if (!page)
                        return -ENOMEM;
 
-               f2fs_get_node_info(sbi, xnid, &ni);
+               err = f2fs_get_node_info(sbi, xnid, &ni);
+               if (err) {
+                       f2fs_put_page(page, 1);
+                       return err;
+               }
 
                phys = (__u64)blk_to_logical(inode, ni.blk_addr);
                len = inode->i_sb->s_blocksize;
@@ -1425,11 +1452,11 @@ out:
  * Note that the aops->readpages() function is ONLY used for read-ahead. If
  * this function ever deviates from doing just read-ahead, it should either
  * use ->readpage() or do the necessary surgery to decouple ->readpages()
- * readom read-ahead.
+ * from read-ahead.
  */
 static int f2fs_mpage_readpages(struct address_space *mapping,
                        struct list_head *pages, struct page *page,
-                       unsigned nr_pages)
+                       unsigned nr_pages, bool is_readahead)
 {
        struct bio *bio = NULL;
        sector_t last_block_in_bio = 0;
@@ -1500,6 +1527,10 @@ got_it:
                                SetPageUptodate(page);
                                goto confused;
                        }
+
+                       if (!f2fs_is_valid_blkaddr(F2FS_I_SB(inode), block_nr,
+                                                               DATA_GENERIC))
+                               goto set_error_page;
                } else {
                        zero_user_segment(page, 0, PAGE_SIZE);
                        if (!PageUptodate(page))
@@ -1519,7 +1550,8 @@ submit_and_realloc:
                        bio = NULL;
                }
                if (bio == NULL) {
-                       bio = f2fs_grab_read_bio(inode, block_nr, nr_pages);
+                       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;
@@ -1563,7 +1595,7 @@ static int f2fs_read_data_page(struct file *file, struct page *page)
        if (f2fs_has_inline_data(inode))
                ret = f2fs_read_inline_data(inode, page);
        if (ret == -EAGAIN)
-               ret = f2fs_mpage_readpages(page->mapping, NULL, page, 1);
+               ret = f2fs_mpage_readpages(page->mapping, NULL, page, 1, false);
        return ret;
 }
 
@@ -1580,12 +1612,13 @@ static int f2fs_read_data_pages(struct file *file,
        if (f2fs_has_inline_data(inode))
                return 0;
 
-       return f2fs_mpage_readpages(mapping, pages, NULL, nr_pages);
+       return f2fs_mpage_readpages(mapping, pages, NULL, nr_pages, true);
 }
 
 static int encrypt_one_page(struct f2fs_io_info *fio)
 {
        struct inode *inode = fio->page->mapping->host;
+       struct page *mpage;
        gfp_t gfp_flags = GFP_NOFS;
 
        if (!f2fs_encrypted_file(inode))
@@ -1597,17 +1630,25 @@ static int encrypt_one_page(struct f2fs_io_info *fio)
 retry_encrypt:
        fio->encrypted_page = fscrypt_encrypt_page(inode, fio->page,
                        PAGE_SIZE, 0, fio->page->index, gfp_flags);
-       if (!IS_ERR(fio->encrypted_page))
-               return 0;
+       if (IS_ERR(fio->encrypted_page)) {
+               /* flush pending IOs and wait for a while in the ENOMEM case */
+               if (PTR_ERR(fio->encrypted_page) == -ENOMEM) {
+                       f2fs_flush_merged_writes(fio->sbi);
+                       congestion_wait(BLK_RW_ASYNC, HZ/50);
+                       gfp_flags |= __GFP_NOFAIL;
+                       goto retry_encrypt;
+               }
+               return PTR_ERR(fio->encrypted_page);
+       }
 
-       /* flush pending IOs and wait for a while in the ENOMEM case */
-       if (PTR_ERR(fio->encrypted_page) == -ENOMEM) {
-               f2fs_flush_merged_writes(fio->sbi);
-               congestion_wait(BLK_RW_ASYNC, HZ/50);
-               gfp_flags |= __GFP_NOFAIL;
-               goto retry_encrypt;
+       mpage = find_lock_page(META_MAPPING(fio->sbi), fio->old_blkaddr);
+       if (mpage) {
+               if (PageUptodate(mpage))
+                       memcpy(page_address(mpage),
+                               page_address(fio->encrypted_page), PAGE_SIZE);
+               f2fs_put_page(mpage, 1);
        }
-       return PTR_ERR(fio->encrypted_page);
+       return 0;
 }
 
 static inline bool check_inplace_update_policy(struct inode *inode,
@@ -1691,6 +1732,7 @@ int f2fs_do_write_data_page(struct f2fs_io_info *fio)
        struct inode *inode = page->mapping->host;
        struct dnode_of_data dn;
        struct extent_info ei = {0,0,0};
+       struct node_info ni;
        bool ipu_force = false;
        int err = 0;
 
@@ -1699,11 +1741,13 @@ int f2fs_do_write_data_page(struct f2fs_io_info *fio)
                        f2fs_lookup_extent_cache(inode, page->index, &ei)) {
                fio->old_blkaddr = ei.blk + page->index - ei.fofs;
 
-               if (is_valid_blkaddr(fio->old_blkaddr)) {
-                       ipu_force = true;
-                       fio->need_lock = LOCK_DONE;
-                       goto got_it;
-               }
+               if (!f2fs_is_valid_blkaddr(fio->sbi, fio->old_blkaddr,
+                                                       DATA_GENERIC))
+                       return -EFAULT;
+
+               ipu_force = true;
+               fio->need_lock = LOCK_DONE;
+               goto got_it;
        }
 
        /* Deadlock due to between page->lock and f2fs_lock_op */
@@ -1722,11 +1766,17 @@ int f2fs_do_write_data_page(struct f2fs_io_info *fio)
                goto out_writepage;
        }
 got_it:
+       if (__is_valid_data_blkaddr(fio->old_blkaddr) &&
+               !f2fs_is_valid_blkaddr(fio->sbi, fio->old_blkaddr,
+                                                       DATA_GENERIC)) {
+               err = -EFAULT;
+               goto out_writepage;
+       }
        /*
         * If current allocation needs SSR,
         * it had better in-place writes for updated data.
         */
-       if (ipu_force || (is_valid_blkaddr(fio->old_blkaddr) &&
+       if (ipu_force || (is_valid_data_blkaddr(fio->sbi, fio->old_blkaddr) &&
                                        need_inplace_update(fio))) {
                err = encrypt_one_page(fio);
                if (err)
@@ -1751,6 +1801,12 @@ got_it:
                fio->need_lock = LOCK_REQ;
        }
 
+       err = f2fs_get_node_info(fio->sbi, dn.nid, &ni);
+       if (err)
+               goto out_writepage;
+
+       fio->version = ni.version;
+
        err = encrypt_one_page(fio);
        if (err)
                goto out_writepage;
@@ -2079,6 +2135,18 @@ continue_unlock:
        return ret;
 }
 
+static inline bool __should_serialize_io(struct inode *inode,
+                                       struct writeback_control *wbc)
+{
+       if (!S_ISREG(inode->i_mode))
+               return false;
+       if (wbc->sync_mode != WB_SYNC_ALL)
+               return true;
+       if (get_dirty_pages(inode) >= SM_I(F2FS_I_SB(inode))->min_seq_blocks)
+               return true;
+       return false;
+}
+
 static int __f2fs_write_data_pages(struct address_space *mapping,
                                                struct writeback_control *wbc,
                                                enum iostat_type io_type)
@@ -2087,6 +2155,7 @@ static int __f2fs_write_data_pages(struct address_space *mapping,
        struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
        struct blk_plug plug;
        int ret;
+       bool locked = false;
 
        /* deal with chardevs and other special file */
        if (!mapping->a_ops->writepage)
@@ -2117,10 +2186,18 @@ static int __f2fs_write_data_pages(struct address_space *mapping,
        else if (atomic_read(&sbi->wb_sync_req[DATA]))
                goto skip_write;
 
+       if (__should_serialize_io(inode, wbc)) {
+               mutex_lock(&sbi->writepages);
+               locked = true;
+       }
+
        blk_start_plug(&plug);
        ret = f2fs_write_cache_pages(mapping, wbc, io_type);
        blk_finish_plug(&plug);
 
+       if (locked)
+               mutex_unlock(&sbi->writepages);
+
        if (wbc->sync_mode == WB_SYNC_ALL)
                atomic_dec(&sbi->wb_sync_req[DATA]);
        /*
@@ -2153,10 +2230,14 @@ static void f2fs_write_failed(struct address_space *mapping, loff_t to)
        loff_t i_size = i_size_read(inode);
 
        if (to > i_size) {
+               down_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
                down_write(&F2FS_I(inode)->i_mmap_sem);
+
                truncate_pagecache(inode, i_size);
                f2fs_truncate_blocks(inode, i_size, true);
+
                up_write(&F2FS_I(inode)->i_mmap_sem);
+               up_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
        }
 }
 
@@ -2251,8 +2332,9 @@ static int f2fs_write_begin(struct file *file, struct address_space *mapping,
 
        trace_f2fs_write_begin(inode, pos, len, flags);
 
-       if (f2fs_is_atomic_file(inode) &&
-                       !f2fs_available_free_memory(sbi, INMEM_PAGES)) {
+       if ((f2fs_is_atomic_file(inode) &&
+                       !f2fs_available_free_memory(sbi, INMEM_PAGES)) ||
+                       is_inode_flag_set(inode, FI_ATOMIC_REVOKE_REQUEST)) {
                err = -ENOMEM;
                drop_atomic = true;
                goto fail;
@@ -2376,14 +2458,20 @@ unlock_out:
 static int check_direct_IO(struct inode *inode, struct iov_iter *iter,
                           loff_t offset)
 {
-       unsigned blocksize_mask = inode->i_sb->s_blocksize - 1;
-
-       if (offset & blocksize_mask)
-               return -EINVAL;
-
-       if (iov_iter_alignment(iter) & blocksize_mask)
-               return -EINVAL;
-
+       unsigned i_blkbits = READ_ONCE(inode->i_blkbits);
+       unsigned blkbits = i_blkbits;
+       unsigned blocksize_mask = (1 << blkbits) - 1;
+       unsigned long align = offset | iov_iter_alignment(iter);
+       struct block_device *bdev = inode->i_sb->s_bdev;
+
+       if (align & blocksize_mask) {
+               if (bdev)
+                       blkbits = blksize_bits(bdev_logical_block_size(bdev));
+               blocksize_mask = (1 << blkbits) - 1;
+               if (align & blocksize_mask)
+                       return -EINVAL;
+               return 1;
+       }
        return 0;
 }
 
@@ -2401,7 +2489,7 @@ static ssize_t f2fs_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
 
        err = check_direct_IO(inode, iter, offset);
        if (err)
-               return err;
+               return err < 0 ? err : 0;
 
        if (f2fs_force_buffered_io(inode, rw))
                return 0;
@@ -2495,6 +2583,10 @@ static int f2fs_set_data_page_dirty(struct page *page)
        if (!PageUptodate(page))
                SetPageUptodate(page);
 
+       /* don't remain PG_checked flag which was set during GC */
+       if (is_cold_data(page))
+               clear_cold_data(page);
+
        if (f2fs_is_atomic_file(inode) && !f2fs_is_commit_atomic_write(inode)) {
                if (!IS_ATOMIC_WRITTEN_PAGE(page)) {
                        f2fs_register_inmem_page(inode, page);
index 2d65e77..214a968 100644 (file)
@@ -215,7 +215,8 @@ static void update_mem_info(struct f2fs_sb_info *sbi)
        si->base_mem += sizeof(struct f2fs_nm_info);
        si->base_mem += __bitmap_size(sbi, NAT_BITMAP);
        si->base_mem += (NM_I(sbi)->nat_bits_blocks << F2FS_BLKSIZE_BITS);
-       si->base_mem += NM_I(sbi)->nat_blocks * NAT_ENTRY_BITMAP_SIZE;
+       si->base_mem += NM_I(sbi)->nat_blocks *
+                               f2fs_bitmap_size(NAT_ENTRY_PER_BLOCK);
        si->base_mem += NM_I(sbi)->nat_blocks / 8;
        si->base_mem += NM_I(sbi)->nat_blocks * sizeof(unsigned short);
 
index 7f955c4..ecc3a4e 100644 (file)
@@ -517,12 +517,11 @@ int f2fs_add_regular_entry(struct inode *dir, const struct qstr *new_name,
        }
 
 start:
-#ifdef CONFIG_F2FS_FAULT_INJECTION
        if (time_to_inject(F2FS_I_SB(dir), FAULT_DIR_DEPTH)) {
                f2fs_show_injection_info(FAULT_DIR_DEPTH);
                return -ENOSPC;
        }
-#endif
+
        if (unlikely(current_depth == MAX_DIR_HASH_DEPTH))
                return -ENOSPC;
 
index 6799c3f..abf9256 100644 (file)
@@ -41,7 +41,6 @@
        } while (0)
 #endif
 
-#ifdef CONFIG_F2FS_FAULT_INJECTION
 enum {
        FAULT_KMALLOC,
        FAULT_KVMALLOC,
@@ -56,16 +55,20 @@ enum {
        FAULT_TRUNCATE,
        FAULT_IO,
        FAULT_CHECKPOINT,
+       FAULT_DISCARD,
        FAULT_MAX,
 };
 
+#ifdef CONFIG_F2FS_FAULT_INJECTION
+#define F2FS_ALL_FAULT_TYPE            ((1 << FAULT_MAX) - 1)
+
 struct f2fs_fault_info {
        atomic_t inject_ops;
        unsigned int inject_rate;
        unsigned int inject_type;
 };
 
-extern char *fault_name[FAULT_MAX];
+extern char *f2fs_fault_name[FAULT_MAX];
 #define IS_FAULT_SET(fi, type) ((fi)->inject_type & (1 << (type)))
 #endif
 
@@ -178,7 +181,6 @@ enum {
 
 #define MAX_DISCARD_BLOCKS(sbi)                BLKS_PER_SEC(sbi)
 #define DEF_MAX_DISCARD_REQUEST                8       /* issue 8 discards per round */
-#define DEF_MAX_DISCARD_LEN            512     /* Max. 2MB per discard */
 #define DEF_MIN_DISCARD_ISSUE_TIME     50      /* 50 ms, if exists */
 #define DEF_MID_DISCARD_ISSUE_TIME     500     /* 500 ms, if device busy */
 #define DEF_MAX_DISCARD_ISSUE_TIME     60000   /* 60 s, if no candidates */
@@ -194,7 +196,7 @@ struct cp_control {
 };
 
 /*
- * For CP/NAT/SIT/SSA readahead
+ * indicate meta/data type
  */
 enum {
        META_CP,
@@ -202,6 +204,8 @@ enum {
        META_SIT,
        META_SSA,
        META_POR,
+       DATA_GENERIC,
+       META_GENERIC,
 };
 
 /* for the list of ino */
@@ -226,6 +230,12 @@ struct inode_entry {
        struct inode *inode;    /* vfs inode pointer */
 };
 
+struct fsync_node_entry {
+       struct list_head list;  /* list head */
+       struct page *page;      /* warm node page pointer */
+       unsigned int seq_id;    /* sequence id */
+};
+
 /* for the bitmap indicate blocks to be discarded */
 struct discard_entry {
        struct list_head list;  /* list head */
@@ -242,9 +252,10 @@ struct discard_entry {
                                        (MAX_PLIST_NUM - 1) : (blk_num - 1))
 
 enum {
-       D_PREP,
-       D_SUBMIT,
-       D_DONE,
+       D_PREP,                 /* initial */
+       D_PARTIAL,              /* partially submitted */
+       D_SUBMIT,               /* all submitted */
+       D_DONE,                 /* finished */
 };
 
 struct discard_info {
@@ -269,7 +280,10 @@ struct discard_cmd {
        struct block_device *bdev;      /* bdev */
        unsigned short ref;             /* reference count */
        unsigned char state;            /* state */
+       unsigned char issuing;          /* issuing discard */
        int error;                      /* bio error */
+       spinlock_t lock;                /* for state/bio_ref updating */
+       unsigned short bio_ref;         /* bio reference count */
 };
 
 enum {
@@ -289,6 +303,7 @@ struct discard_policy {
        unsigned int io_aware_gran;     /* minimum granularity discard not be aware of I/O */
        bool io_aware;                  /* issue discard in idle time */
        bool sync;                      /* submit discard with REQ_SYNC flag */
+       bool ordered;                   /* issue discard by lba order */
        unsigned int granularity;       /* discard granularity */
 };
 
@@ -305,10 +320,12 @@ struct discard_cmd_control {
        unsigned int max_discards;              /* max. discards to be issued */
        unsigned int discard_granularity;       /* discard granularity */
        unsigned int undiscard_blks;            /* # of undiscard blocks */
+       unsigned int next_pos;                  /* next discard position */
        atomic_t issued_discard;                /* # of issued discard */
        atomic_t issing_discard;                /* # of issing discard */
        atomic_t discard_cmd_cnt;               /* # of cached cmd count */
        struct rb_root root;                    /* root of discard rb-tree */
+       bool rbtree_check;                      /* config for consistence check */
 };
 
 /* for the list of fsync inodes, used only during recovery */
@@ -508,13 +525,12 @@ enum {
                                         */
 };
 
+#define DEFAULT_RETRY_IO_COUNT 8       /* maximum retry read IO count */
+
 #define F2FS_LINK_MAX  0xffffffff      /* maximum link count per file */
 
 #define MAX_DIR_RA_PAGES       4       /* maximum ra pages of dir */
 
-/* vector size for gang look-up from extent cache that consists of radix tree */
-#define EXT_TREE_VEC_SIZE      64
-
 /* for in-memory extent cache entry */
 #define F2FS_MIN_EXTENT_LEN    64      /* minimum extent length */
 
@@ -600,6 +616,8 @@ enum {
 #define FADVISE_HOT_BIT                0x20
 #define FADVISE_VERITY_BIT     0x40    /* reserved */
 
+#define FADVISE_MODIFIABLE_BITS        (FADVISE_COLD_BIT | FADVISE_HOT_BIT)
+
 #define file_is_cold(inode)    is_file(inode, FADVISE_COLD_BIT)
 #define file_wrong_pino(inode) is_file(inode, FADVISE_LOST_PINO_BIT)
 #define file_set_cold(inode)   set_file(inode, FADVISE_COLD_BIT)
@@ -669,8 +687,8 @@ struct f2fs_inode_info {
        int i_extra_isize;              /* size of extra space located in i_addr */
        kprojid_t i_projid;             /* id for project quota */
        int i_inline_xattr_size;        /* inline xattr size */
-       struct timespec i_crtime;       /* inode creation time */
-       struct timespec i_disk_time[4]; /* inode disk times */
+       struct timespec64 i_crtime;     /* inode creation time */
+       struct timespec64 i_disk_time[4];/* inode disk times */
 };
 
 static inline void get_extent_info(struct extent_info *ext,
@@ -698,22 +716,22 @@ static inline void set_extent_info(struct extent_info *ei, unsigned int fofs,
 }
 
 static inline bool __is_discard_mergeable(struct discard_info *back,
-                                               struct discard_info *front)
+                       struct discard_info *front, unsigned int max_len)
 {
        return (back->lstart + back->len == front->lstart) &&
-               (back->len + front->len < DEF_MAX_DISCARD_LEN);
+               (back->len + front->len <= max_len);
 }
 
 static inline bool __is_discard_back_mergeable(struct discard_info *cur,
-                                               struct discard_info *back)
+                       struct discard_info *back, unsigned int max_len)
 {
-       return __is_discard_mergeable(back, cur);
+       return __is_discard_mergeable(back, cur, max_len);
 }
 
 static inline bool __is_discard_front_mergeable(struct discard_info *cur,
-                                               struct discard_info *front)
+                       struct discard_info *front, unsigned int max_len)
 {
-       return __is_discard_mergeable(cur, front);
+       return __is_discard_mergeable(cur, front, max_len);
 }
 
 static inline bool __is_extent_mergeable(struct extent_info *back,
@@ -768,6 +786,7 @@ struct f2fs_nm_info {
        struct radix_tree_root nat_set_root;/* root of the nat set cache */
        struct rw_semaphore nat_tree_lock;      /* protect nat_tree_lock */
        struct list_head nat_entries;   /* cached nat entry list (clean) */
+       spinlock_t nat_list_lock;       /* protect clean nat entry list */
        unsigned int nat_cnt;           /* the # of cached nat entries */
        unsigned int dirty_nat_cnt;     /* total num of nat entries in set */
        unsigned int nat_blocks;        /* # of nat blocks */
@@ -894,6 +913,7 @@ struct f2fs_sm_info {
        unsigned int ipu_policy;        /* in-place-update policy */
        unsigned int min_ipu_util;      /* in-place-update threshold */
        unsigned int min_fsync_blocks;  /* threshold for fsync */
+       unsigned int min_seq_blocks;    /* threshold for sequential blocks */
        unsigned int min_hot_blocks;    /* threshold for hot block allocation */
        unsigned int min_ssr_sections;  /* threshold to trigger SSR allocation */
 
@@ -1015,6 +1035,7 @@ struct f2fs_io_info {
        bool retry;             /* need to reallocate block address */
        enum iostat_type io_type;       /* io type */
        struct writeback_control *io_wbc; /* writeback control */
+       unsigned char version;          /* version of the node */
 };
 
 #define is_read_io(rw) ((rw) == READ)
@@ -1066,6 +1087,7 @@ enum {
        SBI_POR_DOING,                          /* recovery is doing or not */
        SBI_NEED_SB_WRITE,                      /* need to recover superblock */
        SBI_NEED_CP,                            /* need to checkpoint */
+       SBI_IS_SHUTDOWN,                        /* shutdown by ioctl */
 };
 
 enum {
@@ -1112,6 +1134,7 @@ struct f2fs_sb_info {
        struct rw_semaphore sb_lock;            /* lock for raw super block */
        int valid_super_block;                  /* valid super block no */
        unsigned long s_flag;                           /* flags for sbi */
+       struct mutex writepages;                /* mutex for writepages() */
 
 #ifdef CONFIG_BLK_DEV_ZONED
        unsigned int blocks_per_blkz;           /* F2FS blocks per zone */
@@ -1148,6 +1171,11 @@ struct f2fs_sb_info {
 
        struct inode_management im[MAX_INO_ENTRY];      /* manage inode cache */
 
+       spinlock_t fsync_node_lock;             /* for node entry lock */
+       struct list_head fsync_node_list;       /* node list head */
+       unsigned int fsync_seg_id;              /* sequence id */
+       unsigned int fsync_node_num;            /* number of node entries */
+
        /* for orphan inode, use 0'th array */
        unsigned int max_orphans;               /* max orphan inodes */
 
@@ -1215,6 +1243,7 @@ struct f2fs_sb_info {
        unsigned int gc_mode;                   /* current GC state */
        /* for skip statistic */
        unsigned long long skipped_atomic_files[2];     /* FG_GC and BG_GC */
+       unsigned long long skipped_gc_rwsem;            /* FG_GC only */
 
        /* threshold for gc trials on pinned files */
        u64 gc_pin_file_threshold;
@@ -1279,7 +1308,7 @@ struct f2fs_sb_info {
 #ifdef CONFIG_F2FS_FAULT_INJECTION
 #define f2fs_show_injection_info(type)                         \
        printk("%sF2FS-fs : inject %s in %s of %pF\n",          \
-               KERN_INFO, fault_name[type],                    \
+               KERN_INFO, f2fs_fault_name[type],               \
                __func__, __builtin_return_address(0))
 static inline bool time_to_inject(struct f2fs_sb_info *sbi, int type)
 {
@@ -1298,6 +1327,12 @@ static inline bool time_to_inject(struct f2fs_sb_info *sbi, int type)
        }
        return false;
 }
+#else
+#define f2fs_show_injection_info(type) do { } while (0)
+static inline bool time_to_inject(struct f2fs_sb_info *sbi, int type)
+{
+       return false;
+}
 #endif
 
 /* For write statistics. Suppose sector size is 512 bytes,
@@ -1326,7 +1361,7 @@ static inline bool is_idle(struct f2fs_sb_info *sbi)
        struct request_list *rl = &q->root_rl;
 
        if (rl->count[BLK_RW_SYNC] || rl->count[BLK_RW_ASYNC])
-               return 0;
+               return false;
 
        return f2fs_time_over(sbi, REQ_TIME);
 }
@@ -1650,13 +1685,12 @@ static inline int inc_valid_block_count(struct f2fs_sb_info *sbi,
        if (ret)
                return ret;
 
-#ifdef CONFIG_F2FS_FAULT_INJECTION
        if (time_to_inject(sbi, FAULT_BLOCK)) {
                f2fs_show_injection_info(FAULT_BLOCK);
                release = *count;
                goto enospc;
        }
-#endif
+
        /*
         * let's increase this in prior to actual block count change in order
         * for f2fs_sync_file to avoid data races when deciding checkpoint.
@@ -1680,18 +1714,20 @@ static inline int inc_valid_block_count(struct f2fs_sb_info *sbi,
                sbi->total_valid_block_count -= diff;
                if (!*count) {
                        spin_unlock(&sbi->stat_lock);
-                       percpu_counter_sub(&sbi->alloc_valid_block_count, diff);
                        goto enospc;
                }
        }
        spin_unlock(&sbi->stat_lock);
 
-       if (unlikely(release))
+       if (unlikely(release)) {
+               percpu_counter_sub(&sbi->alloc_valid_block_count, release);
                dquot_release_reservation_block(inode, release);
+       }
        f2fs_i_blocks_write(inode, *count, true, true);
        return 0;
 
 enospc:
+       percpu_counter_sub(&sbi->alloc_valid_block_count, release);
        dquot_release_reservation_block(inode, release);
        return -ENOSPC;
 }
@@ -1863,12 +1899,10 @@ static inline int inc_valid_node_count(struct f2fs_sb_info *sbi,
                        return ret;
        }
 
-#ifdef CONFIG_F2FS_FAULT_INJECTION
        if (time_to_inject(sbi, FAULT_BLOCK)) {
                f2fs_show_injection_info(FAULT_BLOCK);
                goto enospc;
        }
-#endif
 
        spin_lock(&sbi->stat_lock);
 
@@ -1953,17 +1987,23 @@ static inline s64 valid_inode_count(struct f2fs_sb_info *sbi)
 static inline struct page *f2fs_grab_cache_page(struct address_space *mapping,
                                                pgoff_t index, bool for_write)
 {
-#ifdef CONFIG_F2FS_FAULT_INJECTION
-       struct page *page = find_lock_page(mapping, index);
+       struct page *page;
 
-       if (page)
-               return page;
+       if (IS_ENABLED(CONFIG_F2FS_FAULT_INJECTION)) {
+               if (!for_write)
+                       page = find_get_page_flags(mapping, index,
+                                                       FGP_LOCK | FGP_ACCESSED);
+               else
+                       page = find_lock_page(mapping, index);
+               if (page)
+                       return page;
 
-       if (time_to_inject(F2FS_M_SB(mapping), FAULT_PAGE_ALLOC)) {
-               f2fs_show_injection_info(FAULT_PAGE_ALLOC);
-               return NULL;
+               if (time_to_inject(F2FS_M_SB(mapping), FAULT_PAGE_ALLOC)) {
+                       f2fs_show_injection_info(FAULT_PAGE_ALLOC);
+                       return NULL;
+               }
        }
-#endif
+
        if (!for_write)
                return grab_cache_page(mapping, index);
        return grab_cache_page_write_begin(mapping, index, AOP_FLAG_NOFS);
@@ -1973,12 +2013,11 @@ static inline struct page *f2fs_pagecache_get_page(
                                struct address_space *mapping, pgoff_t index,
                                int fgp_flags, gfp_t gfp_mask)
 {
-#ifdef CONFIG_F2FS_FAULT_INJECTION
        if (time_to_inject(F2FS_M_SB(mapping), FAULT_PAGE_GET)) {
                f2fs_show_injection_info(FAULT_PAGE_GET);
                return NULL;
        }
-#endif
+
        return pagecache_get_page(mapping, index, fgp_flags, gfp_mask);
 }
 
@@ -2043,12 +2082,11 @@ static inline struct bio *f2fs_bio_alloc(struct f2fs_sb_info *sbi,
                        bio = bio_alloc(GFP_NOIO | __GFP_NOFAIL, npages);
                return bio;
        }
-#ifdef CONFIG_F2FS_FAULT_INJECTION
        if (time_to_inject(sbi, FAULT_ALLOC_BIO)) {
                f2fs_show_injection_info(FAULT_ALLOC_BIO);
                return NULL;
        }
-#endif
+
        return bio_alloc(GFP_KERNEL, npages);
 }
 
@@ -2518,7 +2556,6 @@ static inline void clear_file(struct inode *inode, int type)
 
 static inline bool f2fs_skip_inode_update(struct inode *inode, int dsync)
 {
-       struct timespec ts;
        bool ret;
 
        if (dsync) {
@@ -2534,16 +2571,13 @@ static inline bool f2fs_skip_inode_update(struct inode *inode, int dsync)
                        i_size_read(inode) & ~PAGE_MASK)
                return false;
 
-       ts = timespec64_to_timespec(inode->i_atime);
-       if (!timespec_equal(F2FS_I(inode)->i_disk_time, &ts))
+       if (!timespec64_equal(F2FS_I(inode)->i_disk_time, &inode->i_atime))
                return false;
-       ts = timespec64_to_timespec(inode->i_ctime);
-       if (!timespec_equal(F2FS_I(inode)->i_disk_time + 1, &ts))
+       if (!timespec64_equal(F2FS_I(inode)->i_disk_time + 1, &inode->i_ctime))
                return false;
-       ts = timespec64_to_timespec(inode->i_mtime);
-       if (!timespec_equal(F2FS_I(inode)->i_disk_time + 2, &ts))
+       if (!timespec64_equal(F2FS_I(inode)->i_disk_time + 2, &inode->i_mtime))
                return false;
-       if (!timespec_equal(F2FS_I(inode)->i_disk_time + 3,
+       if (!timespec64_equal(F2FS_I(inode)->i_disk_time + 3,
                                                &F2FS_I(inode)->i_crtime))
                return false;
 
@@ -2587,12 +2621,11 @@ static inline bool f2fs_may_extent_tree(struct inode *inode)
 static inline void *f2fs_kmalloc(struct f2fs_sb_info *sbi,
                                        size_t size, gfp_t flags)
 {
-#ifdef CONFIG_F2FS_FAULT_INJECTION
        if (time_to_inject(sbi, FAULT_KMALLOC)) {
                f2fs_show_injection_info(FAULT_KMALLOC);
                return NULL;
        }
-#endif
+
        return kmalloc(size, flags);
 }
 
@@ -2605,12 +2638,11 @@ static inline void *f2fs_kzalloc(struct f2fs_sb_info *sbi,
 static inline void *f2fs_kvmalloc(struct f2fs_sb_info *sbi,
                                        size_t size, gfp_t flags)
 {
-#ifdef CONFIG_F2FS_FAULT_INJECTION
        if (time_to_inject(sbi, FAULT_KVMALLOC)) {
                f2fs_show_injection_info(FAULT_KVMALLOC);
                return NULL;
        }
-#endif
+
        return kvmalloc(size, flags);
 }
 
@@ -2669,13 +2701,39 @@ static inline void f2fs_update_iostat(struct f2fs_sb_info *sbi,
        spin_unlock(&sbi->iostat_lock);
 }
 
-static inline bool is_valid_blkaddr(block_t blkaddr)
+#define __is_meta_io(fio) (PAGE_TYPE_OF_BIO(fio->type) == META &&      \
+                               (!is_read_io(fio->op) || fio->is_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)
+{
+       if (!f2fs_is_valid_blkaddr(sbi, blkaddr, type)) {
+               f2fs_msg(sbi->sb, KERN_ERR,
+                       "invalid blkaddr: %u, type: %d, run fsck to fix.",
+                       blkaddr, type);
+               f2fs_bug_on(sbi, 1);
+       }
+}
+
+static inline bool __is_valid_data_blkaddr(block_t blkaddr)
 {
        if (blkaddr == NEW_ADDR || blkaddr == NULL_ADDR)
                return false;
        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;
+}
+
 /*
  * file.c
  */
@@ -2790,16 +2848,21 @@ struct node_info;
 
 int f2fs_check_nid_range(struct f2fs_sb_info *sbi, nid_t nid);
 bool f2fs_available_free_memory(struct f2fs_sb_info *sbi, int type);
+bool f2fs_in_warm_node_list(struct f2fs_sb_info *sbi, struct page *page);
+void f2fs_init_fsync_node_info(struct f2fs_sb_info *sbi);
+void f2fs_del_fsync_node_entry(struct f2fs_sb_info *sbi, struct page *page);
+void f2fs_reset_fsync_node_info(struct f2fs_sb_info *sbi);
 int f2fs_need_dentry_mark(struct f2fs_sb_info *sbi, nid_t nid);
 bool f2fs_is_checkpointed_node(struct f2fs_sb_info *sbi, nid_t nid);
 bool f2fs_need_inode_block_update(struct f2fs_sb_info *sbi, nid_t ino);
-void f2fs_get_node_info(struct f2fs_sb_info *sbi, nid_t nid,
+int f2fs_get_node_info(struct f2fs_sb_info *sbi, nid_t nid,
                                                struct node_info *ni);
 pgoff_t f2fs_get_next_page_offset(struct dnode_of_data *dn, pgoff_t pgofs);
 int f2fs_get_dnode_of_data(struct dnode_of_data *dn, pgoff_t index, int mode);
 int f2fs_truncate_inode_blocks(struct inode *inode, pgoff_t from);
 int f2fs_truncate_xattr_node(struct inode *inode);
-int f2fs_wait_on_node_pages_writeback(struct f2fs_sb_info *sbi, nid_t ino);
+int f2fs_wait_on_node_pages_writeback(struct f2fs_sb_info *sbi,
+                                       unsigned int seq_id);
 int f2fs_remove_inode_page(struct inode *inode);
 struct page *f2fs_new_inode_page(struct inode *inode);
 struct page *f2fs_new_node_page(struct dnode_of_data *dn, unsigned int ofs);
@@ -2808,11 +2871,12 @@ struct page *f2fs_get_node_page(struct f2fs_sb_info *sbi, pgoff_t nid);
 struct page *f2fs_get_node_page_ra(struct page *parent, int start);
 void f2fs_move_node_page(struct page *node_page, int gc_type);
 int f2fs_fsync_node_pages(struct f2fs_sb_info *sbi, struct inode *inode,
-                       struct writeback_control *wbc, bool atomic);
+                       struct writeback_control *wbc, bool atomic,
+                       unsigned int *seq_id);
 int f2fs_sync_node_pages(struct f2fs_sb_info *sbi,
                        struct writeback_control *wbc,
                        bool do_balance, enum iostat_type io_type);
-void f2fs_build_free_nids(struct f2fs_sb_info *sbi, bool sync, bool mount);
+int f2fs_build_free_nids(struct f2fs_sb_info *sbi, bool sync, bool mount);
 bool f2fs_alloc_nid(struct f2fs_sb_info *sbi, nid_t *nid);
 void f2fs_alloc_nid_done(struct f2fs_sb_info *sbi, nid_t nid);
 void f2fs_alloc_nid_failed(struct f2fs_sb_info *sbi, nid_t nid);
@@ -2820,7 +2884,7 @@ int f2fs_try_to_free_nids(struct f2fs_sb_info *sbi, int nr_shrink);
 void f2fs_recover_inline_xattr(struct inode *inode, struct page *page);
 int f2fs_recover_xattr_data(struct inode *inode, struct page *page);
 int f2fs_recover_inode_page(struct f2fs_sb_info *sbi, struct page *page);
-void f2fs_restore_node_summary(struct f2fs_sb_info *sbi,
+int f2fs_restore_node_summary(struct f2fs_sb_info *sbi,
                        unsigned int segno, struct f2fs_summary_block *sum);
 void f2fs_flush_nat_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc);
 int f2fs_build_node_manager(struct f2fs_sb_info *sbi);
@@ -2898,9 +2962,10 @@ enum rw_hint f2fs_io_type_to_rw_hint(struct f2fs_sb_info *sbi,
 void f2fs_stop_checkpoint(struct f2fs_sb_info *sbi, bool end_io);
 struct page *f2fs_grab_meta_page(struct f2fs_sb_info *sbi, pgoff_t index);
 struct page *f2fs_get_meta_page(struct f2fs_sb_info *sbi, pgoff_t index);
+struct page *f2fs_get_meta_page_nofail(struct f2fs_sb_info *sbi, pgoff_t index);
 struct page *f2fs_get_tmp_page(struct f2fs_sb_info *sbi, pgoff_t index);
-bool f2fs_is_valid_meta_blkaddr(struct f2fs_sb_info *sbi,
-                       block_t blkaddr, int type);
+bool f2fs_is_valid_blkaddr(struct f2fs_sb_info *sbi,
+                                       block_t blkaddr, int type);
 int f2fs_ra_meta_pages(struct f2fs_sb_info *sbi, block_t start, int nrpages,
                        int type, bool sync);
 void f2fs_ra_meta_pages_cond(struct f2fs_sb_info *sbi, pgoff_t index);
@@ -2924,6 +2989,7 @@ int f2fs_get_valid_checkpoint(struct f2fs_sb_info *sbi);
 void f2fs_update_dirty_page(struct inode *inode, struct page *page);
 void f2fs_remove_dirty_inode(struct inode *inode);
 int f2fs_sync_dirty_inodes(struct f2fs_sb_info *sbi, enum inode_type type);
+void f2fs_wait_on_all_pages_writeback(struct f2fs_sb_info *sbi);
 int f2fs_write_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc);
 void f2fs_init_ino_entry_info(struct f2fs_sb_info *sbi);
 int __init f2fs_create_checkpoint_caches(void);
@@ -3362,7 +3428,7 @@ static inline bool f2fs_may_encrypt(struct inode *inode)
 
        return (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode));
 #else
-       return 0;
+       return false;
 #endif
 }
 
@@ -3373,4 +3439,11 @@ static inline bool f2fs_force_buffered_io(struct inode *inode, int rw)
                        F2FS_I_SB(inode)->s_ndevs);
 }
 
+#ifdef CONFIG_F2FS_FAULT_INJECTION
+extern void f2fs_build_fault_attr(struct f2fs_sb_info *sbi, unsigned int rate,
+                                                       unsigned int type);
+#else
+#define f2fs_build_fault_attr(sbi, rate, type)         do { } while (0)
+#endif
+
 #endif
index 6880c6f..5474aaa 100644 (file)
@@ -213,6 +213,7 @@ static int f2fs_do_sync_file(struct file *file, loff_t start, loff_t end,
                .nr_to_write = LONG_MAX,
                .for_reclaim = 0,
        };
+       unsigned int seq_id = 0;
 
        if (unlikely(f2fs_readonly(inode->i_sb)))
                return 0;
@@ -275,7 +276,7 @@ go_write:
        }
 sync_nodes:
        atomic_inc(&sbi->wb_sync_req[NODE]);
-       ret = f2fs_fsync_node_pages(sbi, inode, &wbc, atomic);
+       ret = f2fs_fsync_node_pages(sbi, inode, &wbc, atomic, &seq_id);
        atomic_dec(&sbi->wb_sync_req[NODE]);
        if (ret)
                goto out;
@@ -301,7 +302,7 @@ sync_nodes:
         * given fsync mark.
         */
        if (!atomic) {
-               ret = f2fs_wait_on_node_pages_writeback(sbi, ino);
+               ret = f2fs_wait_on_node_pages_writeback(sbi, seq_id);
                if (ret)
                        goto out;
        }
@@ -350,13 +351,13 @@ static pgoff_t __get_first_dirty_index(struct address_space *mapping,
        return pgofs;
 }
 
-static bool __found_offset(block_t blkaddr, pgoff_t dirty, pgoff_t pgofs,
-                                                       int whence)
+static bool __found_offset(struct f2fs_sb_info *sbi, block_t blkaddr,
+                               pgoff_t dirty, pgoff_t pgofs, int whence)
 {
        switch (whence) {
        case SEEK_DATA:
                if ((blkaddr == NEW_ADDR && dirty == pgofs) ||
-                       is_valid_blkaddr(blkaddr))
+                       is_valid_data_blkaddr(sbi, blkaddr))
                        return true;
                break;
        case SEEK_HOLE:
@@ -420,7 +421,15 @@ static loff_t f2fs_seek_block(struct file *file, loff_t offset, int whence)
                        blkaddr = datablock_addr(dn.inode,
                                        dn.node_page, dn.ofs_in_node);
 
-                       if (__found_offset(blkaddr, dirty, pgofs, whence)) {
+                       if (__is_valid_data_blkaddr(blkaddr) &&
+                               !f2fs_is_valid_blkaddr(F2FS_I_SB(inode),
+                                               blkaddr, DATA_GENERIC)) {
+                               f2fs_put_dnode(&dn);
+                               goto fail;
+                       }
+
+                       if (__found_offset(F2FS_I_SB(inode), blkaddr, dirty,
+                                                       pgofs, whence)) {
                                f2fs_put_dnode(&dn);
                                goto found;
                        }
@@ -513,6 +522,11 @@ void f2fs_truncate_data_blocks_range(struct dnode_of_data *dn, int count)
 
                dn->data_blkaddr = NULL_ADDR;
                f2fs_set_data_blkaddr(dn);
+
+               if (__is_valid_data_blkaddr(blkaddr) &&
+                       !f2fs_is_valid_blkaddr(sbi, blkaddr, DATA_GENERIC))
+                       continue;
+
                f2fs_invalidate_blocks(sbi, blkaddr);
                if (dn->ofs_in_node == 0 && IS_INODE(dn->node_page))
                        clear_inode_flag(dn->inode, FI_FIRST_BLOCK_WRITTEN);
@@ -654,12 +668,11 @@ int f2fs_truncate(struct inode *inode)
 
        trace_f2fs_truncate(inode);
 
-#ifdef CONFIG_F2FS_FAULT_INJECTION
        if (time_to_inject(F2FS_I_SB(inode), FAULT_TRUNCATE)) {
                f2fs_show_injection_info(FAULT_TRUNCATE);
                return -EIO;
        }
-#endif
+
        /* we should check inline_data size */
        if (!f2fs_may_inline_data(inode)) {
                err = f2fs_convert_inline_inode(inode);
@@ -782,22 +795,26 @@ int f2fs_setattr(struct dentry *dentry, struct iattr *attr)
        }
 
        if (attr->ia_valid & ATTR_SIZE) {
-               if (attr->ia_size <= i_size_read(inode)) {
-                       down_write(&F2FS_I(inode)->i_mmap_sem);
-                       truncate_setsize(inode, attr->ia_size);
+               bool to_smaller = (attr->ia_size <= i_size_read(inode));
+
+               down_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
+               down_write(&F2FS_I(inode)->i_mmap_sem);
+
+               truncate_setsize(inode, attr->ia_size);
+
+               if (to_smaller)
                        err = f2fs_truncate(inode);
-                       up_write(&F2FS_I(inode)->i_mmap_sem);
-                       if (err)
-                               return err;
-               } else {
-                       /*
-                        * do not trim all blocks after i_size if target size is
-                        * larger than i_size.
-                        */
-                       down_write(&F2FS_I(inode)->i_mmap_sem);
-                       truncate_setsize(inode, attr->ia_size);
-                       up_write(&F2FS_I(inode)->i_mmap_sem);
+               /*
+                * do not trim all blocks after i_size if target size is
+                * larger than i_size.
+                */
+               up_write(&F2FS_I(inode)->i_mmap_sem);
+               up_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
+
+               if (err)
+                       return err;
 
+               if (!to_smaller) {
                        /* should convert inline inode here */
                        if (!f2fs_may_inline_data(inode)) {
                                err = f2fs_convert_inline_inode(inode);
@@ -944,14 +961,19 @@ static int punch_hole(struct inode *inode, loff_t offset, loff_t len)
 
                        blk_start = (loff_t)pg_start << PAGE_SHIFT;
                        blk_end = (loff_t)pg_end << PAGE_SHIFT;
+
+                       down_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
                        down_write(&F2FS_I(inode)->i_mmap_sem);
+
                        truncate_inode_pages_range(mapping, blk_start,
                                        blk_end - 1);
 
                        f2fs_lock_op(sbi);
                        ret = f2fs_truncate_hole(inode, pg_start, pg_end);
                        f2fs_unlock_op(sbi);
+
                        up_write(&F2FS_I(inode)->i_mmap_sem);
+                       up_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
                }
        }
 
@@ -1054,7 +1076,12 @@ static int __clone_blkaddrs(struct inode *src_inode, struct inode *dst_inode,
                        if (ret)
                                return ret;
 
-                       f2fs_get_node_info(sbi, dn.nid, &ni);
+                       ret = f2fs_get_node_info(sbi, dn.nid, &ni);
+                       if (ret) {
+                               f2fs_put_dnode(&dn);
+                               return ret;
+                       }
+
                        ilen = min((pgoff_t)
                                ADDRS_PER_PAGE(dn.node_page, dst_inode) -
                                                dn.ofs_in_node, len - i);
@@ -1161,25 +1188,33 @@ roll_back:
        return ret;
 }
 
-static int f2fs_do_collapse(struct inode *inode, pgoff_t start, pgoff_t end)
+static int f2fs_do_collapse(struct inode *inode, loff_t offset, loff_t len)
 {
        struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
        pgoff_t nrpages = (i_size_read(inode) + PAGE_SIZE - 1) / PAGE_SIZE;
+       pgoff_t start = offset >> PAGE_SHIFT;
+       pgoff_t end = (offset + len) >> PAGE_SHIFT;
        int ret;
 
        f2fs_balance_fs(sbi, true);
-       f2fs_lock_op(sbi);
 
-       f2fs_drop_extent_tree(inode);
+       /* avoid gc operation during block exchange */
+       down_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
+       down_write(&F2FS_I(inode)->i_mmap_sem);
 
+       f2fs_lock_op(sbi);
+       f2fs_drop_extent_tree(inode);
+       truncate_pagecache(inode, offset);
        ret = __exchange_data_block(inode, inode, end, start, nrpages - end, true);
        f2fs_unlock_op(sbi);
+
+       up_write(&F2FS_I(inode)->i_mmap_sem);
+       up_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
        return ret;
 }
 
 static int f2fs_collapse_range(struct inode *inode, loff_t offset, loff_t len)
 {
-       pgoff_t pg_start, pg_end;
        loff_t new_size;
        int ret;
 
@@ -1194,25 +1229,17 @@ static int f2fs_collapse_range(struct inode *inode, loff_t offset, loff_t len)
        if (ret)
                return ret;
 
-       pg_start = offset >> PAGE_SHIFT;
-       pg_end = (offset + len) >> PAGE_SHIFT;
-
-       /* avoid gc operation during block exchange */
-       down_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
-
-       down_write(&F2FS_I(inode)->i_mmap_sem);
        /* write out all dirty pages from offset */
        ret = filemap_write_and_wait_range(inode->i_mapping, offset, LLONG_MAX);
        if (ret)
-               goto out_unlock;
-
-       truncate_pagecache(inode, offset);
+               return ret;
 
-       ret = f2fs_do_collapse(inode, pg_start, pg_end);
+       ret = f2fs_do_collapse(inode, offset, len);
        if (ret)
-               goto out_unlock;
+               return ret;
 
        /* write out all moved pages, if possible */
+       down_write(&F2FS_I(inode)->i_mmap_sem);
        filemap_write_and_wait_range(inode->i_mapping, offset, LLONG_MAX);
        truncate_pagecache(inode, offset);
 
@@ -1220,11 +1247,9 @@ static int f2fs_collapse_range(struct inode *inode, loff_t offset, loff_t len)
        truncate_pagecache(inode, new_size);
 
        ret = f2fs_truncate_blocks(inode, new_size, true);
+       up_write(&F2FS_I(inode)->i_mmap_sem);
        if (!ret)
                f2fs_i_size_write(inode, new_size);
-out_unlock:
-       up_write(&F2FS_I(inode)->i_mmap_sem);
-       up_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
        return ret;
 }
 
@@ -1290,12 +1315,9 @@ static int f2fs_zero_range(struct inode *inode, loff_t offset, loff_t len,
        if (ret)
                return ret;
 
-       down_write(&F2FS_I(inode)->i_mmap_sem);
        ret = filemap_write_and_wait_range(mapping, offset, offset + len - 1);
        if (ret)
-               goto out_sem;
-
-       truncate_pagecache_range(inode, offset, offset + len - 1);
+               return ret;
 
        pg_start = ((unsigned long long) offset) >> PAGE_SHIFT;
        pg_end = ((unsigned long long) offset + len) >> PAGE_SHIFT;
@@ -1307,7 +1329,7 @@ static int f2fs_zero_range(struct inode *inode, loff_t offset, loff_t len,
                ret = fill_zero(inode, pg_start, off_start,
                                                off_end - off_start);
                if (ret)
-                       goto out_sem;
+                       return ret;
 
                new_size = max_t(loff_t, new_size, offset + len);
        } else {
@@ -1315,7 +1337,7 @@ static int f2fs_zero_range(struct inode *inode, loff_t offset, loff_t len,
                        ret = fill_zero(inode, pg_start++, off_start,
                                                PAGE_SIZE - off_start);
                        if (ret)
-                               goto out_sem;
+                               return ret;
 
                        new_size = max_t(loff_t, new_size,
                                        (loff_t)pg_start << PAGE_SHIFT);
@@ -1326,12 +1348,21 @@ static int f2fs_zero_range(struct inode *inode, loff_t offset, loff_t len,
                        unsigned int end_offset;
                        pgoff_t end;
 
+                       down_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
+                       down_write(&F2FS_I(inode)->i_mmap_sem);
+
+                       truncate_pagecache_range(inode,
+                               (loff_t)index << PAGE_SHIFT,
+                               ((loff_t)pg_end << PAGE_SHIFT) - 1);
+
                        f2fs_lock_op(sbi);
 
                        set_new_dnode(&dn, inode, NULL, NULL, 0);
                        ret = f2fs_get_dnode_of_data(&dn, index, ALLOC_NODE);
                        if (ret) {
                                f2fs_unlock_op(sbi);
+                               up_write(&F2FS_I(inode)->i_mmap_sem);
+                               up_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
                                goto out;
                        }
 
@@ -1340,7 +1371,10 @@ static int f2fs_zero_range(struct inode *inode, loff_t offset, loff_t len,
 
                        ret = f2fs_do_zero_range(&dn, index, end);
                        f2fs_put_dnode(&dn);
+
                        f2fs_unlock_op(sbi);
+                       up_write(&F2FS_I(inode)->i_mmap_sem);
+                       up_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
 
                        f2fs_balance_fs(sbi, dn.node_changed);
 
@@ -1368,9 +1402,6 @@ out:
                else
                        f2fs_i_size_write(inode, new_size);
        }
-out_sem:
-       up_write(&F2FS_I(inode)->i_mmap_sem);
-
        return ret;
 }
 
@@ -1399,26 +1430,27 @@ static int f2fs_insert_range(struct inode *inode, loff_t offset, loff_t len)
 
        f2fs_balance_fs(sbi, true);
 
-       /* avoid gc operation during block exchange */
-       down_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
-
        down_write(&F2FS_I(inode)->i_mmap_sem);
        ret = f2fs_truncate_blocks(inode, i_size_read(inode), true);
+       up_write(&F2FS_I(inode)->i_mmap_sem);
        if (ret)
-               goto out;
+               return ret;
 
        /* write out all dirty pages from offset */
        ret = filemap_write_and_wait_range(inode->i_mapping, offset, LLONG_MAX);
        if (ret)
-               goto out;
-
-       truncate_pagecache(inode, offset);
+               return ret;
 
        pg_start = offset >> PAGE_SHIFT;
        pg_end = (offset + len) >> PAGE_SHIFT;
        delta = pg_end - pg_start;
        idx = (i_size_read(inode) + PAGE_SIZE - 1) / PAGE_SIZE;
 
+       /* avoid gc operation during block exchange */
+       down_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
+       down_write(&F2FS_I(inode)->i_mmap_sem);
+       truncate_pagecache(inode, offset);
+
        while (!ret && idx > pg_start) {
                nr = idx - pg_start;
                if (nr > delta)
@@ -1432,16 +1464,17 @@ static int f2fs_insert_range(struct inode *inode, loff_t offset, loff_t len)
                                        idx + delta, nr, false);
                f2fs_unlock_op(sbi);
        }
+       up_write(&F2FS_I(inode)->i_mmap_sem);
+       up_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
 
        /* write out all moved pages, if possible */
+       down_write(&F2FS_I(inode)->i_mmap_sem);
        filemap_write_and_wait_range(inode->i_mapping, offset, LLONG_MAX);
        truncate_pagecache(inode, offset);
+       up_write(&F2FS_I(inode)->i_mmap_sem);
 
        if (!ret)
                f2fs_i_size_write(inode, new_size);
-out:
-       up_write(&F2FS_I(inode)->i_mmap_sem);
-       up_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
        return ret;
 }
 
@@ -1597,7 +1630,7 @@ static int f2fs_ioc_getflags(struct file *filp, unsigned long arg)
        struct f2fs_inode_info *fi = F2FS_I(inode);
        unsigned int flags = fi->i_flags;
 
-       if (file_is_encrypt(inode))
+       if (f2fs_encrypted_inode(inode))
                flags |= F2FS_ENCRYPT_FL;
        if (f2fs_has_inline_data(inode) || f2fs_has_inline_dentry(inode))
                flags |= F2FS_INLINE_DATA_FL;
@@ -1688,15 +1721,18 @@ static int f2fs_ioc_start_atomic_write(struct file *filp)
 
        inode_lock(inode);
 
-       down_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
-
-       if (f2fs_is_atomic_file(inode))
+       if (f2fs_is_atomic_file(inode)) {
+               if (is_inode_flag_set(inode, FI_ATOMIC_REVOKE_REQUEST))
+                       ret = -EINVAL;
                goto out;
+       }
 
        ret = f2fs_convert_inline_inode(inode);
        if (ret)
                goto out;
 
+       down_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
+
        if (!get_dirty_pages(inode))
                goto skip_flush;
 
@@ -1704,18 +1740,20 @@ static int f2fs_ioc_start_atomic_write(struct file *filp)
                "Unexpected flush for atomic writes: ino=%lu, npages=%u",
                                        inode->i_ino, get_dirty_pages(inode));
        ret = filemap_write_and_wait_range(inode->i_mapping, 0, LLONG_MAX);
-       if (ret)
+       if (ret) {
+               up_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
                goto out;
+       }
 skip_flush:
        set_inode_flag(inode, FI_ATOMIC_FILE);
        clear_inode_flag(inode, FI_ATOMIC_REVOKE_REQUEST);
-       f2fs_update_time(F2FS_I_SB(inode), REQ_TIME);
+       up_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
 
+       f2fs_update_time(F2FS_I_SB(inode), REQ_TIME);
        F2FS_I(inode)->inmem_task = current;
        stat_inc_atomic_write(inode);
        stat_update_max_atomic_write(inode);
 out:
-       up_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
        inode_unlock(inode);
        mnt_drop_write_file(filp);
        return ret;
@@ -1733,9 +1771,9 @@ static int f2fs_ioc_commit_atomic_write(struct file *filp)
        if (ret)
                return ret;
 
-       inode_lock(inode);
+       f2fs_balance_fs(F2FS_I_SB(inode), true);
 
-       down_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
+       inode_lock(inode);
 
        if (f2fs_is_volatile_file(inode)) {
                ret = -EINVAL;
@@ -1761,7 +1799,6 @@ err_out:
                clear_inode_flag(inode, FI_ATOMIC_REVOKE_REQUEST);
                ret = -EINVAL;
        }
-       up_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
        inode_unlock(inode);
        mnt_drop_write_file(filp);
        return ret;
@@ -1853,6 +1890,8 @@ static int f2fs_ioc_abort_volatile_write(struct file *filp)
                ret = f2fs_do_sync_file(filp, 0, LLONG_MAX, 0, true);
        }
 
+       clear_inode_flag(inode, FI_ATOMIC_REVOKE_REQUEST);
+
        inode_unlock(inode);
 
        mnt_drop_write_file(filp);
@@ -1866,7 +1905,7 @@ static int f2fs_ioc_shutdown(struct file *filp, unsigned long arg)
        struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
        struct super_block *sb = sbi->sb;
        __u32 in;
-       int ret;
+       int ret = 0;
 
        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
@@ -1889,6 +1928,7 @@ static int f2fs_ioc_shutdown(struct file *filp, unsigned long arg)
                }
                if (sb) {
                        f2fs_stop_checkpoint(sbi, false);
+                       set_sbi_flag(sbi, SBI_IS_SHUTDOWN);
                        thaw_bdev(sb->s_bdev, sb);
                }
                break;
@@ -1898,13 +1938,16 @@ static int f2fs_ioc_shutdown(struct file *filp, unsigned long arg)
                if (ret)
                        goto out;
                f2fs_stop_checkpoint(sbi, false);
+               set_sbi_flag(sbi, SBI_IS_SHUTDOWN);
                break;
        case F2FS_GOING_DOWN_NOSYNC:
                f2fs_stop_checkpoint(sbi, false);
+               set_sbi_flag(sbi, SBI_IS_SHUTDOWN);
                break;
        case F2FS_GOING_DOWN_METAFLUSH:
                f2fs_sync_meta_pages(sbi, META, LONG_MAX, FS_META_IO);
                f2fs_stop_checkpoint(sbi, false);
+               set_sbi_flag(sbi, SBI_IS_SHUTDOWN);
                break;
        default:
                ret = -EINVAL;
@@ -2107,7 +2150,7 @@ out:
        return ret;
 }
 
-static int f2fs_ioc_f2fs_write_checkpoint(struct file *filp, unsigned long arg)
+static int f2fs_ioc_write_checkpoint(struct file *filp, unsigned long arg)
 {
        struct inode *inode = file_inode(filp);
        struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
@@ -2351,15 +2394,10 @@ static int f2fs_move_file_range(struct file *file_in, loff_t pos_in,
        }
 
        inode_lock(src);
-       down_write(&F2FS_I(src)->i_gc_rwsem[WRITE]);
        if (src != dst) {
                ret = -EBUSY;
                if (!inode_trylock(dst))
                        goto out;
-               if (!down_write_trylock(&F2FS_I(dst)->i_gc_rwsem[WRITE])) {
-                       inode_unlock(dst);
-                       goto out;
-               }
        }
 
        ret = -EINVAL;
@@ -2404,6 +2442,14 @@ static int f2fs_move_file_range(struct file *file_in, loff_t pos_in,
                goto out_unlock;
 
        f2fs_balance_fs(sbi, true);
+
+       down_write(&F2FS_I(src)->i_gc_rwsem[WRITE]);
+       if (src != dst) {
+               ret = -EBUSY;
+               if (!down_write_trylock(&F2FS_I(dst)->i_gc_rwsem[WRITE]))
+                       goto out_src;
+       }
+
        f2fs_lock_op(sbi);
        ret = __exchange_data_block(src, dst, pos_in >> F2FS_BLKSIZE_BITS,
                                pos_out >> F2FS_BLKSIZE_BITS,
@@ -2416,13 +2462,15 @@ static int f2fs_move_file_range(struct file *file_in, loff_t pos_in,
                        f2fs_i_size_write(dst, dst_osize);
        }
        f2fs_unlock_op(sbi);
-out_unlock:
-       if (src != dst) {
+
+       if (src != dst)
                up_write(&F2FS_I(dst)->i_gc_rwsem[WRITE]);
+out_src:
+       up_write(&F2FS_I(src)->i_gc_rwsem[WRITE]);
+out_unlock:
+       if (src != dst)
                inode_unlock(dst);
-       }
 out:
-       up_write(&F2FS_I(src)->i_gc_rwsem[WRITE]);
        inode_unlock(src);
        return ret;
 }
@@ -2782,7 +2830,7 @@ static int f2fs_ioc_set_pin_file(struct file *filp, unsigned long arg)
 
        if (!pin) {
                clear_inode_flag(inode, FI_PIN_FILE);
-               F2FS_I(inode)->i_gc_failures[GC_FAILURE_PIN] = 1;
+               f2fs_i_gc_failures_write(inode, 0);
                goto done;
        }
 
@@ -2888,7 +2936,7 @@ long f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
        case F2FS_IOC_GARBAGE_COLLECT_RANGE:
                return f2fs_ioc_gc_range(filp, arg);
        case F2FS_IOC_WRITE_CHECKPOINT:
-               return f2fs_ioc_f2fs_write_checkpoint(filp, arg);
+               return f2fs_ioc_write_checkpoint(filp, arg);
        case F2FS_IOC_DEFRAGMENT:
                return f2fs_ioc_defragment(filp, arg);
        case F2FS_IOC_MOVE_RANGE:
index 9093be6..5c8d004 100644 (file)
@@ -53,12 +53,10 @@ static int gc_thread_func(void *data)
                        continue;
                }
 
-#ifdef CONFIG_F2FS_FAULT_INJECTION
                if (time_to_inject(sbi, FAULT_CHECKPOINT)) {
                        f2fs_show_injection_info(FAULT_CHECKPOINT);
                        f2fs_stop_checkpoint(sbi, false);
                }
-#endif
 
                if (!sb_start_write_trylock(sbi->sb))
                        continue;
@@ -517,7 +515,11 @@ next_step:
                        continue;
                }
 
-               f2fs_get_node_info(sbi, nid, &ni);
+               if (f2fs_get_node_info(sbi, nid, &ni)) {
+                       f2fs_put_page(node_page, 1);
+                       continue;
+               }
+
                if (ni.blk_addr != start_addr + off) {
                        f2fs_put_page(node_page, 1);
                        continue;
@@ -576,7 +578,10 @@ static bool is_alive(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
        if (IS_ERR(node_page))
                return false;
 
-       f2fs_get_node_info(sbi, nid, dni);
+       if (f2fs_get_node_info(sbi, nid, dni)) {
+               f2fs_put_page(node_page, 1);
+               return false;
+       }
 
        if (sum->version != dni->version) {
                f2fs_msg(sbi->sb, KERN_WARNING,
@@ -594,6 +599,72 @@ static bool is_alive(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
        return true;
 }
 
+static int ra_data_block(struct inode *inode, pgoff_t index)
+{
+       struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
+       struct address_space *mapping = inode->i_mapping;
+       struct dnode_of_data dn;
+       struct page *page;
+       struct extent_info ei = {0, 0, 0};
+       struct f2fs_io_info fio = {
+               .sbi = sbi,
+               .ino = inode->i_ino,
+               .type = DATA,
+               .temp = COLD,
+               .op = REQ_OP_READ,
+               .op_flags = 0,
+               .encrypted_page = NULL,
+               .in_list = false,
+               .retry = false,
+       };
+       int err;
+
+       page = f2fs_grab_cache_page(mapping, index, true);
+       if (!page)
+               return -ENOMEM;
+
+       if (f2fs_lookup_extent_cache(inode, index, &ei)) {
+               dn.data_blkaddr = ei.blk + index - ei.fofs;
+               goto got_it;
+       }
+
+       set_new_dnode(&dn, inode, NULL, NULL, 0);
+       err = f2fs_get_dnode_of_data(&dn, index, LOOKUP_NODE);
+       if (err)
+               goto put_page;
+       f2fs_put_dnode(&dn);
+
+       if (unlikely(!f2fs_is_valid_blkaddr(sbi, dn.data_blkaddr,
+                                               DATA_GENERIC))) {
+               err = -EFAULT;
+               goto put_page;
+       }
+got_it:
+       /* read page */
+       fio.page = page;
+       fio.new_blkaddr = fio.old_blkaddr = dn.data_blkaddr;
+
+       fio.encrypted_page = f2fs_pagecache_get_page(META_MAPPING(sbi),
+                                       dn.data_blkaddr,
+                                       FGP_LOCK | FGP_CREAT, GFP_NOFS);
+       if (!fio.encrypted_page) {
+               err = -ENOMEM;
+               goto put_page;
+       }
+
+       err = f2fs_submit_page_bio(&fio);
+       if (err)
+               goto put_encrypted_page;
+       f2fs_put_page(fio.encrypted_page, 0);
+       f2fs_put_page(page, 1);
+       return 0;
+put_encrypted_page:
+       f2fs_put_page(fio.encrypted_page, 1);
+put_page:
+       f2fs_put_page(page, 1);
+       return err;
+}
+
 /*
  * Move data block via META_MAPPING while keeping locked data page.
  * This can be used to move blocks, aka LBAs, directly on disk.
@@ -615,7 +686,7 @@ static void move_data_block(struct inode *inode, block_t bidx,
        struct dnode_of_data dn;
        struct f2fs_summary sum;
        struct node_info ni;
-       struct page *page;
+       struct page *page, *mpage;
        block_t newaddr;
        int err;
        bool lfs_mode = test_opt(fio.sbi, LFS);
@@ -655,7 +726,10 @@ static void move_data_block(struct inode *inode, block_t bidx,
         */
        f2fs_wait_on_page_writeback(page, DATA, true);
 
-       f2fs_get_node_info(fio.sbi, dn.nid, &ni);
+       err = f2fs_get_node_info(fio.sbi, dn.nid, &ni);
+       if (err)
+               goto put_out;
+
        set_summary(&sum, dn.nid, dn.ofs_in_node, ni.version);
 
        /* read page */
@@ -675,6 +749,23 @@ static void move_data_block(struct inode *inode, block_t bidx,
                goto recover_block;
        }
 
+       mpage = f2fs_pagecache_get_page(META_MAPPING(fio.sbi),
+                                       fio.old_blkaddr, FGP_LOCK, GFP_NOFS);
+       if (mpage) {
+               bool updated = false;
+
+               if (PageUptodate(mpage)) {
+                       memcpy(page_address(fio.encrypted_page),
+                                       page_address(mpage), PAGE_SIZE);
+                       updated = true;
+               }
+               f2fs_put_page(mpage, 1);
+               invalidate_mapping_pages(META_MAPPING(fio.sbi),
+                                       fio.old_blkaddr, fio.old_blkaddr);
+               if (updated)
+                       goto write_page;
+       }
+
        err = f2fs_submit_page_bio(&fio);
        if (err)
                goto put_page_out;
@@ -691,6 +782,7 @@ static void move_data_block(struct inode *inode, block_t bidx,
                goto put_page_out;
        }
 
+write_page:
        set_page_dirty(fio.encrypted_page);
        f2fs_wait_on_page_writeback(fio.encrypted_page, DATA, true);
        if (clear_page_dirty_for_io(fio.encrypted_page))
@@ -865,22 +957,30 @@ next_step:
                        if (IS_ERR(inode) || is_bad_inode(inode))
                                continue;
 
-                       /* if inode uses special I/O path, let's go phase 3 */
-                       if (f2fs_post_read_required(inode)) {
-                               add_gc_inode(gc_list, inode);
-                               continue;
-                       }
-
                        if (!down_write_trylock(
                                &F2FS_I(inode)->i_gc_rwsem[WRITE])) {
                                iput(inode);
+                               sbi->skipped_gc_rwsem++;
+                               continue;
+                       }
+
+                       start_bidx = f2fs_start_bidx_of_node(nofs, inode) +
+                                                               ofs_in_node;
+
+                       if (f2fs_post_read_required(inode)) {
+                               int err = ra_data_block(inode, start_bidx);
+
+                               up_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
+                               if (err) {
+                                       iput(inode);
+                                       continue;
+                               }
+                               add_gc_inode(gc_list, inode);
                                continue;
                        }
 
-                       start_bidx = f2fs_start_bidx_of_node(nofs, inode);
                        data_page = f2fs_get_read_data_page(inode,
-                                       start_bidx + ofs_in_node, REQ_RAHEAD,
-                                       true);
+                                               start_bidx, REQ_RAHEAD, true);
                        up_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
                        if (IS_ERR(data_page)) {
                                iput(inode);
@@ -903,6 +1003,7 @@ next_step:
                                        continue;
                                if (!down_write_trylock(
                                                &fi->i_gc_rwsem[WRITE])) {
+                                       sbi->skipped_gc_rwsem++;
                                        up_write(&fi->i_gc_rwsem[READ]);
                                        continue;
                                }
@@ -986,7 +1087,13 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi,
                        goto next;
 
                sum = page_address(sum_page);
-               f2fs_bug_on(sbi, type != GET_SUM_TYPE((&sum->footer)));
+               if (type != GET_SUM_TYPE((&sum->footer))) {
+                       f2fs_msg(sbi->sb, KERN_ERR, "Inconsistent segment (%u) "
+                               "type [%d, %d] in SSA and SIT",
+                               segno, type, GET_SUM_TYPE((&sum->footer)));
+                       set_sbi_flag(sbi, SBI_NEED_FSCK);
+                       goto next;
+               }
 
                /*
                 * this is to avoid deadlock:
@@ -1034,6 +1141,7 @@ int f2fs_gc(struct f2fs_sb_info *sbi, bool sync,
                .iroot = RADIX_TREE_INIT(gc_list.iroot, GFP_NOFS),
        };
        unsigned long long last_skipped = sbi->skipped_atomic_files[FG_GC];
+       unsigned long long first_skipped;
        unsigned int skipped_round = 0, round = 0;
 
        trace_f2fs_gc_begin(sbi->sb, sync, background,
@@ -1046,6 +1154,8 @@ int f2fs_gc(struct f2fs_sb_info *sbi, bool sync,
                                prefree_segments(sbi));
 
        cpc.reason = __get_cp_reason(sbi);
+       sbi->skipped_gc_rwsem = 0;
+       first_skipped = last_skipped;
 gc_more:
        if (unlikely(!(sbi->sb->s_flags & SB_ACTIVE))) {
                ret = -EINVAL;
@@ -1087,7 +1197,8 @@ gc_more:
        total_freed += seg_freed;
 
        if (gc_type == FG_GC) {
-               if (sbi->skipped_atomic_files[FG_GC] > last_skipped)
+               if (sbi->skipped_atomic_files[FG_GC] > last_skipped ||
+                                               sbi->skipped_gc_rwsem)
                        skipped_round++;
                last_skipped = sbi->skipped_atomic_files[FG_GC];
                round++;
@@ -1096,15 +1207,23 @@ gc_more:
        if (gc_type == FG_GC)
                sbi->cur_victim_sec = NULL_SEGNO;
 
-       if (!sync) {
-               if (has_not_enough_free_secs(sbi, sec_freed, 0)) {
-                       if (skipped_round > MAX_SKIP_ATOMIC_COUNT &&
-                               skipped_round * 2 >= round)
-                               f2fs_drop_inmem_pages_all(sbi, true);
+       if (sync)
+               goto stop;
+
+       if (has_not_enough_free_secs(sbi, sec_freed, 0)) {
+               if (skipped_round <= MAX_SKIP_GC_COUNT ||
+                                       skipped_round * 2 < round) {
                        segno = NULL_SEGNO;
                        goto gc_more;
                }
 
+               if (first_skipped < last_skipped &&
+                               (last_skipped - first_skipped) >
+                                               sbi->skipped_gc_rwsem) {
+                       f2fs_drop_inmem_pages_all(sbi, true);
+                       segno = NULL_SEGNO;
+                       goto gc_more;
+               }
                if (gc_type == FG_GC)
                        ret = f2fs_write_checkpoint(sbi, &cpc);
        }
index 043830b..115dc21 100644 (file)
@@ -121,6 +121,7 @@ int f2fs_convert_inline_page(struct dnode_of_data *dn, struct page *page)
                .encrypted_page = NULL,
                .io_type = FS_DATA_IO,
        };
+       struct node_info ni;
        int dirty, err;
 
        if (!f2fs_exist_data(dn->inode))
@@ -130,6 +131,24 @@ int f2fs_convert_inline_page(struct dnode_of_data *dn, struct page *page)
        if (err)
                return err;
 
+       err = f2fs_get_node_info(fio.sbi, dn->nid, &ni);
+       if (err) {
+               f2fs_put_dnode(dn);
+               return err;
+       }
+
+       fio.version = ni.version;
+
+       if (unlikely(dn->data_blkaddr != NEW_ADDR)) {
+               f2fs_put_dnode(dn);
+               set_sbi_flag(fio.sbi, SBI_NEED_FSCK);
+               f2fs_msg(fio.sbi->sb, KERN_WARNING,
+                       "%s: corrupted inline inode ino=%lx, i_addr[0]:0x%x, "
+                       "run fsck to fix.",
+                       __func__, dn->inode->i_ino, dn->data_blkaddr);
+               return -EINVAL;
+       }
+
        f2fs_bug_on(F2FS_P_SB(page), PageWriteback(page));
 
        f2fs_do_read_inline_data(page, dn->inode_page);
@@ -363,6 +382,17 @@ static int f2fs_move_inline_dirents(struct inode *dir, struct page *ipage,
        if (err)
                goto out;
 
+       if (unlikely(dn.data_blkaddr != NEW_ADDR)) {
+               f2fs_put_dnode(&dn);
+               set_sbi_flag(F2FS_P_SB(page), SBI_NEED_FSCK);
+               f2fs_msg(F2FS_P_SB(page)->sb, KERN_WARNING,
+                       "%s: corrupted inline inode ino=%lx, i_addr[0]:0x%x, "
+                       "run fsck to fix.",
+                       __func__, dir->i_ino, dn.data_blkaddr);
+               err = -EINVAL;
+               goto out;
+       }
+
        f2fs_wait_on_page_writeback(page, DATA, true);
 
        dentry_blk = page_address(page);
@@ -477,6 +507,7 @@ static int f2fs_move_rehashed_dirents(struct inode *dir, struct page *ipage,
        return 0;
 recover:
        lock_page(ipage);
+       f2fs_wait_on_page_writeback(ipage, NODE, true);
        memcpy(inline_dentry, backup_dentry, MAX_INLINE_DATA(dir));
        f2fs_i_depth_write(dir, 0);
        f2fs_i_size_write(dir, MAX_INLINE_DATA(dir));
@@ -668,7 +699,10 @@ int f2fs_inline_data_fiemap(struct inode *inode,
                ilen = start + len;
        ilen -= start;
 
-       f2fs_get_node_info(F2FS_I_SB(inode), inode->i_ino, &ni);
+       err = f2fs_get_node_info(F2FS_I_SB(inode), inode->i_ino, &ni);
+       if (err)
+               goto out;
+
        byteaddr = (__u64)ni.blk_addr << inode->i_sb->s_blocksize_bits;
        byteaddr += (char *)inline_data_addr(inode, ipage) -
                                        (char *)F2FS_INODE(ipage);
index f121c86..959df22 100644 (file)
@@ -68,13 +68,16 @@ static void __get_inode_rdev(struct inode *inode, struct f2fs_inode *ri)
        }
 }
 
-static bool __written_first_block(struct f2fs_inode *ri)
+static int __written_first_block(struct f2fs_sb_info *sbi,
+                                       struct f2fs_inode *ri)
 {
        block_t addr = le32_to_cpu(ri->i_addr[offset_in_addr(ri)]);
 
-       if (is_valid_blkaddr(addr))
-               return true;
-       return false;
+       if (!__is_valid_data_blkaddr(addr))
+               return 1;
+       if (!f2fs_is_valid_blkaddr(sbi, addr, DATA_GENERIC))
+               return -EFAULT;
+       return 0;
 }
 
 static void __set_inode_rdev(struct inode *inode, struct f2fs_inode *ri)
@@ -121,7 +124,7 @@ static bool f2fs_enable_inode_chksum(struct f2fs_sb_info *sbi, struct page *page
        if (!f2fs_sb_has_inode_chksum(sbi->sb))
                return false;
 
-       if (!RAW_IS_INODE(F2FS_NODE(page)) || !(ri->i_inline & F2FS_EXTRA_ATTR))
+       if (!IS_INODE(page) || !(ri->i_inline & F2FS_EXTRA_ATTR))
                return false;
 
        if (!F2FS_FITS_IN_INODE(ri, le16_to_cpu(ri->i_extra_isize),
@@ -159,8 +162,15 @@ bool f2fs_inode_chksum_verify(struct f2fs_sb_info *sbi, struct page *page)
        struct f2fs_inode *ri;
        __u32 provided, calculated;
 
+       if (unlikely(is_sbi_flag_set(sbi, SBI_IS_SHUTDOWN)))
+               return true;
+
+#ifdef CONFIG_F2FS_CHECK_FS
+       if (!f2fs_enable_inode_chksum(sbi, page))
+#else
        if (!f2fs_enable_inode_chksum(sbi, page) ||
                        PageDirty(page) || PageWriteback(page))
+#endif
                return true;
 
        ri = &F2FS_NODE(page)->i;
@@ -185,9 +195,31 @@ void f2fs_inode_chksum_set(struct f2fs_sb_info *sbi, struct page *page)
        ri->i_inode_checksum = cpu_to_le32(f2fs_inode_chksum(sbi, page));
 }
 
-static bool sanity_check_inode(struct inode *inode)
+static bool sanity_check_inode(struct inode *inode, struct page *node_page)
 {
        struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
+       struct f2fs_inode_info *fi = F2FS_I(inode);
+       unsigned long long iblocks;
+
+       iblocks = le64_to_cpu(F2FS_INODE(node_page)->i_blocks);
+       if (!iblocks) {
+               set_sbi_flag(sbi, SBI_NEED_FSCK);
+               f2fs_msg(sbi->sb, KERN_WARNING,
+                       "%s: corrupted inode i_blocks i_ino=%lx iblocks=%llu, "
+                       "run fsck to fix.",
+                       __func__, inode->i_ino, iblocks);
+               return false;
+       }
+
+       if (ino_of_node(node_page) != nid_of_node(node_page)) {
+               set_sbi_flag(sbi, SBI_NEED_FSCK);
+               f2fs_msg(sbi->sb, KERN_WARNING,
+                       "%s: corrupted inode footer i_ino=%lx, ino,nid: "
+                       "[%u, %u] run fsck to fix.",
+                       __func__, inode->i_ino,
+                       ino_of_node(node_page), nid_of_node(node_page));
+               return false;
+       }
 
        if (f2fs_sb_has_flexible_inline_xattr(sbi->sb)
                        && !f2fs_has_extra_attr(inode)) {
@@ -197,6 +229,64 @@ static bool sanity_check_inode(struct inode *inode)
                        __func__, inode->i_ino);
                return false;
        }
+
+       if (f2fs_has_extra_attr(inode) &&
+                       !f2fs_sb_has_extra_attr(sbi->sb)) {
+               set_sbi_flag(sbi, SBI_NEED_FSCK);
+               f2fs_msg(sbi->sb, KERN_WARNING,
+                       "%s: inode (ino=%lx) is with extra_attr, "
+                       "but extra_attr feature is off",
+                       __func__, inode->i_ino);
+               return false;
+       }
+
+       if (fi->i_extra_isize > F2FS_TOTAL_EXTRA_ATTR_SIZE ||
+                       fi->i_extra_isize % sizeof(__le32)) {
+               set_sbi_flag(sbi, SBI_NEED_FSCK);
+               f2fs_msg(sbi->sb, KERN_WARNING,
+                       "%s: inode (ino=%lx) has corrupted i_extra_isize: %d, "
+                       "max: %zu",
+                       __func__, inode->i_ino, fi->i_extra_isize,
+                       F2FS_TOTAL_EXTRA_ATTR_SIZE);
+               return false;
+       }
+
+       if (F2FS_I(inode)->extent_tree) {
+               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 + ei->len - 1,
+                                                       DATA_GENERIC))) {
+                       set_sbi_flag(sbi, SBI_NEED_FSCK);
+                       f2fs_msg(sbi->sb, KERN_WARNING,
+                               "%s: inode (ino=%lx) extent info [%u, %u, %u] "
+                               "is incorrect, run fsck to fix",
+                               __func__, inode->i_ino,
+                               ei->blk, ei->fofs, ei->len);
+                       return false;
+               }
+       }
+
+       if (f2fs_has_inline_data(inode) &&
+                       (!S_ISREG(inode->i_mode) && !S_ISLNK(inode->i_mode))) {
+               set_sbi_flag(sbi, SBI_NEED_FSCK);
+               f2fs_msg(sbi->sb, KERN_WARNING,
+                       "%s: inode (ino=%lx, mode=%u) should not have "
+                       "inline_data, run fsck to fix",
+                       __func__, inode->i_ino, inode->i_mode);
+               return false;
+       }
+
+       if (f2fs_has_inline_dentry(inode) && !S_ISDIR(inode->i_mode)) {
+               set_sbi_flag(sbi, SBI_NEED_FSCK);
+               f2fs_msg(sbi->sb, KERN_WARNING,
+                       "%s: inode (ino=%lx, mode=%u) should not have "
+                       "inline_dentry, run fsck to fix",
+                       __func__, inode->i_ino, inode->i_mode);
+               return false;
+       }
+
        return true;
 }
 
@@ -207,6 +297,7 @@ static int do_read_inode(struct inode *inode)
        struct page *node_page;
        struct f2fs_inode *ri;
        projid_t i_projid;
+       int err;
 
        /* Check if ino is within scope */
        if (f2fs_check_nid_range(sbi, inode->i_ino))
@@ -268,6 +359,11 @@ static int do_read_inode(struct inode *inode)
                fi->i_inline_xattr_size = 0;
        }
 
+       if (!sanity_check_inode(inode, node_page)) {
+               f2fs_put_page(node_page, 1);
+               return -EINVAL;
+       }
+
        /* check data exist */
        if (f2fs_has_inline_data(inode) && !f2fs_exist_data(inode))
                __recover_inline_status(inode, node_page);
@@ -275,8 +371,15 @@ static int do_read_inode(struct inode *inode)
        /* get rdev by using inline_info */
        __get_inode_rdev(inode, ri);
 
-       if (__written_first_block(ri))
-               set_inode_flag(inode, FI_FIRST_BLOCK_WRITTEN);
+       if (S_ISREG(inode->i_mode)) {
+               err = __written_first_block(sbi, ri);
+               if (err < 0) {
+                       f2fs_put_page(node_page, 1);
+                       return err;
+               }
+               if (!err)
+                       set_inode_flag(inode, FI_FIRST_BLOCK_WRITTEN);
+       }
 
        if (!f2fs_need_inode_block_update(sbi, inode->i_ino))
                fi->last_disk_size = inode->i_size;
@@ -297,9 +400,9 @@ static int do_read_inode(struct inode *inode)
                fi->i_crtime.tv_nsec = le32_to_cpu(ri->i_crtime_nsec);
        }
 
-       F2FS_I(inode)->i_disk_time[0] = timespec64_to_timespec(inode->i_atime);
-       F2FS_I(inode)->i_disk_time[1] = timespec64_to_timespec(inode->i_ctime);
-       F2FS_I(inode)->i_disk_time[2] = timespec64_to_timespec(inode->i_mtime);
+       F2FS_I(inode)->i_disk_time[0] = inode->i_atime;
+       F2FS_I(inode)->i_disk_time[1] = inode->i_ctime;
+       F2FS_I(inode)->i_disk_time[2] = inode->i_mtime;
        F2FS_I(inode)->i_disk_time[3] = F2FS_I(inode)->i_crtime;
        f2fs_put_page(node_page, 1);
 
@@ -330,10 +433,6 @@ struct inode *f2fs_iget(struct super_block *sb, unsigned long ino)
        ret = do_read_inode(inode);
        if (ret)
                goto bad_inode;
-       if (!sanity_check_inode(inode)) {
-               ret = -EINVAL;
-               goto bad_inode;
-       }
 make_now:
        if (ino == F2FS_NODE_INO(sbi)) {
                inode->i_mapping->a_ops = &f2fs_node_aops;
@@ -470,10 +569,14 @@ void f2fs_update_inode(struct inode *inode, struct page *node_page)
        if (inode->i_nlink == 0)
                clear_inline_node(node_page);
 
-       F2FS_I(inode)->i_disk_time[0] = timespec64_to_timespec(inode->i_atime);
-       F2FS_I(inode)->i_disk_time[1] = timespec64_to_timespec(inode->i_ctime);
-       F2FS_I(inode)->i_disk_time[2] = timespec64_to_timespec(inode->i_mtime);
+       F2FS_I(inode)->i_disk_time[0] = inode->i_atime;
+       F2FS_I(inode)->i_disk_time[1] = inode->i_ctime;
+       F2FS_I(inode)->i_disk_time[2] = inode->i_mtime;
        F2FS_I(inode)->i_disk_time[3] = F2FS_I(inode)->i_crtime;
+
+#ifdef CONFIG_F2FS_CHECK_FS
+       f2fs_inode_chksum_set(F2FS_I_SB(inode), node_page);
+#endif
 }
 
 void f2fs_update_inode_page(struct inode *inode)
@@ -558,12 +661,11 @@ retry:
        if (F2FS_HAS_BLOCKS(inode))
                err = f2fs_truncate(inode);
 
-#ifdef CONFIG_F2FS_FAULT_INJECTION
        if (time_to_inject(sbi, FAULT_EVICT_INODE)) {
                f2fs_show_injection_info(FAULT_EVICT_INODE);
                err = -EIO;
        }
-#endif
+
        if (!err) {
                f2fs_lock_op(sbi);
                err = f2fs_remove_inode_page(inode);
@@ -626,6 +728,7 @@ void f2fs_handle_failed_inode(struct inode *inode)
 {
        struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
        struct node_info ni;
+       int err;
 
        /*
         * clear nlink of inode in order to release resource of inode
@@ -648,10 +751,16 @@ void f2fs_handle_failed_inode(struct inode *inode)
         * so we can prevent losing this orphan when encoutering checkpoint
         * and following suddenly power-off.
         */
-       f2fs_get_node_info(sbi, inode->i_ino, &ni);
+       err = f2fs_get_node_info(sbi, inode->i_ino, &ni);
+       if (err) {
+               set_sbi_flag(sbi, SBI_NEED_FSCK);
+               f2fs_msg(sbi->sb, KERN_WARNING,
+                       "May loss orphan inode, run fsck to fix.");
+               goto out;
+       }
 
        if (ni.blk_addr != NULL_ADDR) {
-               int err = f2fs_acquire_orphan_inode(sbi);
+               err = f2fs_acquire_orphan_inode(sbi);
                if (err) {
                        set_sbi_flag(sbi, SBI_NEED_FSCK);
                        f2fs_msg(sbi->sb, KERN_WARNING,
@@ -664,6 +773,7 @@ void f2fs_handle_failed_inode(struct inode *inode)
                set_inode_flag(inode, FI_FREE_NID);
        }
 
+out:
        f2fs_unlock_op(sbi);
 
        /* iput will drop the inode object */
index 231b7f3..1f67e38 100644 (file)
@@ -51,7 +51,7 @@ static struct inode *f2fs_new_inode(struct inode *dir, umode_t mode)
        inode->i_ino = ino;
        inode->i_blocks = 0;
        inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode);
-       F2FS_I(inode)->i_crtime = timespec64_to_timespec(inode->i_mtime);
+       F2FS_I(inode)->i_crtime = inode->i_mtime;
        inode->i_generation = sbi->s_next_generation++;
 
        if (S_ISDIR(inode->i_mode))
@@ -246,7 +246,7 @@ int f2fs_update_extension_list(struct f2fs_sb_info *sbi, const char *name,
                return -EINVAL;
 
        if (hot) {
-               strncpy(extlist[count], name, strlen(name));
+               memcpy(extlist[count], name, strlen(name));
                sbi->raw_super->hot_ext_count = hot_count + 1;
        } else {
                char buf[F2FS_MAX_EXTENSION][F2FS_EXTENSION_LEN];
@@ -254,7 +254,7 @@ int f2fs_update_extension_list(struct f2fs_sb_info *sbi, const char *name,
                memcpy(buf, &extlist[cold_count],
                                F2FS_EXTENSION_LEN * hot_count);
                memset(extlist[cold_count], 0, F2FS_EXTENSION_LEN);
-               strncpy(extlist[cold_count], name, strlen(name));
+               memcpy(extlist[cold_count], name, strlen(name));
                memcpy(&extlist[cold_count + 1], buf,
                                F2FS_EXTENSION_LEN * hot_count);
                sbi->raw_super->extension_count = cpu_to_le32(cold_count + 1);
index 10643b1..dd2e45a 100644 (file)
@@ -28,6 +28,7 @@
 static struct kmem_cache *nat_entry_slab;
 static struct kmem_cache *free_nid_slab;
 static struct kmem_cache *nat_entry_set_slab;
+static struct kmem_cache *fsync_node_entry_slab;
 
 /*
  * Check whether the given nid is within node id range.
@@ -112,25 +113,22 @@ static void clear_node_page_dirty(struct page *page)
 
 static struct page *get_current_nat_page(struct f2fs_sb_info *sbi, nid_t nid)
 {
-       pgoff_t index = current_nat_addr(sbi, nid);
-       return f2fs_get_meta_page(sbi, index);
+       return f2fs_get_meta_page_nofail(sbi, current_nat_addr(sbi, nid));
 }
 
 static struct page *get_next_nat_page(struct f2fs_sb_info *sbi, nid_t nid)
 {
        struct page *src_page;
        struct page *dst_page;
-       pgoff_t src_off;
        pgoff_t dst_off;
        void *src_addr;
        void *dst_addr;
        struct f2fs_nm_info *nm_i = NM_I(sbi);
 
-       src_off = current_nat_addr(sbi, nid);
-       dst_off = next_nat_addr(sbi, src_off);
+       dst_off = next_nat_addr(sbi, current_nat_addr(sbi, nid));
 
        /* get current nat block page with lock */
-       src_page = f2fs_get_meta_page(sbi, src_off);
+       src_page = get_current_nat_page(sbi, nid);
        dst_page = f2fs_grab_meta_page(sbi, dst_off);
        f2fs_bug_on(sbi, PageDirty(src_page));
 
@@ -176,14 +174,30 @@ static struct nat_entry *__init_nat_entry(struct f2fs_nm_info *nm_i,
 
        if (raw_ne)
                node_info_from_raw_nat(&ne->ni, raw_ne);
+
+       spin_lock(&nm_i->nat_list_lock);
        list_add_tail(&ne->list, &nm_i->nat_entries);
+       spin_unlock(&nm_i->nat_list_lock);
+
        nm_i->nat_cnt++;
        return ne;
 }
 
 static struct nat_entry *__lookup_nat_cache(struct f2fs_nm_info *nm_i, nid_t n)
 {
-       return radix_tree_lookup(&nm_i->nat_root, n);
+       struct nat_entry *ne;
+
+       ne = radix_tree_lookup(&nm_i->nat_root, n);
+
+       /* for recent accessed nat entry, move it to tail of lru list */
+       if (ne && !get_nat_flag(ne, IS_DIRTY)) {
+               spin_lock(&nm_i->nat_list_lock);
+               if (!list_empty(&ne->list))
+                       list_move_tail(&ne->list, &nm_i->nat_entries);
+               spin_unlock(&nm_i->nat_list_lock);
+       }
+
+       return ne;
 }
 
 static unsigned int __gang_lookup_nat_cache(struct f2fs_nm_info *nm_i,
@@ -194,7 +208,6 @@ static unsigned int __gang_lookup_nat_cache(struct f2fs_nm_info *nm_i,
 
 static void __del_from_nat_cache(struct f2fs_nm_info *nm_i, struct nat_entry *e)
 {
-       list_del(&e->list);
        radix_tree_delete(&nm_i->nat_root, nat_get_nid(e));
        nm_i->nat_cnt--;
        __free_nat_entry(e);
@@ -245,16 +258,21 @@ static void __set_nat_cache_dirty(struct f2fs_nm_info *nm_i,
        nm_i->dirty_nat_cnt++;
        set_nat_flag(ne, IS_DIRTY, true);
 refresh_list:
+       spin_lock(&nm_i->nat_list_lock);
        if (new_ne)
                list_del_init(&ne->list);
        else
                list_move_tail(&ne->list, &head->entry_list);
+       spin_unlock(&nm_i->nat_list_lock);
 }
 
 static void __clear_nat_cache_dirty(struct f2fs_nm_info *nm_i,
                struct nat_entry_set *set, struct nat_entry *ne)
 {
+       spin_lock(&nm_i->nat_list_lock);
        list_move_tail(&ne->list, &nm_i->nat_entries);
+       spin_unlock(&nm_i->nat_list_lock);
+
        set_nat_flag(ne, IS_DIRTY, false);
        set->entry_cnt--;
        nm_i->dirty_nat_cnt--;
@@ -267,6 +285,72 @@ static unsigned int __gang_lookup_nat_set(struct f2fs_nm_info *nm_i,
                                                        start, nr);
 }
 
+bool f2fs_in_warm_node_list(struct f2fs_sb_info *sbi, struct page *page)
+{
+       return NODE_MAPPING(sbi) == page->mapping &&
+                       IS_DNODE(page) && is_cold_node(page);
+}
+
+void f2fs_init_fsync_node_info(struct f2fs_sb_info *sbi)
+{
+       spin_lock_init(&sbi->fsync_node_lock);
+       INIT_LIST_HEAD(&sbi->fsync_node_list);
+       sbi->fsync_seg_id = 0;
+       sbi->fsync_node_num = 0;
+}
+
+static unsigned int f2fs_add_fsync_node_entry(struct f2fs_sb_info *sbi,
+                                                       struct page *page)
+{
+       struct fsync_node_entry *fn;
+       unsigned long flags;
+       unsigned int seq_id;
+
+       fn = f2fs_kmem_cache_alloc(fsync_node_entry_slab, GFP_NOFS);
+
+       get_page(page);
+       fn->page = page;
+       INIT_LIST_HEAD(&fn->list);
+
+       spin_lock_irqsave(&sbi->fsync_node_lock, flags);
+       list_add_tail(&fn->list, &sbi->fsync_node_list);
+       fn->seq_id = sbi->fsync_seg_id++;
+       seq_id = fn->seq_id;
+       sbi->fsync_node_num++;
+       spin_unlock_irqrestore(&sbi->fsync_node_lock, flags);
+
+       return seq_id;
+}
+
+void f2fs_del_fsync_node_entry(struct f2fs_sb_info *sbi, struct page *page)
+{
+       struct fsync_node_entry *fn;
+       unsigned long flags;
+
+       spin_lock_irqsave(&sbi->fsync_node_lock, flags);
+       list_for_each_entry(fn, &sbi->fsync_node_list, list) {
+               if (fn->page == page) {
+                       list_del(&fn->list);
+                       sbi->fsync_node_num--;
+                       spin_unlock_irqrestore(&sbi->fsync_node_lock, flags);
+                       kmem_cache_free(fsync_node_entry_slab, fn);
+                       put_page(page);
+                       return;
+               }
+       }
+       spin_unlock_irqrestore(&sbi->fsync_node_lock, flags);
+       f2fs_bug_on(sbi, 1);
+}
+
+void f2fs_reset_fsync_node_info(struct f2fs_sb_info *sbi)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&sbi->fsync_node_lock, flags);
+       sbi->fsync_seg_id = 0;
+       spin_unlock_irqrestore(&sbi->fsync_node_lock, flags);
+}
+
 int f2fs_need_dentry_mark(struct f2fs_sb_info *sbi, nid_t nid)
 {
        struct f2fs_nm_info *nm_i = NM_I(sbi);
@@ -371,7 +455,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_blkaddr(nat_get_blkaddr(e)) &&
+       f2fs_bug_on(sbi, is_valid_data_blkaddr(sbi, nat_get_blkaddr(e)) &&
                        new_blkaddr == NEW_ADDR);
 
        /* increment version no as node is removed */
@@ -382,7 +466,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_blkaddr(new_blkaddr))
+       if (!is_valid_data_blkaddr(sbi, new_blkaddr))
                set_nat_flag(e, IS_CHECKPOINTED, false);
        __set_nat_cache_dirty(nm_i, e);
 
@@ -405,13 +489,25 @@ int f2fs_try_to_free_nats(struct f2fs_sb_info *sbi, int nr_shrink)
        if (!down_write_trylock(&nm_i->nat_tree_lock))
                return 0;
 
-       while (nr_shrink && !list_empty(&nm_i->nat_entries)) {
+       spin_lock(&nm_i->nat_list_lock);
+       while (nr_shrink) {
                struct nat_entry *ne;
+
+               if (list_empty(&nm_i->nat_entries))
+                       break;
+
                ne = list_first_entry(&nm_i->nat_entries,
                                        struct nat_entry, list);
+               list_del(&ne->list);
+               spin_unlock(&nm_i->nat_list_lock);
+
                __del_from_nat_cache(nm_i, ne);
                nr_shrink--;
+
+               spin_lock(&nm_i->nat_list_lock);
        }
+       spin_unlock(&nm_i->nat_list_lock);
+
        up_write(&nm_i->nat_tree_lock);
        return nr - nr_shrink;
 }
@@ -419,7 +515,7 @@ int f2fs_try_to_free_nats(struct f2fs_sb_info *sbi, int nr_shrink)
 /*
  * This function always returns success
  */
-void f2fs_get_node_info(struct f2fs_sb_info *sbi, nid_t nid,
+int f2fs_get_node_info(struct f2fs_sb_info *sbi, nid_t nid,
                                                struct node_info *ni)
 {
        struct f2fs_nm_info *nm_i = NM_I(sbi);
@@ -443,7 +539,7 @@ void f2fs_get_node_info(struct f2fs_sb_info *sbi, nid_t nid,
                ni->blk_addr = nat_get_blkaddr(e);
                ni->version = nat_get_version(e);
                up_read(&nm_i->nat_tree_lock);
-               return;
+               return 0;
        }
 
        memset(&ne, 0, sizeof(struct f2fs_nat_entry));
@@ -466,6 +562,9 @@ void f2fs_get_node_info(struct f2fs_sb_info *sbi, nid_t nid,
        up_read(&nm_i->nat_tree_lock);
 
        page = f2fs_get_meta_page(sbi, index);
+       if (IS_ERR(page))
+               return PTR_ERR(page);
+
        nat_blk = (struct f2fs_nat_block *)page_address(page);
        ne = nat_blk->entries[nid - start_nid];
        node_info_from_raw_nat(ni, &ne);
@@ -473,6 +572,7 @@ void f2fs_get_node_info(struct f2fs_sb_info *sbi, nid_t nid,
 cache:
        /* cache nat entry */
        cache_nat_entry(sbi, nid, &ne);
+       return 0;
 }
 
 /*
@@ -722,12 +822,15 @@ release_out:
        return err;
 }
 
-static void truncate_node(struct dnode_of_data *dn)
+static int truncate_node(struct dnode_of_data *dn)
 {
        struct f2fs_sb_info *sbi = F2FS_I_SB(dn->inode);
        struct node_info ni;
+       int err;
 
-       f2fs_get_node_info(sbi, dn->nid, &ni);
+       err = f2fs_get_node_info(sbi, dn->nid, &ni);
+       if (err)
+               return err;
 
        /* Deallocate node address */
        f2fs_invalidate_blocks(sbi, ni.blk_addr);
@@ -750,11 +853,14 @@ static void truncate_node(struct dnode_of_data *dn)
 
        dn->node_page = NULL;
        trace_f2fs_truncate_node(dn->inode, dn->nid, ni.blk_addr);
+
+       return 0;
 }
 
 static int truncate_dnode(struct dnode_of_data *dn)
 {
        struct page *page;
+       int err;
 
        if (dn->nid == 0)
                return 1;
@@ -770,7 +876,10 @@ static int truncate_dnode(struct dnode_of_data *dn)
        dn->node_page = page;
        dn->ofs_in_node = 0;
        f2fs_truncate_data_blocks(dn);
-       truncate_node(dn);
+       err = truncate_node(dn);
+       if (err)
+               return err;
+
        return 1;
 }
 
@@ -835,7 +944,9 @@ static int truncate_nodes(struct dnode_of_data *dn, unsigned int nofs,
        if (!ofs) {
                /* remove current indirect node */
                dn->node_page = page;
-               truncate_node(dn);
+               ret = truncate_node(dn);
+               if (ret)
+                       goto out_err;
                freed++;
        } else {
                f2fs_put_page(page, 1);
@@ -893,7 +1004,9 @@ static int truncate_partial_nodes(struct dnode_of_data *dn,
        if (offset[idx + 1] == 0) {
                dn->node_page = pages[idx];
                dn->nid = nid[idx];
-               truncate_node(dn);
+               err = truncate_node(dn);
+               if (err)
+                       goto fail;
        } else {
                f2fs_put_page(pages[idx], 1);
        }
@@ -1014,6 +1127,7 @@ int f2fs_truncate_xattr_node(struct inode *inode)
        nid_t nid = F2FS_I(inode)->i_xattr_nid;
        struct dnode_of_data dn;
        struct page *npage;
+       int err;
 
        if (!nid)
                return 0;
@@ -1022,10 +1136,15 @@ int f2fs_truncate_xattr_node(struct inode *inode)
        if (IS_ERR(npage))
                return PTR_ERR(npage);
 
+       set_new_dnode(&dn, inode, NULL, npage, nid);
+       err = truncate_node(&dn);
+       if (err) {
+               f2fs_put_page(npage, 1);
+               return err;
+       }
+
        f2fs_i_xnid_write(inode, 0);
 
-       set_new_dnode(&dn, inode, NULL, npage, nid);
-       truncate_node(&dn);
        return 0;
 }
 
@@ -1055,11 +1174,19 @@ int f2fs_remove_inode_page(struct inode *inode)
                f2fs_truncate_data_blocks_range(&dn, 1);
 
        /* 0 is possible, after f2fs_new_inode() has failed */
+       if (unlikely(f2fs_cp_error(F2FS_I_SB(inode)))) {
+               f2fs_put_dnode(&dn);
+               return -EIO;
+       }
        f2fs_bug_on(F2FS_I_SB(inode),
                        inode->i_blocks != 0 && inode->i_blocks != 8);
 
        /* will put inode & node pages */
-       truncate_node(&dn);
+       err = truncate_node(&dn);
+       if (err) {
+               f2fs_put_dnode(&dn);
+               return err;
+       }
        return 0;
 }
 
@@ -1092,7 +1219,11 @@ struct page *f2fs_new_node_page(struct dnode_of_data *dn, unsigned int ofs)
                goto fail;
 
 #ifdef CONFIG_F2FS_CHECK_FS
-       f2fs_get_node_info(sbi, dn->nid, &new_ni);
+       err = f2fs_get_node_info(sbi, dn->nid, &new_ni);
+       if (err) {
+               dec_valid_node_count(sbi, dn->inode, !ofs);
+               goto fail;
+       }
        f2fs_bug_on(sbi, new_ni.blk_addr != NULL_ADDR);
 #endif
        new_ni.nid = dn->nid;
@@ -1140,13 +1271,21 @@ static int read_node_page(struct page *page, int op_flags)
                .page = page,
                .encrypted_page = NULL,
        };
+       int err;
 
-       if (PageUptodate(page))
+       if (PageUptodate(page)) {
+#ifdef CONFIG_F2FS_CHECK_FS
+               f2fs_bug_on(sbi, !f2fs_inode_chksum_verify(sbi, page));
+#endif
                return LOCKED_PAGE;
+       }
 
-       f2fs_get_node_info(sbi, page->index, &ni);
+       err = f2fs_get_node_info(sbi, page->index, &ni);
+       if (err)
+               return err;
 
-       if (unlikely(ni.blk_addr == NULL_ADDR)) {
+       if (unlikely(ni.blk_addr == NULL_ADDR) ||
+                       is_sbi_flag_set(sbi, SBI_IS_SHUTDOWN)) {
                ClearPageUptodate(page);
                return -ENOENT;
        }
@@ -1348,7 +1487,7 @@ continue_unlock:
 
 static int __write_node_page(struct page *page, bool atomic, bool *submitted,
                                struct writeback_control *wbc, bool do_balance,
-                               enum iostat_type io_type)
+                               enum iostat_type io_type, unsigned int *seq_id)
 {
        struct f2fs_sb_info *sbi = F2FS_P_SB(page);
        nid_t nid;
@@ -1365,6 +1504,7 @@ static int __write_node_page(struct page *page, bool atomic, bool *submitted,
                .io_type = io_type,
                .io_wbc = wbc,
        };
+       unsigned int seq;
 
        trace_f2fs_writepage(page, NODE);
 
@@ -1374,10 +1514,17 @@ static int __write_node_page(struct page *page, bool atomic, bool *submitted,
        if (unlikely(is_sbi_flag_set(sbi, SBI_POR_DOING)))
                goto redirty_out;
 
+       if (wbc->sync_mode == WB_SYNC_NONE &&
+                       IS_DNODE(page) && is_cold_node(page))
+               goto redirty_out;
+
        /* get old block addr of this node page */
        nid = nid_of_node(page);
        f2fs_bug_on(sbi, page->index != nid);
 
+       if (f2fs_get_node_info(sbi, nid, &ni))
+               goto redirty_out;
+
        if (wbc->for_reclaim) {
                if (!down_read_trylock(&sbi->node_write))
                        goto redirty_out;
@@ -1385,8 +1532,6 @@ static int __write_node_page(struct page *page, bool atomic, bool *submitted,
                down_read(&sbi->node_write);
        }
 
-       f2fs_get_node_info(sbi, nid, &ni);
-
        /* This page is already truncated */
        if (unlikely(ni.blk_addr == NULL_ADDR)) {
                ClearPageUptodate(page);
@@ -1396,11 +1541,22 @@ static int __write_node_page(struct page *page, bool atomic, bool *submitted,
                return 0;
        }
 
+       if (__is_valid_data_blkaddr(ni.blk_addr) &&
+               !f2fs_is_valid_blkaddr(sbi, ni.blk_addr, DATA_GENERIC))
+               goto redirty_out;
+
        if (atomic && !test_opt(sbi, NOBARRIER))
                fio.op_flags |= REQ_PREFLUSH | REQ_FUA;
 
        set_page_writeback(page);
        ClearPageError(page);
+
+       if (f2fs_in_warm_node_list(sbi, page)) {
+               seq = f2fs_add_fsync_node_entry(sbi, page);
+               if (seq_id)
+                       *seq_id = seq;
+       }
+
        fio.old_blkaddr = ni.blk_addr;
        f2fs_do_write_node_page(nid, &fio);
        set_node_addr(sbi, &ni, fio.new_blkaddr, is_fsync_dnode(page));
@@ -1448,7 +1604,7 @@ void f2fs_move_node_page(struct page *node_page, int gc_type)
                        goto out_page;
 
                if (__write_node_page(node_page, false, NULL,
-                                       &wbc, false, FS_GC_NODE_IO))
+                                       &wbc, false, FS_GC_NODE_IO, NULL))
                        unlock_page(node_page);
                goto release_page;
        } else {
@@ -1465,11 +1621,13 @@ release_page:
 static int f2fs_write_node_page(struct page *page,
                                struct writeback_control *wbc)
 {
-       return __write_node_page(page, false, NULL, wbc, false, FS_NODE_IO);
+       return __write_node_page(page, false, NULL, wbc, false,
+                                               FS_NODE_IO, NULL);
 }
 
 int f2fs_fsync_node_pages(struct f2fs_sb_info *sbi, struct inode *inode,
-                       struct writeback_control *wbc, bool atomic)
+                       struct writeback_control *wbc, bool atomic,
+                       unsigned int *seq_id)
 {
        pgoff_t index;
        pgoff_t last_idx = ULONG_MAX;
@@ -1550,7 +1708,7 @@ continue_unlock:
                        ret = __write_node_page(page, atomic &&
                                                page == last_page,
                                                &submitted, wbc, true,
-                                               FS_NODE_IO);
+                                               FS_NODE_IO, seq_id);
                        if (ret) {
                                unlock_page(page);
                                f2fs_put_page(last_page, 0);
@@ -1633,7 +1791,9 @@ next_step:
                                                !is_cold_node(page)))
                                continue;
 lock_node:
-                       if (!trylock_page(page))
+                       if (wbc->sync_mode == WB_SYNC_ALL)
+                               lock_page(page);
+                       else if (!trylock_page(page))
                                continue;
 
                        if (unlikely(page->mapping != NODE_MAPPING(sbi))) {
@@ -1665,7 +1825,7 @@ continue_unlock:
                        set_dentry_mark(page, 0);
 
                        ret = __write_node_page(page, false, &submitted,
-                                               wbc, do_balance, io_type);
+                                               wbc, do_balance, io_type, NULL);
                        if (ret)
                                unlock_page(page);
                        else if (submitted)
@@ -1684,10 +1844,12 @@ continue_unlock:
        }
 
        if (step < 2) {
+               if (wbc->sync_mode == WB_SYNC_NONE && step == 1)
+                       goto out;
                step++;
                goto next_step;
        }
-
+out:
        if (nwritten)
                f2fs_submit_merged_write(sbi, NODE);
 
@@ -1696,35 +1858,46 @@ continue_unlock:
        return ret;
 }
 
-int f2fs_wait_on_node_pages_writeback(struct f2fs_sb_info *sbi, nid_t ino)
+int f2fs_wait_on_node_pages_writeback(struct f2fs_sb_info *sbi,
+                                               unsigned int seq_id)
 {
-       pgoff_t index = 0;
-       struct pagevec pvec;
+       struct fsync_node_entry *fn;
+       struct page *page;
+       struct list_head *head = &sbi->fsync_node_list;
+       unsigned long flags;
+       unsigned int cur_seq_id = 0;
        int ret2, ret = 0;
-       int nr_pages;
 
-       pagevec_init(&pvec);
+       while (seq_id && cur_seq_id < seq_id) {
+               spin_lock_irqsave(&sbi->fsync_node_lock, flags);
+               if (list_empty(head)) {
+                       spin_unlock_irqrestore(&sbi->fsync_node_lock, flags);
+                       break;
+               }
+               fn = list_first_entry(head, struct fsync_node_entry, list);
+               if (fn->seq_id > seq_id) {
+                       spin_unlock_irqrestore(&sbi->fsync_node_lock, flags);
+                       break;
+               }
+               cur_seq_id = fn->seq_id;
+               page = fn->page;
+               get_page(page);
+               spin_unlock_irqrestore(&sbi->fsync_node_lock, flags);
 
-       while ((nr_pages = pagevec_lookup_tag(&pvec, NODE_MAPPING(sbi), &index,
-                               PAGECACHE_TAG_WRITEBACK))) {
-               int i;
+               f2fs_wait_on_page_writeback(page, NODE, true);
+               if (TestClearPageError(page))
+                       ret = -EIO;
 
-               for (i = 0; i < nr_pages; i++) {
-                       struct page *page = pvec.pages[i];
+               put_page(page);
 
-                       if (ino && ino_of_node(page) == ino) {
-                               f2fs_wait_on_page_writeback(page, NODE, true);
-                               if (TestClearPageError(page))
-                                       ret = -EIO;
-                       }
-               }
-               pagevec_release(&pvec);
-               cond_resched();
+               if (ret)
+                       break;
        }
 
        ret2 = filemap_check_errors(NODE_MAPPING(sbi));
        if (!ret)
                ret = ret2;
+
        return ret;
 }
 
@@ -1774,6 +1947,10 @@ static int f2fs_set_node_page_dirty(struct page *page)
 
        if (!PageUptodate(page))
                SetPageUptodate(page);
+#ifdef CONFIG_F2FS_CHECK_FS
+       if (IS_INODE(page))
+               f2fs_inode_chksum_set(F2FS_P_SB(page), page);
+#endif
        if (!PageDirty(page)) {
                __set_page_dirty_nobuffers(page);
                inc_page_count(F2FS_P_SB(page), F2FS_DIRTY_NODES);
@@ -1968,7 +2145,7 @@ static void remove_free_nid(struct f2fs_sb_info *sbi, nid_t nid)
                kmem_cache_free(free_nid_slab, i);
 }
 
-static void scan_nat_page(struct f2fs_sb_info *sbi,
+static int scan_nat_page(struct f2fs_sb_info *sbi,
                        struct page *nat_page, nid_t start_nid)
 {
        struct f2fs_nm_info *nm_i = NM_I(sbi);
@@ -1986,7 +2163,10 @@ static void scan_nat_page(struct f2fs_sb_info *sbi,
                        break;
 
                blk_addr = le32_to_cpu(nat_blk->entries[i].block_addr);
-               f2fs_bug_on(sbi, blk_addr == NEW_ADDR);
+
+               if (blk_addr == NEW_ADDR)
+                       return -EINVAL;
+
                if (blk_addr == NULL_ADDR) {
                        add_free_nid(sbi, start_nid, true, true);
                } else {
@@ -1995,6 +2175,8 @@ static void scan_nat_page(struct f2fs_sb_info *sbi,
                        spin_unlock(&NM_I(sbi)->nid_list_lock);
                }
        }
+
+       return 0;
 }
 
 static void scan_curseg_cache(struct f2fs_sb_info *sbi)
@@ -2050,11 +2232,11 @@ out:
        up_read(&nm_i->nat_tree_lock);
 }
 
-static void __f2fs_build_free_nids(struct f2fs_sb_info *sbi,
+static int __f2fs_build_free_nids(struct f2fs_sb_info *sbi,
                                                bool sync, bool mount)
 {
        struct f2fs_nm_info *nm_i = NM_I(sbi);
-       int i = 0;
+       int i = 0, ret;
        nid_t nid = nm_i->next_scan_nid;
 
        if (unlikely(nid >= nm_i->max_nid))
@@ -2062,17 +2244,17 @@ static void __f2fs_build_free_nids(struct f2fs_sb_info *sbi,
 
        /* Enough entries */
        if (nm_i->nid_cnt[FREE_NID] >= NAT_ENTRY_PER_BLOCK)
-               return;
+               return 0;
 
        if (!sync && !f2fs_available_free_memory(sbi, FREE_NIDS))
-               return;
+               return 0;
 
        if (!mount) {
                /* try to find free nids in free_nid_bitmap */
                scan_free_nid_bits(sbi);
 
                if (nm_i->nid_cnt[FREE_NID] >= NAT_ENTRY_PER_BLOCK)
-                       return;
+                       return 0;
        }
 
        /* readahead nat pages to be scanned */
@@ -2086,8 +2268,16 @@ static void __f2fs_build_free_nids(struct f2fs_sb_info *sbi,
                                                nm_i->nat_block_bitmap)) {
                        struct page *page = get_current_nat_page(sbi, nid);
 
-                       scan_nat_page(sbi, page, nid);
+                       ret = scan_nat_page(sbi, page, nid);
                        f2fs_put_page(page, 1);
+
+                       if (ret) {
+                               up_read(&nm_i->nat_tree_lock);
+                               f2fs_bug_on(sbi, !mount);
+                               f2fs_msg(sbi->sb, KERN_ERR,
+                                       "NAT is corrupt, run fsck to fix it");
+                               return -EINVAL;
+                       }
                }
 
                nid += (NAT_ENTRY_PER_BLOCK - (nid % NAT_ENTRY_PER_BLOCK));
@@ -2108,13 +2298,19 @@ static void __f2fs_build_free_nids(struct f2fs_sb_info *sbi,
 
        f2fs_ra_meta_pages(sbi, NAT_BLOCK_OFFSET(nm_i->next_scan_nid),
                                        nm_i->ra_nid_pages, META_NAT, false);
+
+       return 0;
 }
 
-void f2fs_build_free_nids(struct f2fs_sb_info *sbi, bool sync, bool mount)
+int f2fs_build_free_nids(struct f2fs_sb_info *sbi, bool sync, bool mount)
 {
+       int ret;
+
        mutex_lock(&NM_I(sbi)->build_lock);
-       __f2fs_build_free_nids(sbi, sync, mount);
+       ret = __f2fs_build_free_nids(sbi, sync, mount);
        mutex_unlock(&NM_I(sbi)->build_lock);
+
+       return ret;
 }
 
 /*
@@ -2127,12 +2323,11 @@ bool f2fs_alloc_nid(struct f2fs_sb_info *sbi, nid_t *nid)
        struct f2fs_nm_info *nm_i = NM_I(sbi);
        struct free_nid *i = NULL;
 retry:
-#ifdef CONFIG_F2FS_FAULT_INJECTION
        if (time_to_inject(sbi, FAULT_ALLOC_NID)) {
                f2fs_show_injection_info(FAULT_ALLOC_NID);
                return false;
        }
-#endif
+
        spin_lock(&nm_i->nid_list_lock);
 
        if (unlikely(nm_i->available_nids == 0)) {
@@ -2277,12 +2472,16 @@ int f2fs_recover_xattr_data(struct inode *inode, struct page *page)
        struct dnode_of_data dn;
        struct node_info ni;
        struct page *xpage;
+       int err;
 
        if (!prev_xnid)
                goto recover_xnid;
 
        /* 1: invalidate the previous xattr nid */
-       f2fs_get_node_info(sbi, prev_xnid, &ni);
+       err = f2fs_get_node_info(sbi, prev_xnid, &ni);
+       if (err)
+               return err;
+
        f2fs_invalidate_blocks(sbi, ni.blk_addr);
        dec_valid_node_count(sbi, inode, false);
        set_node_addr(sbi, &ni, NULL_ADDR, false);
@@ -2317,8 +2516,11 @@ int f2fs_recover_inode_page(struct f2fs_sb_info *sbi, struct page *page)
        nid_t ino = ino_of_node(page);
        struct node_info old_ni, new_ni;
        struct page *ipage;
+       int err;
 
-       f2fs_get_node_info(sbi, ino, &old_ni);
+       err = f2fs_get_node_info(sbi, ino, &old_ni);
+       if (err)
+               return err;
 
        if (unlikely(old_ni.blk_addr != NULL_ADDR))
                return -EINVAL;
@@ -2372,7 +2574,7 @@ retry:
        return 0;
 }
 
-void f2fs_restore_node_summary(struct f2fs_sb_info *sbi,
+int f2fs_restore_node_summary(struct f2fs_sb_info *sbi,
                        unsigned int segno, struct f2fs_summary_block *sum)
 {
        struct f2fs_node *rn;
@@ -2394,6 +2596,9 @@ void f2fs_restore_node_summary(struct f2fs_sb_info *sbi,
                for (idx = addr; idx < addr + nrpages; idx++) {
                        struct page *page = f2fs_get_tmp_page(sbi, idx);
 
+                       if (IS_ERR(page))
+                               return PTR_ERR(page);
+
                        rn = F2FS_NODE(page);
                        sum_entry->nid = rn->footer.nid;
                        sum_entry->version = 0;
@@ -2405,6 +2610,7 @@ void f2fs_restore_node_summary(struct f2fs_sb_info *sbi,
                invalidate_mapping_pages(META_MAPPING(sbi), addr,
                                                        addr + nrpages);
        }
+       return 0;
 }
 
 static void remove_nats_in_journal(struct f2fs_sb_info *sbi)
@@ -2582,6 +2788,13 @@ void f2fs_flush_nat_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc)
        nid_t set_idx = 0;
        LIST_HEAD(sets);
 
+       /* during unmount, let's flush nat_bits before checking dirty_nat_cnt */
+       if (enabled_nat_bits(sbi, cpc)) {
+               down_write(&nm_i->nat_tree_lock);
+               remove_nats_in_journal(sbi);
+               up_write(&nm_i->nat_tree_lock);
+       }
+
        if (!nm_i->dirty_nat_cnt)
                return;
 
@@ -2634,7 +2847,13 @@ static int __get_nat_bitmaps(struct f2fs_sb_info *sbi)
        nat_bits_addr = __start_cp_addr(sbi) + sbi->blocks_per_seg -
                                                nm_i->nat_bits_blocks;
        for (i = 0; i < nm_i->nat_bits_blocks; i++) {
-               struct page *page = f2fs_get_meta_page(sbi, nat_bits_addr++);
+               struct page *page;
+
+               page = f2fs_get_meta_page(sbi, nat_bits_addr++);
+               if (IS_ERR(page)) {
+                       disable_nat_bits(sbi, true);
+                       return PTR_ERR(page);
+               }
 
                memcpy(nm_i->nat_bits + (i << F2FS_BLKSIZE_BITS),
                                        page_address(page), F2FS_BLKSIZE);
@@ -2718,6 +2937,7 @@ static int init_node_manager(struct f2fs_sb_info *sbi)
        INIT_RADIX_TREE(&nm_i->nat_root, GFP_NOIO);
        INIT_RADIX_TREE(&nm_i->nat_set_root, GFP_NOIO);
        INIT_LIST_HEAD(&nm_i->nat_entries);
+       spin_lock_init(&nm_i->nat_list_lock);
 
        mutex_init(&nm_i->build_lock);
        spin_lock_init(&nm_i->nid_list_lock);
@@ -2762,8 +2982,8 @@ static int init_free_nid_cache(struct f2fs_sb_info *sbi)
 
        for (i = 0; i < nm_i->nat_blocks; i++) {
                nm_i->free_nid_bitmap[i] = f2fs_kvzalloc(sbi,
-                               NAT_ENTRY_BITMAP_SIZE_ALIGNED, GFP_KERNEL);
-               if (!nm_i->free_nid_bitmap)
+                       f2fs_bitmap_size(NAT_ENTRY_PER_BLOCK), GFP_KERNEL);
+               if (!nm_i->free_nid_bitmap[i])
                        return -ENOMEM;
        }
 
@@ -2801,8 +3021,7 @@ int f2fs_build_node_manager(struct f2fs_sb_info *sbi)
        /* load free nid status from nat_bits table */
        load_free_nid_bitmap(sbi);
 
-       f2fs_build_free_nids(sbi, true, true);
-       return 0;
+       return f2fs_build_free_nids(sbi, true, true);
 }
 
 void f2fs_destroy_node_manager(struct f2fs_sb_info *sbi)
@@ -2837,8 +3056,13 @@ void f2fs_destroy_node_manager(struct f2fs_sb_info *sbi)
                unsigned idx;
 
                nid = nat_get_nid(natvec[found - 1]) + 1;
-               for (idx = 0; idx < found; idx++)
+               for (idx = 0; idx < found; idx++) {
+                       spin_lock(&nm_i->nat_list_lock);
+                       list_del(&natvec[idx]->list);
+                       spin_unlock(&nm_i->nat_list_lock);
+
                        __del_from_nat_cache(nm_i, natvec[idx]);
+               }
        }
        f2fs_bug_on(sbi, nm_i->nat_cnt);
 
@@ -2893,8 +3117,15 @@ int __init f2fs_create_node_manager_caches(void)
                        sizeof(struct nat_entry_set));
        if (!nat_entry_set_slab)
                goto destroy_free_nid;
+
+       fsync_node_entry_slab = f2fs_kmem_cache_create("fsync_node_entry",
+                       sizeof(struct fsync_node_entry));
+       if (!fsync_node_entry_slab)
+               goto destroy_nat_entry_set;
        return 0;
 
+destroy_nat_entry_set:
+       kmem_cache_destroy(nat_entry_set_slab);
 destroy_free_nid:
        kmem_cache_destroy(free_nid_slab);
 destroy_nat_entry:
@@ -2905,6 +3136,7 @@ fail:
 
 void f2fs_destroy_node_manager_caches(void)
 {
+       kmem_cache_destroy(fsync_node_entry_slab);
        kmem_cache_destroy(nat_entry_set_slab);
        kmem_cache_destroy(free_nid_slab);
        kmem_cache_destroy(nat_entry_slab);
index b95e49e..0f4db7a 100644 (file)
@@ -135,6 +135,11 @@ static inline bool excess_cached_nats(struct f2fs_sb_info *sbi)
        return NM_I(sbi)->nat_cnt >= DEF_NAT_CACHE_THRESHOLD;
 }
 
+static inline bool excess_dirty_nodes(struct f2fs_sb_info *sbi)
+{
+       return get_pages(sbi, F2FS_DIRTY_NODES) >= sbi->blocks_per_seg * 8;
+}
+
 enum mem_type {
        FREE_NIDS,      /* indicates the free nid list */
        NAT_ENTRIES,    /* indicates the cached nat entry */
@@ -444,6 +449,10 @@ static inline void set_mark(struct page *page, int mark, int type)
        else
                flag &= ~(0x1 << type);
        rn->footer.flag = cpu_to_le32(flag);
+
+#ifdef CONFIG_F2FS_CHECK_FS
+       f2fs_inode_chksum_set(F2FS_P_SB(page), page);
+#endif
 }
 #define set_dentry_mark(page, mark)    set_mark(page, mark, DENT_BIT_SHIFT)
 #define set_fsync_mark(page, mark)     set_mark(page, mark, FSYNC_BIT_SHIFT)
index 38f25f0..95511ed 100644 (file)
@@ -241,8 +241,8 @@ static int find_fsync_dnodes(struct f2fs_sb_info *sbi, struct list_head *head,
        struct page *page = NULL;
        block_t blkaddr;
        unsigned int loop_cnt = 0;
-       unsigned int free_blocks = sbi->user_block_count -
-                                       valid_user_blocks(sbi);
+       unsigned int free_blocks = MAIN_SEGS(sbi) * sbi->blocks_per_seg -
+                                               valid_user_blocks(sbi);
        int err = 0;
 
        /* get node pages in the current segment */
@@ -252,10 +252,14 @@ static int find_fsync_dnodes(struct f2fs_sb_info *sbi, struct list_head *head,
        while (1) {
                struct fsync_inode_entry *entry;
 
-               if (!f2fs_is_valid_meta_blkaddr(sbi, blkaddr, META_POR))
+               if (!f2fs_is_valid_blkaddr(sbi, blkaddr, META_POR))
                        return 0;
 
                page = f2fs_get_tmp_page(sbi, blkaddr);
+               if (IS_ERR(page)) {
+                       err = PTR_ERR(page);
+                       break;
+               }
 
                if (!is_recoverable_dnode(page))
                        break;
@@ -471,7 +475,10 @@ retry_dn:
 
        f2fs_wait_on_page_writeback(dn.node_page, NODE, true);
 
-       f2fs_get_node_info(sbi, dn.nid, &ni);
+       err = f2fs_get_node_info(sbi, dn.nid, &ni);
+       if (err)
+               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));
 
@@ -507,14 +514,13 @@ retry_dn:
                }
 
                /* dest is valid block, try to recover from src to dest */
-               if (f2fs_is_valid_meta_blkaddr(sbi, dest, META_POR)) {
+               if (f2fs_is_valid_blkaddr(sbi, dest, META_POR)) {
 
                        if (src == NULL_ADDR) {
                                err = f2fs_reserve_new_block(&dn);
-#ifdef CONFIG_F2FS_FAULT_INJECTION
-                               while (err)
+                               while (err &&
+                                      IS_ENABLED(CONFIG_F2FS_FAULT_INJECTION))
                                        err = f2fs_reserve_new_block(&dn);
-#endif
                                /* We should not get -ENOSPC */
                                f2fs_bug_on(sbi, err);
                                if (err)
@@ -568,12 +574,16 @@ static int recover_data(struct f2fs_sb_info *sbi, struct list_head *inode_list,
        while (1) {
                struct fsync_inode_entry *entry;
 
-               if (!f2fs_is_valid_meta_blkaddr(sbi, blkaddr, META_POR))
+               if (!f2fs_is_valid_blkaddr(sbi, blkaddr, META_POR))
                        break;
 
                f2fs_ra_meta_pages_cond(sbi, blkaddr);
 
                page = f2fs_get_tmp_page(sbi, blkaddr);
+               if (IS_ERR(page)) {
+                       err = PTR_ERR(page);
+                       break;
+               }
 
                if (!is_recoverable_dnode(page)) {
                        f2fs_put_page(page, 1);
@@ -628,7 +638,8 @@ int f2fs_recover_fsync_data(struct f2fs_sb_info *sbi, bool check_only)
 #endif
 
        if (s_flags & SB_RDONLY) {
-               f2fs_msg(sbi->sb, KERN_INFO, "orphan cleanup on readonly fs");
+               f2fs_msg(sbi->sb, KERN_INFO,
+                               "recover fsync data on readonly fs");
                sbi->sb->s_flags &= ~SB_RDONLY;
        }
 
index 9efce17..30779aa 100644 (file)
@@ -250,7 +250,13 @@ retry:
                                err = -EAGAIN;
                                goto next;
                        }
-                       f2fs_get_node_info(sbi, dn.nid, &ni);
+
+                       err = f2fs_get_node_info(sbi, dn.nid, &ni);
+                       if (err) {
+                               f2fs_put_dnode(&dn);
+                               return err;
+                       }
+
                        if (cur->old_addr == NEW_ADDR) {
                                f2fs_invalidate_blocks(sbi, dn.data_blkaddr);
                                f2fs_update_data_blkaddr(&dn, NEW_ADDR);
@@ -439,8 +445,10 @@ int f2fs_commit_inmem_pages(struct inode *inode)
        int err;
 
        f2fs_balance_fs(sbi, true);
-       f2fs_lock_op(sbi);
 
+       down_write(&fi->i_gc_rwsem[WRITE]);
+
+       f2fs_lock_op(sbi);
        set_inode_flag(inode, FI_ATOMIC_COMMIT);
 
        mutex_lock(&fi->inmem_lock);
@@ -455,6 +463,8 @@ int f2fs_commit_inmem_pages(struct inode *inode)
        clear_inode_flag(inode, FI_ATOMIC_COMMIT);
 
        f2fs_unlock_op(sbi);
+       up_write(&fi->i_gc_rwsem[WRITE]);
+
        return err;
 }
 
@@ -464,12 +474,10 @@ int f2fs_commit_inmem_pages(struct inode *inode)
  */
 void f2fs_balance_fs(struct f2fs_sb_info *sbi, bool need)
 {
-#ifdef CONFIG_F2FS_FAULT_INJECTION
        if (time_to_inject(sbi, FAULT_CHECKPOINT)) {
                f2fs_show_injection_info(FAULT_CHECKPOINT);
                f2fs_stop_checkpoint(sbi, false);
        }
-#endif
 
        /* balance_fs_bg is able to be pending */
        if (need && excess_cached_nats(sbi))
@@ -503,7 +511,8 @@ void f2fs_balance_fs_bg(struct f2fs_sb_info *sbi)
        else
                f2fs_build_free_nids(sbi, false, false);
 
-       if (!is_idle(sbi) && !excess_dirty_nats(sbi))
+       if (!is_idle(sbi) &&
+               (!excess_dirty_nats(sbi) && !excess_dirty_nodes(sbi)))
                return;
 
        /* checkpoint is the only way to shrink partial cached entries */
@@ -511,6 +520,7 @@ void f2fs_balance_fs_bg(struct f2fs_sb_info *sbi)
                        !f2fs_available_free_memory(sbi, INO_ENTRIES) ||
                        excess_prefree_segs(sbi) ||
                        excess_dirty_nats(sbi) ||
+                       excess_dirty_nodes(sbi) ||
                        f2fs_time_over(sbi, CP_TIME)) {
                if (test_opt(sbi, DATA_FLUSH)) {
                        struct blk_plug plug;
@@ -831,9 +841,12 @@ static struct discard_cmd *__create_discard_cmd(struct f2fs_sb_info *sbi,
        dc->len = len;
        dc->ref = 0;
        dc->state = D_PREP;
+       dc->issuing = 0;
        dc->error = 0;
        init_completion(&dc->wait);
        list_add_tail(&dc->list, pend_list);
+       spin_lock_init(&dc->lock);
+       dc->bio_ref = 0;
        atomic_inc(&dcc->discard_cmd_cnt);
        dcc->undiscard_blks += len;
 
@@ -860,7 +873,7 @@ static void __detach_discard_cmd(struct discard_cmd_control *dcc,
                                                        struct discard_cmd *dc)
 {
        if (dc->state == D_DONE)
-               atomic_dec(&dcc->issing_discard);
+               atomic_sub(dc->issuing, &dcc->issing_discard);
 
        list_del(&dc->list);
        rb_erase(&dc->rb_node, &dcc->root);
@@ -875,9 +888,17 @@ static void __remove_discard_cmd(struct f2fs_sb_info *sbi,
                                                        struct discard_cmd *dc)
 {
        struct discard_cmd_control *dcc = SM_I(sbi)->dcc_info;
+       unsigned long flags;
 
        trace_f2fs_remove_discard(dc->bdev, dc->start, dc->len);
 
+       spin_lock_irqsave(&dc->lock, flags);
+       if (dc->bio_ref) {
+               spin_unlock_irqrestore(&dc->lock, flags);
+               return;
+       }
+       spin_unlock_irqrestore(&dc->lock, flags);
+
        f2fs_bug_on(sbi, dc->ref);
 
        if (dc->error == -EOPNOTSUPP)
@@ -893,10 +914,17 @@ static void __remove_discard_cmd(struct f2fs_sb_info *sbi,
 static void f2fs_submit_discard_endio(struct bio *bio)
 {
        struct discard_cmd *dc = (struct discard_cmd *)bio->bi_private;
+       unsigned long flags;
 
        dc->error = blk_status_to_errno(bio->bi_status);
-       dc->state = D_DONE;
-       complete_all(&dc->wait);
+
+       spin_lock_irqsave(&dc->lock, flags);
+       dc->bio_ref--;
+       if (!dc->bio_ref && dc->state == D_SUBMIT) {
+               dc->state = D_DONE;
+               complete_all(&dc->wait);
+       }
+       spin_unlock_irqrestore(&dc->lock, flags);
        bio_put(bio);
 }
 
@@ -934,6 +962,7 @@ static void __init_discard_policy(struct f2fs_sb_info *sbi,
        /* common policy */
        dpolicy->type = discard_type;
        dpolicy->sync = true;
+       dpolicy->ordered = false;
        dpolicy->granularity = granularity;
 
        dpolicy->max_requests = DEF_MAX_DISCARD_REQUEST;
@@ -945,6 +974,7 @@ static void __init_discard_policy(struct f2fs_sb_info *sbi,
                dpolicy->max_interval = DEF_MAX_DISCARD_ISSUE_TIME;
                dpolicy->io_aware = true;
                dpolicy->sync = false;
+               dpolicy->ordered = true;
                if (utilization(sbi) > DEF_DISCARD_URGENT_UTIL) {
                        dpolicy->granularity = 1;
                        dpolicy->max_interval = DEF_MIN_DISCARD_ISSUE_TIME;
@@ -962,48 +992,115 @@ static void __init_discard_policy(struct f2fs_sb_info *sbi,
        }
 }
 
-
+static void __update_discard_tree_range(struct f2fs_sb_info *sbi,
+                               struct block_device *bdev, block_t lstart,
+                               block_t start, block_t len);
 /* this function is copied from blkdev_issue_discard from block/blk-lib.c */
-static void __submit_discard_cmd(struct f2fs_sb_info *sbi,
+static int __submit_discard_cmd(struct f2fs_sb_info *sbi,
                                                struct discard_policy *dpolicy,
-                                               struct discard_cmd *dc)
+                                               struct discard_cmd *dc,
+                                               unsigned int *issued)
 {
+       struct block_device *bdev = dc->bdev;
+       struct request_queue *q = bdev_get_queue(bdev);
+       unsigned int max_discard_blocks =
+                       SECTOR_TO_BLOCK(q->limits.max_discard_sectors);
        struct discard_cmd_control *dcc = SM_I(sbi)->dcc_info;
        struct list_head *wait_list = (dpolicy->type == DPOLICY_FSTRIM) ?
                                        &(dcc->fstrim_list) : &(dcc->wait_list);
-       struct bio *bio = NULL;
        int flag = dpolicy->sync ? REQ_SYNC : 0;
+       block_t lstart, start, len, total_len;
+       int err = 0;
 
        if (dc->state != D_PREP)
-               return;
+               return 0;
 
        if (is_sbi_flag_set(sbi, SBI_NEED_FSCK))
-               return;
+               return 0;
 
-       trace_f2fs_issue_discard(dc->bdev, dc->start, dc->len);
+       trace_f2fs_issue_discard(bdev, dc->start, dc->len);
 
-       dc->error = __blkdev_issue_discard(dc->bdev,
-                               SECTOR_FROM_BLOCK(dc->start),
-                               SECTOR_FROM_BLOCK(dc->len),
-                               GFP_NOFS, 0, &bio);
-       if (!dc->error) {
-               /* should keep before submission to avoid D_DONE right away */
-               dc->state = D_SUBMIT;
-               atomic_inc(&dcc->issued_discard);
-               atomic_inc(&dcc->issing_discard);
-               if (bio) {
-                       bio->bi_private = dc;
-                       bio->bi_end_io = f2fs_submit_discard_endio;
-                       bio->bi_opf |= flag;
-                       submit_bio(bio);
-                       list_move_tail(&dc->list, wait_list);
-                       __check_sit_bitmap(sbi, dc->start, dc->start + dc->len);
-
-                       f2fs_update_iostat(sbi, FS_DISCARD, 1);
+       lstart = dc->lstart;
+       start = dc->start;
+       len = dc->len;
+       total_len = len;
+
+       dc->len = 0;
+
+       while (total_len && *issued < dpolicy->max_requests && !err) {
+               struct bio *bio = NULL;
+               unsigned long flags;
+               bool last = true;
+
+               if (len > max_discard_blocks) {
+                       len = max_discard_blocks;
+                       last = false;
                }
-       } else {
-               __remove_discard_cmd(sbi, dc);
+
+               (*issued)++;
+               if (*issued == dpolicy->max_requests)
+                       last = true;
+
+               dc->len += len;
+
+               if (time_to_inject(sbi, FAULT_DISCARD)) {
+                       f2fs_show_injection_info(FAULT_DISCARD);
+                       err = -EIO;
+                       goto submit;
+               }
+               err = __blkdev_issue_discard(bdev,
+                                       SECTOR_FROM_BLOCK(start),
+                                       SECTOR_FROM_BLOCK(len),
+                                       GFP_NOFS, 0, &bio);
+submit:
+               if (err) {
+                       spin_lock_irqsave(&dc->lock, flags);
+                       if (dc->state == D_PARTIAL)
+                               dc->state = D_SUBMIT;
+                       spin_unlock_irqrestore(&dc->lock, flags);
+
+                       break;
+               }
+
+               f2fs_bug_on(sbi, !bio);
+
+               /*
+                * should keep before submission to avoid D_DONE
+                * right away
+                */
+               spin_lock_irqsave(&dc->lock, flags);
+               if (last)
+                       dc->state = D_SUBMIT;
+               else
+                       dc->state = D_PARTIAL;
+               dc->bio_ref++;
+               spin_unlock_irqrestore(&dc->lock, flags);
+
+               atomic_inc(&dcc->issing_discard);
+               dc->issuing++;
+               list_move_tail(&dc->list, wait_list);
+
+               /* sanity check on discard range */
+               __check_sit_bitmap(sbi, start, start + len);
+
+               bio->bi_private = dc;
+               bio->bi_end_io = f2fs_submit_discard_endio;
+               bio->bi_opf |= flag;
+               submit_bio(bio);
+
+               atomic_inc(&dcc->issued_discard);
+
+               f2fs_update_iostat(sbi, FS_DISCARD, 1);
+
+               lstart += len;
+               start += len;
+               total_len -= len;
+               len = total_len;
        }
+
+       if (!err && len)
+               __update_discard_tree_range(sbi, bdev, lstart, start, len);
+       return err;
 }
 
 static struct discard_cmd *__insert_discard_tree(struct f2fs_sb_info *sbi,
@@ -1084,10 +1181,11 @@ static void __update_discard_tree_range(struct f2fs_sb_info *sbi,
        struct discard_cmd *dc;
        struct discard_info di = {0};
        struct rb_node **insert_p = NULL, *insert_parent = NULL;
+       struct request_queue *q = bdev_get_queue(bdev);
+       unsigned int max_discard_blocks =
+                       SECTOR_TO_BLOCK(q->limits.max_discard_sectors);
        block_t end = lstart + len;
 
-       mutex_lock(&dcc->cmd_lock);
-
        dc = (struct discard_cmd *)f2fs_lookup_rb_tree_ret(&dcc->root,
                                        NULL, lstart,
                                        (struct rb_entry **)&prev_dc,
@@ -1127,7 +1225,8 @@ static void __update_discard_tree_range(struct f2fs_sb_info *sbi,
 
                if (prev_dc && prev_dc->state == D_PREP &&
                        prev_dc->bdev == bdev &&
-                       __is_discard_back_mergeable(&di, &prev_dc->di)) {
+                       __is_discard_back_mergeable(&di, &prev_dc->di,
+                                                       max_discard_blocks)) {
                        prev_dc->di.len += di.len;
                        dcc->undiscard_blks += di.len;
                        __relocate_discard_cmd(dcc, prev_dc);
@@ -1138,7 +1237,8 @@ static void __update_discard_tree_range(struct f2fs_sb_info *sbi,
 
                if (next_dc && next_dc->state == D_PREP &&
                        next_dc->bdev == bdev &&
-                       __is_discard_front_mergeable(&di, &next_dc->di)) {
+                       __is_discard_front_mergeable(&di, &next_dc->di,
+                                                       max_discard_blocks)) {
                        next_dc->di.lstart = di.lstart;
                        next_dc->di.len += di.len;
                        next_dc->di.start = di.start;
@@ -1161,8 +1261,6 @@ static void __update_discard_tree_range(struct f2fs_sb_info *sbi,
                node = rb_next(&prev_dc->rb_node);
                next_dc = rb_entry_safe(node, struct discard_cmd, rb_node);
        }
-
-       mutex_unlock(&dcc->cmd_lock);
 }
 
 static int __queue_discard_cmd(struct f2fs_sb_info *sbi,
@@ -1177,10 +1275,72 @@ static int __queue_discard_cmd(struct f2fs_sb_info *sbi,
 
                blkstart -= FDEV(devi).start_blk;
        }
+       mutex_lock(&SM_I(sbi)->dcc_info->cmd_lock);
        __update_discard_tree_range(sbi, bdev, lblkstart, blkstart, blklen);
+       mutex_unlock(&SM_I(sbi)->dcc_info->cmd_lock);
        return 0;
 }
 
+static unsigned int __issue_discard_cmd_orderly(struct f2fs_sb_info *sbi,
+                                       struct discard_policy *dpolicy)
+{
+       struct discard_cmd_control *dcc = SM_I(sbi)->dcc_info;
+       struct discard_cmd *prev_dc = NULL, *next_dc = NULL;
+       struct rb_node **insert_p = NULL, *insert_parent = NULL;
+       struct discard_cmd *dc;
+       struct blk_plug plug;
+       unsigned int pos = dcc->next_pos;
+       unsigned int issued = 0;
+       bool io_interrupted = false;
+
+       mutex_lock(&dcc->cmd_lock);
+       dc = (struct discard_cmd *)f2fs_lookup_rb_tree_ret(&dcc->root,
+                                       NULL, pos,
+                                       (struct rb_entry **)&prev_dc,
+                                       (struct rb_entry **)&next_dc,
+                                       &insert_p, &insert_parent, true);
+       if (!dc)
+               dc = next_dc;
+
+       blk_start_plug(&plug);
+
+       while (dc) {
+               struct rb_node *node;
+               int err = 0;
+
+               if (dc->state != D_PREP)
+                       goto next;
+
+               if (dpolicy->io_aware && !is_idle(sbi)) {
+                       io_interrupted = true;
+                       break;
+               }
+
+               dcc->next_pos = dc->lstart + dc->len;
+               err = __submit_discard_cmd(sbi, dpolicy, dc, &issued);
+
+               if (issued >= dpolicy->max_requests)
+                       break;
+next:
+               node = rb_next(&dc->rb_node);
+               if (err)
+                       __remove_discard_cmd(sbi, dc);
+               dc = rb_entry_safe(node, struct discard_cmd, rb_node);
+       }
+
+       blk_finish_plug(&plug);
+
+       if (!dc)
+               dcc->next_pos = 0;
+
+       mutex_unlock(&dcc->cmd_lock);
+
+       if (!issued && io_interrupted)
+               issued = -1;
+
+       return issued;
+}
+
 static int __issue_discard_cmd(struct f2fs_sb_info *sbi,
                                        struct discard_policy *dpolicy)
 {
@@ -1188,19 +1348,24 @@ static int __issue_discard_cmd(struct f2fs_sb_info *sbi,
        struct list_head *pend_list;
        struct discard_cmd *dc, *tmp;
        struct blk_plug plug;
-       int i, iter = 0, issued = 0;
+       int i, issued = 0;
        bool io_interrupted = false;
 
        for (i = MAX_PLIST_NUM - 1; i >= 0; i--) {
                if (i + 1 < dpolicy->granularity)
                        break;
+
+               if (i < DEFAULT_DISCARD_GRANULARITY && dpolicy->ordered)
+                       return __issue_discard_cmd_orderly(sbi, dpolicy);
+
                pend_list = &dcc->pend_list[i];
 
                mutex_lock(&dcc->cmd_lock);
                if (list_empty(pend_list))
                        goto next;
-               f2fs_bug_on(sbi,
-                       !f2fs_check_rb_tree_consistence(sbi, &dcc->root));
+               if (unlikely(dcc->rbtree_check))
+                       f2fs_bug_on(sbi, !f2fs_check_rb_tree_consistence(sbi,
+                                                               &dcc->root));
                blk_start_plug(&plug);
                list_for_each_entry_safe(dc, tmp, pend_list, list) {
                        f2fs_bug_on(sbi, dc->state != D_PREP);
@@ -1208,20 +1373,19 @@ static int __issue_discard_cmd(struct f2fs_sb_info *sbi,
                        if (dpolicy->io_aware && i < dpolicy->io_aware_gran &&
                                                                !is_idle(sbi)) {
                                io_interrupted = true;
-                               goto skip;
+                               break;
                        }
 
-                       __submit_discard_cmd(sbi, dpolicy, dc);
-                       issued++;
-skip:
-                       if (++iter >= dpolicy->max_requests)
+                       __submit_discard_cmd(sbi, dpolicy, dc, &issued);
+
+                       if (issued >= dpolicy->max_requests)
                                break;
                }
                blk_finish_plug(&plug);
 next:
                mutex_unlock(&dcc->cmd_lock);
 
-               if (iter >= dpolicy->max_requests)
+               if (issued >= dpolicy->max_requests || io_interrupted)
                        break;
        }
 
@@ -1319,21 +1483,22 @@ next:
        return trimmed;
 }
 
-static void __wait_all_discard_cmd(struct f2fs_sb_info *sbi,
+static unsigned int __wait_all_discard_cmd(struct f2fs_sb_info *sbi,
                                                struct discard_policy *dpolicy)
 {
        struct discard_policy dp;
+       unsigned int discard_blks;
 
-       if (dpolicy) {
-               __wait_discard_cmd_range(sbi, dpolicy, 0, UINT_MAX);
-               return;
-       }
+       if (dpolicy)
+               return __wait_discard_cmd_range(sbi, dpolicy, 0, UINT_MAX);
 
        /* wait all */
        __init_discard_policy(sbi, &dp, DPOLICY_FSTRIM, 1);
-       __wait_discard_cmd_range(sbi, &dp, 0, UINT_MAX);
+       discard_blks = __wait_discard_cmd_range(sbi, &dp, 0, UINT_MAX);
        __init_discard_policy(sbi, &dp, DPOLICY_UMOUNT, 1);
-       __wait_discard_cmd_range(sbi, &dp, 0, UINT_MAX);
+       discard_blks += __wait_discard_cmd_range(sbi, &dp, 0, UINT_MAX);
+
+       return discard_blks;
 }
 
 /* This should be covered by global mutex, &sit_i->sentry_lock */
@@ -1386,6 +1551,8 @@ bool f2fs_wait_discard_bios(struct f2fs_sb_info *sbi)
 
        /* just to make sure there is no pending discard commands */
        __wait_all_discard_cmd(sbi, NULL);
+
+       f2fs_bug_on(sbi, atomic_read(&dcc->discard_cmd_cnt));
        return dropped;
 }
 
@@ -1643,21 +1810,30 @@ void f2fs_clear_prefree_segments(struct f2fs_sb_info *sbi,
        unsigned int start = 0, end = -1;
        unsigned int secno, start_segno;
        bool force = (cpc->reason & CP_DISCARD);
+       bool need_align = test_opt(sbi, LFS) && sbi->segs_per_sec > 1;
 
        mutex_lock(&dirty_i->seglist_lock);
 
        while (1) {
                int i;
+
+               if (need_align && end != -1)
+                       end--;
                start = find_next_bit(prefree_map, MAIN_SEGS(sbi), end + 1);
                if (start >= MAIN_SEGS(sbi))
                        break;
                end = find_next_zero_bit(prefree_map, MAIN_SEGS(sbi),
                                                                start + 1);
 
-               for (i = start; i < end; i++)
-                       clear_bit(i, prefree_map);
+               if (need_align) {
+                       start = rounddown(start, sbi->segs_per_sec);
+                       end = roundup(end, sbi->segs_per_sec);
+               }
 
-               dirty_i->nr_dirty[PRE] -= end - start;
+               for (i = start; i < end; i++) {
+                       if (test_and_clear_bit(i, prefree_map))
+                               dirty_i->nr_dirty[PRE]--;
+               }
 
                if (!test_opt(sbi, DISCARD))
                        continue;
@@ -1751,7 +1927,9 @@ static int create_discard_cmd_control(struct f2fs_sb_info *sbi)
        dcc->nr_discards = 0;
        dcc->max_discards = MAIN_SEGS(sbi) << sbi->log_blocks_per_seg;
        dcc->undiscard_blks = 0;
+       dcc->next_pos = 0;
        dcc->root = RB_ROOT;
+       dcc->rbtree_check = false;
 
        init_waitqueue_head(&dcc->discard_wait_queue);
        SM_I(sbi)->dcc_info = dcc;
@@ -1901,6 +2079,8 @@ void f2fs_invalidate_blocks(struct f2fs_sb_info *sbi, block_t addr)
        if (addr == NEW_ADDR)
                return;
 
+       invalidate_mapping_pages(META_MAPPING(sbi), addr, addr);
+
        /* add it into sit main buffer */
        down_write(&sit_i->sentry_lock);
 
@@ -1919,7 +2099,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_blkaddr(blkaddr))
+       if (!is_valid_data_blkaddr(sbi, blkaddr))
                return true;
 
        down_read(&sit_i->sentry_lock);
@@ -1983,7 +2163,7 @@ int f2fs_npages_for_summary_flush(struct f2fs_sb_info *sbi, bool for_ra)
  */
 struct page *f2fs_get_sum_page(struct f2fs_sb_info *sbi, unsigned int segno)
 {
-       return f2fs_get_meta_page(sbi, GET_SUM_BLOCK(sbi, segno));
+       return f2fs_get_meta_page_nofail(sbi, GET_SUM_BLOCK(sbi, segno));
 }
 
 void f2fs_update_meta_page(struct f2fs_sb_info *sbi,
@@ -2366,7 +2546,7 @@ bool f2fs_exist_trim_candidates(struct f2fs_sb_info *sbi,
        return has_candidate;
 }
 
-static void __issue_discard_cmd_range(struct f2fs_sb_info *sbi,
+static unsigned int __issue_discard_cmd_range(struct f2fs_sb_info *sbi,
                                        struct discard_policy *dpolicy,
                                        unsigned int start, unsigned int end)
 {
@@ -2376,12 +2556,15 @@ static void __issue_discard_cmd_range(struct f2fs_sb_info *sbi,
        struct discard_cmd *dc;
        struct blk_plug plug;
        int issued;
+       unsigned int trimmed = 0;
 
 next:
        issued = 0;
 
        mutex_lock(&dcc->cmd_lock);
-       f2fs_bug_on(sbi, !f2fs_check_rb_tree_consistence(sbi, &dcc->root));
+       if (unlikely(dcc->rbtree_check))
+               f2fs_bug_on(sbi, !f2fs_check_rb_tree_consistence(sbi,
+                                                               &dcc->root));
 
        dc = (struct discard_cmd *)f2fs_lookup_rb_tree_ret(&dcc->root,
                                        NULL, start,
@@ -2395,6 +2578,7 @@ next:
 
        while (dc && dc->lstart <= end) {
                struct rb_node *node;
+               int err = 0;
 
                if (dc->len < dpolicy->granularity)
                        goto skip;
@@ -2404,19 +2588,24 @@ next:
                        goto skip;
                }
 
-               __submit_discard_cmd(sbi, dpolicy, dc);
+               err = __submit_discard_cmd(sbi, dpolicy, dc, &issued);
 
-               if (++issued >= dpolicy->max_requests) {
+               if (issued >= dpolicy->max_requests) {
                        start = dc->lstart + dc->len;
 
+                       if (err)
+                               __remove_discard_cmd(sbi, dc);
+
                        blk_finish_plug(&plug);
                        mutex_unlock(&dcc->cmd_lock);
-                       __wait_all_discard_cmd(sbi, NULL);
+                       trimmed += __wait_all_discard_cmd(sbi, NULL);
                        congestion_wait(BLK_RW_ASYNC, HZ/50);
                        goto next;
                }
 skip:
                node = rb_next(&dc->rb_node);
+               if (err)
+                       __remove_discard_cmd(sbi, dc);
                dc = rb_entry_safe(node, struct discard_cmd, rb_node);
 
                if (fatal_signal_pending(current))
@@ -2425,6 +2614,8 @@ skip:
 
        blk_finish_plug(&plug);
        mutex_unlock(&dcc->cmd_lock);
+
+       return trimmed;
 }
 
 int f2fs_trim_fs(struct f2fs_sb_info *sbi, struct fstrim_range *range)
@@ -2437,12 +2628,13 @@ int f2fs_trim_fs(struct f2fs_sb_info *sbi, struct fstrim_range *range)
        struct discard_policy dpolicy;
        unsigned long long trimmed = 0;
        int err = 0;
+       bool need_align = test_opt(sbi, LFS) && sbi->segs_per_sec > 1;
 
        if (start >= MAX_BLKADDR(sbi) || range->len < sbi->blocksize)
                return -EINVAL;
 
-       if (end <= MAIN_BLKADDR(sbi))
-               return -EINVAL;
+       if (end < MAIN_BLKADDR(sbi))
+               goto out;
 
        if (is_sbi_flag_set(sbi, SBI_NEED_FSCK)) {
                f2fs_msg(sbi->sb, KERN_WARNING,
@@ -2454,6 +2646,10 @@ int f2fs_trim_fs(struct f2fs_sb_info *sbi, struct fstrim_range *range)
        start_segno = (start <= MAIN_BLKADDR(sbi)) ? 0 : GET_SEGNO(sbi, start);
        end_segno = (end >= MAX_BLKADDR(sbi)) ? MAIN_SEGS(sbi) - 1 :
                                                GET_SEGNO(sbi, end);
+       if (need_align) {
+               start_segno = rounddown(start_segno, sbi->segs_per_sec);
+               end_segno = roundup(end_segno + 1, sbi->segs_per_sec) - 1;
+       }
 
        cpc.reason = CP_DISCARD;
        cpc.trim_minlen = max_t(__u64, 1, F2FS_BYTES_TO_BLK(range->minlen));
@@ -2469,24 +2665,27 @@ int f2fs_trim_fs(struct f2fs_sb_info *sbi, struct fstrim_range *range)
        if (err)
                goto out;
 
-       start_block = START_BLOCK(sbi, start_segno);
-       end_block = START_BLOCK(sbi, end_segno + 1);
-
-       __init_discard_policy(sbi, &dpolicy, DPOLICY_FSTRIM, cpc.trim_minlen);
-       __issue_discard_cmd_range(sbi, &dpolicy, start_block, end_block);
-
        /*
         * We filed discard candidates, but actually we don't need to wait for
         * all of them, since they'll be issued in idle time along with runtime
         * discard option. User configuration looks like using runtime discard
         * or periodic fstrim instead of it.
         */
-       if (!test_opt(sbi, DISCARD)) {
-               trimmed = __wait_discard_cmd_range(sbi, &dpolicy,
+       if (test_opt(sbi, DISCARD))
+               goto out;
+
+       start_block = START_BLOCK(sbi, start_segno);
+       end_block = START_BLOCK(sbi, end_segno + 1);
+
+       __init_discard_policy(sbi, &dpolicy, DPOLICY_FSTRIM, cpc.trim_minlen);
+       trimmed = __issue_discard_cmd_range(sbi, &dpolicy,
+                                       start_block, end_block);
+
+       trimmed += __wait_discard_cmd_range(sbi, &dpolicy,
                                        start_block, end_block);
-               range->len = F2FS_BLK_TO_BYTES(trimmed);
-       }
 out:
+       if (!err)
+               range->len = F2FS_BLK_TO_BYTES(trimmed);
        return err;
 }
 
@@ -2639,8 +2838,8 @@ static int __get_segment_type_6(struct f2fs_io_info *fio)
                        return CURSEG_COLD_DATA;
                if (file_is_hot(inode) ||
                                is_inode_flag_set(inode, FI_HOT_DATA) ||
-                               is_inode_flag_set(inode, FI_ATOMIC_FILE) ||
-                               is_inode_flag_set(inode, FI_VOLATILE_FILE))
+                               f2fs_is_atomic_file(inode) ||
+                               f2fs_is_volatile_file(inode))
                        return CURSEG_HOT_DATA;
                return f2fs_rw_hint_to_seg_type(inode->i_write_hint);
        } else {
@@ -2781,6 +2980,9 @@ static void do_write_page(struct f2fs_summary *sum, struct f2fs_io_info *fio)
 reallocate:
        f2fs_allocate_data_block(fio->sbi, fio->page, fio->old_blkaddr,
                        &fio->new_blkaddr, sum, type, fio, true);
+       if (GET_SEGNO(fio->sbi, fio->old_blkaddr) != NULL_SEGNO)
+               invalidate_mapping_pages(META_MAPPING(fio->sbi),
+                                       fio->old_blkaddr, fio->old_blkaddr);
 
        /* writeout dirty page into bdev */
        f2fs_submit_page_write(fio);
@@ -2836,11 +3038,9 @@ void f2fs_outplace_write_data(struct dnode_of_data *dn,
 {
        struct f2fs_sb_info *sbi = fio->sbi;
        struct f2fs_summary sum;
-       struct node_info ni;
 
        f2fs_bug_on(sbi, dn->data_blkaddr == NULL_ADDR);
-       f2fs_get_node_info(sbi, dn->nid, &ni);
-       set_summary(&sum, dn->nid, dn->ofs_in_node, ni.version);
+       set_summary(&sum, dn->nid, dn->ofs_in_node, fio->version);
        do_write_page(&sum, fio);
        f2fs_update_data_blkaddr(dn, fio->new_blkaddr);
 
@@ -2937,8 +3137,11 @@ void f2fs_do_replace_block(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
 
        if (!recover_curseg || recover_newaddr)
                update_sit_entry(sbi, new_blkaddr, 1);
-       if (GET_SEGNO(sbi, old_blkaddr) != NULL_SEGNO)
+       if (GET_SEGNO(sbi, old_blkaddr) != NULL_SEGNO) {
+               invalidate_mapping_pages(META_MAPPING(sbi),
+                                       old_blkaddr, old_blkaddr);
                update_sit_entry(sbi, old_blkaddr, -1);
+       }
 
        locate_dirty_segment(sbi, GET_SEGNO(sbi, old_blkaddr));
        locate_dirty_segment(sbi, GET_SEGNO(sbi, new_blkaddr));
@@ -2992,7 +3195,7 @@ void f2fs_wait_on_block_writeback(struct f2fs_sb_info *sbi, block_t blkaddr)
 {
        struct page *cpage;
 
-       if (!is_valid_blkaddr(blkaddr))
+       if (!is_valid_data_blkaddr(sbi, blkaddr))
                return;
 
        cpage = find_lock_page(META_MAPPING(sbi), blkaddr);
@@ -3002,7 +3205,7 @@ void f2fs_wait_on_block_writeback(struct f2fs_sb_info *sbi, block_t blkaddr)
        }
 }
 
-static void read_compacted_summaries(struct f2fs_sb_info *sbi)
+static int read_compacted_summaries(struct f2fs_sb_info *sbi)
 {
        struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
        struct curseg_info *seg_i;
@@ -3014,6 +3217,8 @@ static void read_compacted_summaries(struct f2fs_sb_info *sbi)
        start = start_sum_block(sbi);
 
        page = f2fs_get_meta_page(sbi, start++);
+       if (IS_ERR(page))
+               return PTR_ERR(page);
        kaddr = (unsigned char *)page_address(page);
 
        /* Step 1: restore nat cache */
@@ -3054,11 +3259,14 @@ static void read_compacted_summaries(struct f2fs_sb_info *sbi)
                        page = NULL;
 
                        page = f2fs_get_meta_page(sbi, start++);
+                       if (IS_ERR(page))
+                               return PTR_ERR(page);
                        kaddr = (unsigned char *)page_address(page);
                        offset = 0;
                }
        }
        f2fs_put_page(page, 1);
+       return 0;
 }
 
 static int read_normal_summaries(struct f2fs_sb_info *sbi, int type)
@@ -3070,6 +3278,7 @@ static int read_normal_summaries(struct f2fs_sb_info *sbi, int type)
        unsigned short blk_off;
        unsigned int segno = 0;
        block_t blk_addr = 0;
+       int err = 0;
 
        /* get segment number and block addr */
        if (IS_DATASEG(type)) {
@@ -3093,6 +3302,8 @@ static int read_normal_summaries(struct f2fs_sb_info *sbi, int type)
        }
 
        new = f2fs_get_meta_page(sbi, blk_addr);
+       if (IS_ERR(new))
+               return PTR_ERR(new);
        sum = (struct f2fs_summary_block *)page_address(new);
 
        if (IS_NODESEG(type)) {
@@ -3104,7 +3315,9 @@ static int read_normal_summaries(struct f2fs_sb_info *sbi, int type)
                                ns->ofs_in_node = 0;
                        }
                } else {
-                       f2fs_restore_node_summary(sbi, segno, sum);
+                       err = f2fs_restore_node_summary(sbi, segno, sum);
+                       if (err)
+                               goto out;
                }
        }
 
@@ -3124,8 +3337,9 @@ static int read_normal_summaries(struct f2fs_sb_info *sbi, int type)
        curseg->alloc_type = ckpt->alloc_type[type];
        curseg->next_blkoff = blk_off;
        mutex_unlock(&curseg->curseg_mutex);
+out:
        f2fs_put_page(new, 1);
-       return 0;
+       return err;
 }
 
 static int restore_curseg_summaries(struct f2fs_sb_info *sbi)
@@ -3143,7 +3357,9 @@ static int restore_curseg_summaries(struct f2fs_sb_info *sbi)
                                                        META_CP, true);
 
                /* restore for compacted data summary */
-               read_compacted_summaries(sbi);
+               err = read_compacted_summaries(sbi);
+               if (err)
+                       return err;
                type = CURSEG_HOT_NODE;
        }
 
@@ -3274,7 +3490,7 @@ int f2fs_lookup_journal_in_cursum(struct f2fs_journal *journal, int type,
 static struct page *get_current_sit_page(struct f2fs_sb_info *sbi,
                                        unsigned int segno)
 {
-       return f2fs_get_meta_page(sbi, current_sit_addr(sbi, segno));
+       return f2fs_get_meta_page_nofail(sbi, current_sit_addr(sbi, segno));
 }
 
 static struct page *get_next_sit_page(struct f2fs_sb_info *sbi,
@@ -3923,6 +4139,7 @@ int f2fs_build_segment_manager(struct f2fs_sb_info *sbi)
                sm_info->ipu_policy = 1 << F2FS_IPU_FSYNC;
        sm_info->min_ipu_util = DEF_MIN_IPU_UTIL;
        sm_info->min_fsync_blocks = DEF_MIN_FSYNC_BLOCKS;
+       sm_info->min_seq_blocks = sbi->blocks_per_seg * sbi->segs_per_sec;
        sm_info->min_hot_blocks = DEF_MIN_HOT_BLOCKS;
        sm_info->min_ssr_sections = reserved_sections(sbi);
 
index f18fc82..b3d9e31 100644 (file)
@@ -85,7 +85,7 @@
        (GET_SEGOFF_FROM_SEG0(sbi, blk_addr) & ((sbi)->blocks_per_seg - 1))
 
 #define GET_SEGNO(sbi, blk_addr)                                       \
-       ((!is_valid_blkaddr(blk_addr)) ?                        \
+       ((!is_valid_data_blkaddr(sbi, blk_addr)) ?                      \
        NULL_SEGNO : GET_L2R_SEGNO(FREE_I(sbi),                 \
                GET_SEGNO_FROM_SEG0(sbi, blk_addr)))
 #define BLKS_PER_SEC(sbi)                                      \
@@ -215,7 +215,7 @@ struct segment_allocation {
 #define IS_DUMMY_WRITTEN_PAGE(page)                    \
                (page_private(page) == (unsigned long)DUMMY_WRITTEN_PAGE)
 
-#define MAX_SKIP_ATOMIC_COUNT                  16
+#define MAX_SKIP_GC_COUNT                      16
 
 struct inmem_pages {
        struct list_head list;
@@ -448,6 +448,8 @@ static inline void __set_test_and_free(struct f2fs_sb_info *sbi,
        if (test_and_clear_bit(segno, free_i->free_segmap)) {
                free_i->free_segments++;
 
+               if (IS_CURSEC(sbi, secno))
+                       goto skip_free;
                next = find_next_bit(free_i->free_segmap,
                                start_segno + sbi->segs_per_sec, start_segno);
                if (next >= start_segno + sbi->segs_per_sec) {
@@ -455,6 +457,7 @@ static inline void __set_test_and_free(struct f2fs_sb_info *sbi,
                                free_i->free_sections++;
                }
        }
+skip_free:
        spin_unlock(&free_i->segmap_lock);
 }
 
@@ -645,13 +648,10 @@ static inline void verify_block_addr(struct f2fs_io_info *fio, block_t blk_addr)
 {
        struct f2fs_sb_info *sbi = fio->sbi;
 
-       if (PAGE_TYPE_OF_BIO(fio->type) == META &&
-                               (!is_read_io(fio->op) || fio->is_meta))
-               BUG_ON(blk_addr < SEG0_BLKADDR(sbi) ||
-                               blk_addr >= MAIN_BLKADDR(sbi));
+       if (__is_meta_io(fio))
+               verify_blkaddr(sbi, blk_addr, META_GENERIC);
        else
-               BUG_ON(blk_addr < MAIN_BLKADDR(sbi) ||
-                               blk_addr >= MAX_BLKADDR(sbi));
+               verify_blkaddr(sbi, blk_addr, DATA_GENERIC);
 }
 
 /*
index 17bcff7..896b885 100644 (file)
@@ -41,7 +41,7 @@ static struct kmem_cache *f2fs_inode_cachep;
 
 #ifdef CONFIG_F2FS_FAULT_INJECTION
 
-char *fault_name[FAULT_MAX] = {
+char *f2fs_fault_name[FAULT_MAX] = {
        [FAULT_KMALLOC]         = "kmalloc",
        [FAULT_KVMALLOC]        = "kvmalloc",
        [FAULT_PAGE_ALLOC]      = "page alloc",
@@ -55,20 +55,24 @@ char *fault_name[FAULT_MAX] = {
        [FAULT_TRUNCATE]        = "truncate fail",
        [FAULT_IO]              = "IO error",
        [FAULT_CHECKPOINT]      = "checkpoint error",
+       [FAULT_DISCARD]         = "discard error",
 };
 
-static void f2fs_build_fault_attr(struct f2fs_sb_info *sbi,
-                                               unsigned int rate)
+void f2fs_build_fault_attr(struct f2fs_sb_info *sbi, unsigned int rate,
+                                                       unsigned int type)
 {
        struct f2fs_fault_info *ffi = &F2FS_OPTION(sbi).fault_info;
 
        if (rate) {
                atomic_set(&ffi->inject_ops, 0);
                ffi->inject_rate = rate;
-               ffi->inject_type = (1 << FAULT_MAX) - 1;
-       } else {
-               memset(ffi, 0, sizeof(struct f2fs_fault_info));
        }
+
+       if (type)
+               ffi->inject_type = type;
+
+       if (!rate && !type)
+               memset(ffi, 0, sizeof(struct f2fs_fault_info));
 }
 #endif
 
@@ -113,6 +117,7 @@ enum {
        Opt_mode,
        Opt_io_size_bits,
        Opt_fault_injection,
+       Opt_fault_type,
        Opt_lazytime,
        Opt_nolazytime,
        Opt_quota,
@@ -170,6 +175,7 @@ static match_table_t f2fs_tokens = {
        {Opt_mode, "mode=%s"},
        {Opt_io_size_bits, "io_bits=%u"},
        {Opt_fault_injection, "fault_injection=%u"},
+       {Opt_fault_type, "fault_type=%u"},
        {Opt_lazytime, "lazytime"},
        {Opt_nolazytime, "nolazytime"},
        {Opt_quota, "quota"},
@@ -347,12 +353,6 @@ static int f2fs_check_quota_options(struct f2fs_sb_info *sbi)
                        "QUOTA feature is enabled, so ignore jquota_fmt");
                F2FS_OPTION(sbi).s_jquota_fmt = 0;
        }
-       if (f2fs_sb_has_quota_ino(sbi->sb) && f2fs_readonly(sbi->sb)) {
-               f2fs_msg(sbi->sb, KERN_INFO,
-                        "Filesystem with quota feature cannot be mounted RDWR "
-                        "without CONFIG_QUOTA");
-               return -1;
-       }
        return 0;
 }
 #endif
@@ -606,7 +606,18 @@ static int parse_options(struct super_block *sb, char *options)
                        if (args->from && match_int(args, &arg))
                                return -EINVAL;
 #ifdef CONFIG_F2FS_FAULT_INJECTION
-                       f2fs_build_fault_attr(sbi, arg);
+                       f2fs_build_fault_attr(sbi, arg, F2FS_ALL_FAULT_TYPE);
+                       set_opt(sbi, FAULT_INJECTION);
+#else
+                       f2fs_msg(sb, KERN_INFO,
+                               "FAULT_INJECTION was not selected");
+#endif
+                       break;
+               case Opt_fault_type:
+                       if (args->from && match_int(args, &arg))
+                               return -EINVAL;
+#ifdef CONFIG_F2FS_FAULT_INJECTION
+                       f2fs_build_fault_attr(sbi, 0, arg);
                        set_opt(sbi, FAULT_INJECTION);
 #else
                        f2fs_msg(sb, KERN_INFO,
@@ -775,6 +786,19 @@ static int parse_options(struct super_block *sb, char *options)
 #ifdef CONFIG_QUOTA
        if (f2fs_check_quota_options(sbi))
                return -EINVAL;
+#else
+       if (f2fs_sb_has_quota_ino(sbi->sb) && !f2fs_readonly(sbi->sb)) {
+               f2fs_msg(sbi->sb, KERN_INFO,
+                        "Filesystem with quota feature cannot be mounted RDWR "
+                        "without CONFIG_QUOTA");
+               return -EINVAL;
+       }
+       if (f2fs_sb_has_project_quota(sbi->sb) && !f2fs_readonly(sbi->sb)) {
+               f2fs_msg(sb, KERN_ERR,
+                       "Filesystem with project quota feature cannot be "
+                       "mounted RDWR without CONFIG_QUOTA");
+               return -EINVAL;
+       }
 #endif
 
        if (F2FS_IO_SIZE_BITS(sbi) && !test_opt(sbi, LFS)) {
@@ -1030,6 +1054,10 @@ static void f2fs_put_super(struct super_block *sb)
        /* our cp_error case, we can wait for any writeback page */
        f2fs_flush_merged_writes(sbi);
 
+       f2fs_wait_on_all_pages_writeback(sbi);
+
+       f2fs_bug_on(sbi, sbi->fsync_node_num);
+
        iput(sbi->node_inode);
        iput(sbi->meta_inode);
 
@@ -1118,7 +1146,7 @@ static int f2fs_statfs_project(struct super_block *sb,
        dquot = dqget(sb, qid);
        if (IS_ERR(dquot))
                return PTR_ERR(dquot);
-       spin_lock(&dq_data_lock);
+       spin_lock(&dquot->dq_dqb_lock);
 
        limit = (dquot->dq_dqb.dqb_bsoftlimit ?
                 dquot->dq_dqb.dqb_bsoftlimit :
@@ -1141,7 +1169,7 @@ static int f2fs_statfs_project(struct super_block *sb,
                         (buf->f_files - dquot->dq_dqb.dqb_curinodes) : 0;
        }
 
-       spin_unlock(&dq_data_lock);
+       spin_unlock(&dquot->dq_dqb_lock);
        dqput(dquot);
        return 0;
 }
@@ -1310,9 +1338,12 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root)
        if (F2FS_IO_SIZE_BITS(sbi))
                seq_printf(seq, ",io_size=%uKB", F2FS_IO_SIZE_KB(sbi));
 #ifdef CONFIG_F2FS_FAULT_INJECTION
-       if (test_opt(sbi, FAULT_INJECTION))
+       if (test_opt(sbi, FAULT_INJECTION)) {
                seq_printf(seq, ",fault_injection=%u",
                                F2FS_OPTION(sbi).fault_info.inject_rate);
+               seq_printf(seq, ",fault_type=%u",
+                               F2FS_OPTION(sbi).fault_info.inject_type);
+       }
 #endif
 #ifdef CONFIG_QUOTA
        if (test_opt(sbi, QUOTA))
@@ -1343,6 +1374,8 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root)
                seq_printf(seq, ",fsync_mode=%s", "posix");
        else if (F2FS_OPTION(sbi).fsync_mode == FSYNC_MODE_STRICT)
                seq_printf(seq, ",fsync_mode=%s", "strict");
+       else if (F2FS_OPTION(sbi).fsync_mode == FSYNC_MODE_NOBARRIER)
+               seq_printf(seq, ",fsync_mode=%s", "nobarrier");
        return 0;
 }
 
@@ -1355,7 +1388,8 @@ static void default_options(struct f2fs_sb_info *sbi)
        F2FS_OPTION(sbi).alloc_mode = ALLOC_MODE_DEFAULT;
        F2FS_OPTION(sbi).fsync_mode = FSYNC_MODE_POSIX;
        F2FS_OPTION(sbi).test_dummy_encryption = false;
-       sbi->readdir_ra = 1;
+       F2FS_OPTION(sbi).s_resuid = make_kuid(&init_user_ns, F2FS_DEF_RESUID);
+       F2FS_OPTION(sbi).s_resgid = make_kgid(&init_user_ns, F2FS_DEF_RESGID);
 
        set_opt(sbi, BG_GC);
        set_opt(sbi, INLINE_XATTR);
@@ -1365,12 +1399,12 @@ static void default_options(struct f2fs_sb_info *sbi)
        set_opt(sbi, NOHEAP);
        sbi->sb->s_flags |= SB_LAZYTIME;
        set_opt(sbi, FLUSH_MERGE);
-       if (f2fs_sb_has_blkzoned(sbi->sb)) {
-               set_opt_mode(sbi, F2FS_MOUNT_LFS);
+       if (blk_queue_discard(bdev_get_queue(sbi->sb->s_bdev)))
                set_opt(sbi, DISCARD);
-       } else {
+       if (f2fs_sb_has_blkzoned(sbi->sb))
+               set_opt_mode(sbi, F2FS_MOUNT_LFS);
+       else
                set_opt_mode(sbi, F2FS_MOUNT_ADAPTIVE);
-       }
 
 #ifdef CONFIG_F2FS_FS_XATTR
        set_opt(sbi, XATTR_USER);
@@ -1379,9 +1413,7 @@ static void default_options(struct f2fs_sb_info *sbi)
        set_opt(sbi, POSIX_ACL);
 #endif
 
-#ifdef CONFIG_F2FS_FAULT_INJECTION
-       f2fs_build_fault_attr(sbi, 0);
-#endif
+       f2fs_build_fault_attr(sbi, 0, 0);
 }
 
 #ifdef CONFIG_QUOTA
@@ -2229,9 +2261,9 @@ static int sanity_check_raw_super(struct f2fs_sb_info *sbi,
                return 1;
        }
 
-       if (secs_per_zone > total_sections) {
+       if (secs_per_zone > total_sections || !secs_per_zone) {
                f2fs_msg(sb, KERN_INFO,
-                       "Wrong secs_per_zone (%u > %u)",
+                       "Wrong secs_per_zone / total_sections (%u, %u)",
                        secs_per_zone, total_sections);
                return 1;
        }
@@ -2282,12 +2314,20 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
        struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
        unsigned int ovp_segments, reserved_segments;
        unsigned int main_segs, blocks_per_seg;
+       unsigned int sit_segs, nat_segs;
+       unsigned int sit_bitmap_size, nat_bitmap_size;
+       unsigned int log_blocks_per_seg;
+       unsigned int segment_count_main;
+       unsigned int cp_pack_start_sum, cp_payload;
+       block_t user_block_count;
        int i;
 
        total = le32_to_cpu(raw_super->segment_count);
        fsmeta = le32_to_cpu(raw_super->segment_count_ckpt);
-       fsmeta += le32_to_cpu(raw_super->segment_count_sit);
-       fsmeta += le32_to_cpu(raw_super->segment_count_nat);
+       sit_segs = le32_to_cpu(raw_super->segment_count_sit);
+       fsmeta += sit_segs;
+       nat_segs = le32_to_cpu(raw_super->segment_count_nat);
+       fsmeta += nat_segs;
        fsmeta += le32_to_cpu(ckpt->rsvd_segment_count);
        fsmeta += le32_to_cpu(raw_super->segment_count_ssa);
 
@@ -2304,6 +2344,16 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
                return 1;
        }
 
+       user_block_count = le64_to_cpu(ckpt->user_block_count);
+       segment_count_main = le32_to_cpu(raw_super->segment_count_main);
+       log_blocks_per_seg = le32_to_cpu(raw_super->log_blocks_per_seg);
+       if (!user_block_count || user_block_count >=
+                       segment_count_main << log_blocks_per_seg) {
+               f2fs_msg(sbi->sb, KERN_ERR,
+                       "Wrong user_block_count: %u", user_block_count);
+               return 1;
+       }
+
        main_segs = le32_to_cpu(raw_super->segment_count_main);
        blocks_per_seg = sbi->blocks_per_seg;
 
@@ -2318,6 +2368,28 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
                        return 1;
        }
 
+       sit_bitmap_size = le32_to_cpu(ckpt->sit_ver_bitmap_bytesize);
+       nat_bitmap_size = le32_to_cpu(ckpt->nat_ver_bitmap_bytesize);
+
+       if (sit_bitmap_size != ((sit_segs / 2) << log_blocks_per_seg) / 8 ||
+               nat_bitmap_size != ((nat_segs / 2) << log_blocks_per_seg) / 8) {
+               f2fs_msg(sbi->sb, KERN_ERR,
+                       "Wrong bitmap size: sit: %u, nat:%u",
+                       sit_bitmap_size, nat_bitmap_size);
+               return 1;
+       }
+
+       cp_pack_start_sum = __start_sum_addr(sbi);
+       cp_payload = __cp_payload(sbi);
+       if (cp_pack_start_sum < cp_payload + 1 ||
+               cp_pack_start_sum > blocks_per_seg - 1 -
+                       NR_CURSEG_TYPE) {
+               f2fs_msg(sbi->sb, KERN_ERR,
+                       "Wrong cp_pack_start_sum: %u",
+                       cp_pack_start_sum);
+               return 1;
+       }
+
        if (unlikely(f2fs_cp_error(sbi))) {
                f2fs_msg(sbi->sb, KERN_ERR, "A bug case: need to run fsck");
                return 1;
@@ -2651,6 +2723,8 @@ static void f2fs_tuning_parameters(struct f2fs_sb_info *sbi)
                sm_i->dcc_info->discard_granularity = 1;
                sm_i->ipu_policy = 1 << F2FS_IPU_FORCE;
        }
+
+       sbi->readdir_ra = 1;
 }
 
 static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
@@ -2700,9 +2774,6 @@ try_onemore:
        sb->s_fs_info = sbi;
        sbi->raw_super = raw_super;
 
-       F2FS_OPTION(sbi).s_resuid = make_kuid(&init_user_ns, F2FS_DEF_RESUID);
-       F2FS_OPTION(sbi).s_resgid = make_kgid(&init_user_ns, F2FS_DEF_RESGID);
-
        /* precompute checksum seed for metadata */
        if (f2fs_sb_has_inode_chksum(sb))
                sbi->s_chksum_seed = f2fs_chksum(sbi, ~0, raw_super->uuid,
@@ -2771,6 +2842,7 @@ try_onemore:
        /* init f2fs-specific super block info */
        sbi->valid_super_block = valid_super_block;
        mutex_init(&sbi->gc_mutex);
+       mutex_init(&sbi->writepages);
        mutex_init(&sbi->cp_mutex);
        init_rwsem(&sbi->node_write);
        init_rwsem(&sbi->node_change);
@@ -2865,6 +2937,8 @@ try_onemore:
 
        f2fs_init_ino_entry_info(sbi);
 
+       f2fs_init_fsync_node_info(sbi);
+
        /* setup f2fs internal modules */
        err = f2fs_build_segment_manager(sbi);
        if (err) {
@@ -2912,10 +2986,11 @@ try_onemore:
                err = PTR_ERR(root);
                goto free_stats;
        }
-       if (!S_ISDIR(root->i_mode) || !root->i_blocks || !root->i_size) {
+       if (!S_ISDIR(root->i_mode) || !root->i_blocks ||
+                       !root->i_size || !root->i_nlink) {
                iput(root);
                err = -EINVAL;
-               goto free_node_inode;
+               goto free_stats;
        }
 
        sb->s_root = d_make_root(root); /* allocate root dentry */
@@ -2929,10 +3004,7 @@ try_onemore:
                goto free_root_inode;
 
 #ifdef CONFIG_QUOTA
-       /*
-        * Turn on quotas which were not enabled for read-only mounts if
-        * filesystem has quota feature, so that they are updated correctly.
-        */
+       /* Enable quota usage during mount */
        if (f2fs_sb_has_quota_ino(sb) && !f2fs_readonly(sb)) {
                err = f2fs_enable_quotas(sb);
                if (err) {
@@ -3090,9 +3162,19 @@ static struct dentry *f2fs_mount(struct file_system_type *fs_type, int flags,
 static void kill_f2fs_super(struct super_block *sb)
 {
        if (sb->s_root) {
-               set_sbi_flag(F2FS_SB(sb), SBI_IS_CLOSE);
-               f2fs_stop_gc_thread(F2FS_SB(sb));
-               f2fs_stop_discard_thread(F2FS_SB(sb));
+               struct f2fs_sb_info *sbi = F2FS_SB(sb);
+
+               set_sbi_flag(sbi, SBI_IS_CLOSE);
+               f2fs_stop_gc_thread(sbi);
+               f2fs_stop_discard_thread(sbi);
+
+               if (is_sbi_flag_set(sbi, SBI_IS_DIRTY) ||
+                               !is_set_ckpt_flags(sbi, CP_UMOUNT_FLAG)) {
+                       struct cp_control cpc = {
+                               .reason = CP_UMOUNT,
+                       };
+                       f2fs_write_checkpoint(sbi, &cpc);
+               }
        }
        kill_block_super(sb);
 }
index 2e7e611..81c0e53 100644 (file)
@@ -9,6 +9,7 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
+#include <linux/compiler.h>
 #include <linux/proc_fs.h>
 #include <linux/f2fs_fs.h>
 #include <linux/seq_file.h>
@@ -252,6 +253,7 @@ out:
                if (t >= 1) {
                        sbi->gc_mode = GC_URGENT;
                        if (sbi->gc_thread) {
+                               sbi->gc_thread->gc_wake = 1;
                                wake_up_interruptible_all(
                                        &sbi->gc_thread->gc_wait_queue_head);
                                wake_up_discard_thread(sbi, true);
@@ -286,8 +288,10 @@ static ssize_t f2fs_sbi_store(struct f2fs_attr *a,
        bool gc_entry = (!strcmp(a->attr.name, "gc_urgent") ||
                                        a->struct_type == GC_THREAD);
 
-       if (gc_entry)
-               down_read(&sbi->sb->s_umount);
+       if (gc_entry) {
+               if (!down_read_trylock(&sbi->sb->s_umount))
+                       return -EAGAIN;
+       }
        ret = __sbi_store(a, sbi, buf, count);
        if (gc_entry)
                up_read(&sbi->sb->s_umount);
@@ -393,6 +397,7 @@ F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, batched_trim_sections, trim_sections);
 F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, ipu_policy, ipu_policy);
 F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, min_ipu_util, min_ipu_util);
 F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, min_fsync_blocks, min_fsync_blocks);
+F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, min_seq_blocks, min_seq_blocks);
 F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, min_hot_blocks, min_hot_blocks);
 F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, min_ssr_sections, min_ssr_sections);
 F2FS_RW_ATTR(NM_INFO, f2fs_nm_info, ram_thresh, ram_thresh);
@@ -445,6 +450,7 @@ static struct attribute *f2fs_attrs[] = {
        ATTR_LIST(ipu_policy),
        ATTR_LIST(min_ipu_util),
        ATTR_LIST(min_fsync_blocks),
+       ATTR_LIST(min_seq_blocks),
        ATTR_LIST(min_hot_blocks),
        ATTR_LIST(min_ssr_sections),
        ATTR_LIST(max_victim_search),
@@ -516,7 +522,8 @@ static struct kobject f2fs_feat = {
        .kset   = &f2fs_kset,
 };
 
-static int segment_info_seq_show(struct seq_file *seq, void *offset)
+static int __maybe_unused segment_info_seq_show(struct seq_file *seq,
+                                               void *offset)
 {
        struct super_block *sb = seq->private;
        struct f2fs_sb_info *sbi = F2FS_SB(sb);
@@ -543,7 +550,8 @@ static int segment_info_seq_show(struct seq_file *seq, void *offset)
        return 0;
 }
 
-static int segment_bits_seq_show(struct seq_file *seq, void *offset)
+static int __maybe_unused segment_bits_seq_show(struct seq_file *seq,
+                                               void *offset)
 {
        struct super_block *sb = seq->private;
        struct f2fs_sb_info *sbi = F2FS_SB(sb);
@@ -567,7 +575,8 @@ static int segment_bits_seq_show(struct seq_file *seq, void *offset)
        return 0;
 }
 
-static int iostat_info_seq_show(struct seq_file *seq, void *offset)
+static int __maybe_unused iostat_info_seq_show(struct seq_file *seq,
+                                              void *offset)
 {
        struct super_block *sb = seq->private;
        struct f2fs_sb_info *sbi = F2FS_SB(sb);
@@ -609,6 +618,28 @@ static int iostat_info_seq_show(struct seq_file *seq, void *offset)
        return 0;
 }
 
+static int __maybe_unused victim_bits_seq_show(struct seq_file *seq,
+                                               void *offset)
+{
+       struct super_block *sb = seq->private;
+       struct f2fs_sb_info *sbi = F2FS_SB(sb);
+       struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
+       int i;
+
+       seq_puts(seq, "format: victim_secmap bitmaps\n");
+
+       for (i = 0; i < MAIN_SECS(sbi); i++) {
+               if ((i % 10) == 0)
+                       seq_printf(seq, "%-10d", i);
+               seq_printf(seq, "%d", test_bit(i, dirty_i->victim_secmap) ? 1 : 0);
+               if ((i % 10) == 9 || i == (MAIN_SECS(sbi) - 1))
+                       seq_putc(seq, '\n');
+               else
+                       seq_putc(seq, ' ');
+       }
+       return 0;
+}
+
 int __init f2fs_init_sysfs(void)
 {
        int ret;
@@ -658,6 +689,8 @@ int f2fs_register_sysfs(struct f2fs_sb_info *sbi)
                                segment_bits_seq_show, sb);
                proc_create_single_data("iostat_info", S_IRUGO, sbi->s_proc,
                                iostat_info_seq_show, sb);
+               proc_create_single_data("victim_bits", S_IRUGO, sbi->s_proc,
+                               victim_bits_seq_show, sb);
        }
        return 0;
 }
@@ -668,6 +701,7 @@ void f2fs_unregister_sysfs(struct f2fs_sb_info *sbi)
                remove_proc_entry("iostat_info", sbi->s_proc);
                remove_proc_entry("segment_info", sbi->s_proc);
                remove_proc_entry("segment_bits", sbi->s_proc);
+               remove_proc_entry("victim_bits", sbi->s_proc);
                remove_proc_entry(sbi->sb->s_id, f2fs_proc_root);
        }
        kobject_del(&sbi->s_kobj);
index 7082718..77a010e 100644 (file)
@@ -37,9 +37,6 @@ static int f2fs_xattr_generic_get(const struct xattr_handler *handler,
                        return -EOPNOTSUPP;
                break;
        case F2FS_XATTR_INDEX_TRUSTED:
-               if (!capable(CAP_SYS_ADMIN))
-                       return -EPERM;
-               break;
        case F2FS_XATTR_INDEX_SECURITY:
                break;
        default:
@@ -62,9 +59,6 @@ static int f2fs_xattr_generic_set(const struct xattr_handler *handler,
                        return -EOPNOTSUPP;
                break;
        case F2FS_XATTR_INDEX_TRUSTED:
-               if (!capable(CAP_SYS_ADMIN))
-                       return -EPERM;
-               break;
        case F2FS_XATTR_INDEX_SECURITY:
                break;
        default:
@@ -100,12 +94,22 @@ static int f2fs_xattr_advise_set(const struct xattr_handler *handler,
                const char *name, const void *value,
                size_t size, int flags)
 {
+       unsigned char old_advise = F2FS_I(inode)->i_advise;
+       unsigned char new_advise;
+
        if (!inode_owner_or_capable(inode))
                return -EPERM;
        if (value == NULL)
                return -EINVAL;
 
-       F2FS_I(inode)->i_advise |= *(char *)value;
+       new_advise = *(char *)value;
+       if (new_advise & ~FADVISE_MODIFIABLE_BITS)
+               return -EINVAL;
+
+       new_advise = new_advise & FADVISE_MODIFIABLE_BITS;
+       new_advise |= old_advise & ~FADVISE_MODIFIABLE_BITS;
+
+       F2FS_I(inode)->i_advise = new_advise;
        f2fs_mark_inode_dirty_sync(inode, true);
        return 0;
 }
index e9bed49..78d501c 100644 (file)
@@ -225,7 +225,8 @@ static inline void cache_init(struct fat_cache_id *cid, int fclus, int dclus)
 int fat_get_cluster(struct inode *inode, int cluster, int *fclus, int *dclus)
 {
        struct super_block *sb = inode->i_sb;
-       const int limit = sb->s_maxbytes >> MSDOS_SB(sb)->cluster_bits;
+       struct msdos_sb_info *sbi = MSDOS_SB(sb);
+       const int limit = sb->s_maxbytes >> sbi->cluster_bits;
        struct fat_entry fatent;
        struct fat_cache_id cid;
        int nr;
@@ -234,6 +235,12 @@ int fat_get_cluster(struct inode *inode, int cluster, int *fclus, int *dclus)
 
        *fclus = 0;
        *dclus = MSDOS_I(inode)->i_start;
+       if (!fat_valid_entry(sbi, *dclus)) {
+               fat_fs_error_ratelimit(sb,
+                       "%s: invalid start cluster (i_pos %lld, start %08x)",
+                       __func__, MSDOS_I(inode)->i_pos, *dclus);
+               return -EIO;
+       }
        if (cluster == 0)
                return 0;
 
@@ -250,9 +257,8 @@ int fat_get_cluster(struct inode *inode, int cluster, int *fclus, int *dclus)
                /* prevent the infinite loop of cluster chain */
                if (*fclus > limit) {
                        fat_fs_error_ratelimit(sb,
-                                       "%s: detected the cluster chain loop"
-                                       " (i_pos %lld)", __func__,
-                                       MSDOS_I(inode)->i_pos);
+                               "%s: detected the cluster chain loop (i_pos %lld)",
+                               __func__, MSDOS_I(inode)->i_pos);
                        nr = -EIO;
                        goto out;
                }
@@ -262,9 +268,8 @@ int fat_get_cluster(struct inode *inode, int cluster, int *fclus, int *dclus)
                        goto out;
                else if (nr == FAT_ENT_FREE) {
                        fat_fs_error_ratelimit(sb,
-                                      "%s: invalid cluster chain (i_pos %lld)",
-                                      __func__,
-                                      MSDOS_I(inode)->i_pos);
+                               "%s: invalid cluster chain (i_pos %lld)",
+                               __func__, MSDOS_I(inode)->i_pos);
                        nr = -EIO;
                        goto out;
                } else if (nr == FAT_ENT_EOF) {
index 8e100c3..7f5f369 100644 (file)
@@ -1130,7 +1130,7 @@ error:
        return err;
 }
 
-int fat_alloc_new_dir(struct inode *dir, struct timespec *ts)
+int fat_alloc_new_dir(struct inode *dir, struct timespec64 *ts)
 {
        struct super_block *sb = dir->i_sb;
        struct msdos_sb_info *sbi = MSDOS_SB(sb);
index 8fc1093..9d7d2d5 100644 (file)
@@ -304,7 +304,7 @@ extern int fat_scan_logstart(struct inode *dir, int i_logstart,
                             struct fat_slot_info *sinfo);
 extern int fat_get_dotdot_entry(struct inode *dir, struct buffer_head **bh,
                                struct msdos_dir_entry **de);
-extern int fat_alloc_new_dir(struct inode *dir, struct timespec *ts);
+extern int fat_alloc_new_dir(struct inode *dir, struct timespec64 *ts);
 extern int fat_add_entries(struct inode *dir, void *slots, int nr_slots,
                           struct fat_slot_info *sinfo);
 extern int fat_remove_entries(struct inode *dir, struct fat_slot_info *sinfo);
@@ -348,6 +348,11 @@ static inline void fatent_brelse(struct fat_entry *fatent)
        fatent->fat_inode = NULL;
 }
 
+static inline bool fat_valid_entry(struct msdos_sb_info *sbi, int entry)
+{
+       return FAT_START_ENT <= entry && entry < sbi->max_cluster;
+}
+
 extern void fat_ent_access_init(struct super_block *sb);
 extern int fat_ent_read(struct inode *inode, struct fat_entry *fatent,
                        int entry);
@@ -357,6 +362,7 @@ extern int fat_alloc_clusters(struct inode *inode, int *cluster,
                              int nr_cluster);
 extern int fat_free_clusters(struct inode *inode, int cluster);
 extern int fat_count_free_clusters(struct super_block *sb);
+extern int fat_trim_fs(struct inode *inode, struct fstrim_range *range);
 
 /* fat/file.c */
 extern long fat_generic_ioctl(struct file *filp, unsigned int cmd,
@@ -406,9 +412,9 @@ void fat_msg(struct super_block *sb, const char *level, const char *fmt, ...);
         } while (0)
 extern int fat_clusters_flush(struct super_block *sb);
 extern int fat_chain_add(struct inode *inode, int new_dclus, int nr_cluster);
-extern void fat_time_fat2unix(struct msdos_sb_info *sbi, struct timespec *ts,
+extern void fat_time_fat2unix(struct msdos_sb_info *sbi, struct timespec64 *ts,
                              __le16 __time, __le16 __date, u8 time_cs);
-extern void fat_time_unix2fat(struct msdos_sb_info *sbi, struct timespec *ts,
+extern void fat_time_unix2fat(struct msdos_sb_info *sbi, struct timespec64 *ts,
                              __le16 *time, __le16 *date, u8 *time_cs);
 extern int fat_sync_bhs(struct buffer_head **bhs, int nr_bhs);
 
index bac10de..defc216 100644 (file)
@@ -4,6 +4,7 @@
  */
 
 #include <linux/blkdev.h>
+#include <linux/sched/signal.h>
 #include "fat.h"
 
 struct fatent_operations {
@@ -23,7 +24,7 @@ static void fat12_ent_blocknr(struct super_block *sb, int entry,
 {
        struct msdos_sb_info *sbi = MSDOS_SB(sb);
        int bytes = entry + (entry >> 1);
-       WARN_ON(entry < FAT_START_ENT || sbi->max_cluster <= entry);
+       WARN_ON(!fat_valid_entry(sbi, entry));
        *offset = bytes & (sb->s_blocksize - 1);
        *blocknr = sbi->fat_start + (bytes >> sb->s_blocksize_bits);
 }
@@ -33,7 +34,7 @@ static void fat_ent_blocknr(struct super_block *sb, int entry,
 {
        struct msdos_sb_info *sbi = MSDOS_SB(sb);
        int bytes = (entry << sbi->fatent_shift);
-       WARN_ON(entry < FAT_START_ENT || sbi->max_cluster <= entry);
+       WARN_ON(!fat_valid_entry(sbi, entry));
        *offset = bytes & (sb->s_blocksize - 1);
        *blocknr = sbi->fat_start + (bytes >> sb->s_blocksize_bits);
 }
@@ -353,7 +354,7 @@ int fat_ent_read(struct inode *inode, struct fat_entry *fatent, int entry)
        int err, offset;
        sector_t blocknr;
 
-       if (entry < FAT_START_ENT || sbi->max_cluster <= entry) {
+       if (!fat_valid_entry(sbi, entry)) {
                fatent_brelse(fatent);
                fat_fs_error(sb, "invalid access to FAT (entry 0x%08x)", entry);
                return -EIO;
@@ -690,3 +691,104 @@ out:
        unlock_fat(sbi);
        return err;
 }
+
+static int fat_trim_clusters(struct super_block *sb, u32 clus, u32 nr_clus)
+{
+       struct msdos_sb_info *sbi = MSDOS_SB(sb);
+       return sb_issue_discard(sb, fat_clus_to_blknr(sbi, clus),
+                               nr_clus * sbi->sec_per_clus, GFP_NOFS, 0);
+}
+
+int fat_trim_fs(struct inode *inode, struct fstrim_range *range)
+{
+       struct super_block *sb = inode->i_sb;
+       struct msdos_sb_info *sbi = MSDOS_SB(sb);
+       const struct fatent_operations *ops = sbi->fatent_ops;
+       struct fat_entry fatent;
+       u64 ent_start, ent_end, minlen, trimmed = 0;
+       u32 free = 0;
+       unsigned long reada_blocks, reada_mask, cur_block = 0;
+       int err = 0;
+
+       /*
+        * FAT data is organized as clusters, trim at the granulary of cluster.
+        *
+        * fstrim_range is in byte, convert vaules to cluster index.
+        * Treat sectors before data region as all used, not to trim them.
+        */
+       ent_start = max_t(u64, range->start>>sbi->cluster_bits, FAT_START_ENT);
+       ent_end = ent_start + (range->len >> sbi->cluster_bits) - 1;
+       minlen = range->minlen >> sbi->cluster_bits;
+
+       if (ent_start >= sbi->max_cluster || range->len < sbi->cluster_size)
+               return -EINVAL;
+       if (ent_end >= sbi->max_cluster)
+               ent_end = sbi->max_cluster - 1;
+
+       reada_blocks = FAT_READA_SIZE >> sb->s_blocksize_bits;
+       reada_mask = reada_blocks - 1;
+
+       fatent_init(&fatent);
+       lock_fat(sbi);
+       fatent_set_entry(&fatent, ent_start);
+       while (fatent.entry <= ent_end) {
+               /* readahead of fat blocks */
+               if ((cur_block & reada_mask) == 0) {
+                       unsigned long rest = sbi->fat_length - cur_block;
+                       fat_ent_reada(sb, &fatent, min(reada_blocks, rest));
+               }
+               cur_block++;
+
+               err = fat_ent_read_block(sb, &fatent);
+               if (err)
+                       goto error;
+               do {
+                       if (ops->ent_get(&fatent) == FAT_ENT_FREE) {
+                               free++;
+                       } else if (free) {
+                               if (free >= minlen) {
+                                       u32 clus = fatent.entry - free;
+
+                                       err = fat_trim_clusters(sb, clus, free);
+                                       if (err && err != -EOPNOTSUPP)
+                                               goto error;
+                                       if (!err)
+                                               trimmed += free;
+                                       err = 0;
+                               }
+                               free = 0;
+                       }
+               } while (fat_ent_next(sbi, &fatent) && fatent.entry <= ent_end);
+
+               if (fatal_signal_pending(current)) {
+                       err = -ERESTARTSYS;
+                       goto error;
+               }
+
+               if (need_resched()) {
+                       fatent_brelse(&fatent);
+                       unlock_fat(sbi);
+                       cond_resched();
+                       lock_fat(sbi);
+               }
+       }
+       /* handle scenario when tail entries are all free */
+       if (free && free >= minlen) {
+               u32 clus = fatent.entry - free;
+
+               err = fat_trim_clusters(sb, clus, free);
+               if (err && err != -EOPNOTSUPP)
+                       goto error;
+               if (!err)
+                       trimmed += free;
+               err = 0;
+       }
+
+error:
+       fatent_brelse(&fatent);
+       unlock_fat(sbi);
+
+       range->len = trimmed << sbi->cluster_bits;
+
+       return err;
+}
index 4724cc9..4f3d72f 100644 (file)
@@ -121,6 +121,37 @@ static int fat_ioctl_get_volume_id(struct inode *inode, u32 __user *user_attr)
        return put_user(sbi->vol_id, user_attr);
 }
 
+static int fat_ioctl_fitrim(struct inode *inode, unsigned long arg)
+{
+       struct super_block *sb = inode->i_sb;
+       struct fstrim_range __user *user_range;
+       struct fstrim_range range;
+       struct request_queue *q = bdev_get_queue(sb->s_bdev);
+       int err;
+
+       if (!capable(CAP_SYS_ADMIN))
+               return -EPERM;
+
+       if (!blk_queue_discard(q))
+               return -EOPNOTSUPP;
+
+       user_range = (struct fstrim_range __user *)arg;
+       if (copy_from_user(&range, user_range, sizeof(range)))
+               return -EFAULT;
+
+       range.minlen = max_t(unsigned int, range.minlen,
+                            q->limits.discard_granularity);
+
+       err = fat_trim_fs(inode, &range);
+       if (err < 0)
+               return err;
+
+       if (copy_to_user(user_range, &range, sizeof(range)))
+               return -EFAULT;
+
+       return 0;
+}
+
 long fat_generic_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 {
        struct inode *inode = file_inode(filp);
@@ -133,6 +164,8 @@ long fat_generic_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
                return fat_ioctl_set_attributes(filp, user_attr);
        case FAT_IOCTL_GET_VOLUME_ID:
                return fat_ioctl_get_volume_id(inode, user_attr);
+       case FITRIM:
+               return fat_ioctl_fitrim(inode, arg);
        default:
                return -ENOTTY; /* Inappropriate ioctl for device */
        }
index bfd589e..d6b81e3 100644 (file)
@@ -508,7 +508,6 @@ static int fat_validate_dir(struct inode *dir)
 /* doesn't deal with root inode */
 int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de)
 {
-       struct timespec ts;
        struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb);
        int error;
 
@@ -559,14 +558,11 @@ int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de)
        inode->i_blocks = ((inode->i_size + (sbi->cluster_size - 1))
                           & ~((loff_t)sbi->cluster_size - 1)) >> 9;
 
-       fat_time_fat2unix(sbi, &ts, de->time, de->date, 0);
-       inode->i_mtime = timespec_to_timespec64(ts);
+       fat_time_fat2unix(sbi, &inode->i_mtime, de->time, de->date, 0);
        if (sbi->options.isvfat) {
-               fat_time_fat2unix(sbi, &ts, de->ctime,
+               fat_time_fat2unix(sbi, &inode->i_ctime, de->ctime,
                                  de->cdate, de->ctime_cs);
-               inode->i_ctime = timespec_to_timespec64(ts);
-               fat_time_fat2unix(sbi, &ts, 0, de->adate, 0);
-               inode->i_atime = timespec_to_timespec64(ts);
+               fat_time_fat2unix(sbi, &inode->i_atime, 0, de->adate, 0);
        } else
                inode->i_ctime = inode->i_atime = inode->i_mtime;
 
@@ -843,7 +839,6 @@ static int fat_statfs(struct dentry *dentry, struct kstatfs *buf)
 
 static int __fat_write_inode(struct inode *inode, int wait)
 {
-       struct timespec ts;
        struct super_block *sb = inode->i_sb;
        struct msdos_sb_info *sbi = MSDOS_SB(sb);
        struct buffer_head *bh;
@@ -881,16 +876,13 @@ retry:
                raw_entry->size = cpu_to_le32(inode->i_size);
        raw_entry->attr = fat_make_attrs(inode);
        fat_set_start(raw_entry, MSDOS_I(inode)->i_logstart);
-       ts = timespec64_to_timespec(inode->i_mtime);
-       fat_time_unix2fat(sbi, &ts, &raw_entry->time,
+       fat_time_unix2fat(sbi, &inode->i_mtime, &raw_entry->time,
                          &raw_entry->date, NULL);
        if (sbi->options.isvfat) {
                __le16 atime;
-               ts = timespec64_to_timespec(inode->i_ctime);
-               fat_time_unix2fat(sbi, &ts, &raw_entry->ctime,
+               fat_time_unix2fat(sbi, &inode->i_ctime, &raw_entry->ctime,
                                  &raw_entry->cdate, &raw_entry->ctime_cs);
-               ts = timespec64_to_timespec(inode->i_atime);
-               fat_time_unix2fat(sbi, &ts, &atime,
+               fat_time_unix2fat(sbi, &inode->i_atime, &atime,
                                  &raw_entry->adate, NULL);
        }
        spin_unlock(&sbi->inode_hash_lock);
index f9bdc1e..573836d 100644 (file)
@@ -180,17 +180,18 @@ int fat_chain_add(struct inode *inode, int new_dclus, int nr_cluster)
 #define IS_LEAP_YEAR(y)        (!((y) & 3) && (y) != YEAR_2100)
 
 /* Linear day numbers of the respective 1sts in non-leap years. */
-static time_t days_in_year[] = {
+static long days_in_year[] = {
        /* Jan  Feb  Mar  Apr  May  Jun  Jul  Aug  Sep  Oct  Nov  Dec */
        0,   0,  31,  59,  90, 120, 151, 181, 212, 243, 273, 304, 334, 0, 0, 0,
 };
 
 /* Convert a FAT time/date pair to a UNIX date (seconds since 1 1 70). */
-void fat_time_fat2unix(struct msdos_sb_info *sbi, struct timespec *ts,
+void fat_time_fat2unix(struct msdos_sb_info *sbi, struct timespec64 *ts,
                       __le16 __time, __le16 __date, u8 time_cs)
 {
        u16 time = le16_to_cpu(__time), date = le16_to_cpu(__date);
-       time_t second, day, leap_day, month, year;
+       time64_t second;
+       long day, leap_day, month, year;
 
        year  = date >> 9;
        month = max(1, (date >> 5) & 0xf);
@@ -205,7 +206,7 @@ void fat_time_fat2unix(struct msdos_sb_info *sbi, struct timespec *ts,
        second =  (time & 0x1f) << 1;
        second += ((time >> 5) & 0x3f) * SECS_PER_MIN;
        second += (time >> 11) * SECS_PER_HOUR;
-       second += (year * 365 + leap_day
+       second += (time64_t)(year * 365 + leap_day
                   + days_in_year[month] + day
                   + DAYS_DELTA) * SECS_PER_DAY;
 
@@ -224,11 +225,11 @@ void fat_time_fat2unix(struct msdos_sb_info *sbi, struct timespec *ts,
 }
 
 /* Convert linear UNIX date to a FAT time/date pair. */
-void fat_time_unix2fat(struct msdos_sb_info *sbi, struct timespec *ts,
+void fat_time_unix2fat(struct msdos_sb_info *sbi, struct timespec64 *ts,
                       __le16 *time, __le16 *date, u8 *time_cs)
 {
        struct tm tm;
-       time_to_tm(ts->tv_sec,
+       time64_to_tm(ts->tv_sec,
                   (sbi->options.tz_set ? sbi->options.time_offset :
                   -sys_tz.tz_minuteswest) * SECS_PER_MIN, &tm);
 
index 16a832c..efb8c40 100644 (file)
@@ -225,7 +225,7 @@ static struct dentry *msdos_lookup(struct inode *dir, struct dentry *dentry,
 /***** Creates a directory entry (name is already formatted). */
 static int msdos_add_entry(struct inode *dir, const unsigned char *name,
                           int is_dir, int is_hid, int cluster,
-                          struct timespec *ts, struct fat_slot_info *sinfo)
+                          struct timespec64 *ts, struct fat_slot_info *sinfo)
 {
        struct msdos_sb_info *sbi = MSDOS_SB(dir->i_sb);
        struct msdos_dir_entry de;
@@ -250,7 +250,7 @@ static int msdos_add_entry(struct inode *dir, const unsigned char *name,
        if (err)
                return err;
 
-       dir->i_ctime = dir->i_mtime = timespec_to_timespec64(*ts);
+       dir->i_ctime = dir->i_mtime = *ts;
        if (IS_DIRSYNC(dir))
                (void)fat_sync_inode(dir);
        else
@@ -267,7 +267,6 @@ static int msdos_create(struct inode *dir, struct dentry *dentry, umode_t mode,
        struct inode *inode = NULL;
        struct fat_slot_info sinfo;
        struct timespec64 ts;
-       struct timespec t;
        unsigned char msdos_name[MSDOS_NAME];
        int err, is_hid;
 
@@ -286,8 +285,7 @@ static int msdos_create(struct inode *dir, struct dentry *dentry, umode_t mode,
        }
 
        ts = current_time(dir);
-       t = timespec64_to_timespec(ts);
-       err = msdos_add_entry(dir, msdos_name, 0, is_hid, 0, &t, &sinfo);
+       err = msdos_add_entry(dir, msdos_name, 0, is_hid, 0, &ts, &sinfo);
        if (err)
                goto out;
        inode = fat_build_inode(sb, sinfo.de, sinfo.i_pos);
@@ -347,7 +345,6 @@ static int msdos_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
        struct inode *inode;
        unsigned char msdos_name[MSDOS_NAME];
        struct timespec64 ts;
-       struct timespec t;
        int err, is_hid, cluster;
 
        mutex_lock(&MSDOS_SB(sb)->s_lock);
@@ -365,13 +362,12 @@ static int msdos_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
        }
 
        ts = current_time(dir);
-       t = timespec64_to_timespec(ts);
-       cluster = fat_alloc_new_dir(dir, &t);
+       cluster = fat_alloc_new_dir(dir, &ts);
        if (cluster < 0) {
                err = cluster;
                goto out;
        }
-       err = msdos_add_entry(dir, msdos_name, 1, is_hid, cluster, &t, &sinfo);
+       err = msdos_add_entry(dir, msdos_name, 1, is_hid, cluster, &ts, &sinfo);
        if (err)
                goto out_free;
        inc_nlink(dir);
@@ -503,9 +499,8 @@ static int do_msdos_rename(struct inode *old_dir, unsigned char *old_name,
                new_i_pos = MSDOS_I(new_inode)->i_pos;
                fat_detach(new_inode);
        } else {
-               struct timespec t = timespec64_to_timespec(ts);
                err = msdos_add_entry(new_dir, new_name, is_dir, is_hid, 0,
-                                     &t, &sinfo);
+                                     &ts, &sinfo);
                if (err)
                        goto out;
                new_i_pos = sinfo.i_pos;
index 9a54691..82cd1e6 100644 (file)
@@ -577,7 +577,7 @@ xlate_to_uni(const unsigned char *name, int len, unsigned char *outname,
 
 static int vfat_build_slots(struct inode *dir, const unsigned char *name,
                            int len, int is_dir, int cluster,
-                           struct timespec *ts,
+                           struct timespec64 *ts,
                            struct msdos_dir_slot *slots, int *nr_slots)
 {
        struct msdos_sb_info *sbi = MSDOS_SB(dir->i_sb);
@@ -653,7 +653,7 @@ out_free:
 }
 
 static int vfat_add_entry(struct inode *dir, const struct qstr *qname,
-                         int is_dir, int cluster, struct timespec *ts,
+                         int is_dir, int cluster, struct timespec64 *ts,
                          struct fat_slot_info *sinfo)
 {
        struct msdos_dir_slot *slots;
@@ -678,7 +678,7 @@ static int vfat_add_entry(struct inode *dir, const struct qstr *qname,
                goto cleanup;
 
        /* update timestamp */
-       dir->i_ctime = dir->i_mtime = dir->i_atime = timespec_to_timespec64(*ts);
+       dir->i_ctime = dir->i_mtime = dir->i_atime = *ts;
        if (IS_DIRSYNC(dir))
                (void)fat_sync_inode(dir);
        else
@@ -762,14 +762,12 @@ static int vfat_create(struct inode *dir, struct dentry *dentry, umode_t mode,
        struct inode *inode;
        struct fat_slot_info sinfo;
        struct timespec64 ts;
-       struct timespec t;
        int err;
 
        mutex_lock(&MSDOS_SB(sb)->s_lock);
 
        ts = current_time(dir);
-       t = timespec64_to_timespec(ts);
-       err = vfat_add_entry(dir, &dentry->d_name, 0, 0, &t, &sinfo);
+       err = vfat_add_entry(dir, &dentry->d_name, 0, 0, &ts, &sinfo);
        if (err)
                goto out;
        inode_inc_iversion(dir);
@@ -853,19 +851,17 @@ static int vfat_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
        struct inode *inode;
        struct fat_slot_info sinfo;
        struct timespec64 ts;
-       struct timespec t;
        int err, cluster;
 
        mutex_lock(&MSDOS_SB(sb)->s_lock);
 
        ts = current_time(dir);
-       t = timespec64_to_timespec(ts);
-       cluster = fat_alloc_new_dir(dir, &t);
+       cluster = fat_alloc_new_dir(dir, &ts);
        if (cluster < 0) {
                err = cluster;
                goto out;
        }
-       err = vfat_add_entry(dir, &dentry->d_name, 1, cluster, &t, &sinfo);
+       err = vfat_add_entry(dir, &dentry->d_name, 1, cluster, &ts, &sinfo);
        if (err)
                goto out_free;
        inode_inc_iversion(dir);
@@ -904,7 +900,6 @@ static int vfat_rename(struct inode *old_dir, struct dentry *old_dentry,
        struct inode *old_inode, *new_inode;
        struct fat_slot_info old_sinfo, sinfo;
        struct timespec64 ts;
-       struct timespec t;
        loff_t new_i_pos;
        int err, is_dir, update_dotdot, corrupt = 0;
        struct super_block *sb = old_dir->i_sb;
@@ -939,9 +934,8 @@ static int vfat_rename(struct inode *old_dir, struct dentry *old_dentry,
                new_i_pos = MSDOS_I(new_inode)->i_pos;
                fat_detach(new_inode);
        } else {
-               t = timespec64_to_timespec(ts);
                err = vfat_add_entry(new_dir, &new_dentry->d_name, is_dir, 0,
-                                    &t, &sinfo);
+                                    &ts, &sinfo);
                if (err)
                        goto out;
                new_i_pos = sinfo.i_pos;
index 12273b6..4137d96 100644 (file)
@@ -116,7 +116,7 @@ int f_setown(struct file *filp, unsigned long arg, int force)
        struct pid *pid = NULL;
        int who = arg, ret = 0;
 
-       type = PIDTYPE_PID;
+       type = PIDTYPE_TGID;
        if (who < 0) {
                /* avoid overflow below */
                if (who == INT_MIN)
@@ -143,7 +143,7 @@ EXPORT_SYMBOL(f_setown);
 
 void f_delown(struct file *filp)
 {
-       f_modown(filp, NULL, PIDTYPE_PID, 1);
+       f_modown(filp, NULL, PIDTYPE_TGID, 1);
 }
 
 pid_t f_getown(struct file *filp)
@@ -171,11 +171,11 @@ static int f_setown_ex(struct file *filp, unsigned long arg)
 
        switch (owner.type) {
        case F_OWNER_TID:
-               type = PIDTYPE_MAX;
+               type = PIDTYPE_PID;
                break;
 
        case F_OWNER_PID:
-               type = PIDTYPE_PID;
+               type = PIDTYPE_TGID;
                break;
 
        case F_OWNER_PGRP:
@@ -206,11 +206,11 @@ static int f_getown_ex(struct file *filp, unsigned long arg)
        read_lock(&filp->f_owner.lock);
        owner.pid = pid_vnr(filp->f_owner.pid);
        switch (filp->f_owner.pid_type) {
-       case PIDTYPE_MAX:
+       case PIDTYPE_PID:
                owner.type = F_OWNER_TID;
                break;
 
-       case PIDTYPE_PID:
+       case PIDTYPE_TGID:
                owner.type = F_OWNER_PID;
                break;
 
@@ -723,7 +723,7 @@ static inline int sigio_perm(struct task_struct *p,
 
 static void send_sigio_to_task(struct task_struct *p,
                               struct fown_struct *fown,
-                              int fd, int reason, int group)
+                              int fd, int reason, enum pid_type type)
 {
        /*
         * F_SETSIG can change ->signum lockless in parallel, make
@@ -767,11 +767,11 @@ static void send_sigio_to_task(struct task_struct *p,
                        else
                                si.si_band = mangle_poll(band_table[reason - POLL_IN]);
                        si.si_fd    = fd;
-                       if (!do_send_sig_info(signum, &si, p, group))
+                       if (!do_send_sig_info(signum, &si, p, type))
                                break;
                /* fall-through: fall back on the old plain SIGIO signal */
                case 0:
-                       do_send_sig_info(SIGIO, SEND_SIG_PRIV, p, group);
+                       do_send_sig_info(SIGIO, SEND_SIG_PRIV, p, type);
        }
 }
 
@@ -780,34 +780,36 @@ void send_sigio(struct fown_struct *fown, int fd, int band)
        struct task_struct *p;
        enum pid_type type;
        struct pid *pid;
-       int group = 1;
        
        read_lock(&fown->lock);
 
        type = fown->pid_type;
-       if (type == PIDTYPE_MAX) {
-               group = 0;
-               type = PIDTYPE_PID;
-       }
-
        pid = fown->pid;
        if (!pid)
                goto out_unlock_fown;
-       
-       read_lock(&tasklist_lock);
-       do_each_pid_task(pid, type, p) {
-               send_sigio_to_task(p, fown, fd, band, group);
-       } while_each_pid_task(pid, type, p);
-       read_unlock(&tasklist_lock);
+
+       if (type <= PIDTYPE_TGID) {
+               rcu_read_lock();
+               p = pid_task(pid, PIDTYPE_PID);
+               if (p)
+                       send_sigio_to_task(p, fown, fd, band, type);
+               rcu_read_unlock();
+       } else {
+               read_lock(&tasklist_lock);
+               do_each_pid_task(pid, type, p) {
+                       send_sigio_to_task(p, fown, fd, band, type);
+               } while_each_pid_task(pid, type, p);
+               read_unlock(&tasklist_lock);
+       }
  out_unlock_fown:
        read_unlock(&fown->lock);
 }
 
 static void send_sigurg_to_task(struct task_struct *p,
-                               struct fown_struct *fown, int group)
+                               struct fown_struct *fown, enum pid_type type)
 {
        if (sigio_perm(p, fown, SIGURG))
-               do_send_sig_info(SIGURG, SEND_SIG_PRIV, p, group);
+               do_send_sig_info(SIGURG, SEND_SIG_PRIV, p, type);
 }
 
 int send_sigurg(struct fown_struct *fown)
@@ -815,28 +817,30 @@ int send_sigurg(struct fown_struct *fown)
        struct task_struct *p;
        enum pid_type type;
        struct pid *pid;
-       int group = 1;
        int ret = 0;
        
        read_lock(&fown->lock);
 
        type = fown->pid_type;
-       if (type == PIDTYPE_MAX) {
-               group = 0;
-               type = PIDTYPE_PID;
-       }
-
        pid = fown->pid;
        if (!pid)
                goto out_unlock_fown;
 
        ret = 1;
-       
-       read_lock(&tasklist_lock);
-       do_each_pid_task(pid, type, p) {
-               send_sigurg_to_task(p, fown, group);
-       } while_each_pid_task(pid, type, p);
-       read_unlock(&tasklist_lock);
+
+       if (type <= PIDTYPE_TGID) {
+               rcu_read_lock();
+               p = pid_task(pid, PIDTYPE_PID);
+               if (p)
+                       send_sigurg_to_task(p, fown, type);
+               rcu_read_unlock();
+       } else {
+               read_lock(&tasklist_lock);
+               do_each_pid_task(pid, type, p) {
+                       send_sigurg_to_task(p, fown, type);
+               } while_each_pid_task(pid, type, p);
+               read_unlock(&tasklist_lock);
+       }
  out_unlock_fown:
        read_unlock(&fown->lock);
        return ret;
index d6eccd0..e49af4c 100644 (file)
@@ -52,7 +52,8 @@ static void file_free_rcu(struct rcu_head *head)
 static inline void file_free(struct file *f)
 {
        security_file_free(f);
-       percpu_counter_dec(&nr_files);
+       if (!(f->f_mode & FMODE_NOACCOUNT))
+               percpu_counter_dec(&nr_files);
        call_rcu(&f->f_u.fu_rcuhead, file_free_rcu);
 }
 
@@ -91,6 +92,34 @@ int proc_nr_files(struct ctl_table *table, int write,
 }
 #endif
 
+static struct file *__alloc_file(int flags, const struct cred *cred)
+{
+       struct file *f;
+       int error;
+
+       f = kmem_cache_zalloc(filp_cachep, GFP_KERNEL);
+       if (unlikely(!f))
+               return ERR_PTR(-ENOMEM);
+
+       f->f_cred = get_cred(cred);
+       error = security_file_alloc(f);
+       if (unlikely(error)) {
+               file_free_rcu(&f->f_u.fu_rcuhead);
+               return ERR_PTR(error);
+       }
+
+       atomic_long_set(&f->f_count, 1);
+       rwlock_init(&f->f_owner.lock);
+       spin_lock_init(&f->f_lock);
+       mutex_init(&f->f_pos_lock);
+       eventpoll_init_file(f);
+       f->f_flags = flags;
+       f->f_mode = OPEN_FMODE(flags);
+       /* f->f_version: 0 */
+
+       return f;
+}
+
 /* Find an unused file structure and return a pointer to it.
  * Returns an error pointer if some error happend e.g. we over file
  * structures limit, run out of memory or operation is not permitted.
@@ -105,7 +134,6 @@ struct file *alloc_empty_file(int flags, const struct cred *cred)
 {
        static long old_max;
        struct file *f;
-       int error;
 
        /*
         * Privileged users can go above max_files
@@ -119,26 +147,10 @@ struct file *alloc_empty_file(int flags, const struct cred *cred)
                        goto over;
        }
 
-       f = kmem_cache_zalloc(filp_cachep, GFP_KERNEL);
-       if (unlikely(!f))
-               return ERR_PTR(-ENOMEM);
-
-       f->f_cred = get_cred(cred);
-       error = security_file_alloc(f);
-       if (unlikely(error)) {
-               file_free_rcu(&f->f_u.fu_rcuhead);
-               return ERR_PTR(error);
-       }
+       f = __alloc_file(flags, cred);
+       if (!IS_ERR(f))
+               percpu_counter_inc(&nr_files);
 
-       atomic_long_set(&f->f_count, 1);
-       rwlock_init(&f->f_owner.lock);
-       spin_lock_init(&f->f_lock);
-       mutex_init(&f->f_pos_lock);
-       eventpoll_init_file(f);
-       f->f_flags = flags;
-       f->f_mode = OPEN_FMODE(flags);
-       /* f->f_version: 0 */
-       percpu_counter_inc(&nr_files);
        return f;
 
 over:
@@ -150,6 +162,21 @@ over:
        return ERR_PTR(-ENFILE);
 }
 
+/*
+ * Variant of alloc_empty_file() that doesn't check and modify nr_files.
+ *
+ * Should not be used unless there's a very good reason to do so.
+ */
+struct file *alloc_empty_file_noaccount(int flags, const struct cred *cred)
+{
+       struct file *f = __alloc_file(flags, cred);
+
+       if (!IS_ERR(f))
+               f->f_mode |= FMODE_NOACCOUNT;
+
+       return f;
+}
+
 /**
  * alloc_file - allocate and initialize a 'struct file'
  *
index c6b88fa..11ea2c4 100644 (file)
@@ -127,6 +127,16 @@ static bool fuse_block_alloc(struct fuse_conn *fc, bool for_background)
        return !fc->initialized || (for_background && fc->blocked);
 }
 
+static void fuse_drop_waiting(struct fuse_conn *fc)
+{
+       if (fc->connected) {
+               atomic_dec(&fc->num_waiting);
+       } else if (atomic_dec_and_test(&fc->num_waiting)) {
+               /* wake up aborters */
+               wake_up_all(&fc->blocked_waitq);
+       }
+}
+
 static struct fuse_req *__fuse_get_req(struct fuse_conn *fc, unsigned npages,
                                       bool for_background)
 {
@@ -175,7 +185,7 @@ static struct fuse_req *__fuse_get_req(struct fuse_conn *fc, unsigned npages,
        return req;
 
  out:
-       atomic_dec(&fc->num_waiting);
+       fuse_drop_waiting(fc);
        return ERR_PTR(err);
 }
 
@@ -285,7 +295,7 @@ void fuse_put_request(struct fuse_conn *fc, struct fuse_req *req)
 
                if (test_bit(FR_WAITING, &req->flags)) {
                        __clear_bit(FR_WAITING, &req->flags);
-                       atomic_dec(&fc->num_waiting);
+                       fuse_drop_waiting(fc);
                }
 
                if (req->stolen_file)
@@ -371,7 +381,7 @@ static void request_end(struct fuse_conn *fc, struct fuse_req *req)
        struct fuse_iqueue *fiq = &fc->iq;
 
        if (test_and_set_bit(FR_FINISHED, &req->flags))
-               return;
+               goto put_request;
 
        spin_lock(&fiq->waitq.lock);
        list_del_init(&req->intr_entry);
@@ -400,6 +410,7 @@ static void request_end(struct fuse_conn *fc, struct fuse_req *req)
        wake_up(&req->waitq);
        if (req->end)
                req->end(fc, req);
+put_request:
        fuse_put_request(fc, req);
 }
 
@@ -1362,8 +1373,8 @@ static ssize_t fuse_dev_splice_read(struct file *in, loff_t *ppos,
        if (!fud)
                return -EPERM;
 
-       bufs = kmalloc_array(pipe->buffers, sizeof(struct pipe_buffer),
-                            GFP_KERNEL);
+       bufs = kvmalloc_array(pipe->buffers, sizeof(struct pipe_buffer),
+                             GFP_KERNEL);
        if (!bufs)
                return -ENOMEM;
 
@@ -1396,7 +1407,7 @@ out:
        for (; page_nr < cs.nr_segs; page_nr++)
                put_page(bufs[page_nr].page);
 
-       kfree(bufs);
+       kvfree(bufs);
        return ret;
 }
 
@@ -1944,12 +1955,15 @@ static ssize_t fuse_dev_splice_write(struct pipe_inode_info *pipe,
        if (!fud)
                return -EPERM;
 
-       bufs = kmalloc_array(pipe->buffers, sizeof(struct pipe_buffer),
-                            GFP_KERNEL);
-       if (!bufs)
+       pipe_lock(pipe);
+
+       bufs = kvmalloc_array(pipe->nrbufs, sizeof(struct pipe_buffer),
+                             GFP_KERNEL);
+       if (!bufs) {
+               pipe_unlock(pipe);
                return -ENOMEM;
+       }
 
-       pipe_lock(pipe);
        nbuf = 0;
        rem = 0;
        for (idx = 0; idx < pipe->nrbufs && rem < len; idx++)
@@ -2003,7 +2017,7 @@ static ssize_t fuse_dev_splice_write(struct pipe_inode_info *pipe,
                pipe_buf_release(pipe, &bufs[idx]);
 
 out:
-       kfree(bufs);
+       kvfree(bufs);
        return ret;
 }
 
@@ -2087,8 +2101,7 @@ void fuse_abort_conn(struct fuse_conn *fc, bool is_abort)
        if (fc->connected) {
                struct fuse_dev *fud;
                struct fuse_req *req, *next;
-               LIST_HEAD(to_end1);
-               LIST_HEAD(to_end2);
+               LIST_HEAD(to_end);
 
                fc->connected = 0;
                fc->blocked = 0;
@@ -2105,11 +2118,12 @@ void fuse_abort_conn(struct fuse_conn *fc, bool is_abort)
                                set_bit(FR_ABORTED, &req->flags);
                                if (!test_bit(FR_LOCKED, &req->flags)) {
                                        set_bit(FR_PRIVATE, &req->flags);
-                                       list_move(&req->list, &to_end1);
+                                       __fuse_get_request(req);
+                                       list_move(&req->list, &to_end);
                                }
                                spin_unlock(&req->waitq.lock);
                        }
-                       list_splice_init(&fpq->processing, &to_end2);
+                       list_splice_tail_init(&fpq->processing, &to_end);
                        spin_unlock(&fpq->lock);
                }
                fc->max_background = UINT_MAX;
@@ -2117,9 +2131,9 @@ void fuse_abort_conn(struct fuse_conn *fc, bool is_abort)
 
                spin_lock(&fiq->waitq.lock);
                fiq->connected = 0;
-               list_splice_init(&fiq->pending, &to_end2);
-               list_for_each_entry(req, &to_end2, list)
+               list_for_each_entry(req, &fiq->pending, list)
                        clear_bit(FR_PENDING, &req->flags);
+               list_splice_tail_init(&fiq->pending, &to_end);
                while (forget_pending(fiq))
                        kfree(dequeue_forget(fiq, 1, NULL));
                wake_up_all_locked(&fiq->waitq);
@@ -2129,19 +2143,18 @@ void fuse_abort_conn(struct fuse_conn *fc, bool is_abort)
                wake_up_all(&fc->blocked_waitq);
                spin_unlock(&fc->lock);
 
-               while (!list_empty(&to_end1)) {
-                       req = list_first_entry(&to_end1, struct fuse_req, list);
-                       __fuse_get_request(req);
-                       list_del_init(&req->list);
-                       request_end(fc, req);
-               }
-               end_requests(fc, &to_end2);
+               end_requests(fc, &to_end);
        } else {
                spin_unlock(&fc->lock);
        }
 }
 EXPORT_SYMBOL_GPL(fuse_abort_conn);
 
+void fuse_wait_aborted(struct fuse_conn *fc)
+{
+       wait_event(fc->blocked_waitq, atomic_read(&fc->num_waiting) == 0);
+}
+
 int fuse_dev_release(struct inode *inode, struct file *file)
 {
        struct fuse_dev *fud = fuse_get_dev(file);
@@ -2149,9 +2162,15 @@ int fuse_dev_release(struct inode *inode, struct file *file)
        if (fud) {
                struct fuse_conn *fc = fud->fc;
                struct fuse_pqueue *fpq = &fud->pq;
+               LIST_HEAD(to_end);
 
+               spin_lock(&fpq->lock);
                WARN_ON(!list_empty(&fpq->io));
-               end_requests(fc, &fpq->processing);
+               list_splice_init(&fpq->processing, &to_end);
+               spin_unlock(&fpq->lock);
+
+               end_requests(fc, &to_end);
+
                /* Are we the last open device? */
                if (atomic_dec_and_test(&fc->dev_count)) {
                        WARN_ON(fc->iq.fasync != NULL);
index d80aab0..0979609 100644 (file)
@@ -355,11 +355,12 @@ static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
        struct inode *inode;
        struct dentry *newent;
        bool outarg_valid = true;
+       bool locked;
 
-       fuse_lock_inode(dir);
+       locked = fuse_lock_inode(dir);
        err = fuse_lookup_name(dir->i_sb, get_node_id(dir), &entry->d_name,
                               &outarg, &inode);
-       fuse_unlock_inode(dir);
+       fuse_unlock_inode(dir, locked);
        if (err == -ENOENT) {
                outarg_valid = false;
                err = 0;
@@ -1347,6 +1348,7 @@ static int fuse_readdir(struct file *file, struct dir_context *ctx)
        struct fuse_conn *fc = get_fuse_conn(inode);
        struct fuse_req *req;
        u64 attr_version = 0;
+       bool locked;
 
        if (is_bad_inode(inode))
                return -EIO;
@@ -1374,9 +1376,9 @@ static int fuse_readdir(struct file *file, struct dir_context *ctx)
                fuse_read_fill(req, file, ctx->pos, PAGE_SIZE,
                               FUSE_READDIR);
        }
-       fuse_lock_inode(inode);
+       locked = fuse_lock_inode(inode);
        fuse_request_send(fc, req);
-       fuse_unlock_inode(inode);
+       fuse_unlock_inode(inode, locked);
        nbytes = req->out.args[0].size;
        err = req->out.h.error;
        fuse_put_request(fc, req);
index a201fb0..32d0b88 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/slab.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
+#include <linux/sched/signal.h>
 #include <linux/module.h>
 #include <linux/compat.h>
 #include <linux/swap.h>
@@ -866,6 +867,7 @@ static int fuse_readpages_fill(void *_data, struct page *page)
        }
 
        if (WARN_ON(req->num_pages >= req->max_pages)) {
+               unlock_page(page);
                fuse_put_request(fc, req);
                return -EIO;
        }
@@ -2048,7 +2050,7 @@ static void fuse_vma_close(struct vm_area_struct *vma)
  * - sync(2)
  * - try_to_free_pages() with order > PAGE_ALLOC_COSTLY_ORDER
  */
-static int fuse_page_mkwrite(struct vm_fault *vmf)
+static vm_fault_t fuse_page_mkwrite(struct vm_fault *vmf)
 {
        struct page *page = vmf->page;
        struct inode *inode = file_inode(vmf->vma->vm_file);
index 5256ad3..f78e961 100644 (file)
@@ -862,6 +862,7 @@ void fuse_request_send_background_locked(struct fuse_conn *fc,
 
 /* Abort all requests */
 void fuse_abort_conn(struct fuse_conn *fc, bool is_abort);
+void fuse_wait_aborted(struct fuse_conn *fc);
 
 /**
  * Invalidate inode attributes
@@ -974,8 +975,8 @@ int fuse_do_setattr(struct dentry *dentry, struct iattr *attr,
 
 void fuse_set_initialized(struct fuse_conn *fc);
 
-void fuse_unlock_inode(struct inode *inode);
-void fuse_lock_inode(struct inode *inode);
+void fuse_unlock_inode(struct inode *inode, bool locked);
+bool fuse_lock_inode(struct inode *inode);
 
 int fuse_setxattr(struct inode *inode, const char *name, const void *value,
                  size_t size, int flags);
index a24df88..db9e60b 100644 (file)
@@ -208,7 +208,7 @@ void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr,
        struct fuse_inode *fi = get_fuse_inode(inode);
        bool is_wb = fc->writeback_cache;
        loff_t oldsize;
-       struct timespec old_mtime;
+       struct timespec64 old_mtime;
 
        spin_lock(&fc->lock);
        if ((attr_version != 0 && fi->attr_version > attr_version) ||
@@ -217,7 +217,7 @@ void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr,
                return;
        }
 
-       old_mtime = timespec64_to_timespec(inode->i_mtime);
+       old_mtime = inode->i_mtime;
        fuse_change_attributes_common(inode, attr, attr_valid);
 
        oldsize = inode->i_size;
@@ -237,7 +237,7 @@ void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr,
                        truncate_pagecache(inode, attr->size);
                        inval = true;
                } else if (fc->auto_inval_data) {
-                       struct timespec new_mtime = {
+                       struct timespec64 new_mtime = {
                                .tv_sec = attr->mtime,
                                .tv_nsec = attr->mtimensec,
                        };
@@ -246,7 +246,7 @@ void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr,
                         * Auto inval mode also checks and invalidates if mtime
                         * has changed.
                         */
-                       if (!timespec_equal(&old_mtime, &new_mtime))
+                       if (!timespec64_equal(&old_mtime, &new_mtime))
                                inval = true;
                }
 
@@ -357,15 +357,21 @@ int fuse_reverse_inval_inode(struct super_block *sb, u64 nodeid,
        return 0;
 }
 
-void fuse_lock_inode(struct inode *inode)
+bool fuse_lock_inode(struct inode *inode)
 {
-       if (!get_fuse_conn(inode)->parallel_dirops)
+       bool locked = false;
+
+       if (!get_fuse_conn(inode)->parallel_dirops) {
                mutex_lock(&get_fuse_inode(inode)->mutex);
+               locked = true;
+       }
+
+       return locked;
 }
 
-void fuse_unlock_inode(struct inode *inode)
+void fuse_unlock_inode(struct inode *inode, bool locked)
 {
-       if (!get_fuse_conn(inode)->parallel_dirops)
+       if (locked)
                mutex_unlock(&get_fuse_inode(inode)->mutex);
 }
 
@@ -391,9 +397,6 @@ static void fuse_put_super(struct super_block *sb)
 {
        struct fuse_conn *fc = get_fuse_conn_super(sb);
 
-       fuse_send_destroy(fc);
-
-       fuse_abort_conn(fc, false);
        mutex_lock(&fuse_mutex);
        list_del(&fc->entry);
        fuse_ctl_remove_conn(fc);
@@ -1210,16 +1213,25 @@ static struct dentry *fuse_mount(struct file_system_type *fs_type,
        return mount_nodev(fs_type, flags, raw_data, fuse_fill_super);
 }
 
-static void fuse_kill_sb_anon(struct super_block *sb)
+static void fuse_sb_destroy(struct super_block *sb)
 {
        struct fuse_conn *fc = get_fuse_conn_super(sb);
 
        if (fc) {
+               fuse_send_destroy(fc);
+
+               fuse_abort_conn(fc, false);
+               fuse_wait_aborted(fc);
+
                down_write(&fc->killsb);
                fc->sb = NULL;
                up_write(&fc->killsb);
        }
+}
 
+static void fuse_kill_sb_anon(struct super_block *sb)
+{
+       fuse_sb_destroy(sb);
        kill_anon_super(sb);
 }
 
@@ -1242,14 +1254,7 @@ static struct dentry *fuse_mount_blk(struct file_system_type *fs_type,
 
 static void fuse_kill_sb_blk(struct super_block *sb)
 {
-       struct fuse_conn *fc = get_fuse_conn_super(sb);
-
-       if (fc) {
-               down_write(&fc->killsb);
-               fc->sb = NULL;
-               up_write(&fc->killsb);
-       }
-
+       fuse_sb_destroy(sb);
        kill_block_super(sb);
 }
 
index ad04a57..9a87724 100644 (file)
@@ -75,9 +75,10 @@ int hfs_brec_insert(struct hfs_find_data *fd, void *entry, int entry_len)
        if (!fd->bnode) {
                if (!tree->root)
                        hfs_btree_inc_height(tree);
-               fd->bnode = hfs_bnode_find(tree, tree->leaf_head);
-               if (IS_ERR(fd->bnode))
-                       return PTR_ERR(fd->bnode);
+               node = hfs_bnode_find(tree, tree->leaf_head);
+               if (IS_ERR(node))
+                       return PTR_ERR(node);
+               fd->bnode = node;
                fd->record = -1;
        }
        new_node = NULL;
index 7cc8b4a..a633718 100644 (file)
@@ -11,18 +11,3 @@ config HFSPLUS_FS
          MacOS 8. It includes all Mac specific filesystem data such as
          data forks and creator codes, but it also has several UNIX
          style features such as file ownership and permissions.
-
-config HFSPLUS_FS_POSIX_ACL
-       bool "HFS+ POSIX Access Control Lists"
-       depends on HFSPLUS_FS
-       select FS_POSIX_ACL
-       help
-         POSIX Access Control Lists (ACLs) support permissions for users and
-         groups beyond the owner/group/world scheme.
-
-         It needs to understand that POSIX ACLs are treated only under
-         Linux. POSIX ACLs doesn't mean something under Mac OS X.
-         Mac OS X beginning with version 10.4 ("Tiger") support NFSv4 ACLs,
-         which are part of the NFSv4 standard.
-
-         If you don't know what Access Control Lists are, say N
index f6a5654..9ed20e6 100644 (file)
@@ -8,5 +8,3 @@ obj-$(CONFIG_HFSPLUS_FS) += hfsplus.o
 hfsplus-objs := super.o options.o inode.o ioctl.o extents.o catalog.o dir.o btree.o \
                bnode.o brec.o bfind.o tables.o unicode.o wrapper.o bitmap.o part_tbl.o \
                attributes.o xattr.o xattr_user.o xattr_security.o xattr_trusted.o
-
-hfsplus-$(CONFIG_HFSPLUS_FS_POSIX_ACL) += posix_acl.o
diff --git a/fs/hfsplus/acl.h b/fs/hfsplus/acl.h
deleted file mode 100644 (file)
index 488c2b7..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * linux/fs/hfsplus/acl.h
- *
- * Vyacheslav Dubeyko <slava@dubeyko.com>
- *
- * Handler for Posix Access Control Lists (ACLs) support.
- */
-
-#include <linux/posix_acl_xattr.h>
-
-#ifdef CONFIG_HFSPLUS_FS_POSIX_ACL
-
-/* posix_acl.c */
-struct posix_acl *hfsplus_get_posix_acl(struct inode *inode, int type);
-int hfsplus_set_posix_acl(struct inode *inode, struct posix_acl *acl,
-               int type);
-extern int hfsplus_init_posix_acl(struct inode *, struct inode *);
-
-#else  /* CONFIG_HFSPLUS_FS_POSIX_ACL */
-#define hfsplus_get_posix_acl NULL
-#define hfsplus_set_posix_acl NULL
-
-static inline int hfsplus_init_posix_acl(struct inode *inode, struct inode *dir)
-{
-       return 0;
-}
-#endif  /* CONFIG_HFSPLUS_FS_POSIX_ACL */
index 808f4d8..ed8eacb 100644 (file)
@@ -73,9 +73,10 @@ int hfs_brec_insert(struct hfs_find_data *fd, void *entry, int entry_len)
        if (!fd->bnode) {
                if (!tree->root)
                        hfs_btree_inc_height(tree);
-               fd->bnode = hfs_bnode_find(tree, tree->leaf_head);
-               if (IS_ERR(fd->bnode))
-                       return PTR_ERR(fd->bnode);
+               node = hfs_bnode_find(tree, tree->leaf_head);
+               if (IS_ERR(node))
+                       return PTR_ERR(node);
+               fd->bnode = node;
                fd->record = -1;
        }
        new_node = NULL;
index b525437..f376626 100644 (file)
@@ -18,7 +18,6 @@
 #include "hfsplus_fs.h"
 #include "hfsplus_raw.h"
 #include "xattr.h"
-#include "acl.h"
 
 static inline void hfsplus_instantiate(struct dentry *dentry,
                                       struct inode *inode, u32 cnid)
@@ -78,13 +77,13 @@ again:
                                cpu_to_be32(HFSP_HARDLINK_TYPE) &&
                                entry.file.user_info.fdCreator ==
                                cpu_to_be32(HFSP_HFSPLUS_CREATOR) &&
+                               HFSPLUS_SB(sb)->hidden_dir &&
                                (entry.file.create_date ==
                                        HFSPLUS_I(HFSPLUS_SB(sb)->hidden_dir)->
                                                create_date ||
                                entry.file.create_date ==
                                        HFSPLUS_I(d_inode(sb->s_root))->
-                                               create_date) &&
-                               HFSPLUS_SB(sb)->hidden_dir) {
+                                               create_date)) {
                        struct qstr str;
                        char name[32];
 
@@ -455,7 +454,7 @@ static int hfsplus_symlink(struct inode *dir, struct dentry *dentry,
        if (res)
                goto out_err;
 
-       res = hfsplus_init_inode_security(inode, dir, &dentry->d_name);
+       res = hfsplus_init_security(inode, dir, &dentry->d_name);
        if (res == -EOPNOTSUPP)
                res = 0; /* Operation is not supported. */
        else if (res) {
@@ -496,7 +495,7 @@ static int hfsplus_mknod(struct inode *dir, struct dentry *dentry,
        if (res)
                goto failed_mknod;
 
-       res = hfsplus_init_inode_security(inode, dir, &dentry->d_name);
+       res = hfsplus_init_security(inode, dir, &dentry->d_name);
        if (res == -EOPNOTSUPP)
                res = 0; /* Operation is not supported. */
        else if (res) {
@@ -567,10 +566,6 @@ const struct inode_operations hfsplus_dir_inode_operations = {
        .mknod                  = hfsplus_mknod,
        .rename                 = hfsplus_rename,
        .listxattr              = hfsplus_listxattr,
-#ifdef CONFIG_HFSPLUS_FS_POSIX_ACL
-       .get_acl                = hfsplus_get_posix_acl,
-       .set_acl                = hfsplus_set_posix_acl,
-#endif
 };
 
 const struct file_operations hfsplus_dir_operations = {
index e877093..8e0f597 100644 (file)
@@ -336,6 +336,9 @@ static int hfsplus_free_extents(struct super_block *sb,
        int i;
        int err = 0;
 
+       /* Mapping the allocation file may lock the extent tree */
+       WARN_ON(mutex_is_locked(&HFSPLUS_SB(sb)->ext_tree->tree_lock));
+
        hfsplus_dump_extent(extent);
        for (i = 0; i < 8; extent++, i++) {
                count = be32_to_cpu(extent->block_count);
@@ -415,11 +418,13 @@ int hfsplus_free_fork(struct super_block *sb, u32 cnid,
                if (res)
                        break;
                start = be32_to_cpu(fd.key->ext.start_block);
-               hfsplus_free_extents(sb, ext_entry,
-                                    total_blocks - start,
-                                    total_blocks);
                hfs_brec_remove(&fd);
+
+               mutex_unlock(&fd.tree->tree_lock);
+               hfsplus_free_extents(sb, ext_entry, total_blocks - start,
+                                    total_blocks);
                total_blocks = start;
+               mutex_lock(&fd.tree->tree_lock);
        } while (total_blocks > blocks);
        hfs_find_exit(&fd);
 
@@ -576,15 +581,20 @@ void hfsplus_file_truncate(struct inode *inode)
        }
        while (1) {
                if (alloc_cnt == hip->first_blocks) {
+                       mutex_unlock(&fd.tree->tree_lock);
                        hfsplus_free_extents(sb, hip->first_extents,
                                             alloc_cnt, alloc_cnt - blk_cnt);
                        hfsplus_dump_extent(hip->first_extents);
                        hip->first_blocks = blk_cnt;
+                       mutex_lock(&fd.tree->tree_lock);
                        break;
                }
                res = __hfsplus_ext_cache_extent(&fd, inode, alloc_cnt);
                if (res)
                        break;
+               hfs_brec_remove(&fd);
+
+               mutex_unlock(&fd.tree->tree_lock);
                start = hip->cached_start;
                hfsplus_free_extents(sb, hip->cached_extents,
                                     alloc_cnt - start, alloc_cnt - blk_cnt);
@@ -596,7 +606,7 @@ void hfsplus_file_truncate(struct inode *inode)
                alloc_cnt = start;
                hip->cached_start = hip->cached_blocks = 0;
                hip->extent_state &= ~(HFSPLUS_EXT_DIRTY | HFSPLUS_EXT_NEW);
-               hfs_brec_remove(&fd);
+               mutex_lock(&fd.tree->tree_lock);
        }
        hfs_find_exit(&fd);
 
index d9255ab..8e03943 100644 (file)
@@ -31,7 +31,6 @@
 #define DBG_EXTENT     0x00000020
 #define DBG_BITMAP     0x00000040
 #define DBG_ATTR_MOD   0x00000080
-#define DBG_ACL_MOD    0x00000100
 
 #if 0
 #define DBG_MASK       (DBG_EXTENT|DBG_INODE|DBG_BNODE_MOD)
index c824f70..8e9427a 100644 (file)
@@ -21,7 +21,6 @@
 #include "hfsplus_fs.h"
 #include "hfsplus_raw.h"
 #include "xattr.h"
-#include "acl.h"
 
 static int hfsplus_readpage(struct file *file, struct page *page)
 {
@@ -267,12 +266,6 @@ static int hfsplus_setattr(struct dentry *dentry, struct iattr *attr)
        setattr_copy(inode, attr);
        mark_inode_dirty(inode);
 
-       if (attr->ia_valid & ATTR_MODE) {
-               error = posix_acl_chmod(inode, inode->i_mode);
-               if (unlikely(error))
-                       return error;
-       }
-
        return 0;
 }
 
@@ -336,10 +329,6 @@ int hfsplus_file_fsync(struct file *file, loff_t start, loff_t end,
 static const struct inode_operations hfsplus_file_inode_operations = {
        .setattr        = hfsplus_setattr,
        .listxattr      = hfsplus_listxattr,
-#ifdef CONFIG_HFSPLUS_FS_POSIX_ACL
-       .get_acl        = hfsplus_get_posix_acl,
-       .set_acl        = hfsplus_set_posix_acl,
-#endif
 };
 
 static const struct file_operations hfsplus_file_operations = {
diff --git a/fs/hfsplus/posix_acl.c b/fs/hfsplus/posix_acl.c
deleted file mode 100644 (file)
index 066114d..0000000
+++ /dev/null
@@ -1,144 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * linux/fs/hfsplus/posix_acl.c
- *
- * Vyacheslav Dubeyko <slava@dubeyko.com>
- *
- * Handler for Posix Access Control Lists (ACLs) support.
- */
-
-#include "hfsplus_fs.h"
-#include "xattr.h"
-#include "acl.h"
-
-struct posix_acl *hfsplus_get_posix_acl(struct inode *inode, int type)
-{
-       struct posix_acl *acl;
-       char *xattr_name;
-       char *value = NULL;
-       ssize_t size;
-
-       hfs_dbg(ACL_MOD, "[%s]: ino %lu\n", __func__, inode->i_ino);
-
-       switch (type) {
-       case ACL_TYPE_ACCESS:
-               xattr_name = XATTR_NAME_POSIX_ACL_ACCESS;
-               break;
-       case ACL_TYPE_DEFAULT:
-               xattr_name = XATTR_NAME_POSIX_ACL_DEFAULT;
-               break;
-       default:
-               return ERR_PTR(-EINVAL);
-       }
-
-       size = __hfsplus_getxattr(inode, xattr_name, NULL, 0);
-
-       if (size > 0) {
-               value = (char *)hfsplus_alloc_attr_entry();
-               if (unlikely(!value))
-                       return ERR_PTR(-ENOMEM);
-               size = __hfsplus_getxattr(inode, xattr_name, value, size);
-       }
-
-       if (size > 0)
-               acl = posix_acl_from_xattr(&init_user_ns, value, size);
-       else if (size == -ENODATA)
-               acl = NULL;
-       else
-               acl = ERR_PTR(size);
-
-       hfsplus_destroy_attr_entry((hfsplus_attr_entry *)value);
-
-       return acl;
-}
-
-static int __hfsplus_set_posix_acl(struct inode *inode, struct posix_acl *acl,
-                                  int type)
-{
-       int err;
-       char *xattr_name;
-       size_t size = 0;
-       char *value = NULL;
-
-       hfs_dbg(ACL_MOD, "[%s]: ino %lu\n", __func__, inode->i_ino);
-
-       switch (type) {
-       case ACL_TYPE_ACCESS:
-               xattr_name = XATTR_NAME_POSIX_ACL_ACCESS;
-               break;
-
-       case ACL_TYPE_DEFAULT:
-               xattr_name = XATTR_NAME_POSIX_ACL_DEFAULT;
-               if (!S_ISDIR(inode->i_mode))
-                       return acl ? -EACCES : 0;
-               break;
-
-       default:
-               return -EINVAL;
-       }
-
-       if (acl) {
-               size = posix_acl_xattr_size(acl->a_count);
-               if (unlikely(size > HFSPLUS_MAX_INLINE_DATA_SIZE))
-                       return -ENOMEM;
-               value = (char *)hfsplus_alloc_attr_entry();
-               if (unlikely(!value))
-                       return -ENOMEM;
-               err = posix_acl_to_xattr(&init_user_ns, acl, value, size);
-               if (unlikely(err < 0))
-                       goto end_set_acl;
-       }
-
-       err = __hfsplus_setxattr(inode, xattr_name, value, size, 0);
-
-end_set_acl:
-       hfsplus_destroy_attr_entry((hfsplus_attr_entry *)value);
-
-       if (!err)
-               set_cached_acl(inode, type, acl);
-
-       return err;
-}
-
-int hfsplus_set_posix_acl(struct inode *inode, struct posix_acl *acl, int type)
-{
-       int err;
-
-       if (type == ACL_TYPE_ACCESS && acl) {
-               err = posix_acl_update_mode(inode, &inode->i_mode, &acl);
-               if (err)
-                       return err;
-       }
-       return __hfsplus_set_posix_acl(inode, acl, type);
-}
-
-int hfsplus_init_posix_acl(struct inode *inode, struct inode *dir)
-{
-       int err = 0;
-       struct posix_acl *default_acl, *acl;
-
-       hfs_dbg(ACL_MOD,
-               "[%s]: ino %lu, dir->ino %lu\n",
-               __func__, inode->i_ino, dir->i_ino);
-
-       if (S_ISLNK(inode->i_mode))
-               return 0;
-
-       err = posix_acl_create(dir, &inode->i_mode, &default_acl, &acl);
-       if (err)
-               return err;
-
-       if (default_acl) {
-               err = __hfsplus_set_posix_acl(inode, default_acl,
-                                             ACL_TYPE_DEFAULT);
-               posix_acl_release(default_acl);
-       }
-
-       if (acl) {
-               if (!err)
-                       err = __hfsplus_set_posix_acl(inode, acl,
-                                                     ACL_TYPE_ACCESS);
-               posix_acl_release(acl);
-       }
-       return err;
-}
index a6c0f54..eb4535e 100644 (file)
@@ -524,8 +524,10 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent)
                goto out_put_root;
        if (!hfs_brec_read(&fd, &entry, sizeof(entry))) {
                hfs_find_exit(&fd);
-               if (entry.type != cpu_to_be16(HFSPLUS_FOLDER))
+               if (entry.type != cpu_to_be16(HFSPLUS_FOLDER)) {
+                       err = -EINVAL;
                        goto out_put_root;
+               }
                inode = hfsplus_iget(sb, be32_to_cpu(entry.folder.id));
                if (IS_ERR(inode)) {
                        err = PTR_ERR(inode);
@@ -562,8 +564,8 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent)
                                goto out_put_hidden_dir;
                        }
 
-                       err = hfsplus_init_inode_security(sbi->hidden_dir,
-                                                               root, &str);
+                       err = hfsplus_init_security(sbi->hidden_dir,
+                                                       root, &str);
                        if (err == -EOPNOTSUPP)
                                err = 0; /* Operation is not supported. */
                        else if (err) {
index dfa90c2..c8d1b2b 100644 (file)
@@ -272,8 +272,8 @@ static inline int asc2unichar(struct super_block *sb, const char *astr, int len,
        return size;
 }
 
-/* Decomposes a single unicode character. */
-static inline u16 *decompose_unichar(wchar_t uc, int *size)
+/* Decomposes a non-Hangul unicode character. */
+static u16 *hfsplus_decompose_nonhangul(wchar_t uc, int *size)
 {
        int off;
 
@@ -296,6 +296,51 @@ static inline u16 *decompose_unichar(wchar_t uc, int *size)
        return hfsplus_decompose_table + (off / 4);
 }
 
+/*
+ * Try to decompose a unicode character as Hangul. Return 0 if @uc is not
+ * precomposed Hangul, otherwise return the length of the decomposition.
+ *
+ * This function was adapted from sample code from the Unicode Standard
+ * Annex #15: Unicode Normalization Forms, version 3.2.0.
+ *
+ * Copyright (C) 1991-2018 Unicode, Inc.  All rights reserved.  Distributed
+ * under the Terms of Use in http://www.unicode.org/copyright.html.
+ */
+static int hfsplus_try_decompose_hangul(wchar_t uc, u16 *result)
+{
+       int index;
+       int l, v, t;
+
+       index = uc - Hangul_SBase;
+       if (index < 0 || index >= Hangul_SCount)
+               return 0;
+
+       l = Hangul_LBase + index / Hangul_NCount;
+       v = Hangul_VBase + (index % Hangul_NCount) / Hangul_TCount;
+       t = Hangul_TBase + index % Hangul_TCount;
+
+       result[0] = l;
+       result[1] = v;
+       if (t != Hangul_TBase) {
+               result[2] = t;
+               return 3;
+       }
+       return 2;
+}
+
+/* Decomposes a single unicode character. */
+static u16 *decompose_unichar(wchar_t uc, int *size, u16 *hangul_buffer)
+{
+       u16 *result;
+
+       /* Hangul is handled separately */
+       result = hangul_buffer;
+       *size = hfsplus_try_decompose_hangul(uc, result);
+       if (*size == 0)
+               result = hfsplus_decompose_nonhangul(uc, size);
+       return result;
+}
+
 int hfsplus_asc2uni(struct super_block *sb,
                    struct hfsplus_unistr *ustr, int max_unistr_len,
                    const char *astr, int len)
@@ -303,13 +348,14 @@ int hfsplus_asc2uni(struct super_block *sb,
        int size, dsize, decompose;
        u16 *dstr, outlen = 0;
        wchar_t c;
+       u16 dhangul[3];
 
        decompose = !test_bit(HFSPLUS_SB_NODECOMPOSE, &HFSPLUS_SB(sb)->flags);
        while (outlen < max_unistr_len && len > 0) {
                size = asc2unichar(sb, astr, len, &c);
 
                if (decompose)
-                       dstr = decompose_unichar(c, &dsize);
+                       dstr = decompose_unichar(c, &dsize, dhangul);
                else
                        dstr = NULL;
                if (dstr) {
@@ -344,6 +390,7 @@ int hfsplus_hash_dentry(const struct dentry *dentry, struct qstr *str)
        unsigned long hash;
        wchar_t c;
        u16 c2;
+       u16 dhangul[3];
 
        casefold = test_bit(HFSPLUS_SB_CASEFOLD, &HFSPLUS_SB(sb)->flags);
        decompose = !test_bit(HFSPLUS_SB_NODECOMPOSE, &HFSPLUS_SB(sb)->flags);
@@ -357,7 +404,7 @@ int hfsplus_hash_dentry(const struct dentry *dentry, struct qstr *str)
                len -= size;
 
                if (decompose)
-                       dstr = decompose_unichar(c, &dsize);
+                       dstr = decompose_unichar(c, &dsize, dhangul);
                else
                        dstr = NULL;
                if (dstr) {
@@ -396,6 +443,7 @@ int hfsplus_compare_dentry(const struct dentry *dentry,
        const char *astr1, *astr2;
        u16 c1, c2;
        wchar_t c;
+       u16 dhangul_1[3], dhangul_2[3];
 
        casefold = test_bit(HFSPLUS_SB_CASEFOLD, &HFSPLUS_SB(sb)->flags);
        decompose = !test_bit(HFSPLUS_SB_NODECOMPOSE, &HFSPLUS_SB(sb)->flags);
@@ -413,7 +461,8 @@ int hfsplus_compare_dentry(const struct dentry *dentry,
                        len1 -= size;
 
                        if (decompose)
-                               dstr1 = decompose_unichar(c, &dsize1);
+                               dstr1 = decompose_unichar(c, &dsize1,
+                                                         dhangul_1);
                        if (!decompose || !dstr1) {
                                c1 = c;
                                dstr1 = &c1;
@@ -427,7 +476,8 @@ int hfsplus_compare_dentry(const struct dentry *dentry,
                        len2 -= size;
 
                        if (decompose)
-                               dstr2 = decompose_unichar(c, &dsize2);
+                               dstr2 = decompose_unichar(c, &dsize2,
+                                                         dhangul_2);
                        if (!decompose || !dstr2) {
                                c2 = c;
                                dstr2 = &c2;
index e538b75..d5403b4 100644 (file)
@@ -8,10 +8,8 @@
  */
 
 #include "hfsplus_fs.h"
-#include <linux/posix_acl_xattr.h>
 #include <linux/nls.h>
 #include "xattr.h"
-#include "acl.h"
 
 static int hfsplus_removexattr(struct inode *inode, const char *name);
 
@@ -19,10 +17,6 @@ const struct xattr_handler *hfsplus_xattr_handlers[] = {
        &hfsplus_xattr_osx_handler,
        &hfsplus_xattr_user_handler,
        &hfsplus_xattr_trusted_handler,
-#ifdef CONFIG_HFSPLUS_FS_POSIX_ACL
-       &posix_acl_access_xattr_handler,
-       &posix_acl_default_xattr_handler,
-#endif
        &hfsplus_xattr_security_handler,
        NULL
 };
index a4e611d..d14e362 100644 (file)
@@ -38,7 +38,4 @@ ssize_t hfsplus_listxattr(struct dentry *dentry, char *buffer, size_t size);
 int hfsplus_init_security(struct inode *inode, struct inode *dir,
                                const struct qstr *qstr);
 
-int hfsplus_init_inode_security(struct inode *inode, struct inode *dir,
-                               const struct qstr *qstr);
-
 #endif
index f5550b0..cfbe6a3 100644 (file)
@@ -12,7 +12,6 @@
 
 #include "hfsplus_fs.h"
 #include "xattr.h"
-#include "acl.h"
 
 static int hfsplus_security_getxattr(const struct xattr_handler *handler,
                                     struct dentry *unused, struct inode *inode,
@@ -72,18 +71,6 @@ int hfsplus_init_security(struct inode *inode, struct inode *dir,
                                        &hfsplus_initxattrs, NULL);
 }
 
-int hfsplus_init_inode_security(struct inode *inode,
-                                               struct inode *dir,
-                                               const struct qstr *qstr)
-{
-       int err;
-
-       err = hfsplus_init_posix_acl(inode, dir);
-       if (!err)
-               err = hfsplus_init_security(inode, dir, qstr);
-       return err;
-}
-
 const struct xattr_handler hfsplus_xattr_security_handler = {
        .prefix = XATTR_SECURITY_PREFIX,
        .get    = hfsplus_security_getxattr,
index 082b7c7..1aee391 100644 (file)
@@ -565,7 +565,7 @@ static int hpfs_rename(struct inode *old_dir, struct dentry *old_dentry,
                        err = -EFSERROR;
                        goto end1;
                }
-               err = r == 2 ? -ENOSPC : r == 1 ? -EFSERROR : 0;
+               err = -ENOSPC;
                goto end1;
        }
 
index 346a146..32920a1 100644 (file)
@@ -410,7 +410,6 @@ static void remove_inode_hugepages(struct inode *inode, loff_t lstart,
        int i, freed = 0;
        bool truncate_op = (lend == LLONG_MAX);
 
-       memset(&pseudo_vma, 0, sizeof(struct vm_area_struct));
        vma_init(&pseudo_vma, current->mm);
        pseudo_vma.vm_flags = (VM_HUGETLB | VM_MAYSHARE | VM_SHARED);
        pagevec_init(&pvec);
@@ -595,7 +594,6 @@ static long hugetlbfs_fallocate(struct file *file, int mode, loff_t offset,
         * allocation routines.  If NUMA is configured, use page index
         * as input to create an allocation policy.
         */
-       memset(&pseudo_vma, 0, sizeof(struct vm_area_struct));
        vma_init(&pseudo_vma, mm);
        pseudo_vma.vm_flags = (VM_HUGETLB | VM_MAYSHARE | VM_SHARED);
        pseudo_vma.vm_file = file;
index a06de44..42f6d25 100644 (file)
@@ -1596,49 +1596,16 @@ sector_t bmap(struct inode *inode, sector_t block)
 EXPORT_SYMBOL(bmap);
 
 /*
- * Update times in overlayed inode from underlying real inode
- */
-static void update_ovl_inode_times(struct dentry *dentry, struct inode *inode,
-                              bool rcu)
-{
-       struct dentry *upperdentry;
-
-       /*
-        * Nothing to do if in rcu or if non-overlayfs
-        */
-       if (rcu || likely(!(dentry->d_flags & DCACHE_OP_REAL)))
-               return;
-
-       upperdentry = d_real(dentry, NULL, 0, D_REAL_UPPER);
-
-       /*
-        * If file is on lower then we can't update atime, so no worries about
-        * stale mtime/ctime.
-        */
-       if (upperdentry) {
-               struct inode *realinode = d_inode(upperdentry);
-
-               if ((!timespec64_equal(&inode->i_mtime, &realinode->i_mtime) ||
-                    !timespec64_equal(&inode->i_ctime, &realinode->i_ctime))) {
-                       inode->i_mtime = realinode->i_mtime;
-                       inode->i_ctime = realinode->i_ctime;
-               }
-       }
-}
-
-/*
  * With relative atime, only update atime if the previous atime is
  * earlier than either the ctime or mtime or if at least a day has
  * passed since the last atime update.
  */
-static int relatime_need_update(const struct path *path, struct inode *inode,
-                               struct timespec now, bool rcu)
+static int relatime_need_update(struct vfsmount *mnt, struct inode *inode,
+                            struct timespec now)
 {
 
-       if (!(path->mnt->mnt_flags & MNT_RELATIME))
+       if (!(mnt->mnt_flags & MNT_RELATIME))
                return 1;
-
-       update_ovl_inode_times(path->dentry, inode, rcu);
        /*
         * Is mtime younger than atime? If yes, update atime:
         */
@@ -1709,8 +1676,7 @@ static int update_time(struct inode *inode, struct timespec64 *time, int flags)
  *     This function automatically handles read only file systems and media,
  *     as well as the "noatime" flag and inode specific "noatime" markers.
  */
-bool __atime_needs_update(const struct path *path, struct inode *inode,
-                         bool rcu)
+bool atime_needs_update(const struct path *path, struct inode *inode)
 {
        struct vfsmount *mnt = path->mnt;
        struct timespec64 now;
@@ -1736,7 +1702,7 @@ bool __atime_needs_update(const struct path *path, struct inode *inode,
 
        now = current_time(inode);
 
-       if (!relatime_need_update(path, inode, timespec64_to_timespec(now), rcu))
+       if (!relatime_need_update(mnt, inode, timespec64_to_timespec(now)))
                return false;
 
        if (timespec64_equal(&inode->i_atime, &now))
@@ -1751,7 +1717,7 @@ void touch_atime(const struct path *path)
        struct inode *inode = d_inode(path->dentry);
        struct timespec64 now;
 
-       if (!__atime_needs_update(path, inode, false))
+       if (!atime_needs_update(path, inode))
                return;
 
        if (!sb_start_write_trylock(inode->i_sb))
index 50a28fc..d410186 100644 (file)
@@ -82,10 +82,8 @@ extern void __init mnt_init(void);
 
 extern int __mnt_want_write(struct vfsmount *);
 extern int __mnt_want_write_file(struct file *);
-extern int mnt_want_write_file_path(struct file *);
 extern void __mnt_drop_write(struct vfsmount *);
 extern void __mnt_drop_write_file(struct file *);
-extern void mnt_drop_write_file_path(struct file *);
 
 /*
  * fs_struct.c
@@ -96,6 +94,7 @@ extern void chroot_fs_refs(const struct path *, const struct path *);
  * file_table.c
  */
 extern struct file *alloc_empty_file(int, const struct cred *);
+extern struct file *alloc_empty_file_noaccount(int, const struct cred *);
 
 /*
  * super.c
@@ -136,13 +135,6 @@ extern long prune_icache_sb(struct super_block *sb, struct shrink_control *sc);
 extern void inode_add_lru(struct inode *inode);
 extern int dentry_needs_remove_privs(struct dentry *dentry);
 
-extern bool __atime_needs_update(const struct path *, struct inode *, bool);
-static inline bool atime_needs_update_rcu(const struct path *path,
-                                         struct inode *inode)
-{
-       return __atime_needs_update(path, inode, true);
-}
-
 /*
  * fs-writeback.c
  */
@@ -185,7 +177,6 @@ extern const struct dentry_operations ns_dentry_operations;
  */
 extern int do_vfs_ioctl(struct file *file, unsigned int fd, unsigned int cmd,
                    unsigned long arg);
-extern long vfs_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
 
 /*
  * iomap support:
index b445b13..3212c29 100644 (file)
@@ -49,6 +49,7 @@ long vfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
  out:
        return error;
 }
+EXPORT_SYMBOL(vfs_ioctl);
 
 static int ioctl_fibmap(struct file *filp, int __user *p)
 {
index 009071e..74762b1 100644 (file)
@@ -290,7 +290,7 @@ iomap_readpage_actor(struct inode *inode, loff_t pos, loff_t length, void *data,
        sector_t sector;
 
        if (iomap->type == IOMAP_INLINE) {
-               WARN_ON_ONCE(poff);
+               WARN_ON_ONCE(pos);
                iomap_read_inline_data(inode, page, iomap);
                return PAGE_SIZE;
        }
index 96c1d14..c2a1286 100644 (file)
@@ -187,7 +187,7 @@ __be32 nlmclnt_grant(const struct sockaddr *addr, const struct nlm_lock *lock)
                        continue;
                if (!rpc_cmp_addr(nlm_addr(block->b_host), addr))
                        continue;
-               if (nfs_compare_fh(NFS_FH(file_inode(fl_blocked->fl_file)) ,fh) != 0)
+               if (nfs_compare_fh(NFS_FH(locks_inode(fl_blocked->fl_file)), fh) != 0)
                        continue;
                /* Alright, we found a lock. Set the return status
                 * and wake up the caller
index a2c0dfc..d20b92f 100644 (file)
@@ -128,7 +128,7 @@ static void nlmclnt_setlockargs(struct nlm_rqst *req, struct file_lock *fl)
        char *nodename = req->a_host->h_rpcclnt->cl_nodename;
 
        nlmclnt_next_cookie(&argp->cookie);
-       memcpy(&lock->fh, NFS_FH(file_inode(fl->fl_file)), sizeof(struct nfs_fh));
+       memcpy(&lock->fh, NFS_FH(locks_inode(fl->fl_file)), sizeof(struct nfs_fh));
        lock->caller  = nodename;
        lock->oh.data = req->a_owner;
        lock->oh.len  = snprintf(req->a_owner, sizeof(req->a_owner), "%u@%s",
index 3701bcc..74330da 100644 (file)
@@ -405,8 +405,8 @@ nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file,
        __be32                  ret;
 
        dprintk("lockd: nlmsvc_lock(%s/%ld, ty=%d, pi=%d, %Ld-%Ld, bl=%d)\n",
-                               file_inode(file->f_file)->i_sb->s_id,
-                               file_inode(file->f_file)->i_ino,
+                               locks_inode(file->f_file)->i_sb->s_id,
+                               locks_inode(file->f_file)->i_ino,
                                lock->fl.fl_type, lock->fl.fl_pid,
                                (long long)lock->fl.fl_start,
                                (long long)lock->fl.fl_end,
@@ -511,8 +511,8 @@ nlmsvc_testlock(struct svc_rqst *rqstp, struct nlm_file *file,
        __be32                  ret;
 
        dprintk("lockd: nlmsvc_testlock(%s/%ld, ty=%d, %Ld-%Ld)\n",
-                               file_inode(file->f_file)->i_sb->s_id,
-                               file_inode(file->f_file)->i_ino,
+                               locks_inode(file->f_file)->i_sb->s_id,
+                               locks_inode(file->f_file)->i_ino,
                                lock->fl.fl_type,
                                (long long)lock->fl.fl_start,
                                (long long)lock->fl.fl_end);
@@ -566,8 +566,8 @@ nlmsvc_unlock(struct net *net, struct nlm_file *file, struct nlm_lock *lock)
        int     error;
 
        dprintk("lockd: nlmsvc_unlock(%s/%ld, pi=%d, %Ld-%Ld)\n",
-                               file_inode(file->f_file)->i_sb->s_id,
-                               file_inode(file->f_file)->i_ino,
+                               locks_inode(file->f_file)->i_sb->s_id,
+                               locks_inode(file->f_file)->i_ino,
                                lock->fl.fl_pid,
                                (long long)lock->fl.fl_start,
                                (long long)lock->fl.fl_end);
@@ -595,8 +595,8 @@ nlmsvc_cancel_blocked(struct net *net, struct nlm_file *file, struct nlm_lock *l
        int status = 0;
 
        dprintk("lockd: nlmsvc_cancel(%s/%ld, pi=%d, %Ld-%Ld)\n",
-                               file_inode(file->f_file)->i_sb->s_id,
-                               file_inode(file->f_file)->i_ino,
+                               locks_inode(file->f_file)->i_sb->s_id,
+                               locks_inode(file->f_file)->i_ino,
                                lock->fl.fl_pid,
                                (long long)lock->fl.fl_start,
                                (long long)lock->fl.fl_end);
index 4ec3d6e..899360b 100644 (file)
@@ -44,7 +44,7 @@ static inline void nlm_debug_print_fh(char *msg, struct nfs_fh *f)
 
 static inline void nlm_debug_print_file(char *msg, struct nlm_file *file)
 {
-       struct inode *inode = file_inode(file->f_file);
+       struct inode *inode = locks_inode(file->f_file);
 
        dprintk("lockd: %s %s/%ld\n",
                msg, inode->i_sb->s_id, inode->i_ino);
@@ -414,7 +414,7 @@ nlmsvc_match_sb(void *datap, struct nlm_file *file)
 {
        struct super_block *sb = datap;
 
-       return sb == file_inode(file->f_file)->i_sb;
+       return sb == locks_inode(file->f_file)->i_sb;
 }
 
 /**
index bc047a7..2ecb4db 100644 (file)
 #define IS_OFDLCK(fl)  (fl->fl_flags & FL_OFDLCK)
 #define IS_REMOTELCK(fl)       (fl->fl_pid <= 0)
 
-static inline bool is_remote_lock(struct file *filp)
-{
-       return likely(!(filp->f_path.dentry->d_sb->s_flags & SB_NOREMOTELOCK));
-}
-
 static bool lease_breaking(struct file_lock *fl)
 {
        return fl->fl_flags & (FL_UNLOCK_PENDING | FL_DOWNGRADE_PENDING);
@@ -542,7 +537,7 @@ lease_setup(struct file_lock *fl, void **priv)
        if (!fasync_insert_entry(fa->fa_fd, filp, &fl->fl_fasync, fa))
                *priv = NULL;
 
-       __f_setown(filp, task_pid(current), PIDTYPE_PID, 0);
+       __f_setown(filp, task_pid(current), PIDTYPE_TGID, 0);
 }
 
 static const struct lock_manager_operations lease_manager_ops = {
@@ -1651,8 +1646,7 @@ check_conflicting_open(const struct dentry *dentry, const long arg, int flags)
        if (flags & FL_LAYOUT)
                return 0;
 
-       if ((arg == F_RDLCK) &&
-           (atomic_read(&d_real_inode(dentry)->i_writecount) > 0))
+       if ((arg == F_RDLCK) && (atomic_read(&inode->i_writecount) > 0))
                return -EAGAIN;
 
        if ((arg == F_WRLCK) && ((d_count(dentry) > 1) ||
@@ -1873,7 +1867,7 @@ EXPORT_SYMBOL(generic_setlease);
 int
 vfs_setlease(struct file *filp, long arg, struct file_lock **lease, void **priv)
 {
-       if (filp->f_op->setlease && is_remote_lock(filp))
+       if (filp->f_op->setlease)
                return filp->f_op->setlease(filp, arg, lease, priv);
        else
                return generic_setlease(filp, arg, lease, priv);
@@ -2020,7 +2014,7 @@ SYSCALL_DEFINE2(flock, unsigned int, fd, unsigned int, cmd)
        if (error)
                goto out_free;
 
-       if (f.file->f_op->flock && is_remote_lock(f.file))
+       if (f.file->f_op->flock)
                error = f.file->f_op->flock(f.file,
                                          (can_sleep) ? F_SETLKW : F_SETLK,
                                          lock);
@@ -2046,7 +2040,7 @@ SYSCALL_DEFINE2(flock, unsigned int, fd, unsigned int, cmd)
  */
 int vfs_test_lock(struct file *filp, struct file_lock *fl)
 {
-       if (filp->f_op->lock && is_remote_lock(filp))
+       if (filp->f_op->lock)
                return filp->f_op->lock(filp, F_GETLK, fl);
        posix_test_lock(filp, fl);
        return 0;
@@ -2196,7 +2190,7 @@ out:
  */
 int vfs_lock_file(struct file *filp, unsigned int cmd, struct file_lock *fl, struct file_lock *conf)
 {
-       if (filp->f_op->lock && is_remote_lock(filp))
+       if (filp->f_op->lock)
                return filp->f_op->lock(filp, cmd, fl);
        else
                return posix_lock_file(filp, fl, conf);
@@ -2518,7 +2512,7 @@ locks_remove_flock(struct file *filp, struct file_lock_context *flctx)
        if (list_empty(&flctx->flc_flock))
                return;
 
-       if (filp->f_op->flock && is_remote_lock(filp))
+       if (filp->f_op->flock)
                filp->f_op->flock(filp, F_SETLKW, &fl);
        else
                flock_lock_inode(inode, &fl);
@@ -2605,7 +2599,7 @@ EXPORT_SYMBOL(posix_unblock_lock);
  */
 int vfs_cancel_lock(struct file *filp, struct file_lock *fl)
 {
-       if (filp->f_op->lock && is_remote_lock(filp))
+       if (filp->f_op->lock)
                return filp->f_op->lock(filp, F_CANCELLK, fl);
        return 0;
 }
index 3cd3962..0cab649 100644 (file)
@@ -887,6 +887,8 @@ static inline void put_link(struct nameidata *nd)
 
 int sysctl_protected_symlinks __read_mostly = 0;
 int sysctl_protected_hardlinks __read_mostly = 0;
+int sysctl_protected_fifos __read_mostly;
+int sysctl_protected_regular __read_mostly;
 
 /**
  * may_follow_link - Check symlink following for unsafe situations
@@ -1003,6 +1005,45 @@ static int may_linkat(struct path *link)
        return -EPERM;
 }
 
+/**
+ * may_create_in_sticky - Check whether an O_CREAT open in a sticky directory
+ *                       should be allowed, or not, on files that already
+ *                       exist.
+ * @dir: the sticky parent directory
+ * @inode: the inode of the file to open
+ *
+ * Block an O_CREAT open of a FIFO (or a regular file) when:
+ *   - sysctl_protected_fifos (or sysctl_protected_regular) is enabled
+ *   - the file already exists
+ *   - we are in a sticky directory
+ *   - we don't own the file
+ *   - the owner of the directory doesn't own the file
+ *   - the directory is world writable
+ * If the sysctl_protected_fifos (or sysctl_protected_regular) is set to 2
+ * the directory doesn't have to be world writable: being group writable will
+ * be enough.
+ *
+ * Returns 0 if the open is allowed, -ve on error.
+ */
+static int may_create_in_sticky(struct dentry * const dir,
+                               struct inode * const inode)
+{
+       if ((!sysctl_protected_fifos && S_ISFIFO(inode->i_mode)) ||
+           (!sysctl_protected_regular && S_ISREG(inode->i_mode)) ||
+           likely(!(dir->d_inode->i_mode & S_ISVTX)) ||
+           uid_eq(inode->i_uid, dir->d_inode->i_uid) ||
+           uid_eq(current_fsuid(), inode->i_uid))
+               return 0;
+
+       if (likely(dir->d_inode->i_mode & 0002) ||
+           (dir->d_inode->i_mode & 0020 &&
+            ((sysctl_protected_fifos >= 2 && S_ISFIFO(inode->i_mode)) ||
+             (sysctl_protected_regular >= 2 && S_ISREG(inode->i_mode))))) {
+               return -EACCES;
+       }
+       return 0;
+}
+
 static __always_inline
 const char *get_link(struct nameidata *nd)
 {
@@ -1015,7 +1056,7 @@ const char *get_link(struct nameidata *nd)
        if (!(nd->flags & LOOKUP_RCU)) {
                touch_atime(&last->link);
                cond_resched();
-       } else if (atime_needs_update_rcu(&last->link, inode)) {
+       } else if (atime_needs_update(&last->link, inode)) {
                if (unlikely(unlazy_walk(nd)))
                        return ERR_PTR(-ECHILD);
                touch_atime(&last->link);
@@ -3348,9 +3389,15 @@ finish_open:
        if (error)
                return error;
        audit_inode(nd->name, nd->path.dentry, 0);
-       error = -EISDIR;
-       if ((open_flag & O_CREAT) && d_is_dir(nd->path.dentry))
-               goto out;
+       if (open_flag & O_CREAT) {
+               error = -EISDIR;
+               if (d_is_dir(nd->path.dentry))
+                       goto out;
+               error = may_create_in_sticky(dir,
+                                            d_backing_inode(nd->path.dentry));
+               if (unlikely(error))
+                       goto out;
+       }
        error = -ENOTDIR;
        if ((nd->flags & LOOKUP_DIRECTORY) && !d_can_lookup(nd->path.dentry))
                goto out;
index bd2f4c6..9918655 100644 (file)
@@ -61,9 +61,6 @@ __setup("mphash_entries=", set_mphash_entries);
 static u64 event;
 static DEFINE_IDA(mnt_id_ida);
 static DEFINE_IDA(mnt_group_ida);
-static DEFINE_SPINLOCK(mnt_id_lock);
-static int mnt_id_start = 0;
-static int mnt_group_start = 1;
 
 static struct hlist_head *mount_hashtable __read_mostly;
 static struct hlist_head *mountpoint_hashtable __read_mostly;
@@ -101,50 +98,30 @@ static inline struct hlist_head *mp_hash(struct dentry *dentry)
 
 static int mnt_alloc_id(struct mount *mnt)
 {
-       int res;
+       int res = ida_alloc(&mnt_id_ida, GFP_KERNEL);
 
-retry:
-       ida_pre_get(&mnt_id_ida, GFP_KERNEL);
-       spin_lock(&mnt_id_lock);
-       res = ida_get_new_above(&mnt_id_ida, mnt_id_start, &mnt->mnt_id);
-       if (!res)
-               mnt_id_start = mnt->mnt_id + 1;
-       spin_unlock(&mnt_id_lock);
-       if (res == -EAGAIN)
-               goto retry;
-
-       return res;
+       if (res < 0)
+               return res;
+       mnt->mnt_id = res;
+       return 0;
 }
 
 static void mnt_free_id(struct mount *mnt)
 {
-       int id = mnt->mnt_id;
-       spin_lock(&mnt_id_lock);
-       ida_remove(&mnt_id_ida, id);
-       if (mnt_id_start > id)
-               mnt_id_start = id;
-       spin_unlock(&mnt_id_lock);
+       ida_free(&mnt_id_ida, mnt->mnt_id);
 }
 
 /*
  * Allocate a new peer group ID
- *
- * mnt_group_ida is protected by namespace_sem
  */
 static int mnt_alloc_group_id(struct mount *mnt)
 {
-       int res;
+       int res = ida_alloc_min(&mnt_group_ida, 1, GFP_KERNEL);
 
-       if (!ida_pre_get(&mnt_group_ida, GFP_KERNEL))
-               return -ENOMEM;
-
-       res = ida_get_new_above(&mnt_group_ida,
-                               mnt_group_start,
-                               &mnt->mnt_group_id);
-       if (!res)
-               mnt_group_start = mnt->mnt_group_id + 1;
-
-       return res;
+       if (res < 0)
+               return res;
+       mnt->mnt_group_id = res;
+       return 0;
 }
 
 /*
@@ -152,10 +129,7 @@ static int mnt_alloc_group_id(struct mount *mnt)
  */
 void mnt_release_group_id(struct mount *mnt)
 {
-       int id = mnt->mnt_group_id;
-       ida_remove(&mnt_group_ida, id);
-       if (mnt_group_start > id)
-               mnt_group_start = id;
+       ida_free(&mnt_group_ida, mnt->mnt_group_id);
        mnt->mnt_group_id = 0;
 }
 
@@ -431,74 +405,20 @@ int __mnt_want_write_file(struct file *file)
 }
 
 /**
- * mnt_want_write_file_path - get write access to a file's mount
- * @file: the file who's mount on which to take a write
- *
- * This is like mnt_want_write, but it takes a file and can
- * do some optimisations if the file is open for write already
- *
- * Called by the vfs for cases when we have an open file at hand, but will do an
- * inode operation on it (important distinction for files opened on overlayfs,
- * since the file operations will come from the real underlying file, while
- * inode operations come from the overlay).
- */
-int mnt_want_write_file_path(struct file *file)
-{
-       int ret;
-
-       sb_start_write(file->f_path.mnt->mnt_sb);
-       ret = __mnt_want_write_file(file);
-       if (ret)
-               sb_end_write(file->f_path.mnt->mnt_sb);
-       return ret;
-}
-
-static inline int may_write_real(struct file *file)
-{
-       struct dentry *dentry = file->f_path.dentry;
-       struct dentry *upperdentry;
-
-       /* Writable file? */
-       if (file->f_mode & FMODE_WRITER)
-               return 0;
-
-       /* Not overlayfs? */
-       if (likely(!(dentry->d_flags & DCACHE_OP_REAL)))
-               return 0;
-
-       /* File refers to upper, writable layer? */
-       upperdentry = d_real(dentry, NULL, 0, D_REAL_UPPER);
-       if (upperdentry &&
-           (file_inode(file) == d_inode(upperdentry) ||
-            file_inode(file) == d_inode(dentry)))
-               return 0;
-
-       /* Lower layer: can't write to real file, sorry... */
-       return -EPERM;
-}
-
-/**
  * mnt_want_write_file - get write access to a file's mount
  * @file: the file who's mount on which to take a write
  *
  * This is like mnt_want_write, but it takes a file and can
  * do some optimisations if the file is open for write already
- *
- * Mostly called by filesystems from their ioctl operation before performing
- * modification.  On overlayfs this needs to check if the file is on a read-only
- * lower layer and deny access in that case.
  */
 int mnt_want_write_file(struct file *file)
 {
        int ret;
 
-       ret = may_write_real(file);
-       if (!ret) {
-               sb_start_write(file_inode(file)->i_sb);
-               ret = __mnt_want_write_file(file);
-               if (ret)
-                       sb_end_write(file_inode(file)->i_sb);
-       }
+       sb_start_write(file_inode(file)->i_sb);
+       ret = __mnt_want_write_file(file);
+       if (ret)
+               sb_end_write(file_inode(file)->i_sb);
        return ret;
 }
 EXPORT_SYMBOL_GPL(mnt_want_write_file);
@@ -538,14 +458,9 @@ void __mnt_drop_write_file(struct file *file)
        __mnt_drop_write(file->f_path.mnt);
 }
 
-void mnt_drop_write_file_path(struct file *file)
-{
-       mnt_drop_write(file->f_path.mnt);
-}
-
 void mnt_drop_write_file(struct file *file)
 {
-       __mnt_drop_write(file->f_path.mnt);
+       __mnt_drop_write_file(file);
        sb_end_write(file_inode(file)->i_sb);
 }
 EXPORT_SYMBOL(mnt_drop_write_file);
index 7cb5c38..06cb0c1 100644 (file)
@@ -753,6 +753,7 @@ out:
        case -ENODEV:
                /* Our extent block devices are unavailable */
                set_bit(NFS_LSEG_UNAVAILABLE, &lseg->pls_flags);
+               /* Fall through */
        case 0:
                return lseg;
        default:
index a7efd83..dec5880 100644 (file)
@@ -204,7 +204,7 @@ static bool bl_map_stripe(struct pnfs_block_dev *dev, u64 offset,
        chunk = div_u64(offset, dev->chunk_size);
        div_u64_rem(chunk, dev->nr_children, &chunk_idx);
 
-       if (chunk_idx > dev->nr_children) {
+       if (chunk_idx >= dev->nr_children) {
                dprintk("%s: invalid chunk idx %d (%lld/%lld)\n",
                        __func__, chunk_idx, offset, dev->chunk_size);
                /* error, should not happen */
index a20a0bc..8f34daf 100644 (file)
@@ -184,6 +184,18 @@ struct cb_notify_lock_args {
 extern __be32 nfs4_callback_notify_lock(void *argp, void *resp,
                                         struct cb_process_state *cps);
 #endif /* CONFIG_NFS_V4_1 */
+#ifdef CONFIG_NFS_V4_2
+struct cb_offloadargs {
+       struct nfs_fh           coa_fh;
+       nfs4_stateid            coa_stateid;
+       uint32_t                error;
+       uint64_t                wr_count;
+       struct nfs_writeverf    wr_writeverf;
+};
+
+extern __be32 nfs4_callback_offload(void *args, void *dummy,
+                                   struct cb_process_state *cps);
+#endif /* CONFIG_NFS_V4_2 */
 extern int check_gss_callback_principal(struct nfs_client *, struct svc_rqst *);
 extern __be32 nfs4_callback_getattr(void *argp, void *resp,
                                    struct cb_process_state *cps);
index 64c214f..fa515d5 100644 (file)
@@ -215,9 +215,9 @@ static u32 pnfs_check_callback_stateid(struct pnfs_layout_hdr *lo,
 {
        u32 oldseq, newseq;
 
-       /* Is the stateid still not initialised? */
+       /* Is the stateid not initialised? */
        if (!pnfs_layout_is_valid(lo))
-               return NFS4ERR_DELAY;
+               return NFS4ERR_NOMATCHING_LAYOUT;
 
        /* Mismatched stateid? */
        if (!nfs4_stateid_match_other(&lo->plh_stateid, new))
@@ -273,7 +273,6 @@ static u32 initiate_file_draining(struct nfs_client *clp,
        rv = pnfs_check_callback_stateid(lo, &args->cbl_stateid);
        if (rv != NFS_OK)
                goto unlock;
-       pnfs_set_layout_stateid(lo, &args->cbl_stateid, true);
 
        /*
         * Enforce RFC5661 Section 12.5.5.2.1.5 (Bulk Recall and Return)
@@ -283,19 +282,23 @@ static u32 initiate_file_draining(struct nfs_client *clp,
                goto unlock;
        }
 
-       if (pnfs_mark_matching_lsegs_return(lo, &free_me_list,
+       pnfs_set_layout_stateid(lo, &args->cbl_stateid, true);
+       switch (pnfs_mark_matching_lsegs_return(lo, &free_me_list,
                                &args->cbl_range,
                                be32_to_cpu(args->cbl_stateid.seqid))) {
+       case 0:
+       case -EBUSY:
+               /* There are layout segments that need to be returned */
                rv = NFS4_OK;
-               goto unlock;
-       }
-
-       /* Embrace your forgetfulness! */
-       rv = NFS4ERR_NOMATCHING_LAYOUT;
+               break;
+       case -ENOENT:
+               /* Embrace your forgetfulness! */
+               rv = NFS4ERR_NOMATCHING_LAYOUT;
 
-       if (NFS_SERVER(ino)->pnfs_curr_ld->return_range) {
-               NFS_SERVER(ino)->pnfs_curr_ld->return_range(lo,
-                       &args->cbl_range);
+               if (NFS_SERVER(ino)->pnfs_curr_ld->return_range) {
+                       NFS_SERVER(ino)->pnfs_curr_ld->return_range(lo,
+                               &args->cbl_range);
+               }
        }
 unlock:
        spin_unlock(&ino->i_lock);
@@ -328,8 +331,6 @@ static u32 initiate_bulk_draining(struct nfs_client *clp,
 static u32 do_callback_layoutrecall(struct nfs_client *clp,
                                    struct cb_layoutrecallargs *args)
 {
-       write_seqcount_begin(&clp->cl_callback_count);
-       write_seqcount_end(&clp->cl_callback_count);
        if (args->cbl_recall_type == RETURN_FILE)
                return initiate_file_draining(clp, args);
        return initiate_bulk_draining(clp, args);
@@ -441,11 +442,14 @@ validate_seqid(const struct nfs4_slot_table *tbl, const struct nfs4_slot *slot,
  * a match.  If the slot is in use and the sequence numbers match, the
  * client is still waiting for a response to the original request.
  */
-static bool referring_call_exists(struct nfs_client *clp,
+static int referring_call_exists(struct nfs_client *clp,
                                  uint32_t nrclists,
-                                 struct referring_call_list *rclists)
+                                 struct referring_call_list *rclists,
+                                 spinlock_t *lock)
+       __releases(lock)
+       __acquires(lock)
 {
-       bool status = false;
+       int status = 0;
        int i, j;
        struct nfs4_session *session;
        struct nfs4_slot_table *tbl;
@@ -468,8 +472,10 @@ static bool referring_call_exists(struct nfs_client *clp,
 
                for (j = 0; j < rclist->rcl_nrefcalls; j++) {
                        ref = &rclist->rcl_refcalls[j];
+                       spin_unlock(lock);
                        status = nfs4_slot_wait_on_seqid(tbl, ref->rc_slotid,
                                        ref->rc_sequenceid, HZ >> 1) < 0;
+                       spin_lock(lock);
                        if (status)
                                goto out;
                }
@@ -546,7 +552,8 @@ __be32 nfs4_callback_sequence(void *argp, void *resp,
         * related callback was received before the response to the original
         * call.
         */
-       if (referring_call_exists(clp, args->csa_nrclists, args->csa_rclists)) {
+       if (referring_call_exists(clp, args->csa_nrclists, args->csa_rclists,
+                               &tbl->slot_tbl_lock) < 0) {
                status = htonl(NFS4ERR_DELAY);
                goto out_unlock;
        }
@@ -660,3 +667,57 @@ __be32 nfs4_callback_notify_lock(void *argp, void *resp,
        return htonl(NFS4_OK);
 }
 #endif /* CONFIG_NFS_V4_1 */
+#ifdef CONFIG_NFS_V4_2
+static void nfs4_copy_cb_args(struct nfs4_copy_state *cp_state,
+                               struct cb_offloadargs *args)
+{
+       cp_state->count = args->wr_count;
+       cp_state->error = args->error;
+       if (!args->error) {
+               cp_state->verf.committed = args->wr_writeverf.committed;
+               memcpy(&cp_state->verf.verifier.data[0],
+                       &args->wr_writeverf.verifier.data[0],
+                       NFS4_VERIFIER_SIZE);
+       }
+}
+
+__be32 nfs4_callback_offload(void *data, void *dummy,
+                            struct cb_process_state *cps)
+{
+       struct cb_offloadargs *args = data;
+       struct nfs_server *server;
+       struct nfs4_copy_state *copy;
+       bool found = false;
+
+       spin_lock(&cps->clp->cl_lock);
+       rcu_read_lock();
+       list_for_each_entry_rcu(server, &cps->clp->cl_superblocks,
+                               client_link) {
+               list_for_each_entry(copy, &server->ss_copies, copies) {
+                       if (memcmp(args->coa_stateid.other,
+                                       copy->stateid.other,
+                                       sizeof(args->coa_stateid.other)))
+                               continue;
+                       nfs4_copy_cb_args(copy, args);
+                       complete(&copy->completion);
+                       found = true;
+                       goto out;
+               }
+       }
+out:
+       rcu_read_unlock();
+       if (!found) {
+               copy = kzalloc(sizeof(struct nfs4_copy_state), GFP_NOFS);
+               if (!copy) {
+                       spin_unlock(&cps->clp->cl_lock);
+                       return htonl(NFS4ERR_SERVERFAULT);
+               }
+               memcpy(&copy->stateid, &args->coa_stateid, NFS4_STATEID_SIZE);
+               nfs4_copy_cb_args(copy, args);
+               list_add_tail(&copy->copies, &cps->clp->pending_cb_stateids);
+       }
+       spin_unlock(&cps->clp->cl_lock);
+
+       return 0;
+}
+#endif /* CONFIG_NFS_V4_2 */
index a813979..a87a562 100644 (file)
@@ -38,6 +38,9 @@
 #define CB_OP_RECALLSLOT_RES_MAXSZ     (CB_OP_HDR_RES_MAXSZ)
 #define CB_OP_NOTIFY_LOCK_RES_MAXSZ    (CB_OP_HDR_RES_MAXSZ)
 #endif /* CONFIG_NFS_V4_1 */
+#ifdef CONFIG_NFS_V4_2
+#define CB_OP_OFFLOAD_RES_MAXSZ                (CB_OP_HDR_RES_MAXSZ)
+#endif /* CONFIG_NFS_V4_2 */
 
 #define NFSDBG_FACILITY NFSDBG_CALLBACK
 
@@ -527,7 +530,72 @@ static __be32 decode_notify_lock_args(struct svc_rqst *rqstp,
 }
 
 #endif /* CONFIG_NFS_V4_1 */
+#ifdef CONFIG_NFS_V4_2
+static __be32 decode_write_response(struct xdr_stream *xdr,
+                                       struct cb_offloadargs *args)
+{
+       __be32 *p;
+
+       /* skip the always zero field */
+       p = read_buf(xdr, 4);
+       if (unlikely(!p))
+               goto out;
+       p++;
+
+       /* decode count, stable_how, verifier */
+       p = xdr_inline_decode(xdr, 8 + 4);
+       if (unlikely(!p))
+               goto out;
+       p = xdr_decode_hyper(p, &args->wr_count);
+       args->wr_writeverf.committed = be32_to_cpup(p);
+       p = xdr_inline_decode(xdr, NFS4_VERIFIER_SIZE);
+       if (likely(p)) {
+               memcpy(&args->wr_writeverf.verifier.data[0], p,
+                       NFS4_VERIFIER_SIZE);
+               return 0;
+       }
+out:
+       return htonl(NFS4ERR_RESOURCE);
+}
+
+static __be32 decode_offload_args(struct svc_rqst *rqstp,
+                                       struct xdr_stream *xdr,
+                                       void *data)
+{
+       struct cb_offloadargs *args = data;
+       __be32 *p;
+       __be32 status;
+
+       /* decode fh */
+       status = decode_fh(xdr, &args->coa_fh);
+       if (unlikely(status != 0))
+               return status;
 
+       /* decode stateid */
+       status = decode_stateid(xdr, &args->coa_stateid);
+       if (unlikely(status != 0))
+               return status;
+
+       /* decode status */
+       p = read_buf(xdr, 4);
+       if (unlikely(!p))
+               goto out;
+       args->error = ntohl(*p++);
+       if (!args->error) {
+               status = decode_write_response(xdr, args);
+               if (unlikely(status != 0))
+                       return status;
+       } else {
+               p = xdr_inline_decode(xdr, 8);
+               if (unlikely(!p))
+                       goto out;
+               p = xdr_decode_hyper(p, &args->wr_count);
+       }
+       return 0;
+out:
+       return htonl(NFS4ERR_RESOURCE);
+}
+#endif /* CONFIG_NFS_V4_2 */
 static __be32 encode_string(struct xdr_stream *xdr, unsigned int len, const char *str)
 {
        if (unlikely(xdr_stream_encode_opaque(xdr, str, len) < 0))
@@ -773,7 +841,10 @@ preprocess_nfs42_op(int nop, unsigned int op_nr, struct callback_op **op)
        if (status != htonl(NFS4ERR_OP_ILLEGAL))
                return status;
 
-       if (op_nr == OP_CB_OFFLOAD)
+       if (op_nr == OP_CB_OFFLOAD) {
+               *op = &callback_ops[op_nr];
+               return htonl(NFS_OK);
+       } else
                return htonl(NFS4ERR_NOTSUPP);
        return htonl(NFS4ERR_OP_ILLEGAL);
 }
@@ -883,16 +954,21 @@ static __be32 nfs4_callback_compound(struct svc_rqst *rqstp)
 
        if (hdr_arg.minorversion == 0) {
                cps.clp = nfs4_find_client_ident(SVC_NET(rqstp), hdr_arg.cb_ident);
-               if (!cps.clp || !check_gss_callback_principal(cps.clp, rqstp))
+               if (!cps.clp || !check_gss_callback_principal(cps.clp, rqstp)) {
+                       if (cps.clp)
+                               nfs_put_client(cps.clp);
                        goto out_invalidcred;
+               }
        }
 
        cps.minorversion = hdr_arg.minorversion;
        hdr_res.taglen = hdr_arg.taglen;
        hdr_res.tag = hdr_arg.tag;
-       if (encode_compound_hdr_res(&xdr_out, &hdr_res) != 0)
+       if (encode_compound_hdr_res(&xdr_out, &hdr_res) != 0) {
+               if (cps.clp)
+                       nfs_put_client(cps.clp);
                return rpc_system_err;
-
+       }
        while (status == 0 && nops != hdr_arg.nops) {
                status = process_op(nops, rqstp, &xdr_in,
                                    rqstp->rq_argp, &xdr_out, rqstp->rq_resp,
@@ -969,6 +1045,13 @@ static struct callback_op callback_ops[] = {
                .res_maxsize = CB_OP_NOTIFY_LOCK_RES_MAXSZ,
        },
 #endif /* CONFIG_NFS_V4_1 */
+#ifdef CONFIG_NFS_V4_2
+       [OP_CB_OFFLOAD] = {
+               .process_op = nfs4_callback_offload,
+               .decode_args = decode_offload_args,
+               .res_maxsize = CB_OP_OFFLOAD_RES_MAXSZ,
+       },
+#endif /* CONFIG_NFS_V4_2 */
 };
 
 /*
index 377a616..96d5f81 100644 (file)
@@ -886,6 +886,7 @@ struct nfs_server *nfs_alloc_server(void)
        INIT_LIST_HEAD(&server->delegations);
        INIT_LIST_HEAD(&server->layouts);
        INIT_LIST_HEAD(&server->state_owners_lru);
+       INIT_LIST_HEAD(&server->ss_copies);
 
        atomic_set(&server->active, 0);
 
index d7f158c..8bfaa65 100644 (file)
@@ -904,23 +904,29 @@ static loff_t nfs_llseek_dir(struct file *filp, loff_t offset, int whence)
        dfprintk(FILE, "NFS: llseek dir(%pD2, %lld, %d)\n",
                        filp, offset, whence);
 
-       inode_lock(inode);
        switch (whence) {
-               case 1:
-                       offset += filp->f_pos;
-               case 0:
-                       if (offset >= 0)
-                               break;
-               default:
-                       offset = -EINVAL;
-                       goto out;
+       default:
+               return -EINVAL;
+       case SEEK_SET:
+               if (offset < 0)
+                       return -EINVAL;
+               inode_lock(inode);
+               break;
+       case SEEK_CUR:
+               if (offset == 0)
+                       return filp->f_pos;
+               inode_lock(inode);
+               offset += filp->f_pos;
+               if (offset < 0) {
+                       inode_unlock(inode);
+                       return -EINVAL;
+               }
        }
        if (offset != filp->f_pos) {
                filp->f_pos = offset;
                dir_ctx->dir_cookie = 0;
                dir_ctx->duped = 0;
        }
-out:
        inode_unlock(inode);
        return offset;
 }
@@ -1032,7 +1038,7 @@ int nfs_lookup_verify_inode(struct inode *inode, unsigned int flags)
        if (flags & LOOKUP_REVAL)
                goto out_force;
 out:
-       return (inode->i_nlink == 0) ? -ENOENT : 0;
+       return (inode->i_nlink == 0) ? -ESTALE : 0;
 out_force:
        if (flags & LOOKUP_RCU)
                return -ECHILD;
@@ -2499,7 +2505,9 @@ static int nfs_execute_ok(struct inode *inode, int mask)
        struct nfs_server *server = NFS_SERVER(inode);
        int ret = 0;
 
-       if (nfs_check_cache_invalid(inode, NFS_INO_INVALID_ACCESS)) {
+       if (S_ISDIR(inode->i_mode))
+               return 0;
+       if (nfs_check_cache_invalid(inode, NFS_INO_INVALID_OTHER)) {
                if (mask & MAY_NOT_BLOCK)
                        return -ECHILD;
                ret = __nfs_revalidate_inode(server, inode);
index 621c517..aa12c30 100644 (file)
@@ -758,7 +758,7 @@ static void nfs_direct_write_schedule_work(struct work_struct *work)
 
 static void nfs_direct_write_complete(struct nfs_direct_req *dreq)
 {
-       schedule_work(&dreq->work); /* Calls nfs_direct_write_schedule_work */
+       queue_work(nfsiod_workqueue, &dreq->work); /* Calls nfs_direct_write_schedule_work */
 }
 
 static void nfs_direct_write_completion(struct nfs_pgio_header *hdr)
index 81cca49..29553fd 100644 (file)
@@ -532,13 +532,13 @@ const struct address_space_operations nfs_file_aops = {
  * writable, implying that someone is about to modify the page through a
  * shared-writable mapping
  */
-static int nfs_vm_page_mkwrite(struct vm_fault *vmf)
+static vm_fault_t nfs_vm_page_mkwrite(struct vm_fault *vmf)
 {
        struct page *page = vmf->page;
        struct file *filp = vmf->vma->vm_file;
        struct inode *inode = file_inode(filp);
        unsigned pagelen;
-       int ret = VM_FAULT_NOPAGE;
+       vm_fault_t ret = VM_FAULT_NOPAGE;
        struct address_space *mapping;
 
        dfprintk(PAGECACHE, "NFS: vm_page_mkwrite(%pD2(%lu), offset %lld)\n",
index 8f00379..cae4333 100644 (file)
@@ -812,7 +812,6 @@ ff_layout_pg_get_read(struct nfs_pageio_descriptor *pgio,
                      struct nfs_page *req,
                      bool strict_iomode)
 {
-retry_strict:
        pnfs_put_lseg(pgio->pg_lseg);
        pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode,
                                           req->wb_context,
@@ -825,16 +824,6 @@ retry_strict:
                pgio->pg_error = PTR_ERR(pgio->pg_lseg);
                pgio->pg_lseg = NULL;
        }
-
-       /* If we don't have checking, do get a IOMODE_RW
-        * segment, and the server wants to avoid READs
-        * there, then retry!
-        */
-       if (pgio->pg_lseg && !strict_iomode &&
-           ff_layout_avoid_read_on_rw(pgio->pg_lseg)) {
-               strict_iomode = true;
-               goto retry_strict;
-       }
 }
 
 static void
@@ -849,14 +838,16 @@ ff_layout_pg_init_read(struct nfs_pageio_descriptor *pgio,
 retry:
        pnfs_generic_pg_check_layout(pgio);
        /* Use full layout for now */
-       if (!pgio->pg_lseg)
+       if (!pgio->pg_lseg) {
                ff_layout_pg_get_read(pgio, req, false);
-       else if (ff_layout_avoid_read_on_rw(pgio->pg_lseg))
+               if (!pgio->pg_lseg)
+                       goto out_nolseg;
+       }
+       if (ff_layout_avoid_read_on_rw(pgio->pg_lseg)) {
                ff_layout_pg_get_read(pgio, req, true);
-
-       /* If no lseg, fall back to read through mds */
-       if (pgio->pg_lseg == NULL)
-               goto out_mds;
+               if (!pgio->pg_lseg)
+                       goto out_nolseg;
+       }
 
        ds = ff_layout_choose_best_ds_for_read(pgio->pg_lseg, 0, &ds_idx);
        if (!ds) {
@@ -878,6 +869,9 @@ retry:
        pgm->pg_bsize = mirror->mirror_ds->ds_versions[0].rsize;
 
        return;
+out_nolseg:
+       if (pgio->pg_error < 0)
+               return;
 out_mds:
        pnfs_put_lseg(pgio->pg_lseg);
        pgio->pg_lseg = NULL;
@@ -1323,6 +1317,7 @@ static void ff_layout_read_record_layoutstats_done(struct rpc_task *task,
                        FF_LAYOUT_COMP(hdr->lseg, hdr->pgio_mirror_idx),
                        hdr->args.count,
                        hdr->res.count);
+       set_bit(NFS_LSEG_LAYOUTRETURN, &hdr->lseg->pls_flags);
 }
 
 static int ff_layout_read_prepare_common(struct rpc_task *task,
@@ -1507,6 +1502,7 @@ static void ff_layout_write_record_layoutstats_done(struct rpc_task *task,
                        FF_LAYOUT_COMP(hdr->lseg, hdr->pgio_mirror_idx),
                        hdr->args.count, hdr->res.count,
                        hdr->res.verf->committed);
+       set_bit(NFS_LSEG_LAYOUTRETURN, &hdr->lseg->pls_flags);
 }
 
 static int ff_layout_write_prepare_common(struct rpc_task *task,
@@ -1615,6 +1611,7 @@ static void ff_layout_commit_record_layoutstats_done(struct rpc_task *task,
        nfs4_ff_layout_stat_io_end_write(task,
                        FF_LAYOUT_COMP(cdata->lseg, cdata->ds_commit_index),
                        count, count, NFS_FILE_SYNC);
+       set_bit(NFS_LSEG_LAYOUTRETURN, &cdata->lseg->pls_flags);
 }
 
 static void ff_layout_commit_prepare_common(struct rpc_task *task,
index 7173a4e..9fce185 100644 (file)
@@ -108,6 +108,7 @@ struct posix_acl *nfs3_get_acl(struct inode *inode, int type)
                case -EPROTONOSUPPORT:
                        dprintk("NFS_V3_ACL extension not supported; disabling\n");
                        server->caps &= ~NFS_CAP_ACLS;
+                       /* fall through */
                case -ENOTSUPP:
                        status = -EOPNOTSUPP;
                default:
@@ -229,6 +230,7 @@ static int __nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl,
                        dprintk("NFS_V3_ACL SETACL RPC not supported"
                                        "(will not retry)\n");
                        server->caps &= ~NFS_CAP_ACLS;
+                       /* fall through */
                case -ENOTSUPP:
                        status = -EOPNOTSUPP;
        }
index 5f59b6f..ac5b784 100644 (file)
@@ -17,6 +17,7 @@
 #include "internal.h"
 
 #define NFSDBG_FACILITY NFSDBG_PROC
+static int nfs42_do_offload_cancel_async(struct file *dst, nfs4_stateid *std);
 
 static int _nfs42_proc_fallocate(struct rpc_message *msg, struct file *filep,
                struct nfs_lock_context *lock, loff_t offset, loff_t len)
@@ -130,6 +131,91 @@ out_unlock:
        return err;
 }
 
+static int handle_async_copy(struct nfs42_copy_res *res,
+                            struct nfs_server *server,
+                            struct file *src,
+                            struct file *dst,
+                            nfs4_stateid *src_stateid)
+{
+       struct nfs4_copy_state *copy;
+       int status = NFS4_OK;
+       bool found_pending = false;
+       struct nfs_open_context *ctx = nfs_file_open_context(dst);
+
+       spin_lock(&server->nfs_client->cl_lock);
+       list_for_each_entry(copy, &server->nfs_client->pending_cb_stateids,
+                               copies) {
+               if (memcmp(&res->write_res.stateid, &copy->stateid,
+                               NFS4_STATEID_SIZE))
+                       continue;
+               found_pending = true;
+               list_del(&copy->copies);
+               break;
+       }
+       if (found_pending) {
+               spin_unlock(&server->nfs_client->cl_lock);
+               goto out;
+       }
+
+       copy = kzalloc(sizeof(struct nfs4_copy_state), GFP_NOFS);
+       if (!copy) {
+               spin_unlock(&server->nfs_client->cl_lock);
+               return -ENOMEM;
+       }
+       memcpy(&copy->stateid, &res->write_res.stateid, NFS4_STATEID_SIZE);
+       init_completion(&copy->completion);
+       copy->parent_state = ctx->state;
+
+       list_add_tail(&copy->copies, &server->ss_copies);
+       spin_unlock(&server->nfs_client->cl_lock);
+
+       status = wait_for_completion_interruptible(&copy->completion);
+       spin_lock(&server->nfs_client->cl_lock);
+       list_del_init(&copy->copies);
+       spin_unlock(&server->nfs_client->cl_lock);
+       if (status == -ERESTARTSYS) {
+               goto out_cancel;
+       } else if (copy->flags) {
+               status = -EAGAIN;
+               goto out_cancel;
+       }
+out:
+       res->write_res.count = copy->count;
+       memcpy(&res->write_res.verifier, &copy->verf, sizeof(copy->verf));
+       status = -copy->error;
+
+       kfree(copy);
+       return status;
+out_cancel:
+       nfs42_do_offload_cancel_async(dst, &copy->stateid);
+       kfree(copy);
+       return status;
+}
+
+static int process_copy_commit(struct file *dst, loff_t pos_dst,
+                              struct nfs42_copy_res *res)
+{
+       struct nfs_commitres cres;
+       int status = -ENOMEM;
+
+       cres.verf = kzalloc(sizeof(struct nfs_writeverf), GFP_NOFS);
+       if (!cres.verf)
+               goto out;
+
+       status = nfs4_proc_commit(dst, pos_dst, res->write_res.count, &cres);
+       if (status)
+               goto out_free;
+       if (nfs_write_verifier_cmp(&res->write_res.verifier.verifier,
+                                   &cres.verf->verifier)) {
+               dprintk("commit verf differs from copy verf\n");
+               status = -EAGAIN;
+       }
+out_free:
+       kfree(cres.verf);
+out:
+       return status;
+}
+
 static ssize_t _nfs42_proc_copy(struct file *src,
                                struct nfs_lock_context *src_lock,
                                struct file *dst,
@@ -168,9 +254,16 @@ static ssize_t _nfs42_proc_copy(struct file *src,
        if (status)
                return status;
 
-       res->commit_res.verf = kzalloc(sizeof(struct nfs_writeverf), GFP_NOFS);
-       if (!res->commit_res.verf)
-               return -ENOMEM;
+       res->commit_res.verf = NULL;
+       if (args->sync) {
+               res->commit_res.verf =
+                       kzalloc(sizeof(struct nfs_writeverf), GFP_NOFS);
+               if (!res->commit_res.verf)
+                       return -ENOMEM;
+       }
+       set_bit(NFS_CLNT_DST_SSC_COPY_STATE,
+               &dst_lock->open_context->state->flags);
+
        status = nfs4_call_sync(server->client, server, &msg,
                                &args->seq_args, &res->seq_res, 0);
        if (status == -ENOTSUPP)
@@ -178,18 +271,34 @@ static ssize_t _nfs42_proc_copy(struct file *src,
        if (status)
                goto out;
 
-       if (nfs_write_verifier_cmp(&res->write_res.verifier.verifier,
+       if (args->sync &&
+               nfs_write_verifier_cmp(&res->write_res.verifier.verifier,
                                    &res->commit_res.verf->verifier)) {
                status = -EAGAIN;
                goto out;
        }
 
+       if (!res->synchronous) {
+               status = handle_async_copy(res, server, src, dst,
+                               &args->src_stateid);
+               if (status)
+                       return status;
+       }
+
+       if ((!res->synchronous || !args->sync) &&
+                       res->write_res.verifier.committed != NFS_FILE_SYNC) {
+               status = process_copy_commit(dst, pos_dst, res);
+               if (status)
+                       return status;
+       }
+
        truncate_pagecache_range(dst_inode, pos_dst,
                                 pos_dst + res->write_res.count);
 
        status = res->write_res.count;
 out:
-       kfree(res->commit_res.verf);
+       if (args->sync)
+               kfree(res->commit_res.verf);
        return status;
 }
 
@@ -206,6 +315,7 @@ ssize_t nfs42_proc_copy(struct file *src, loff_t pos_src,
                .dst_fh         = NFS_FH(file_inode(dst)),
                .dst_pos        = pos_dst,
                .count          = count,
+               .sync           = false,
        };
        struct nfs42_copy_res res;
        struct nfs4_exception src_exception = {
@@ -247,7 +357,11 @@ ssize_t nfs42_proc_copy(struct file *src, loff_t pos_src,
                if (err == -ENOTSUPP) {
                        err = -EOPNOTSUPP;
                        break;
-               } if (err == -EAGAIN) {
+               } else if (err == -EAGAIN) {
+                       dst_exception.retry = 1;
+                       continue;
+               } else if (err == -NFS4ERR_OFFLOAD_NO_REQS && !args.sync) {
+                       args.sync = true;
                        dst_exception.retry = 1;
                        continue;
                }
@@ -264,6 +378,89 @@ out_put_src_lock:
        return err;
 }
 
+struct nfs42_offloadcancel_data {
+       struct nfs_server *seq_server;
+       struct nfs42_offload_status_args args;
+       struct nfs42_offload_status_res res;
+};
+
+static void nfs42_offload_cancel_prepare(struct rpc_task *task, void *calldata)
+{
+       struct nfs42_offloadcancel_data *data = calldata;
+
+       nfs4_setup_sequence(data->seq_server->nfs_client,
+                               &data->args.osa_seq_args,
+                               &data->res.osr_seq_res, task);
+}
+
+static void nfs42_offload_cancel_done(struct rpc_task *task, void *calldata)
+{
+       struct nfs42_offloadcancel_data *data = calldata;
+
+       nfs41_sequence_done(task, &data->res.osr_seq_res);
+       if (task->tk_status &&
+               nfs4_async_handle_error(task, data->seq_server, NULL,
+                       NULL) == -EAGAIN)
+               rpc_restart_call_prepare(task);
+}
+
+static void nfs42_free_offloadcancel_data(void *data)
+{
+       kfree(data);
+}
+
+static const struct rpc_call_ops nfs42_offload_cancel_ops = {
+       .rpc_call_prepare = nfs42_offload_cancel_prepare,
+       .rpc_call_done = nfs42_offload_cancel_done,
+       .rpc_release = nfs42_free_offloadcancel_data,
+};
+
+static int nfs42_do_offload_cancel_async(struct file *dst,
+                                        nfs4_stateid *stateid)
+{
+       struct nfs_server *dst_server = NFS_SERVER(file_inode(dst));
+       struct nfs42_offloadcancel_data *data = NULL;
+       struct nfs_open_context *ctx = nfs_file_open_context(dst);
+       struct rpc_task *task;
+       struct rpc_message msg = {
+               .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OFFLOAD_CANCEL],
+               .rpc_cred = ctx->cred,
+       };
+       struct rpc_task_setup task_setup_data = {
+               .rpc_client = dst_server->client,
+               .rpc_message = &msg,
+               .callback_ops = &nfs42_offload_cancel_ops,
+               .workqueue = nfsiod_workqueue,
+               .flags = RPC_TASK_ASYNC,
+       };
+       int status;
+
+       if (!(dst_server->caps & NFS_CAP_OFFLOAD_CANCEL))
+               return -EOPNOTSUPP;
+
+       data = kzalloc(sizeof(struct nfs42_offloadcancel_data), GFP_NOFS);
+       if (data == NULL)
+               return -ENOMEM;
+
+       data->seq_server = dst_server;
+       data->args.osa_src_fh = NFS_FH(file_inode(dst));
+       memcpy(&data->args.osa_stateid, stateid,
+               sizeof(data->args.osa_stateid));
+       msg.rpc_argp = &data->args;
+       msg.rpc_resp = &data->res;
+       task_setup_data.callback_data = data;
+       nfs4_init_sequence(&data->args.osa_seq_args, &data->res.osr_seq_res,
+                          1, 0);
+       task = rpc_run_task(&task_setup_data);
+       if (IS_ERR(task))
+               return PTR_ERR(task);
+       status = rpc_wait_for_completion_task(task);
+       if (status == -ENOTSUPP)
+               dst_server->caps &= ~NFS_CAP_OFFLOAD_CANCEL;
+       rpc_put_task(task);
+       return status;
+}
+
 static loff_t _nfs42_proc_llseek(struct file *filep,
                struct nfs_lock_context *lock, loff_t offset, int whence)
 {
index 5966e1e..69f72ed 100644 (file)
@@ -26,6 +26,9 @@
                                         NFS42_WRITE_RES_SIZE + \
                                         1 /* cr_consecutive */ + \
                                         1 /* cr_synchronous */)
+#define encode_offload_cancel_maxsz    (op_encode_hdr_maxsz + \
+                                        XDR_QUADLEN(NFS4_STATEID_SIZE))
+#define decode_offload_cancel_maxsz    (op_decode_hdr_maxsz)
 #define encode_deallocate_maxsz                (op_encode_hdr_maxsz + \
                                         encode_fallocate_maxsz)
 #define decode_deallocate_maxsz                (op_decode_hdr_maxsz)
                                         decode_putfh_maxsz + \
                                         decode_copy_maxsz + \
                                         decode_commit_maxsz)
+#define NFS4_enc_offload_cancel_sz     (compound_encode_hdr_maxsz + \
+                                        encode_putfh_maxsz + \
+                                        encode_offload_cancel_maxsz)
+#define NFS4_dec_offload_cancel_sz     (compound_decode_hdr_maxsz + \
+                                        decode_putfh_maxsz + \
+                                        decode_offload_cancel_maxsz)
 #define NFS4_enc_deallocate_sz         (compound_encode_hdr_maxsz + \
                                         encode_putfh_maxsz + \
                                         encode_deallocate_maxsz + \
@@ -141,10 +150,18 @@ static void encode_copy(struct xdr_stream *xdr,
        encode_uint64(xdr, args->count);
 
        encode_uint32(xdr, 1); /* consecutive = true */
-       encode_uint32(xdr, 1); /* synchronous = true */
+       encode_uint32(xdr, args->sync);
        encode_uint32(xdr, 0); /* src server list */
 }
 
+static void encode_offload_cancel(struct xdr_stream *xdr,
+                                 const struct nfs42_offload_status_args *args,
+                                 struct compound_hdr *hdr)
+{
+       encode_op_hdr(xdr, OP_OFFLOAD_CANCEL, decode_offload_cancel_maxsz, hdr);
+       encode_nfs4_stateid(xdr, &args->osa_stateid);
+}
+
 static void encode_deallocate(struct xdr_stream *xdr,
                              const struct nfs42_falloc_args *args,
                              struct compound_hdr *hdr)
@@ -256,7 +273,27 @@ static void nfs4_xdr_enc_copy(struct rpc_rqst *req,
        encode_savefh(xdr, &hdr);
        encode_putfh(xdr, args->dst_fh, &hdr);
        encode_copy(xdr, args, &hdr);
-       encode_copy_commit(xdr, args, &hdr);
+       if (args->sync)
+               encode_copy_commit(xdr, args, &hdr);
+       encode_nops(&hdr);
+}
+
+/*
+ * Encode OFFLOAD_CANEL request
+ */
+static void nfs4_xdr_enc_offload_cancel(struct rpc_rqst *req,
+                                       struct xdr_stream *xdr,
+                                       const void *data)
+{
+       const struct nfs42_offload_status_args *args = data;
+       struct compound_hdr hdr = {
+               .minorversion = nfs4_xdr_minorversion(&args->osa_seq_args),
+       };
+
+       encode_compound_hdr(xdr, req, &hdr);
+       encode_sequence(xdr, &args->osa_seq_args, &hdr);
+       encode_putfh(xdr, args->osa_src_fh, &hdr);
+       encode_offload_cancel(xdr, args, &hdr);
        encode_nops(&hdr);
 }
 
@@ -353,21 +390,23 @@ static int decode_write_response(struct xdr_stream *xdr,
                                 struct nfs42_write_res *res)
 {
        __be32 *p;
+       int status, count;
 
-       p = xdr_inline_decode(xdr, 4 + 8 + 4);
+       p = xdr_inline_decode(xdr, 4);
        if (unlikely(!p))
                goto out_overflow;
-
-       /*
-        * We never use asynchronous mode, so warn if a server returns
-        * a stateid.
-        */
-       if (unlikely(*p != 0)) {
-               pr_err_once("%s: server has set unrequested "
-                               "asynchronous mode\n", __func__);
+       count = be32_to_cpup(p);
+       if (count > 1)
                return -EREMOTEIO;
+       else if (count == 1) {
+               status = decode_opaque_fixed(xdr, &res->stateid,
+                               NFS4_STATEID_SIZE);
+               if (unlikely(status))
+                       goto out_overflow;
        }
-       p++;
+       p = xdr_inline_decode(xdr, 8 + 4);
+       if (unlikely(!p))
+               goto out_overflow;
        p = xdr_decode_hyper(p, &res->count);
        res->verifier.committed = be32_to_cpup(p);
        return decode_verifier(xdr, &res->verifier.verifier);
@@ -413,6 +452,12 @@ static int decode_copy(struct xdr_stream *xdr, struct nfs42_copy_res *res)
        return decode_copy_requirements(xdr, res);
 }
 
+static int decode_offload_cancel(struct xdr_stream *xdr,
+                                struct nfs42_offload_status_res *res)
+{
+       return decode_op_hdr(xdr, OP_OFFLOAD_CANCEL);
+}
+
 static int decode_deallocate(struct xdr_stream *xdr, struct nfs42_falloc_res *res)
 {
        return decode_op_hdr(xdr, OP_DEALLOCATE);
@@ -507,7 +552,34 @@ static int nfs4_xdr_dec_copy(struct rpc_rqst *rqstp,
        status = decode_copy(xdr, res);
        if (status)
                goto out;
-       status = decode_commit(xdr, &res->commit_res);
+       if (res->commit_res.verf)
+               status = decode_commit(xdr, &res->commit_res);
+out:
+       return status;
+}
+
+/*
+ * Decode OFFLOAD_CANCEL response
+ */
+static int nfs4_xdr_dec_offload_cancel(struct rpc_rqst *rqstp,
+                                      struct xdr_stream *xdr,
+                                      void *data)
+{
+       struct nfs42_offload_status_res *res = data;
+       struct compound_hdr hdr;
+       int status;
+
+       status = decode_compound_hdr(xdr, &hdr);
+       if (status)
+               goto out;
+       status = decode_sequence(xdr, &res->osr_seq_res, rqstp);
+       if (status)
+               goto out;
+       status = decode_putfh(xdr);
+       if (status)
+               goto out;
+       status = decode_offload_cancel(xdr, res);
+
 out:
        return status;
 }
index 51beb6e..3a69041 100644 (file)
@@ -163,6 +163,9 @@ enum {
        NFS_STATE_RECOVERY_FAILED,      /* OPEN stateid state recovery failed */
        NFS_STATE_MAY_NOTIFY_LOCK,      /* server may CB_NOTIFY_LOCK */
        NFS_STATE_CHANGE_WAIT,          /* A state changing operation is outstanding */
+#ifdef CONFIG_NFS_V4_2
+       NFS_CLNT_DST_SSC_COPY_STATE,    /* dst server open state on client*/
+#endif /* CONFIG_NFS_V4_2 */
 };
 
 struct nfs4_state {
@@ -273,6 +276,9 @@ int nfs4_replace_transport(struct nfs_server *server,
 
 /* nfs4proc.c */
 extern int nfs4_handle_exception(struct nfs_server *, int, struct nfs4_exception *);
+extern int nfs4_async_handle_error(struct rpc_task *task,
+                                  struct nfs_server *server,
+                                  struct nfs4_state *state, long *timeout);
 extern int nfs4_call_sync(struct rpc_clnt *, struct nfs_server *,
                          struct rpc_message *, struct nfs4_sequence_args *,
                          struct nfs4_sequence_res *, int);
@@ -505,7 +511,7 @@ extern int nfs4_sequence_done(struct rpc_task *task,
                              struct nfs4_sequence_res *res);
 
 extern void nfs4_free_lock_state(struct nfs_server *server, struct nfs4_lock_state *lsp);
-
+extern int nfs4_proc_commit(struct file *dst, __u64 offset, __u32 count, struct nfs_commitres *res);
 extern const nfs4_stateid zero_stateid;
 extern const nfs4_stateid invalid_stateid;
 
index 9796314..146e308 100644 (file)
@@ -156,9 +156,23 @@ nfs4_shutdown_ds_clients(struct nfs_client *clp)
        }
 }
 
+static void
+nfs4_cleanup_callback(struct nfs_client *clp)
+{
+       struct nfs4_copy_state *cp_state;
+
+       while (!list_empty(&clp->pending_cb_stateids)) {
+               cp_state = list_entry(clp->pending_cb_stateids.next,
+                                       struct nfs4_copy_state, copies);
+               list_del(&cp_state->copies);
+               kfree(cp_state);
+       }
+}
+
 void nfs41_shutdown_client(struct nfs_client *clp)
 {
        if (nfs4_has_session(clp)) {
+               nfs4_cleanup_callback(clp);
                nfs4_shutdown_ds_clients(clp);
                nfs4_destroy_session(clp->cl_session);
                nfs4_destroy_clientid(clp);
@@ -202,6 +216,7 @@ struct nfs_client *nfs4_alloc_client(const struct nfs_client_initdata *cl_init)
 #if IS_ENABLED(CONFIG_NFS_V4_1)
        init_waitqueue_head(&clp->cl_lock_waitq);
 #endif
+       INIT_LIST_HEAD(&clp->pending_cb_stateids);
        return clp;
 
 error:
@@ -1127,7 +1142,7 @@ struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *data,
        nfs_server_copy_userdata(server, parent_server);
 
        /* Get a client representation */
-#ifdef CONFIG_SUNRPC_XPRT_RDMA
+#if IS_ENABLED(CONFIG_SUNRPC_XPRT_RDMA)
        rpc_set_port(data->addr, NFS_RDMA_PORT);
        error = nfs4_set_client(server, data->hostname,
                                data->addr,
@@ -1139,7 +1154,7 @@ struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *data,
                                parent_client->cl_net);
        if (!error)
                goto init_server;
-#endif /* CONFIG_SUNRPC_XPRT_RDMA */
+#endif /* IS_ENABLED(CONFIG_SUNRPC_XPRT_RDMA) */
 
        rpc_set_port(data->addr, NFS_PORT);
        error = nfs4_set_client(server, data->hostname,
@@ -1153,7 +1168,7 @@ struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *data,
        if (error < 0)
                goto error;
 
-#ifdef CONFIG_SUNRPC_XPRT_RDMA
+#if IS_ENABLED(CONFIG_SUNRPC_XPRT_RDMA)
 init_server:
 #endif
        error = nfs_init_server_rpcclient(server, parent_server->client->cl_timeout, data->authflavor);
index 6b3b372..4288a6e 100644 (file)
@@ -133,10 +133,15 @@ static ssize_t nfs4_copy_file_range(struct file *file_in, loff_t pos_in,
                                    struct file *file_out, loff_t pos_out,
                                    size_t count, unsigned int flags)
 {
+       ssize_t ret;
+
        if (file_inode(file_in) == file_inode(file_out))
                return -EINVAL;
-
-       return nfs42_proc_copy(file_in, pos_in, file_out, pos_out, count);
+retry:
+       ret = nfs42_proc_copy(file_in, pos_in, file_out, pos_out, count);
+       if (ret == -EAGAIN)
+               goto retry;
+       return ret;
 }
 
 static loff_t nfs4_file_llseek(struct file *filep, loff_t offset, int whence)
@@ -149,6 +154,7 @@ static loff_t nfs4_file_llseek(struct file *filep, loff_t offset, int whence)
                ret = nfs42_proc_llseek(filep, offset, whence);
                if (ret != -ENOTSUPP)
                        return ret;
+               /* Fall through */
        default:
                return nfs_file_llseek(filep, offset, whence);
        }
index b6f9d84..3f23b68 100644 (file)
@@ -506,6 +506,7 @@ static int nfs_idmap_prepare_message(char *desc, struct idmap *idmap,
        switch (token) {
        case Opt_find_uid:
                im->im_type = IDMAP_TYPE_USER;
+               /* Fall through */
        case Opt_find_gid:
                im->im_conv = IDMAP_CONV_NAMETOID;
                ret = match_strlcpy(im->im_name, &substr, IDMAP_NAMESZ);
@@ -513,9 +514,12 @@ static int nfs_idmap_prepare_message(char *desc, struct idmap *idmap,
 
        case Opt_find_user:
                im->im_type = IDMAP_TYPE_USER;
+               /* Fall through */
        case Opt_find_group:
                im->im_conv = IDMAP_CONV_IDTONAME;
                ret = match_int(&substr, &im->im_id);
+               if (ret)
+                       goto out;
                break;
 
        default:
index b790976..34830f6 100644 (file)
@@ -449,6 +449,7 @@ static int nfs4_do_handle_exception(struct nfs_server *server,
                                                stateid);
                                goto wait_on_recovery;
                        }
+                       /* Fall through */
                case -NFS4ERR_OPENMODE:
                        if (inode) {
                                int err;
@@ -501,8 +502,10 @@ static int nfs4_do_handle_exception(struct nfs_server *server,
                                ret = -EBUSY;
                                break;
                        }
+                       /* Fall through */
                case -NFS4ERR_DELAY:
                        nfs_inc_server_stats(server, NFSIOS_DELAY);
+                       /* Fall through */
                case -NFS4ERR_GRACE:
                case -NFS4ERR_LAYOUTTRYLATER:
                case -NFS4ERR_RECALLCONFLICT:
@@ -581,12 +584,19 @@ nfs4_async_handle_exception(struct rpc_task *task, struct nfs_server *server,
                ret = -EIO;
        return ret;
 out_retry:
-       if (ret == 0)
+       if (ret == 0) {
                exception->retry = 1;
+               /*
+                * For NFS4ERR_MOVED, the client transport will need to
+                * be recomputed after migration recovery has completed.
+                */
+               if (errorcode == -NFS4ERR_MOVED)
+                       rpc_task_release_transport(task);
+       }
        return ret;
 }
 
-static int
+int
 nfs4_async_handle_error(struct rpc_task *task, struct nfs_server *server,
                        struct nfs4_state *state, long *timeout)
 {
@@ -1071,15 +1081,30 @@ int nfs4_call_sync(struct rpc_clnt *clnt,
        return nfs4_call_sync_sequence(clnt, server, msg, args, res);
 }
 
-static void update_changeattr(struct inode *dir, struct nfs4_change_info *cinfo,
-               unsigned long timestamp)
+static void
+nfs4_inc_nlink_locked(struct inode *inode)
+{
+       NFS_I(inode)->cache_validity |= NFS_INO_INVALID_OTHER;
+       inc_nlink(inode);
+}
+
+static void
+nfs4_dec_nlink_locked(struct inode *inode)
+{
+       NFS_I(inode)->cache_validity |= NFS_INO_INVALID_OTHER;
+       drop_nlink(inode);
+}
+
+static void
+update_changeattr_locked(struct inode *dir, struct nfs4_change_info *cinfo,
+               unsigned long timestamp, unsigned long cache_validity)
 {
        struct nfs_inode *nfsi = NFS_I(dir);
 
-       spin_lock(&dir->i_lock);
        nfsi->cache_validity |= NFS_INO_INVALID_CTIME
                | NFS_INO_INVALID_MTIME
-               | NFS_INO_INVALID_DATA;
+               | NFS_INO_INVALID_DATA
+               | cache_validity;
        if (cinfo->atomic && cinfo->before == inode_peek_iversion_raw(dir)) {
                nfsi->cache_validity &= ~NFS_INO_REVAL_PAGECACHE;
                nfsi->attrtimeo_timestamp = jiffies;
@@ -1092,7 +1117,16 @@ static void update_changeattr(struct inode *dir, struct nfs4_change_info *cinfo,
        inode_set_iversion_raw(dir, cinfo->after);
        nfsi->read_cache_jiffies = timestamp;
        nfsi->attr_gencount = nfs_inc_attr_generation_counter();
+       nfsi->cache_validity &= ~NFS_INO_INVALID_CHANGE;
        nfs_fscache_invalidate(dir);
+}
+
+static void
+update_changeattr(struct inode *dir, struct nfs4_change_info *cinfo,
+               unsigned long timestamp, unsigned long cache_validity)
+{
+       spin_lock(&dir->i_lock);
+       update_changeattr_locked(dir, cinfo, timestamp, cache_validity);
        spin_unlock(&dir->i_lock);
 }
 
@@ -1354,6 +1388,7 @@ static int can_open_delegated(struct nfs_delegation *delegation, fmode_t fmode,
        case NFS4_OPEN_CLAIM_PREVIOUS:
                if (!test_bit(NFS_DELEGATION_NEED_RECLAIM, &delegation->flags))
                        break;
+               /* Fall through */
        default:
                return 0;
        }
@@ -1773,6 +1808,10 @@ nfs4_opendata_check_deleg(struct nfs4_opendata *data, struct nfs4_state *state)
                                data->o_res.delegation_type,
                                &data->o_res.delegation,
                                data->o_res.pagemod_limit);
+
+       if (data->o_res.do_recall)
+               nfs_async_inode_return_delegation(state->inode,
+                                                 &data->o_res.delegation);
 }
 
 /*
@@ -2119,6 +2158,7 @@ int nfs4_open_delegation_recall(struct nfs_open_context *ctx,
                err = nfs4_open_recover_helper(opendata, FMODE_WRITE);
                if (err)
                        break;
+               /* Fall through */
        case FMODE_READ:
                err = nfs4_open_recover_helper(opendata, FMODE_READ);
        }
@@ -2248,6 +2288,7 @@ static void nfs4_open_prepare(struct rpc_task *task, void *calldata)
        case NFS4_OPEN_CLAIM_DELEG_CUR_FH:
        case NFS4_OPEN_CLAIM_DELEG_PREV_FH:
                data->o_arg.open_bitmap = &nfs4_open_noattr_bitmap[0];
+               /* Fall through */
        case NFS4_OPEN_CLAIM_FH:
                task->tk_msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_NOATTR];
        }
@@ -2481,7 +2522,7 @@ static int _nfs4_proc_open(struct nfs4_opendata *data,
                if (data->file_created ||
                    inode_peek_iversion_raw(dir) != o_res->cinfo.after)
                        update_changeattr(dir, &o_res->cinfo,
-                                       o_res->f_attr->time_start);
+                                       o_res->f_attr->time_start, 0);
        }
        if ((o_res->rflags & NFS4_OPEN_RESULT_LOCKTYPE_POSIX) == 0)
                server->caps &= ~NFS_CAP_POSIX_LOCK;
@@ -2843,6 +2884,9 @@ static int _nfs4_open_and_get_state(struct nfs4_opendata *opendata,
                                nfs_save_change_attribute(d_inode(opendata->dir)));
        }
 
+       /* Parse layoutget results before we check for access */
+       pnfs_parse_lgopen(state->inode, opendata->lgp, ctx);
+
        ret = nfs4_opendata_access(sp->so_cred, opendata, state, fmode, flags);
        if (ret != 0)
                goto out;
@@ -2851,8 +2895,6 @@ static int _nfs4_open_and_get_state(struct nfs4_opendata *opendata,
                nfs_inode_attach_open_context(ctx);
                if (read_seqcount_retry(&sp->so_reclaim_seqcount, seq))
                        nfs4_schedule_stateid_recovery(server, state);
-               else
-                       pnfs_parse_lgopen(state->inode, opendata->lgp, ctx);
        }
 
 out:
@@ -3220,7 +3262,8 @@ static void nfs4_close_done(struct rpc_task *task, void *data)
                        calldata->res.lr_res = NULL;
                        break;
                case -NFS4ERR_OLD_STATEID:
-                       if (nfs4_refresh_layout_stateid(&calldata->arg.lr_args->stateid,
+                       if (nfs4_layoutreturn_refresh_stateid(&calldata->arg.lr_args->stateid,
+                                               &calldata->arg.lr_args->range,
                                                calldata->inode))
                                goto lr_restart;
                        /* Fallthrough */
@@ -4236,7 +4279,8 @@ out:
        return status;
 }
 
-static int _nfs4_proc_remove(struct inode *dir, const struct qstr *name)
+static int
+_nfs4_proc_remove(struct inode *dir, const struct qstr *name, u32 ftype)
 {
        struct nfs_server *server = NFS_SERVER(dir);
        struct nfs_removeargs args = {
@@ -4255,8 +4299,14 @@ static int _nfs4_proc_remove(struct inode *dir, const struct qstr *name)
        int status;
 
        status = nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 1);
-       if (status == 0)
-               update_changeattr(dir, &res.cinfo, timestamp);
+       if (status == 0) {
+               spin_lock(&dir->i_lock);
+               update_changeattr_locked(dir, &res.cinfo, timestamp, 0);
+               /* Removing a directory decrements nlink in the parent */
+               if (ftype == NF4DIR && dir->i_nlink > 2)
+                       nfs4_dec_nlink_locked(dir);
+               spin_unlock(&dir->i_lock);
+       }
        return status;
 }
 
@@ -4273,7 +4323,7 @@ static int nfs4_proc_remove(struct inode *dir, struct dentry *dentry)
                        nfs4_inode_make_writeable(inode);
        }
        do {
-               err = _nfs4_proc_remove(dir, &dentry->d_name);
+               err = _nfs4_proc_remove(dir, &dentry->d_name, NF4REG);
                trace_nfs4_remove(dir, &dentry->d_name, err);
                err = nfs4_handle_exception(NFS_SERVER(dir), err,
                                &exception);
@@ -4287,7 +4337,7 @@ static int nfs4_proc_rmdir(struct inode *dir, const struct qstr *name)
        int err;
 
        do {
-               err = _nfs4_proc_remove(dir, name);
+               err = _nfs4_proc_remove(dir, name, NF4DIR);
                trace_nfs4_remove(dir, name, err);
                err = nfs4_handle_exception(NFS_SERVER(dir), err,
                                &exception);
@@ -4331,7 +4381,8 @@ static int nfs4_proc_unlink_done(struct rpc_task *task, struct inode *dir)
                                    &data->timeout) == -EAGAIN)
                return 0;
        if (task->tk_status == 0)
-               update_changeattr(dir, &res->cinfo, res->dir_attr->time_start);
+               update_changeattr(dir, &res->cinfo,
+                               res->dir_attr->time_start, 0);
        return 1;
 }
 
@@ -4373,9 +4424,18 @@ static int nfs4_proc_rename_done(struct rpc_task *task, struct inode *old_dir,
                return 0;
 
        if (task->tk_status == 0) {
-               update_changeattr(old_dir, &res->old_cinfo, res->old_fattr->time_start);
-               if (new_dir != old_dir)
-                       update_changeattr(new_dir, &res->new_cinfo, res->new_fattr->time_start);
+               if (new_dir != old_dir) {
+                       /* Note: If we moved a directory, nlink will change */
+                       update_changeattr(old_dir, &res->old_cinfo,
+                                       res->old_fattr->time_start,
+                                       NFS_INO_INVALID_OTHER);
+                       update_changeattr(new_dir, &res->new_cinfo,
+                                       res->new_fattr->time_start,
+                                       NFS_INO_INVALID_OTHER);
+               } else
+                       update_changeattr(old_dir, &res->old_cinfo,
+                                       res->old_fattr->time_start,
+                                       0);
        }
        return 1;
 }
@@ -4416,7 +4476,7 @@ static int _nfs4_proc_link(struct inode *inode, struct inode *dir, const struct
 
        status = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1);
        if (!status) {
-               update_changeattr(dir, &res.cinfo, res.fattr->time_start);
+               update_changeattr(dir, &res.cinfo, res.fattr->time_start, 0);
                status = nfs_post_op_update_inode(inode, res.fattr);
                if (!status)
                        nfs_setsecurity(inode, res.fattr, res.label);
@@ -4491,8 +4551,13 @@ static int nfs4_do_create(struct inode *dir, struct dentry *dentry, struct nfs4_
        int status = nfs4_call_sync(NFS_SERVER(dir)->client, NFS_SERVER(dir), &data->msg,
                                    &data->arg.seq_args, &data->res.seq_res, 1);
        if (status == 0) {
-               update_changeattr(dir, &data->res.dir_cinfo,
-                               data->res.fattr->time_start);
+               spin_lock(&dir->i_lock);
+               update_changeattr_locked(dir, &data->res.dir_cinfo,
+                               data->res.fattr->time_start, 0);
+               /* Creating a directory bumps nlink in the parent */
+               if (data->arg.ftype == NF4DIR)
+                       nfs4_inc_nlink_locked(dir);
+               spin_unlock(&dir->i_lock);
                status = nfs_instantiate(dentry, data->res.fh, data->res.fattr, data->res.label);
        }
        return status;
@@ -5073,6 +5138,40 @@ static void nfs4_proc_commit_setup(struct nfs_commit_data *data, struct rpc_mess
        nfs4_state_protect(server->nfs_client, NFS_SP4_MACH_CRED_COMMIT, clnt, msg);
 }
 
+static int _nfs4_proc_commit(struct file *dst, struct nfs_commitargs *args,
+                               struct nfs_commitres *res)
+{
+       struct inode *dst_inode = file_inode(dst);
+       struct nfs_server *server = NFS_SERVER(dst_inode);
+       struct rpc_message msg = {
+               .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_COMMIT],
+               .rpc_argp = args,
+               .rpc_resp = res,
+       };
+
+       args->fh = NFS_FH(dst_inode);
+       return nfs4_call_sync(server->client, server, &msg,
+                       &args->seq_args, &res->seq_res, 1);
+}
+
+int nfs4_proc_commit(struct file *dst, __u64 offset, __u32 count, struct nfs_commitres *res)
+{
+       struct nfs_commitargs args = {
+               .offset = offset,
+               .count = count,
+       };
+       struct nfs_server *dst_server = NFS_SERVER(file_inode(dst));
+       struct nfs4_exception exception = { };
+       int status;
+
+       do {
+               status = _nfs4_proc_commit(dst, &args, res);
+               status = nfs4_handle_exception(dst_server, status, &exception);
+       } while (exception.retry);
+
+       return status;
+}
+
 struct nfs4_renewdata {
        struct nfs_client       *client;
        unsigned long           timestamp;
@@ -5902,7 +6001,8 @@ static void nfs4_delegreturn_done(struct rpc_task *task, void *calldata)
                        data->res.lr_res = NULL;
                        break;
                case -NFS4ERR_OLD_STATEID:
-                       if (nfs4_refresh_layout_stateid(&data->args.lr_args->stateid,
+                       if (nfs4_layoutreturn_refresh_stateid(&data->args.lr_args->stateid,
+                                               &data->args.lr_args->range,
                                                data->inode))
                                goto lr_restart;
                        /* Fallthrough */
@@ -6209,11 +6309,13 @@ static void nfs4_locku_done(struct rpc_task *task, void *data)
                        if (nfs4_update_lock_stateid(calldata->lsp,
                                        &calldata->res.stateid))
                                break;
+                       /* Fall through */
                case -NFS4ERR_ADMIN_REVOKED:
                case -NFS4ERR_EXPIRED:
                        nfs4_free_revoked_stateid(calldata->server,
                                        &calldata->arg.stateid,
                                        task->tk_msg.rpc_cred);
+                       /* Fall through */
                case -NFS4ERR_BAD_STATEID:
                case -NFS4ERR_OLD_STATEID:
                case -NFS4ERR_STALE_STATEID:
@@ -7727,7 +7829,7 @@ static int nfs4_sp4_select_mode(struct nfs_client *clp,
        }
 out:
        clp->cl_sp4_flags = flags;
-       return 0;
+       return ret;
 }
 
 struct nfs41_exchange_id_data {
@@ -8168,7 +8270,7 @@ static void nfs4_init_channel_attrs(struct nfs41_create_session_args *args,
        args->bc_attrs.max_resp_sz = max_bc_payload;
        args->bc_attrs.max_resp_sz_cached = 0;
        args->bc_attrs.max_ops = NFS4_MAX_BACK_CHANNEL_OPS;
-       args->bc_attrs.max_reqs = min_t(unsigned short, max_session_cb_slots, 1);
+       args->bc_attrs.max_reqs = max_t(unsigned short, max_session_cb_slots, 1);
 
        dprintk("%s: Back Channel : max_rqst_sz=%u max_resp_sz=%u "
                "max_resp_sz_cached=%u max_ops=%u max_reqs=%u\n",
@@ -8851,7 +8953,8 @@ static void nfs4_layoutreturn_done(struct rpc_task *task, void *calldata)
        server = NFS_SERVER(lrp->args.inode);
        switch (task->tk_status) {
        case -NFS4ERR_OLD_STATEID:
-               if (nfs4_refresh_layout_stateid(&lrp->args.stateid,
+               if (nfs4_layoutreturn_refresh_stateid(&lrp->args.stateid,
+                                       &lrp->args.range,
                                        lrp->args.inode))
                        goto out_restart;
                /* Fallthrough */
@@ -9554,6 +9657,7 @@ static const struct nfs4_minor_version_ops nfs_v4_2_minor_ops = {
                | NFS_CAP_LGOPEN
                | NFS_CAP_ALLOCATE
                | NFS_CAP_COPY
+               | NFS_CAP_OFFLOAD_CANCEL
                | NFS_CAP_DEALLOCATE
                | NFS_CAP_SEEK
                | NFS_CAP_LAYOUTSTATS
index 2bf2eaa..3df0eb5 100644 (file)
@@ -274,7 +274,7 @@ static int nfs4_drain_slot_tbl(struct nfs4_slot_table *tbl)
 static int nfs4_begin_drain_session(struct nfs_client *clp)
 {
        struct nfs4_session *ses = clp->cl_session;
-       int ret = 0;
+       int ret;
 
        if (clp->cl_slot_tbl)
                return nfs4_drain_slot_tbl(clp->cl_slot_tbl);
@@ -1525,6 +1525,7 @@ restart:
                default:
                        pr_err("NFS: %s: unhandled error %d\n",
                                        __func__, status);
+                       /* Fall through */
                case -ENOMEM:
                case -NFS4ERR_DENIED:
                case -NFS4ERR_RECLAIM_BAD:
@@ -1588,6 +1589,22 @@ restart:
                                }
                                clear_bit(NFS_STATE_RECLAIM_NOGRACE,
                                        &state->flags);
+#ifdef CONFIG_NFS_V4_2
+                               if (test_bit(NFS_CLNT_DST_SSC_COPY_STATE, &state->flags)) {
+                                       struct nfs4_copy_state *copy;
+
+                                       spin_lock(&sp->so_server->nfs_client->cl_lock);
+                                       list_for_each_entry(copy, &sp->so_server->ss_copies, copies) {
+                                               if (memcmp(&state->stateid.other, &copy->parent_state->stateid.other, NFS4_STATEID_SIZE))
+                                                       continue;
+                                               copy->flags = 1;
+                                               complete(&copy->completion);
+                                               printk("AGLO: server rebooted waking up the copy\n");
+                                               break;
+                                       }
+                                       spin_unlock(&sp->so_server->nfs_client->cl_lock);
+                               }
+#endif /* CONFIG_NFS_V4_2 */
                                nfs4_put_open_state(state);
                                spin_lock(&sp->so_lock);
                                goto restart;
@@ -1597,6 +1614,7 @@ restart:
                        default:
                                printk(KERN_ERR "NFS: %s: unhandled error %d\n",
                                        __func__, status);
+                               /* Fall through */
                        case -ENOENT:
                        case -ENOMEM:
                        case -EACCES:
@@ -1608,6 +1626,7 @@ restart:
                                break;
                        case -EAGAIN:
                                ssleep(1);
+                               /* Fall through */
                        case -NFS4ERR_ADMIN_REVOKED:
                        case -NFS4ERR_STALE_STATEID:
                        case -NFS4ERR_OLD_STATEID:
@@ -1939,7 +1958,9 @@ static int nfs4_establish_lease(struct nfs_client *clp)
                clp->cl_mvops->reboot_recovery_ops;
        int status;
 
-       nfs4_begin_drain_session(clp);
+       status = nfs4_begin_drain_session(clp);
+       if (status != 0)
+               return status;
        cred = nfs4_get_clid_cred(clp);
        if (cred == NULL)
                return -ENOENT;
@@ -2027,7 +2048,9 @@ static int nfs4_try_migration(struct nfs_server *server, struct rpc_cred *cred)
                goto out;
        }
 
-       nfs4_begin_drain_session(clp);
+       status = nfs4_begin_drain_session(clp);
+       if (status != 0)
+               return status;
 
        status = nfs4_replace_transport(server, locations);
        if (status != 0) {
@@ -2190,9 +2213,11 @@ again:
        case -ETIMEDOUT:
                if (clnt->cl_softrtry)
                        break;
+               /* Fall through */
        case -NFS4ERR_DELAY:
        case -EAGAIN:
                ssleep(1);
+               /* Fall through */
        case -NFS4ERR_STALE_CLIENTID:
                dprintk("NFS: %s after status %d, retrying\n",
                        __func__, status);
@@ -2204,6 +2229,7 @@ again:
                }
                if (clnt->cl_auth->au_flavor == RPC_AUTH_UNIX)
                        break;
+               /* Fall through */
        case -NFS4ERR_CLID_INUSE:
        case -NFS4ERR_WRONGSEC:
                /* No point in retrying if we already used RPC_AUTH_UNIX */
@@ -2374,7 +2400,9 @@ static int nfs4_reset_session(struct nfs_client *clp)
 
        if (!nfs4_has_session(clp))
                return 0;
-       nfs4_begin_drain_session(clp);
+       status = nfs4_begin_drain_session(clp);
+       if (status != 0)
+               return status;
        cred = nfs4_get_clid_cred(clp);
        status = nfs4_proc_destroy_session(clp->cl_session, cred);
        switch (status) {
@@ -2417,7 +2445,9 @@ static int nfs4_bind_conn_to_session(struct nfs_client *clp)
 
        if (!nfs4_has_session(clp))
                return 0;
-       nfs4_begin_drain_session(clp);
+       ret = nfs4_begin_drain_session(clp);
+       if (ret != 0)
+               return ret;
        cred = nfs4_get_clid_cred(clp);
        ret = nfs4_proc_bind_conn_to_session(clp, cred);
        if (cred)
index cd41d25..b7bde12 100644 (file)
@@ -7789,6 +7789,7 @@ const struct rpc_procinfo nfs4_procedures[] = {
        PROC42(LAYOUTSTATS,     enc_layoutstats,        dec_layoutstats),
        PROC42(CLONE,           enc_clone,              dec_clone),
        PROC42(COPY,            enc_copy,               dec_copy),
+       PROC42(OFFLOAD_CANCEL,  enc_offload_cancel,     dec_offload_cancel),
        PROC(LOOKUPP,           enc_lookupp,            dec_lookupp),
 };
 
index 67d19cd..bb5476a 100644 (file)
@@ -561,6 +561,7 @@ static void nfs_pgio_rpcsetup(struct nfs_pgio_header *hdr,
        case FLUSH_COND_STABLE:
                if (nfs_reqs_to_commit(cinfo))
                        break;
+               /* fall through */
        default:
                hdr->args.stable = NFS_FILE_SYNC;
        }
index bcc3add..e8f232d 100644 (file)
@@ -361,18 +361,32 @@ pnfs_clear_lseg_state(struct pnfs_layout_segment *lseg,
 /*
  * Update the seqid of a layout stateid
  */
-bool nfs4_refresh_layout_stateid(nfs4_stateid *dst, struct inode *inode)
+bool nfs4_layoutreturn_refresh_stateid(nfs4_stateid *dst,
+               struct pnfs_layout_range *dst_range,
+               struct inode *inode)
 {
        struct pnfs_layout_hdr *lo;
+       struct pnfs_layout_range range = {
+               .iomode = IOMODE_ANY,
+               .offset = 0,
+               .length = NFS4_MAX_UINT64,
+       };
        bool ret = false;
+       LIST_HEAD(head);
+       int err;
 
        spin_lock(&inode->i_lock);
        lo = NFS_I(inode)->layout;
        if (lo && nfs4_stateid_match_other(dst, &lo->plh_stateid)) {
-               dst->seqid = lo->plh_stateid.seqid;
-               ret = true;
+               err = pnfs_mark_matching_lsegs_return(lo, &head, &range, 0);
+               if (err != -EBUSY) {
+                       dst->seqid = lo->plh_stateid.seqid;
+                       *dst_range = range;
+                       ret = true;
+               }
        }
        spin_unlock(&inode->i_lock);
+       pnfs_free_lseg_list(&head);
        return ret;
 }
 
@@ -1018,7 +1032,6 @@ pnfs_alloc_init_layoutget_args(struct inode *ino,
        nfs4_stateid_copy(&lgp->args.stateid, stateid);
        lgp->gfp_flags = gfp_flags;
        lgp->cred = get_rpccred(ctx->cred);
-       lgp->callback_count = raw_seqcount_begin(&server->nfs_client->cl_callback_count);
        return lgp;
 }
 
@@ -1160,12 +1173,21 @@ static bool
 pnfs_layout_need_return(struct pnfs_layout_hdr *lo)
 {
        struct pnfs_layout_segment *s;
+       enum pnfs_iomode iomode;
+       u32 seq;
 
        if (!test_bit(NFS_LAYOUT_RETURN_REQUESTED, &lo->plh_flags))
                return false;
 
-       /* Defer layoutreturn until all lsegs are done */
+       seq = lo->plh_return_seq;
+       iomode = lo->plh_return_iomode;
+
+       /* Defer layoutreturn until all recalled lsegs are done */
        list_for_each_entry(s, &lo->plh_segs, pls_list) {
+               if (seq && pnfs_seqid_is_newer(s->pls_seq, seq))
+                       continue;
+               if (iomode != IOMODE_ANY && s->pls_range.iomode != iomode)
+                       continue;
                if (test_bit(NFS_LSEG_LAYOUTRETURN, &s->pls_flags))
                        return false;
        }
@@ -1609,7 +1631,7 @@ pnfs_lseg_range_match(const struct pnfs_layout_range *ls_range,
            (range->iomode != ls_range->iomode &&
             strict_iomode) ||
            !pnfs_lseg_range_intersecting(ls_range, range))
-               return 0;
+               return false;
 
        /* range1 covers only the first byte in the range */
        range1 = *range;
@@ -1631,7 +1653,6 @@ pnfs_find_lseg(struct pnfs_layout_hdr *lo,
 
        list_for_each_entry(lseg, &lo->plh_segs, pls_list) {
                if (test_bit(NFS_LSEG_VALID, &lseg->pls_flags) &&
-                   !test_bit(NFS_LSEG_LAYOUTRETURN, &lseg->pls_flags) &&
                    pnfs_lseg_range_match(&lseg->pls_range, range,
                                          strict_iomode)) {
                        ret = pnfs_get_lseg(lseg);
@@ -1731,6 +1752,17 @@ static bool pnfs_prepare_to_retry_layoutget(struct pnfs_layout_hdr *lo)
                                   TASK_UNINTERRUPTIBLE);
 }
 
+static void nfs_layoutget_begin(struct pnfs_layout_hdr *lo)
+{
+       atomic_inc(&lo->plh_outstanding);
+}
+
+static void nfs_layoutget_end(struct pnfs_layout_hdr *lo)
+{
+       if (atomic_dec_and_test(&lo->plh_outstanding))
+               wake_up_var(&lo->plh_outstanding);
+}
+
 static void pnfs_clear_first_layoutget(struct pnfs_layout_hdr *lo)
 {
        unsigned long *bitlock = &lo->plh_flags;
@@ -1791,12 +1823,6 @@ pnfs_update_layout(struct inode *ino,
                goto out;
        }
 
-       if (iomode == IOMODE_READ && i_size_read(ino) == 0) {
-               trace_pnfs_update_layout(ino, pos, count, iomode, lo, lseg,
-                                PNFS_UPDATE_LAYOUT_RD_ZEROLEN);
-               goto out;
-       }
-
        if (pnfs_within_mdsthreshold(ctx, ino, iomode)) {
                trace_pnfs_update_layout(ino, pos, count, iomode, lo, lseg,
                                 PNFS_UPDATE_LAYOUT_MDSTHRESH);
@@ -1830,6 +1856,21 @@ lookup_again:
                goto out_unlock;
        }
 
+       /*
+        * If the layout segment list is empty, but there are outstanding
+        * layoutget calls, then they might be subject to a layoutrecall.
+        */
+       if (list_empty(&lo->plh_segs) &&
+           atomic_read(&lo->plh_outstanding) != 0) {
+               spin_unlock(&ino->i_lock);
+               if (wait_var_event_killable(&lo->plh_outstanding,
+                                       atomic_read(&lo->plh_outstanding) == 0
+                                       || !list_empty(&lo->plh_segs)))
+                       goto out_put_layout_hdr;
+               pnfs_put_layout_hdr(lo);
+               goto lookup_again;
+       }
+
        lseg = pnfs_find_lseg(lo, &arg, strict_iomode);
        if (lseg) {
                trace_pnfs_update_layout(ino, pos, count, iomode, lo, lseg,
@@ -1903,7 +1944,7 @@ lookup_again:
                                PNFS_UPDATE_LAYOUT_BLOCKED);
                goto out_unlock;
        }
-       atomic_inc(&lo->plh_outstanding);
+       nfs_layoutget_begin(lo);
        spin_unlock(&ino->i_lock);
 
        _add_to_server_list(lo, server);
@@ -1920,14 +1961,14 @@ lookup_again:
        if (!lgp) {
                trace_pnfs_update_layout(ino, pos, count, iomode, lo, NULL,
                                         PNFS_UPDATE_LAYOUT_NOMEM);
-               atomic_dec(&lo->plh_outstanding);
+               nfs_layoutget_end(lo);
                goto out_put_layout_hdr;
        }
 
        lseg = nfs4_proc_layoutget(lgp, &timeout);
        trace_pnfs_update_layout(ino, pos, count, iomode, lo, lseg,
                                 PNFS_UPDATE_LAYOUT_SEND_LAYOUTGET);
-       atomic_dec(&lo->plh_outstanding);
+       nfs_layoutget_end(lo);
        if (IS_ERR(lseg)) {
                switch(PTR_ERR(lseg)) {
                case -EBUSY:
@@ -1935,15 +1976,6 @@ lookup_again:
                                lseg = NULL;
                        break;
                case -ERECALLCONFLICT:
-                       /* Huh? We hold no layouts, how is there a recall? */
-                       if (first) {
-                               lseg = NULL;
-                               break;
-                       }
-                       /* Destroy the existing layout and start over */
-                       if (time_after(jiffies, giveup))
-                               pnfs_destroy_layout(NFS_I(ino));
-                       /* Fallthrough */
                case -EAGAIN:
                        break;
                default:
@@ -2022,7 +2054,7 @@ _pnfs_grab_empty_layout(struct inode *ino, struct nfs_open_context *ctx)
                goto out_unlock;
        if (test_and_set_bit(NFS_LAYOUT_FIRST_LAYOUTGET, &lo->plh_flags))
                goto out_unlock;
-       atomic_inc(&lo->plh_outstanding);
+       nfs_layoutget_begin(lo);
        spin_unlock(&ino->i_lock);
        _add_to_server_list(lo, NFS_SERVER(ino));
        return lo;
@@ -2146,9 +2178,6 @@ void pnfs_parse_lgopen(struct inode *ino, struct nfs4_layoutget *lgp,
        } else
                lo = NFS_I(lgp->args.inode)->layout;
 
-       if (read_seqcount_retry(&srv->nfs_client->cl_callback_count,
-                               lgp->callback_count))
-               return;
        lseg = pnfs_layout_process(lgp);
        if (!IS_ERR(lseg)) {
                iomode = lgp->args.range.iomode;
@@ -2163,8 +2192,8 @@ void nfs4_lgopen_release(struct nfs4_layoutget *lgp)
                struct inode *inode = lgp->args.inode;
                if (inode) {
                        struct pnfs_layout_hdr *lo = NFS_I(inode)->layout;
-                       atomic_dec(&lo->plh_outstanding);
                        pnfs_clear_first_layoutget(lo);
+                       nfs_layoutget_end(lo);
                }
                pnfs_layoutget_free(lgp);
        }
@@ -2238,15 +2267,31 @@ out_forget:
        return ERR_PTR(-EAGAIN);
 }
 
+static int
+mark_lseg_invalid_or_return(struct pnfs_layout_segment *lseg,
+               struct list_head *tmp_list)
+{
+       if (!mark_lseg_invalid(lseg, tmp_list))
+               return 0;
+       pnfs_cache_lseg_for_layoutreturn(lseg->pls_layout, lseg);
+       return 1;
+}
+
 /**
  * pnfs_mark_matching_lsegs_return - Free or return matching layout segments
  * @lo: pointer to layout header
  * @tmp_list: list header to be used with pnfs_free_lseg_list()
  * @return_range: describe layout segment ranges to be returned
+ * @seq: stateid seqid to match
  *
  * This function is mainly intended for use by layoutrecall. It attempts
  * to free the layout segment immediately, or else to mark it for return
  * as soon as its reference count drops to zero.
+ *
+ * Returns
+ * - 0: a layoutreturn needs to be scheduled.
+ * - EBUSY: there are layout segment that are still in use.
+ * - ENOENT: there are no layout segments that need to be returned.
  */
 int
 pnfs_mark_matching_lsegs_return(struct pnfs_layout_hdr *lo,
@@ -2259,9 +2304,6 @@ pnfs_mark_matching_lsegs_return(struct pnfs_layout_hdr *lo,
 
        dprintk("%s:Begin lo %p\n", __func__, lo);
 
-       if (list_empty(&lo->plh_segs))
-               return 0;
-
        assert_spin_locked(&lo->plh_inode->i_lock);
 
        list_for_each_entry_safe(lseg, next, &lo->plh_segs, pls_list)
@@ -2271,16 +2313,23 @@ pnfs_mark_matching_lsegs_return(struct pnfs_layout_hdr *lo,
                                lseg, lseg->pls_range.iomode,
                                lseg->pls_range.offset,
                                lseg->pls_range.length);
-                       if (mark_lseg_invalid(lseg, tmp_list))
+                       if (mark_lseg_invalid_or_return(lseg, tmp_list))
                                continue;
                        remaining++;
                        set_bit(NFS_LSEG_LAYOUTRETURN, &lseg->pls_flags);
                }
 
-       if (remaining)
+       if (remaining) {
                pnfs_set_plh_return_info(lo, return_range->iomode, seq);
+               return -EBUSY;
+       }
 
-       return remaining;
+       if (!list_empty(&lo->plh_return_segs)) {
+               pnfs_set_plh_return_info(lo, return_range->iomode, seq);
+               return 0;
+       }
+
+       return -ENOENT;
 }
 
 void pnfs_error_mark_layout_for_return(struct inode *inode,
@@ -2305,7 +2354,7 @@ void pnfs_error_mark_layout_for_return(struct inode *inode,
         * segments at hand when sending layoutreturn. See pnfs_put_lseg()
         * for how it works.
         */
-       if (!pnfs_mark_matching_lsegs_return(lo, &lo->plh_return_segs, &range, 0)) {
+       if (pnfs_mark_matching_lsegs_return(lo, &lo->plh_return_segs, &range, 0) != -EBUSY) {
                nfs4_stateid stateid;
                enum pnfs_iomode iomode;
 
index 3fe8142..ece367e 100644 (file)
@@ -259,7 +259,9 @@ int pnfs_destroy_layouts_byfsid(struct nfs_client *clp,
                bool is_recall);
 int pnfs_destroy_layouts_byclid(struct nfs_client *clp,
                bool is_recall);
-bool nfs4_refresh_layout_stateid(nfs4_stateid *dst, struct inode *inode);
+bool nfs4_layoutreturn_refresh_stateid(nfs4_stateid *dst,
+               struct pnfs_layout_range *dst_range,
+               struct inode *inode);
 void pnfs_put_layout_hdr(struct pnfs_layout_hdr *lo);
 void pnfs_set_layout_stateid(struct pnfs_layout_hdr *lo,
                             const nfs4_stateid *new,
@@ -780,7 +782,8 @@ static inline void nfs4_pnfs_v3_ds_connect_unload(void)
 {
 }
 
-static inline bool nfs4_refresh_layout_stateid(nfs4_stateid *dst,
+static inline bool nfs4_layoutreturn_refresh_stateid(nfs4_stateid *dst,
+               struct pnfs_layout_range *dst_range,
                struct inode *inode)
 {
        return false;
index 32ba2d4..d5e4d3c 100644 (file)
@@ -61,7 +61,7 @@ EXPORT_SYMBOL_GPL(pnfs_generic_commit_release);
 
 /* The generic layer is about to remove the req from the commit list.
  * If this will make the bucket empty, it will need to put the lseg reference.
- * Note this must be called holding i_lock
+ * Note this must be called holding nfsi->commit_mutex
  */
 void
 pnfs_generic_clear_request_commit(struct nfs_page *req,
@@ -149,9 +149,7 @@ restart:
                if (list_empty(&b->written)) {
                        freeme = b->wlseg;
                        b->wlseg = NULL;
-                       spin_unlock(&cinfo->inode->i_lock);
                        pnfs_put_lseg(freeme);
-                       spin_lock(&cinfo->inode->i_lock);
                        goto restart;
                }
        }
@@ -167,7 +165,7 @@ static void pnfs_generic_retry_commit(struct nfs_commit_info *cinfo, int idx)
        LIST_HEAD(pages);
        int i;
 
-       spin_lock(&cinfo->inode->i_lock);
+       mutex_lock(&NFS_I(cinfo->inode)->commit_mutex);
        for (i = idx; i < fl_cinfo->nbuckets; i++) {
                bucket = &fl_cinfo->buckets[i];
                if (list_empty(&bucket->committing))
@@ -177,12 +175,12 @@ static void pnfs_generic_retry_commit(struct nfs_commit_info *cinfo, int idx)
                list_for_each(pos, &bucket->committing)
                        cinfo->ds->ncommitting--;
                list_splice_init(&bucket->committing, &pages);
-               spin_unlock(&cinfo->inode->i_lock);
+               mutex_unlock(&NFS_I(cinfo->inode)->commit_mutex);
                nfs_retry_commit(&pages, freeme, cinfo, i);
                pnfs_put_lseg(freeme);
-               spin_lock(&cinfo->inode->i_lock);
+               mutex_lock(&NFS_I(cinfo->inode)->commit_mutex);
        }
-       spin_unlock(&cinfo->inode->i_lock);
+       mutex_unlock(&NFS_I(cinfo->inode)->commit_mutex);
 }
 
 static unsigned int
@@ -222,13 +220,13 @@ void pnfs_fetch_commit_bucket_list(struct list_head *pages,
        struct list_head *pos;
 
        bucket = &cinfo->ds->buckets[data->ds_commit_index];
-       spin_lock(&cinfo->inode->i_lock);
+       mutex_lock(&NFS_I(cinfo->inode)->commit_mutex);
        list_for_each(pos, &bucket->committing)
                cinfo->ds->ncommitting--;
        list_splice_init(&bucket->committing, pages);
        data->lseg = bucket->clseg;
        bucket->clseg = NULL;
-       spin_unlock(&cinfo->inode->i_lock);
+       mutex_unlock(&NFS_I(cinfo->inode)->commit_mutex);
 
 }
 
index 5e470e2..ac4b2f0 100644 (file)
@@ -884,7 +884,7 @@ int nfs_show_stats(struct seq_file *m, struct dentry *root)
 #endif
        seq_printf(m, "\n");
 
-       rpc_print_iostats(m, nfss->client);
+       rpc_clnt_show_stats(m, nfss->client);
 
        return 0;
 }
@@ -2899,7 +2899,7 @@ static int param_set_portnr(const char *val, const struct kernel_param *kp)
        if (!val)
                return -EINVAL;
        ret = kstrtoul(val, 0, &num);
-       if (ret == -EINVAL || num > NFS_CALLBACK_MAXPORTNR)
+       if (ret || num > NFS_CALLBACK_MAXPORTNR)
                return -EINVAL;
        *((unsigned int *)kp->arg) = num;
        return 0;
index a057b4f..586726a 100644 (file)
@@ -1406,6 +1406,8 @@ static void nfs_async_write_error(struct list_head *head)
 static void nfs_async_write_reschedule_io(struct nfs_pgio_header *hdr)
 {
        nfs_async_write_error(&hdr->pages);
+       filemap_fdatawrite_range(hdr->inode->i_mapping, hdr->args.offset,
+                       hdr->args.offset + hdr->args.count - 1);
 }
 
 static const struct nfs_pgio_completion_ops nfs_async_write_completion_ops = {
index 36358d4..426f550 100644 (file)
@@ -102,6 +102,7 @@ struct nfsd_net {
 
        time_t nfsd4_lease;
        time_t nfsd4_grace;
+       bool somebody_reclaimed;
 
        bool nfsd_net_up;
        bool lockd_up;
index 6259a4b..9eb8086 100644 (file)
@@ -202,7 +202,8 @@ nfsd3_proc_write(struct svc_rqst *rqstp)
 
        fh_copy(&resp->fh, &argp->fh);
        resp->committed = argp->stable;
-       nvecs = svc_fill_write_vector(rqstp, &argp->first, cnt);
+       nvecs = svc_fill_write_vector(rqstp, rqstp->rq_arg.pages,
+                                     &argp->first, cnt);
        if (!nvecs)
                RETURN_STATUS(nfserr_io);
        nfserr = nfsd_write(rqstp, &resp->fh, argp->offset,
@@ -289,6 +290,7 @@ nfsd3_proc_symlink(struct svc_rqst *rqstp)
                RETURN_STATUS(nfserr_nametoolong);
 
        argp->tname = svc_fill_symlink_pathname(rqstp, &argp->first,
+                                               page_address(rqstp->rq_arg.pages[0]),
                                                argp->tlen);
        if (IS_ERR(argp->tname))
                RETURN_STATUS(nfserrno(PTR_ERR(argp->tname)));
@@ -302,6 +304,7 @@ nfsd3_proc_symlink(struct svc_rqst *rqstp)
        fh_init(&resp->fh, NFS3_FHSIZE);
        nfserr = nfsd_symlink(rqstp, &resp->dirfh, argp->fname, argp->flen,
                                                   argp->tname, &resp->fh);
+       kfree(argp->tname);
        RETURN_STATUS(nfserr);
 }
 
index 1f04d2a..601bf33 100644 (file)
@@ -746,30 +746,17 @@ static int max_cb_time(struct net *net)
        return max(nn->nfsd4_lease/10, (time_t)1) * HZ;
 }
 
-static struct rpc_cred *callback_cred;
-
-int set_callback_cred(void)
-{
-       if (callback_cred)
-               return 0;
-       callback_cred = rpc_lookup_machine_cred("nfs");
-       if (!callback_cred)
-               return -ENOMEM;
-       return 0;
-}
-
-void cleanup_callback_cred(void)
-{
-       if (callback_cred) {
-               put_rpccred(callback_cred);
-               callback_cred = NULL;
-       }
-}
-
 static struct rpc_cred *get_backchannel_cred(struct nfs4_client *clp, struct rpc_clnt *client, struct nfsd4_session *ses)
 {
        if (clp->cl_minorversion == 0) {
-               return get_rpccred(callback_cred);
+               char *principal = clp->cl_cred.cr_targ_princ ?
+                                       clp->cl_cred.cr_targ_princ : "nfs";
+               struct rpc_cred *cred;
+
+               cred = rpc_lookup_machine_cred(principal);
+               if (!IS_ERR(cred))
+                       get_rpccred(cred);
+               return cred;
        } else {
                struct rpc_auth *auth = client->cl_auth;
                struct auth_cred acred = {};
@@ -980,6 +967,7 @@ static bool nfsd4_cb_sequence_done(struct rpc_task *task, struct nfsd4_callback
                break;
        case -ESERVERFAULT:
                ++session->se_cb_seq_nr;
+               /* Fall through */
        case 1:
        case -NFS4ERR_BADSESSION:
                nfsd4_mark_cb_fault(cb->cb_clp, cb->cb_seq_status);
index 228faf0..2b36aa0 100644 (file)
@@ -133,27 +133,20 @@ void nfsd4_setup_layout_type(struct svc_export *exp)
        if (!(exp->ex_flags & NFSEXP_PNFS))
                return;
 
-       /*
-        * If flex file is configured, use it by default. Otherwise
-        * check if the file system supports exporting a block-like layout.
-        * If the block device supports reservations prefer the SCSI layout,
-        * otherwise advertise the block layout.
-        */
 #ifdef CONFIG_NFSD_FLEXFILELAYOUT
        exp->ex_layout_types |= 1 << LAYOUT_FLEX_FILES;
 #endif
 #ifdef CONFIG_NFSD_BLOCKLAYOUT
-       /* overwrite flex file layout selection if needed */
        if (sb->s_export_op->get_uuid &&
            sb->s_export_op->map_blocks &&
            sb->s_export_op->commit_blocks)
                exp->ex_layout_types |= 1 << LAYOUT_BLOCK_VOLUME;
 #endif
 #ifdef CONFIG_NFSD_SCSILAYOUT
-       /* overwrite block layout selection if needed */
        if (sb->s_export_op->map_blocks &&
            sb->s_export_op->commit_blocks &&
-           sb->s_bdev && sb->s_bdev->bd_disk->fops->pr_ops)
+           sb->s_bdev && sb->s_bdev->bd_disk->fops->pr_ops &&
+               blk_queue_scsi_passthrough(sb->s_bdev->bd_disk->queue))
                exp->ex_layout_types |= 1 << LAYOUT_SCSI;
 #endif
 }
index 5d99e88..b7bc6e1 100644 (file)
@@ -354,6 +354,7 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
        struct svc_fh *resfh = NULL;
        struct net *net = SVC_NET(rqstp);
        struct nfsd_net *nn = net_generic(net, nfsd_net_id);
+       bool reclaim = false;
 
        dprintk("NFSD: nfsd4_open filename %.*s op_openowner %p\n",
                (int)open->op_fname.len, open->op_fname.data,
@@ -424,6 +425,7 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
                        if (status)
                                goto out;
                        open->op_openowner->oo_flags |= NFS4_OO_CONFIRMED;
+                       reclaim = true;
                case NFS4_OPEN_CLAIM_FH:
                case NFS4_OPEN_CLAIM_DELEG_CUR_FH:
                        status = do_open_fhandle(rqstp, cstate, open);
@@ -452,6 +454,8 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
        WARN(status && open->op_created,
             "nfsd4_process_open2 failed to open newly-created file! status=%u\n",
             be32_to_cpu(status));
+       if (reclaim && !status)
+               nn->somebody_reclaimed = true;
 out:
        if (resfh && resfh != &cstate->current_fh) {
                fh_dup2(&cstate->current_fh, resfh);
@@ -982,24 +986,6 @@ out:
        return status;
 }
 
-static int fill_in_write_vector(struct kvec *vec, struct nfsd4_write *write)
-{
-        int i = 1;
-        int buflen = write->wr_buflen;
-
-        vec[0].iov_base = write->wr_head.iov_base;
-        vec[0].iov_len = min_t(int, buflen, write->wr_head.iov_len);
-        buflen -= vec[0].iov_len;
-
-        while (buflen) {
-                vec[i].iov_base = page_address(write->wr_pagelist[i - 1]);
-                vec[i].iov_len = min_t(int, PAGE_SIZE, buflen);
-                buflen -= vec[i].iov_len;
-                i++;
-        }
-        return i;
-}
-
 static __be32
 nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
            union nfsd4_op_u *u)
@@ -1027,7 +1013,10 @@ nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
        write->wr_how_written = write->wr_stable_how;
        gen_boot_verifier(&write->wr_verifier, SVC_NET(rqstp));
 
-       nvecs = fill_in_write_vector(rqstp->rq_vec, write);
+       nvecs = svc_fill_write_vector(rqstp, write->wr_pagelist,
+                                     &write->wr_head, write->wr_buflen);
+       if (!nvecs)
+               return nfserr_io;
        WARN_ON_ONCE(nvecs > ARRAY_SIZE(rqstp->rq_vec));
 
        status = nfsd_vfs_write(rqstp, &cstate->current_fh, filp,
@@ -1599,7 +1588,7 @@ static const char *nfsd4_op_name(unsigned opnum);
  */
 static __be32 nfs41_check_op_ordering(struct nfsd4_compoundargs *args)
 {
-       struct nfsd4_op *op = &args->ops[0];
+       struct nfsd4_op *first_op = &args->ops[0];
 
        /* These ordering requirements don't apply to NFSv4.0: */
        if (args->minorversion == 0)
@@ -1607,12 +1596,17 @@ static __be32 nfs41_check_op_ordering(struct nfsd4_compoundargs *args)
        /* This is weird, but OK, not our problem: */
        if (args->opcnt == 0)
                return nfs_ok;
-       if (op->status == nfserr_op_illegal)
+       if (first_op->status == nfserr_op_illegal)
                return nfs_ok;
-       if (!(nfsd4_ops[op->opnum].op_flags & ALLOWED_AS_FIRST_OP))
+       if (!(nfsd4_ops[first_op->opnum].op_flags & ALLOWED_AS_FIRST_OP))
                return nfserr_op_not_in_session;
-       if (op->opnum == OP_SEQUENCE)
+       if (first_op->opnum == OP_SEQUENCE)
                return nfs_ok;
+       /*
+        * So first_op is something allowed outside a session, like
+        * EXCHANGE_ID; but then it has to be the only op in the
+        * compound:
+        */
        if (args->opcnt != 1)
                return nfserr_not_only_op;
        return nfs_ok;
@@ -1726,6 +1720,7 @@ nfsd4_proc_compound(struct svc_rqst *rqstp)
        if (status) {
                op = &args->ops[0];
                op->status = status;
+               resp->opcnt = 1;
                goto encode_op;
        }
 
index 8571414..b0ca0ef 100644 (file)
@@ -1979,8 +1979,10 @@ static int copy_cred(struct svc_cred *target, struct svc_cred *source)
        target->cr_principal = kstrdup(source->cr_principal, GFP_KERNEL);
        target->cr_raw_principal = kstrdup(source->cr_raw_principal,
                                                                GFP_KERNEL);
-       if ((source->cr_principal && ! target->cr_principal) ||
-           (source->cr_raw_principal && ! target->cr_raw_principal))
+       target->cr_targ_princ = kstrdup(source->cr_targ_princ, GFP_KERNEL);
+       if ((source->cr_principal && !target->cr_principal) ||
+           (source->cr_raw_principal && !target->cr_raw_principal) ||
+           (source->cr_targ_princ && !target->cr_targ_princ))
                return -ENOMEM;
 
        target->cr_flavor = source->cr_flavor;
@@ -2057,6 +2059,7 @@ same_creds(struct svc_cred *cr1, struct svc_cred *cr2)
                || (!gid_eq(cr1->cr_gid, cr2->cr_gid))
                || !groups_equal(cr1->cr_group_info, cr2->cr_group_info))
                return false;
+       /* XXX: check that cr_targ_princ fields match ? */
        if (cr1->cr_principal == cr2->cr_principal)
                return true;
        if (!cr1->cr_principal || !cr2->cr_principal)
@@ -2956,18 +2959,18 @@ out_no_session:
        return status;
 }
 
-static bool nfsd4_compound_in_session(struct nfsd4_session *session, struct nfs4_sessionid *sid)
+static bool nfsd4_compound_in_session(struct nfsd4_compound_state *cstate, struct nfs4_sessionid *sid)
 {
-       if (!session)
+       if (!cstate->session)
                return false;
-       return !memcmp(sid, &session->se_sessionid, sizeof(*sid));
+       return !memcmp(sid, &cstate->session->se_sessionid, sizeof(*sid));
 }
 
 __be32
 nfsd4_destroy_session(struct svc_rqst *r, struct nfsd4_compound_state *cstate,
                union nfsd4_op_u *u)
 {
-       struct nfsd4_destroy_session *sessionid = &u->destroy_session;
+       struct nfs4_sessionid *sessionid = &u->destroy_session.sessionid;
        struct nfsd4_session *ses;
        __be32 status;
        int ref_held_by_me = 0;
@@ -2975,14 +2978,14 @@ nfsd4_destroy_session(struct svc_rqst *r, struct nfsd4_compound_state *cstate,
        struct nfsd_net *nn = net_generic(net, nfsd_net_id);
 
        status = nfserr_not_only_op;
-       if (nfsd4_compound_in_session(cstate->session, &sessionid->sessionid)) {
+       if (nfsd4_compound_in_session(cstatesessionid)) {
                if (!nfsd4_last_compound_op(r))
                        goto out;
                ref_held_by_me++;
        }
-       dump_sessionid(__func__, &sessionid->sessionid);
+       dump_sessionid(__func__, sessionid);
        spin_lock(&nn->client_lock);
-       ses = find_in_sessionid_hashtbl(&sessionid->sessionid, net, &status);
+       ses = find_in_sessionid_hashtbl(sessionid, net, &status);
        if (!ses)
                goto out_client_lock;
        status = nfserr_wrong_cred;
@@ -3945,9 +3948,9 @@ static void nfsd_break_one_deleg(struct nfs4_delegation *dp)
        /*
         * We're assuming the state code never drops its reference
         * without first removing the lease.  Since we're in this lease
-        * callback (and since the lease code is serialized by the kernel
-        * lock) we know the server hasn't removed the lease yet, we know
-        * it's safe to take a reference.
+        * callback (and since the lease code is serialized by the
+        * i_lock) we know the server hasn't removed the lease yet, and
+        * we know it's safe to take a reference.
         */
        refcount_inc(&dp->dl_stid.sc_count);
        nfsd4_run_cb(&dp->dl_recall);
@@ -4693,6 +4696,28 @@ nfsd4_end_grace(struct nfsd_net *nn)
         */
 }
 
+/*
+ * If we've waited a lease period but there are still clients trying to
+ * reclaim, wait a little longer to give them a chance to finish.
+ */
+static bool clients_still_reclaiming(struct nfsd_net *nn)
+{
+       unsigned long now = get_seconds();
+       unsigned long double_grace_period_end = nn->boot_time +
+                                               2 * nn->nfsd4_lease;
+
+       if (!nn->somebody_reclaimed)
+               return false;
+       nn->somebody_reclaimed = false;
+       /*
+        * If we've given them *two* lease times to reclaim, and they're
+        * still not done, give up:
+        */
+       if (time_after(now, double_grace_period_end))
+               return false;
+       return true;
+}
+
 static time_t
 nfs4_laundromat(struct nfsd_net *nn)
 {
@@ -4706,6 +4731,11 @@ nfs4_laundromat(struct nfsd_net *nn)
        time_t t, new_timeo = nn->nfsd4_lease;
 
        dprintk("NFSD: laundromat service - starting\n");
+
+       if (clients_still_reclaiming(nn)) {
+               new_timeo = 0;
+               goto out;
+       }
        nfsd4_end_grace(nn);
        INIT_LIST_HEAD(&reaplist);
        spin_lock(&nn->client_lock);
@@ -4803,7 +4833,7 @@ nfs4_laundromat(struct nfsd_net *nn)
                posix_unblock_lock(&nbl->nbl_lock);
                free_blocked_lock(nbl);
        }
-
+out:
        new_timeo = max_t(time_t, new_timeo, NFSD_LAUNDROMAT_MINTIMEOUT);
        return new_timeo;
 }
@@ -6053,6 +6083,8 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
        case 0: /* success! */
                nfs4_inc_and_copy_stateid(&lock->lk_resp_stateid, &lock_stp->st_stid);
                status = 0;
+               if (lock->lk_reclaim)
+                       nn->somebody_reclaimed = true;
                break;
        case FILE_LOCK_DEFERRED:
                nbl = NULL;
@@ -6293,7 +6325,7 @@ check_for_locks(struct nfs4_file *fp, struct nfs4_lockowner *lowner)
                return status;
        }
 
-       inode = file_inode(filp);
+       inode = locks_inode(filp);
        flctx = inode->i_flctx;
 
        if (flctx && !list_empty_careful(&flctx->flc_posix)) {
@@ -7199,14 +7231,10 @@ nfs4_state_start(void)
 {
        int ret;
 
-       ret = set_callback_cred();
-       if (ret)
-               return ret;
-
        laundry_wq = alloc_workqueue("%s", WQ_UNBOUND, 0, "nfsd4");
        if (laundry_wq == NULL) {
                ret = -ENOMEM;
-               goto out_cleanup_cred;
+               goto out;
        }
        ret = nfsd4_create_callback_queue();
        if (ret)
@@ -7217,8 +7245,7 @@ nfs4_state_start(void)
 
 out_free_laundry:
        destroy_workqueue(laundry_wq);
-out_cleanup_cred:
-       cleanup_callback_cred();
+out:
        return ret;
 }
 
@@ -7255,7 +7282,6 @@ nfs4_state_shutdown(void)
 {
        destroy_workqueue(laundry_wq);
        nfsd4_destroy_callback_queue();
-       cleanup_callback_cred();
 }
 
 static void
index a96843c..418fa9c 100644 (file)
@@ -1390,10 +1390,8 @@ nfsd4_decode_exchange_id(struct nfsd4_compoundargs *argp,
                        p += XDR_QUADLEN(dummy);
                }
 
-               /* ssp_window and ssp_num_gss_handles */
+               /* ignore ssp_window and ssp_num_gss_handles: */
                READ_BUF(8);
-               dummy = be32_to_cpup(p++);
-               dummy = be32_to_cpup(p++);
                break;
        default:
                goto xdr_error;
@@ -2006,6 +2004,31 @@ static __be32 *encode_change(__be32 *p, struct kstat *stat, struct inode *inode,
        return p;
 }
 
+/*
+ * ctime (in NFSv4, time_metadata) is not writeable, and the client
+ * doesn't really care what resolution could theoretically be stored by
+ * the filesystem.
+ *
+ * The client cares how close together changes can be while still
+ * guaranteeing ctime changes.  For most filesystems (which have
+ * timestamps with nanosecond fields) that is limited by the resolution
+ * of the time returned from current_time() (which I'm assuming to be
+ * 1/HZ).
+ */
+static __be32 *encode_time_delta(__be32 *p, struct inode *inode)
+{
+       struct timespec ts;
+       u32 ns;
+
+       ns = max_t(u32, NSEC_PER_SEC/HZ, inode->i_sb->s_time_gran);
+       ts = ns_to_timespec(ns);
+
+       p = xdr_encode_hyper(p, ts.tv_sec);
+       *p++ = cpu_to_be32(ts.tv_nsec);
+
+       return p;
+}
+
 static __be32 *encode_cinfo(__be32 *p, struct nfsd4_change_info *c)
 {
        *p++ = cpu_to_be32(c->atomic);
@@ -2797,9 +2820,7 @@ out_acl:
                p = xdr_reserve_space(xdr, 12);
                if (!p)
                        goto out_resource;
-               *p++ = cpu_to_be32(0);
-               *p++ = cpu_to_be32(1);
-               *p++ = cpu_to_be32(0);
+               p = encode_time_delta(p, d_inode(dentry));
        }
        if (bmval1 & FATTR4_WORD1_TIME_METADATA) {
                p = xdr_reserve_space(xdr, 12);
@@ -2868,6 +2889,16 @@ out_acl:
                        goto out;
        }
 
+       if (bmval2 & FATTR4_WORD2_CHANGE_ATTR_TYPE) {
+               p = xdr_reserve_space(xdr, 4);
+               if (!p)
+                       goto out_resource;
+               if (IS_I_VERSION(d_inode(dentry)))
+                       *p++ = cpu_to_be32(NFS4_CHANGE_TYPE_IS_MONOTONIC_INCR);
+               else
+                       *p++ = cpu_to_be32(NFS4_CHANGE_TYPE_IS_TIME_METADATA);
+       }
+
        if (bmval2 & FATTR4_WORD2_SECURITY_LABEL) {
                status = nfsd4_encode_security_label(xdr, rqstp, context,
                                                                contextlen);
index d107b44..7fb9f7c 100644 (file)
@@ -73,7 +73,7 @@ static ssize_t write_recoverydir(struct file *file, char *buf, size_t size);
 static ssize_t write_v4_end_grace(struct file *file, char *buf, size_t size);
 #endif
 
-static ssize_t (*write_op[])(struct file *, char *, size_t) = {
+static ssize_t (*const write_op[])(struct file *, char *, size_t) = {
        [NFSD_Fh] = write_filehandle,
        [NFSD_FO_UnlockIP] = write_unlock_ip,
        [NFSD_FO_UnlockFS] = write_unlock_fs,
@@ -1237,8 +1237,9 @@ static __net_init int nfsd_init_net(struct net *net)
        retval = nfsd_idmap_init(net);
        if (retval)
                goto out_idmap_error;
-       nn->nfsd4_lease = 90;   /* default lease time */
-       nn->nfsd4_grace = 90;
+       nn->nfsd4_lease = 45;   /* default lease time */
+       nn->nfsd4_grace = 45;
+       nn->somebody_reclaimed = false;
        nn->clverifier_counter = prandom_u32();
        nn->clientid_counter = prandom_u32();
 
index 3fce905..0668999 100644 (file)
@@ -360,6 +360,7 @@ void                nfsd_lockd_shutdown(void);
 
 #define NFSD4_2_SUPPORTED_ATTRS_WORD2 \
        (NFSD4_1_SUPPORTED_ATTRS_WORD2 | \
+       FATTR4_WORD2_CHANGE_ATTR_TYPE | \
        FATTR4_WORD2_MODE_UMASK | \
        NFSD4_2_SECURITY_ATTRS)
 
index a008e76..b319080 100644 (file)
@@ -451,7 +451,7 @@ static bool fsid_type_ok_for_exp(u8 fsid_type, struct svc_export *exp)
        switch (fsid_type) {
        case FSID_DEV:
                if (!old_valid_dev(exp_sb(exp)->s_dev))
-                       return 0;
+                       return false;
                /* FALL THROUGH */
        case FSID_MAJOR_MINOR:
        case FSID_ENCODE_DEV:
@@ -461,13 +461,13 @@ static bool fsid_type_ok_for_exp(u8 fsid_type, struct svc_export *exp)
        case FSID_UUID8:
        case FSID_UUID16:
                if (!is_root_export(exp))
-                       return 0;
+                       return false;
                /* fall through */
        case FSID_UUID4_INUM:
        case FSID_UUID16_INUM:
                return exp->ex_uuid != NULL;
        }
-       return 1;
+       return true;
 }
 
 
index f107f9f..0d20fd1 100644 (file)
@@ -218,7 +218,8 @@ nfsd_proc_write(struct svc_rqst *rqstp)
                SVCFH_fmt(&argp->fh),
                argp->len, argp->offset);
 
-       nvecs = svc_fill_write_vector(rqstp, &argp->first, cnt);
+       nvecs = svc_fill_write_vector(rqstp, rqstp->rq_arg.pages,
+                                     &argp->first, cnt);
        if (!nvecs)
                return nfserr_io;
        nfserr = nfsd_write(rqstp, fh_copy(&resp->fh, &argp->fh),
@@ -453,6 +454,7 @@ nfsd_proc_symlink(struct svc_rqst *rqstp)
                return nfserr_nametoolong;
 
        argp->tname = svc_fill_symlink_pathname(rqstp, &argp->first,
+                                               page_address(rqstp->rq_arg.pages[0]),
                                                argp->tlen);
        if (IS_ERR(argp->tname))
                return nfserrno(PTR_ERR(argp->tname));
@@ -465,6 +467,7 @@ nfsd_proc_symlink(struct svc_rqst *rqstp)
        nfserr = nfsd_symlink(rqstp, &argp->ffh, argp->fname, argp->flen,
                                                 argp->tname, &newfh);
 
+       kfree(argp->tname);
        fh_put(&argp->ffh);
        fh_put(&newfh);
        return nfserr;
index f3772ea..0b15dac 100644 (file)
@@ -617,8 +617,6 @@ extern struct nfs4_client_reclaim *nfsd4_find_reclaim_client(const char *recdir,
                                                        struct nfsd_net *nn);
 extern __be32 nfs4_check_open_reclaim(clientid_t *clid,
                struct nfsd4_compound_state *cstate, struct nfsd_net *nn);
-extern int set_callback_cred(void);
-extern void cleanup_callback_cred(void);
 extern void nfsd4_probe_callback(struct nfs4_client *clp);
 extern void nfsd4_probe_callback_sync(struct nfs4_client *clp);
 extern void nfsd4_change_callback(struct nfs4_client *clp, struct nfs4_cb_conn *);
index c5fa3de..7da0fac 100644 (file)
@@ -51,7 +51,7 @@ int nilfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
        return err;
 }
 
-static int nilfs_page_mkwrite(struct vm_fault *vmf)
+static vm_fault_t nilfs_page_mkwrite(struct vm_fault *vmf)
 {
        struct vm_area_struct *vma = vmf->vma;
        struct page *page = vmf->page;
index 6ffeca8..1b9067c 100644 (file)
@@ -834,7 +834,7 @@ static int nilfs_setup_super(struct super_block *sb, int is_mount)
                sbp[0]->s_max_mnt_count = cpu_to_le16(NILFS_DFL_MAX_MNT_COUNT);
 
        sbp[0]->s_mnt_count = cpu_to_le16(mnt_count + 1);
-       sbp[0]->s_mtime = cpu_to_le64(get_seconds());
+       sbp[0]->s_mtime = cpu_to_le64(ktime_get_real_seconds());
 
 skip_mount_setup:
        sbp[0]->s_state =
index a6365e6..58d77dc 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/fs.h>
 #include <linux/module.h>
 #include <linux/sched.h>
+#include <linux/sched/signal.h>
 #include <linux/dnotify.h>
 #include <linux/init.h>
 #include <linux/spinlock.h>
@@ -353,7 +354,7 @@ int fcntl_dirnotify(int fd, struct file *filp, unsigned long arg)
                goto out;
        }
 
-       __f_setown(filp, task_pid(current), PIDTYPE_PID, 0);
+       __f_setown(filp, task_pid(current), PIDTYPE_TGID, 0);
 
        error = attach_dn(dn, dn_mark, id, fd, filp, mask);
        /* !error means that we attached the dn to the dn_mark, so don't free it */
index eb4e751..94b5215 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/mount.h>
 #include <linux/sched.h>
 #include <linux/sched/user.h>
+#include <linux/sched/signal.h>
 #include <linux/types.h>
 #include <linux/wait.h>
 #include <linux/audit.h>
index 255f758..9fa35cb 100644 (file)
@@ -2537,19 +2537,14 @@ static int ocfs2_file_clone_range(struct file *file_in,
                                         len, false);
 }
 
-static ssize_t ocfs2_file_dedupe_range(struct file *src_file,
-                                      u64 loff,
-                                      u64 len,
-                                      struct file *dst_file,
-                                      u64 dst_loff)
+static int ocfs2_file_dedupe_range(struct file *file_in,
+                                  loff_t pos_in,
+                                  struct file *file_out,
+                                  loff_t pos_out,
+                                  u64 len)
 {
-       int error;
-
-       error = ocfs2_reflink_remap_range(src_file, loff, dst_file, dst_loff,
+       return ocfs2_reflink_remap_range(file_in, pos_in, file_out, pos_out,
                                          len, true);
-       if (error)
-               return error;
-       return len;
 }
 
 const struct inode_operations ocfs2_file_iops = {
index d98e192..0285ce7 100644 (file)
--- a/fs/open.c
+++ b/fs/open.c
@@ -68,7 +68,6 @@ int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs,
 long vfs_truncate(const struct path *path, loff_t length)
 {
        struct inode *inode;
-       struct dentry *upperdentry;
        long error;
 
        inode = path->dentry->d_inode;
@@ -91,17 +90,7 @@ long vfs_truncate(const struct path *path, loff_t length)
        if (IS_APPEND(inode))
                goto mnt_drop_write_and_out;
 
-       /*
-        * If this is an overlayfs then do as if opening the file so we get
-        * write access on the upper inode, not on the overlay inode.  For
-        * non-overlay filesystems d_real() is an identity function.
-        */
-       upperdentry = d_real(path->dentry, NULL, O_WRONLY, 0);
-       error = PTR_ERR(upperdentry);
-       if (IS_ERR(upperdentry))
-               goto mnt_drop_write_and_out;
-
-       error = get_write_access(upperdentry->d_inode);
+       error = get_write_access(inode);
        if (error)
                goto mnt_drop_write_and_out;
 
@@ -120,7 +109,7 @@ long vfs_truncate(const struct path *path, loff_t length)
                error = do_truncate(path->dentry, length, 0, NULL);
 
 put_write_and_out:
-       put_write_access(upperdentry->d_inode);
+       put_write_access(inode);
 mnt_drop_write_and_out:
        mnt_drop_write(path->mnt);
 out:
@@ -707,12 +696,12 @@ int ksys_fchown(unsigned int fd, uid_t user, gid_t group)
        if (!f.file)
                goto out;
 
-       error = mnt_want_write_file_path(f.file);
+       error = mnt_want_write_file(f.file);
        if (error)
                goto out_fput;
        audit_file(f.file);
        error = chown_common(&f.file->f_path, user, group);
-       mnt_drop_write_file_path(f.file);
+       mnt_drop_write_file(f.file);
 out_fput:
        fdput(f);
 out:
@@ -887,13 +876,8 @@ EXPORT_SYMBOL(file_path);
  */
 int vfs_open(const struct path *path, struct file *file)
 {
-       struct dentry *dentry = d_real(path->dentry, NULL, file->f_flags, 0);
-
-       if (IS_ERR(dentry))
-               return PTR_ERR(dentry);
-
        file->f_path = *path;
-       return do_dentry_open(file, d_backing_inode(dentry), NULL);
+       return do_dentry_open(file, d_backing_inode(path->dentry), NULL);
 }
 
 struct file *dentry_open(const struct path *path, int flags,
@@ -919,6 +903,24 @@ struct file *dentry_open(const struct path *path, int flags,
 }
 EXPORT_SYMBOL(dentry_open);
 
+struct file *open_with_fake_path(const struct path *path, int flags,
+                               struct inode *inode, const struct cred *cred)
+{
+       struct file *f = alloc_empty_file_noaccount(flags, cred);
+       if (!IS_ERR(f)) {
+               int error;
+
+               f->f_path = *path;
+               error = do_dentry_open(f, inode, NULL);
+               if (error) {
+                       fput(f);
+                       f = ERR_PTR(error);
+               }
+       }
+       return f;
+}
+EXPORT_SYMBOL(open_with_fake_path);
+
 static inline int build_open_flags(int flags, umode_t mode, struct open_flags *op)
 {
        int lookup_flags = 0;
index 9384164..2ef91be 100644 (file)
@@ -64,6 +64,7 @@ config OVERLAY_FS_NFS_EXPORT
        bool "Overlayfs: turn on NFS export feature by default"
        depends on OVERLAY_FS
        depends on OVERLAY_FS_INDEX
+       depends on !OVERLAY_FS_METACOPY
        help
          If this config option is enabled then overlay filesystems will use
          the index directory to decode overlay NFS file handles by default.
@@ -103,3 +104,21 @@ config OVERLAY_FS_XINO_AUTO
          For more information, see Documentation/filesystems/overlayfs.txt
 
          If unsure, say N.
+
+config OVERLAY_FS_METACOPY
+       bool "Overlayfs: turn on metadata only copy up feature by default"
+       depends on OVERLAY_FS
+       select OVERLAY_FS_REDIRECT_DIR
+       help
+         If this config option is enabled then overlay filesystems will
+         copy up only metadata where appropriate and data copy up will
+         happen when a file is opened for WRITE operation. It is still
+         possible to turn off this feature globally with the "metacopy=off"
+         module option or on a filesystem instance basis with the
+         "metacopy=off" mount option.
+
+         Note, that this feature is not backward compatible.  That is,
+         mounting an overlay which has metacopy only inodes on a kernel
+         that doesn't support this feature will have unexpected results.
+
+         If unsure, say N.
index 3080234..46e1ff8 100644 (file)
@@ -4,5 +4,5 @@
 
 obj-$(CONFIG_OVERLAY_FS) += overlay.o
 
-overlay-objs := super.o namei.o util.o inode.o dir.o readdir.o copy_up.o \
-               export.o
+overlay-objs := super.o namei.o util.o inode.o file.o dir.o readdir.o \
+               copy_up.o export.o
index ddaddb4..296037a 100644 (file)
 
 #define OVL_COPY_UP_CHUNK_SIZE (1 << 20)
 
-static bool __read_mostly ovl_check_copy_up;
-module_param_named(check_copy_up, ovl_check_copy_up, bool,
-                  S_IWUSR | S_IRUGO);
-MODULE_PARM_DESC(ovl_check_copy_up,
-                "Warn on copy-up when causing process also has a R/O fd open");
-
-static int ovl_check_fd(const void *data, struct file *f, unsigned int fd)
+static int ovl_ccup_set(const char *buf, const struct kernel_param *param)
 {
-       const struct dentry *dentry = data;
-
-       if (file_inode(f) == d_inode(dentry))
-               pr_warn_ratelimited("overlayfs: Warning: Copying up %pD, but open R/O on fd %u which will cease to be coherent [pid=%d %s]\n",
-                                   f, fd, current->pid, current->comm);
+       pr_warn("overlayfs: \"check_copy_up\" module option is obsolete\n");
        return 0;
 }
 
-/*
- * Check the fds open by this process and warn if something like the following
- * scenario is about to occur:
- *
- *     fd1 = open("foo", O_RDONLY);
- *     fd2 = open("foo", O_RDWR);
- */
-static void ovl_do_check_copy_up(struct dentry *dentry)
+static int ovl_ccup_get(char *buf, const struct kernel_param *param)
 {
-       if (ovl_check_copy_up)
-               iterate_fd(current->files, 0, ovl_check_fd, dentry);
+       return sprintf(buf, "N\n");
 }
 
+module_param_call(check_copy_up, ovl_ccup_set, ovl_ccup_get, NULL, 0644);
+MODULE_PARM_DESC(ovl_check_copy_up, "Obsolete; does nothing");
+
 int ovl_copy_xattr(struct dentry *old, struct dentry *new)
 {
        ssize_t list_size, size, value_size = 0;
@@ -195,6 +180,16 @@ out_fput:
        return error;
 }
 
+static int ovl_set_size(struct dentry *upperdentry, struct kstat *stat)
+{
+       struct iattr attr = {
+               .ia_valid = ATTR_SIZE,
+               .ia_size = stat->size,
+       };
+
+       return notify_change(upperdentry, &attr, NULL);
+}
+
 static int ovl_set_timestamps(struct dentry *upperdentry, struct kstat *stat)
 {
        struct iattr attr = {
@@ -403,6 +398,7 @@ struct ovl_copy_up_ctx {
        bool tmpfile;
        bool origin;
        bool indexed;
+       bool metacopy;
 };
 
 static int ovl_link_up(struct ovl_copy_up_ctx *c)
@@ -505,28 +501,10 @@ static int ovl_copy_up_inode(struct ovl_copy_up_ctx *c, struct dentry *temp)
 {
        int err;
 
-       if (S_ISREG(c->stat.mode)) {
-               struct path upperpath;
-
-               ovl_path_upper(c->dentry, &upperpath);
-               BUG_ON(upperpath.dentry != NULL);
-               upperpath.dentry = temp;
-
-               err = ovl_copy_up_data(&c->lowerpath, &upperpath, c->stat.size);
-               if (err)
-                       return err;
-       }
-
        err = ovl_copy_xattr(c->lowerpath.dentry, temp);
        if (err)
                return err;
 
-       inode_lock(temp->d_inode);
-       err = ovl_set_attr(temp, &c->stat);
-       inode_unlock(temp->d_inode);
-       if (err)
-               return err;
-
        /*
         * Store identifier of lower inode in upper inode xattr to
         * allow lookup of the copy up origin inode.
@@ -540,7 +518,34 @@ static int ovl_copy_up_inode(struct ovl_copy_up_ctx *c, struct dentry *temp)
                        return err;
        }
 
-       return 0;
+       if (S_ISREG(c->stat.mode) && !c->metacopy) {
+               struct path upperpath, datapath;
+
+               ovl_path_upper(c->dentry, &upperpath);
+               BUG_ON(upperpath.dentry != NULL);
+               upperpath.dentry = temp;
+
+               ovl_path_lowerdata(c->dentry, &datapath);
+               err = ovl_copy_up_data(&datapath, &upperpath, c->stat.size);
+               if (err)
+                       return err;
+       }
+
+       if (c->metacopy) {
+               err = ovl_check_setxattr(c->dentry, temp, OVL_XATTR_METACOPY,
+                                        NULL, 0, -EOPNOTSUPP);
+               if (err)
+                       return err;
+       }
+
+       inode_lock(temp->d_inode);
+       if (c->metacopy)
+               err = ovl_set_size(temp, &c->stat);
+       if (!err)
+               err = ovl_set_attr(temp, &c->stat);
+       inode_unlock(temp->d_inode);
+
+       return err;
 }
 
 static int ovl_copy_up_locked(struct ovl_copy_up_ctx *c)
@@ -575,6 +580,8 @@ static int ovl_copy_up_locked(struct ovl_copy_up_ctx *c)
        if (err)
                goto out;
 
+       if (!c->metacopy)
+               ovl_set_upperdata(d_inode(c->dentry));
        inode = d_inode(c->dentry);
        ovl_inode_update(inode, newdentry);
        if (S_ISDIR(inode->i_mode))
@@ -677,6 +684,49 @@ out:
        return err;
 }
 
+static bool ovl_need_meta_copy_up(struct dentry *dentry, umode_t mode,
+                                 int flags)
+{
+       struct ovl_fs *ofs = dentry->d_sb->s_fs_info;
+
+       if (!ofs->config.metacopy)
+               return false;
+
+       if (!S_ISREG(mode))
+               return false;
+
+       if (flags && ((OPEN_FMODE(flags) & FMODE_WRITE) || (flags & O_TRUNC)))
+               return false;
+
+       return true;
+}
+
+/* Copy up data of an inode which was copied up metadata only in the past. */
+static int ovl_copy_up_meta_inode_data(struct ovl_copy_up_ctx *c)
+{
+       struct path upperpath, datapath;
+       int err;
+
+       ovl_path_upper(c->dentry, &upperpath);
+       if (WARN_ON(upperpath.dentry == NULL))
+               return -EIO;
+
+       ovl_path_lowerdata(c->dentry, &datapath);
+       if (WARN_ON(datapath.dentry == NULL))
+               return -EIO;
+
+       err = ovl_copy_up_data(&datapath, &upperpath, c->stat.size);
+       if (err)
+               return err;
+
+       err = vfs_removexattr(upperpath.dentry, OVL_XATTR_METACOPY);
+       if (err)
+               return err;
+
+       ovl_set_upperdata(d_inode(c->dentry));
+       return err;
+}
+
 static int ovl_copy_up_one(struct dentry *parent, struct dentry *dentry,
                           int flags)
 {
@@ -698,6 +748,8 @@ static int ovl_copy_up_one(struct dentry *parent, struct dentry *dentry,
        if (err)
                return err;
 
+       ctx.metacopy = ovl_need_meta_copy_up(dentry, ctx.stat.mode, flags);
+
        if (parent) {
                ovl_path_upper(parent, &parentpath);
                ctx.destdir = parentpath.dentry;
@@ -719,9 +771,8 @@ static int ovl_copy_up_one(struct dentry *parent, struct dentry *dentry,
                if (IS_ERR(ctx.link))
                        return PTR_ERR(ctx.link);
        }
-       ovl_do_check_copy_up(ctx.lowerpath.dentry);
 
-       err = ovl_copy_up_start(dentry);
+       err = ovl_copy_up_start(dentry, flags);
        /* err < 0: interrupted, err > 0: raced with another copy-up */
        if (unlikely(err)) {
                if (err > 0)
@@ -731,6 +782,8 @@ static int ovl_copy_up_one(struct dentry *parent, struct dentry *dentry,
                        err = ovl_do_copy_up(&ctx);
                if (!err && parent && !ovl_dentry_has_upper_alias(dentry))
                        err = ovl_link_up(&ctx);
+               if (!err && ovl_dentry_needs_data_copy_up_locked(dentry, flags))
+                       err = ovl_copy_up_meta_inode_data(&ctx);
                ovl_copy_up_end(dentry);
        }
        do_delayed_call(&done);
@@ -756,21 +809,7 @@ int ovl_copy_up_flags(struct dentry *dentry, int flags)
                struct dentry *next;
                struct dentry *parent = NULL;
 
-               /*
-                * Check if copy-up has happened as well as for upper alias (in
-                * case of hard links) is there.
-                *
-                * Both checks are lockless:
-                *  - false negatives: will recheck under oi->lock
-                *  - false positives:
-                *    + ovl_dentry_upper() uses memory barriers to ensure the
-                *      upper dentry is up-to-date
-                *    + ovl_dentry_has_upper_alias() relies on locking of
-                *      upper parent i_rwsem to prevent reordering copy-up
-                *      with rename.
-                */
-               if (ovl_dentry_upper(dentry) &&
-                   (ovl_dentry_has_upper_alias(dentry) || disconnected))
+               if (ovl_already_copied_up(dentry, flags))
                        break;
 
                next = dget(dentry);
@@ -795,6 +834,41 @@ int ovl_copy_up_flags(struct dentry *dentry, int flags)
        return err;
 }
 
+static bool ovl_open_need_copy_up(struct dentry *dentry, int flags)
+{
+       /* Copy up of disconnected dentry does not set upper alias */
+       if (ovl_already_copied_up(dentry, flags))
+               return false;
+
+       if (special_file(d_inode(dentry)->i_mode))
+               return false;
+
+       if (!ovl_open_flags_need_copy_up(flags))
+               return false;
+
+       return true;
+}
+
+int ovl_open_maybe_copy_up(struct dentry *dentry, unsigned int file_flags)
+{
+       int err = 0;
+
+       if (ovl_open_need_copy_up(dentry, file_flags)) {
+               err = ovl_want_write(dentry);
+               if (!err) {
+                       err = ovl_copy_up_flags(dentry, file_flags);
+                       ovl_drop_write(dentry);
+               }
+       }
+
+       return err;
+}
+
+int ovl_copy_up_with_data(struct dentry *dentry)
+{
+       return ovl_copy_up_flags(dentry, O_WRONLY);
+}
+
 int ovl_copy_up(struct dentry *dentry)
 {
        return ovl_copy_up_flags(dentry, 0);
index f480b1a..276914a 100644 (file)
@@ -24,6 +24,8 @@ module_param_named(redirect_max, ovl_redirect_max, ushort, 0644);
 MODULE_PARM_DESC(ovl_redirect_max,
                 "Maximum length of absolute redirect xattr value");
 
+static int ovl_set_redirect(struct dentry *dentry, bool samedir);
+
 int ovl_cleanup(struct inode *wdir, struct dentry *wdentry)
 {
        int err;
@@ -242,7 +244,7 @@ static int ovl_instantiate(struct dentry *dentry, struct inode *inode,
                .newinode = inode,
        };
 
-       ovl_dentry_version_inc(dentry->d_parent, false);
+       ovl_dir_modified(dentry->d_parent, false);
        ovl_dentry_set_upper_alias(dentry);
        if (!hardlink) {
                /*
@@ -601,6 +603,10 @@ static int ovl_create_object(struct dentry *dentry, int mode, dev_t rdev,
        if (!inode)
                goto out_drop_write;
 
+       spin_lock(&inode->i_lock);
+       inode->i_state |= I_CREATING;
+       spin_unlock(&inode->i_lock);
+
        inode_init_owner(inode, dentry->d_parent->d_inode, mode);
        attr.mode = inode->i_mode;
 
@@ -657,6 +663,12 @@ static int ovl_link(struct dentry *old, struct inode *newdir,
        if (err)
                goto out_drop_write;
 
+       if (ovl_is_metacopy_dentry(old)) {
+               err = ovl_set_redirect(old, false);
+               if (err)
+                       goto out_drop_write;
+       }
+
        err = ovl_nlink_start(old, &locked);
        if (err)
                goto out_drop_write;
@@ -722,7 +734,7 @@ static int ovl_remove_and_whiteout(struct dentry *dentry,
        if (err)
                goto out_d_drop;
 
-       ovl_dentry_version_inc(dentry->d_parent, true);
+       ovl_dir_modified(dentry->d_parent, true);
 out_d_drop:
        d_drop(dentry);
 out_dput_upper:
@@ -767,7 +779,7 @@ static int ovl_remove_upper(struct dentry *dentry, bool is_dir,
                err = vfs_rmdir(dir, upper);
        else
                err = vfs_unlink(dir, upper, NULL);
-       ovl_dentry_version_inc(dentry->d_parent, ovl_type_origin(dentry));
+       ovl_dir_modified(dentry->d_parent, ovl_type_origin(dentry));
 
        /*
         * Keeping this dentry hashed would mean having to release
@@ -797,6 +809,7 @@ static int ovl_do_remove(struct dentry *dentry, bool is_dir)
        int err;
        bool locked = false;
        const struct cred *old_cred;
+       struct dentry *upperdentry;
        bool lower_positive = ovl_lower_positive(dentry);
        LIST_HEAD(list);
 
@@ -832,6 +845,17 @@ static int ovl_do_remove(struct dentry *dentry, bool is_dir)
                        drop_nlink(dentry->d_inode);
        }
        ovl_nlink_end(dentry, locked);
+
+       /*
+        * Copy ctime
+        *
+        * Note: we fail to update ctime if there was no copy-up, only a
+        * whiteout
+        */
+       upperdentry = ovl_dentry_upper(dentry);
+       if (upperdentry)
+               ovl_copyattr(d_inode(upperdentry), d_inode(dentry));
+
 out_drop_write:
        ovl_drop_write(dentry);
 out:
@@ -862,13 +886,13 @@ static bool ovl_can_move(struct dentry *dentry)
                !d_is_dir(dentry) || !ovl_type_merge_or_lower(dentry);
 }
 
-static char *ovl_get_redirect(struct dentry *dentry, bool samedir)
+static char *ovl_get_redirect(struct dentry *dentry, bool abs_redirect)
 {
        char *buf, *ret;
        struct dentry *d, *tmp;
        int buflen = ovl_redirect_max + 1;
 
-       if (samedir) {
+       if (!abs_redirect) {
                ret = kstrndup(dentry->d_name.name, dentry->d_name.len,
                               GFP_KERNEL);
                goto out;
@@ -922,15 +946,43 @@ out:
        return ret ? ret : ERR_PTR(-ENOMEM);
 }
 
+static bool ovl_need_absolute_redirect(struct dentry *dentry, bool samedir)
+{
+       struct dentry *lowerdentry;
+
+       if (!samedir)
+               return true;
+
+       if (d_is_dir(dentry))
+               return false;
+
+       /*
+        * For non-dir hardlinked files, we need absolute redirects
+        * in general as two upper hardlinks could be in different
+        * dirs. We could put a relative redirect now and convert
+        * it to absolute redirect later. But when nlink > 1 and
+        * indexing is on, that means relative redirect needs to be
+        * converted to absolute during copy up of another lower
+        * hardllink as well.
+        *
+        * So without optimizing too much, just check if lower is
+        * a hard link or not. If lower is hard link, put absolute
+        * redirect.
+        */
+       lowerdentry = ovl_dentry_lower(dentry);
+       return (d_inode(lowerdentry)->i_nlink > 1);
+}
+
 static int ovl_set_redirect(struct dentry *dentry, bool samedir)
 {
        int err;
        const char *redirect = ovl_dentry_get_redirect(dentry);
+       bool absolute_redirect = ovl_need_absolute_redirect(dentry, samedir);
 
-       if (redirect && (samedir || redirect[0] == '/'))
+       if (redirect && (!absolute_redirect || redirect[0] == '/'))
                return 0;
 
-       redirect = ovl_get_redirect(dentry, samedir);
+       redirect = ovl_get_redirect(dentry, absolute_redirect);
        if (IS_ERR(redirect))
                return PTR_ERR(redirect);
 
@@ -1106,22 +1158,20 @@ static int ovl_rename(struct inode *olddir, struct dentry *old,
                goto out_dput;
 
        err = 0;
-       if (is_dir) {
-               if (ovl_type_merge_or_lower(old))
-                       err = ovl_set_redirect(old, samedir);
-               else if (!old_opaque && ovl_type_merge(new->d_parent))
-                       err = ovl_set_opaque_xerr(old, olddentry, -EXDEV);
-               if (err)
-                       goto out_dput;
-       }
-       if (!overwrite && new_is_dir) {
-               if (ovl_type_merge_or_lower(new))
-                       err = ovl_set_redirect(new, samedir);
-               else if (!new_opaque && ovl_type_merge(old->d_parent))
-                       err = ovl_set_opaque_xerr(new, newdentry, -EXDEV);
-               if (err)
-                       goto out_dput;
-       }
+       if (ovl_type_merge_or_lower(old))
+               err = ovl_set_redirect(old, samedir);
+       else if (is_dir && !old_opaque && ovl_type_merge(new->d_parent))
+               err = ovl_set_opaque_xerr(old, olddentry, -EXDEV);
+       if (err)
+               goto out_dput;
+
+       if (!overwrite && ovl_type_merge_or_lower(new))
+               err = ovl_set_redirect(new, samedir);
+       else if (!overwrite && new_is_dir && !new_opaque &&
+                ovl_type_merge(old->d_parent))
+               err = ovl_set_opaque_xerr(new, newdentry, -EXDEV);
+       if (err)
+               goto out_dput;
 
        err = ovl_do_rename(old_upperdir->d_inode, olddentry,
                            new_upperdir->d_inode, newdentry, flags);
@@ -1138,10 +1188,15 @@ static int ovl_rename(struct inode *olddir, struct dentry *old,
                        drop_nlink(d_inode(new));
        }
 
-       ovl_dentry_version_inc(old->d_parent, ovl_type_origin(old) ||
-                              (!overwrite && ovl_type_origin(new)));
-       ovl_dentry_version_inc(new->d_parent, ovl_type_origin(old) ||
-                              (d_inode(new) && ovl_type_origin(new)));
+       ovl_dir_modified(old->d_parent, ovl_type_origin(old) ||
+                        (!overwrite && ovl_type_origin(new)));
+       ovl_dir_modified(new->d_parent, ovl_type_origin(old) ||
+                        (d_inode(new) && ovl_type_origin(new)));
+
+       /* copy ctime: */
+       ovl_copyattr(d_inode(olddentry), d_inode(old));
+       if (d_inode(new) && ovl_dentry_upper(new))
+               ovl_copyattr(d_inode(newdentry), d_inode(new));
 
 out_dput:
        dput(newdentry);
index 9941ece..8fa37cd 100644 (file)
@@ -317,6 +317,9 @@ static struct dentry *ovl_obtain_alias(struct super_block *sb,
                return ERR_CAST(inode);
        }
 
+       if (upper)
+               ovl_set_flag(OVL_UPPERDATA, inode);
+
        dentry = d_find_any_alias(inode);
        if (!dentry) {
                dentry = d_alloc_anon(inode->i_sb);
diff --git a/fs/overlayfs/file.c b/fs/overlayfs/file.c
new file mode 100644 (file)
index 0000000..32e9282
--- /dev/null
@@ -0,0 +1,511 @@
+/*
+ * Copyright (C) 2017 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+
+#include <linux/cred.h>
+#include <linux/file.h>
+#include <linux/mount.h>
+#include <linux/xattr.h>
+#include <linux/uio.h>
+#include "overlayfs.h"
+
+static char ovl_whatisit(struct inode *inode, struct inode *realinode)
+{
+       if (realinode != ovl_inode_upper(inode))
+               return 'l';
+       if (ovl_has_upperdata(inode))
+               return 'u';
+       else
+               return 'm';
+}
+
+static struct file *ovl_open_realfile(const struct file *file,
+                                     struct inode *realinode)
+{
+       struct inode *inode = file_inode(file);
+       struct file *realfile;
+       const struct cred *old_cred;
+
+       old_cred = ovl_override_creds(inode->i_sb);
+       realfile = open_with_fake_path(&file->f_path, file->f_flags | O_NOATIME,
+                                      realinode, current_cred());
+       revert_creds(old_cred);
+
+       pr_debug("open(%p[%pD2/%c], 0%o) -> (%p, 0%o)\n",
+                file, file, ovl_whatisit(inode, realinode), file->f_flags,
+                realfile, IS_ERR(realfile) ? 0 : realfile->f_flags);
+
+       return realfile;
+}
+
+#define OVL_SETFL_MASK (O_APPEND | O_NONBLOCK | O_NDELAY | O_DIRECT)
+
+static int ovl_change_flags(struct file *file, unsigned int flags)
+{
+       struct inode *inode = file_inode(file);
+       int err;
+
+       /* No atime modificaton on underlying */
+       flags |= O_NOATIME;
+
+       /* If some flag changed that cannot be changed then something's amiss */
+       if (WARN_ON((file->f_flags ^ flags) & ~OVL_SETFL_MASK))
+               return -EIO;
+
+       flags &= OVL_SETFL_MASK;
+
+       if (((flags ^ file->f_flags) & O_APPEND) && IS_APPEND(inode))
+               return -EPERM;
+
+       if (flags & O_DIRECT) {
+               if (!file->f_mapping->a_ops ||
+                   !file->f_mapping->a_ops->direct_IO)
+                       return -EINVAL;
+       }
+
+       if (file->f_op->check_flags) {
+               err = file->f_op->check_flags(flags);
+               if (err)
+                       return err;
+       }
+
+       spin_lock(&file->f_lock);
+       file->f_flags = (file->f_flags & ~OVL_SETFL_MASK) | flags;
+       spin_unlock(&file->f_lock);
+
+       return 0;
+}
+
+static int ovl_real_fdget_meta(const struct file *file, struct fd *real,
+                              bool allow_meta)
+{
+       struct inode *inode = file_inode(file);
+       struct inode *realinode;
+
+       real->flags = 0;
+       real->file = file->private_data;
+
+       if (allow_meta)
+               realinode = ovl_inode_real(inode);
+       else
+               realinode = ovl_inode_realdata(inode);
+
+       /* Has it been copied up since we'd opened it? */
+       if (unlikely(file_inode(real->file) != realinode)) {
+               real->flags = FDPUT_FPUT;
+               real->file = ovl_open_realfile(file, realinode);
+
+               return PTR_ERR_OR_ZERO(real->file);
+       }
+
+       /* Did the flags change since open? */
+       if (unlikely((file->f_flags ^ real->file->f_flags) & ~O_NOATIME))
+               return ovl_change_flags(real->file, file->f_flags);
+
+       return 0;
+}
+
+static int ovl_real_fdget(const struct file *file, struct fd *real)
+{
+       return ovl_real_fdget_meta(file, real, false);
+}
+
+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);
+       if (err)
+               return err;
+
+       /* No longer need these flags, so don't pass them on to underlying fs */
+       file->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
+
+       realfile = ovl_open_realfile(file, ovl_inode_realdata(inode));
+       if (IS_ERR(realfile))
+               return PTR_ERR(realfile);
+
+       /* For O_DIRECT dentry_open() checks f_mapping->a_ops->direct_IO */
+       file->f_mapping = realfile->f_mapping;
+
+       file->private_data = realfile;
+
+       return 0;
+}
+
+static int ovl_release(struct inode *inode, struct file *file)
+{
+       fput(file->private_data);
+
+       return 0;
+}
+
+static loff_t ovl_llseek(struct file *file, loff_t offset, int whence)
+{
+       struct inode *realinode = ovl_inode_real(file_inode(file));
+
+       return generic_file_llseek_size(file, offset, whence,
+                                       realinode->i_sb->s_maxbytes,
+                                       i_size_read(realinode));
+}
+
+static void ovl_file_accessed(struct file *file)
+{
+       struct inode *inode, *upperinode;
+
+       if (file->f_flags & O_NOATIME)
+               return;
+
+       inode = file_inode(file);
+       upperinode = ovl_inode_upper(inode);
+
+       if (!upperinode)
+               return;
+
+       if ((!timespec64_equal(&inode->i_mtime, &upperinode->i_mtime) ||
+            !timespec64_equal(&inode->i_ctime, &upperinode->i_ctime))) {
+               inode->i_mtime = upperinode->i_mtime;
+               inode->i_ctime = upperinode->i_ctime;
+       }
+
+       touch_atime(&file->f_path);
+}
+
+static rwf_t ovl_iocb_to_rwf(struct kiocb *iocb)
+{
+       int ifl = iocb->ki_flags;
+       rwf_t flags = 0;
+
+       if (ifl & IOCB_NOWAIT)
+               flags |= RWF_NOWAIT;
+       if (ifl & IOCB_HIPRI)
+               flags |= RWF_HIPRI;
+       if (ifl & IOCB_DSYNC)
+               flags |= RWF_DSYNC;
+       if (ifl & IOCB_SYNC)
+               flags |= RWF_SYNC;
+
+       return flags;
+}
+
+static ssize_t ovl_read_iter(struct kiocb *iocb, struct iov_iter *iter)
+{
+       struct file *file = iocb->ki_filp;
+       struct fd real;
+       const struct cred *old_cred;
+       ssize_t ret;
+
+       if (!iov_iter_count(iter))
+               return 0;
+
+       ret = ovl_real_fdget(file, &real);
+       if (ret)
+               return ret;
+
+       old_cred = ovl_override_creds(file_inode(file)->i_sb);
+       ret = vfs_iter_read(real.file, iter, &iocb->ki_pos,
+                           ovl_iocb_to_rwf(iocb));
+       revert_creds(old_cred);
+
+       ovl_file_accessed(file);
+
+       fdput(real);
+
+       return ret;
+}
+
+static ssize_t ovl_write_iter(struct kiocb *iocb, struct iov_iter *iter)
+{
+       struct file *file = iocb->ki_filp;
+       struct inode *inode = file_inode(file);
+       struct fd real;
+       const struct cred *old_cred;
+       ssize_t ret;
+
+       if (!iov_iter_count(iter))
+               return 0;
+
+       inode_lock(inode);
+       /* Update mode */
+       ovl_copyattr(ovl_inode_real(inode), inode);
+       ret = file_remove_privs(file);
+       if (ret)
+               goto out_unlock;
+
+       ret = ovl_real_fdget(file, &real);
+       if (ret)
+               goto out_unlock;
+
+       old_cred = ovl_override_creds(file_inode(file)->i_sb);
+       ret = vfs_iter_write(real.file, iter, &iocb->ki_pos,
+                            ovl_iocb_to_rwf(iocb));
+       revert_creds(old_cred);
+
+       /* Update size */
+       ovl_copyattr(ovl_inode_real(inode), inode);
+
+       fdput(real);
+
+out_unlock:
+       inode_unlock(inode);
+
+       return ret;
+}
+
+static int ovl_fsync(struct file *file, loff_t start, loff_t end, int datasync)
+{
+       struct fd real;
+       const struct cred *old_cred;
+       int ret;
+
+       ret = ovl_real_fdget_meta(file, &real, !datasync);
+       if (ret)
+               return ret;
+
+       /* Don't sync lower file for fear of receiving EROFS error */
+       if (file_inode(real.file) == ovl_inode_upper(file_inode(file))) {
+               old_cred = ovl_override_creds(file_inode(file)->i_sb);
+               ret = vfs_fsync_range(real.file, start, end, datasync);
+               revert_creds(old_cred);
+       }
+
+       fdput(real);
+
+       return ret;
+}
+
+static int ovl_mmap(struct file *file, struct vm_area_struct *vma)
+{
+       struct file *realfile = file->private_data;
+       const struct cred *old_cred;
+       int ret;
+
+       if (!realfile->f_op->mmap)
+               return -ENODEV;
+
+       if (WARN_ON(file != vma->vm_file))
+               return -EIO;
+
+       vma->vm_file = get_file(realfile);
+
+       old_cred = ovl_override_creds(file_inode(file)->i_sb);
+       ret = call_mmap(vma->vm_file, vma);
+       revert_creds(old_cred);
+
+       if (ret) {
+               /* Drop reference count from new vm_file value */
+               fput(realfile);
+       } else {
+               /* Drop reference count from previous vm_file value */
+               fput(file);
+       }
+
+       ovl_file_accessed(file);
+
+       return ret;
+}
+
+static long ovl_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
+{
+       struct inode *inode = file_inode(file);
+       struct fd real;
+       const struct cred *old_cred;
+       int ret;
+
+       ret = ovl_real_fdget(file, &real);
+       if (ret)
+               return ret;
+
+       old_cred = ovl_override_creds(file_inode(file)->i_sb);
+       ret = vfs_fallocate(real.file, mode, offset, len);
+       revert_creds(old_cred);
+
+       /* Update size */
+       ovl_copyattr(ovl_inode_real(inode), inode);
+
+       fdput(real);
+
+       return ret;
+}
+
+static long ovl_real_ioctl(struct file *file, unsigned int cmd,
+                          unsigned long arg)
+{
+       struct fd real;
+       const struct cred *old_cred;
+       long ret;
+
+       ret = ovl_real_fdget(file, &real);
+       if (ret)
+               return ret;
+
+       old_cred = ovl_override_creds(file_inode(file)->i_sb);
+       ret = vfs_ioctl(real.file, cmd, arg);
+       revert_creds(old_cred);
+
+       fdput(real);
+
+       return ret;
+}
+
+static long ovl_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+       long ret;
+       struct inode *inode = file_inode(file);
+
+       switch (cmd) {
+       case FS_IOC_GETFLAGS:
+               ret = ovl_real_ioctl(file, cmd, 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);
+               break;
+
+       default:
+               ret = -ENOTTY;
+       }
+
+       return ret;
+}
+
+static long ovl_compat_ioctl(struct file *file, unsigned int cmd,
+                            unsigned long arg)
+{
+       switch (cmd) {
+       case FS_IOC32_GETFLAGS:
+               cmd = FS_IOC_GETFLAGS;
+               break;
+
+       case FS_IOC32_SETFLAGS:
+               cmd = FS_IOC_SETFLAGS;
+               break;
+
+       default:
+               return -ENOIOCTLCMD;
+       }
+
+       return ovl_ioctl(file, cmd, arg);
+}
+
+enum ovl_copyop {
+       OVL_COPY,
+       OVL_CLONE,
+       OVL_DEDUPE,
+};
+
+static ssize_t ovl_copyfile(struct file *file_in, loff_t pos_in,
+                           struct file *file_out, loff_t pos_out,
+                           u64 len, unsigned int flags, enum ovl_copyop op)
+{
+       struct inode *inode_out = file_inode(file_out);
+       struct fd real_in, real_out;
+       const struct cred *old_cred;
+       ssize_t ret;
+
+       ret = ovl_real_fdget(file_out, &real_out);
+       if (ret)
+               return ret;
+
+       ret = ovl_real_fdget(file_in, &real_in);
+       if (ret) {
+               fdput(real_out);
+               return ret;
+       }
+
+       old_cred = ovl_override_creds(file_inode(file_out)->i_sb);
+       switch (op) {
+       case OVL_COPY:
+               ret = vfs_copy_file_range(real_in.file, pos_in,
+                                         real_out.file, pos_out, len, flags);
+               break;
+
+       case OVL_CLONE:
+               ret = vfs_clone_file_range(real_in.file, pos_in,
+                                          real_out.file, pos_out, len);
+               break;
+
+       case OVL_DEDUPE:
+               ret = vfs_dedupe_file_range_one(real_in.file, pos_in,
+                                               real_out.file, pos_out, len);
+               break;
+       }
+       revert_creds(old_cred);
+
+       /* Update size */
+       ovl_copyattr(ovl_inode_real(inode_out), inode_out);
+
+       fdput(real_in);
+       fdput(real_out);
+
+       return ret;
+}
+
+static ssize_t ovl_copy_file_range(struct file *file_in, loff_t pos_in,
+                                  struct file *file_out, loff_t pos_out,
+                                  size_t len, unsigned int flags)
+{
+       return ovl_copyfile(file_in, pos_in, file_out, pos_out, len, flags,
+                           OVL_COPY);
+}
+
+static int ovl_clone_file_range(struct file *file_in, loff_t pos_in,
+                               struct file *file_out, loff_t pos_out, u64 len)
+{
+       return ovl_copyfile(file_in, pos_in, file_out, pos_out, len, 0,
+                           OVL_CLONE);
+}
+
+static int ovl_dedupe_file_range(struct file *file_in, loff_t pos_in,
+                                struct file *file_out, loff_t pos_out, u64 len)
+{
+       /*
+        * Don't copy up because of a dedupe request, this wouldn't make sense
+        * most of the time (data would be duplicated instead of deduplicated).
+        */
+       if (!ovl_inode_upper(file_inode(file_in)) ||
+           !ovl_inode_upper(file_inode(file_out)))
+               return -EPERM;
+
+       return ovl_copyfile(file_in, pos_in, file_out, pos_out, len, 0,
+                           OVL_DEDUPE);
+}
+
+const struct file_operations ovl_file_operations = {
+       .open           = ovl_open,
+       .release        = ovl_release,
+       .llseek         = ovl_llseek,
+       .read_iter      = ovl_read_iter,
+       .write_iter     = ovl_write_iter,
+       .fsync          = ovl_fsync,
+       .mmap           = ovl_mmap,
+       .fallocate      = ovl_fallocate,
+       .unlocked_ioctl = ovl_ioctl,
+       .compat_ioctl   = ovl_compat_ioctl,
+
+       .copy_file_range        = ovl_copy_file_range,
+       .clone_file_range       = ovl_clone_file_range,
+       .dedupe_file_range      = ovl_dedupe_file_range,
+};
index ed16a89..e0bb217 100644 (file)
 int ovl_setattr(struct dentry *dentry, struct iattr *attr)
 {
        int err;
+       bool full_copy_up = false;
        struct dentry *upperdentry;
        const struct cred *old_cred;
 
-       /*
-        * Check for permissions before trying to copy-up.  This is redundant
-        * since it will be rechecked later by ->setattr() on upper dentry.  But
-        * without this, copy-up can be triggered by just about anybody.
-        *
-        * We don't initialize inode->size, which just means that
-        * inode_newsize_ok() will always check against MAX_LFS_FILESIZE and not
-        * check for a swapfile (which this won't be anyway).
-        */
        err = setattr_prepare(dentry, attr);
        if (err)
                return err;
@@ -39,10 +31,33 @@ int ovl_setattr(struct dentry *dentry, struct iattr *attr)
        if (err)
                goto out;
 
-       err = ovl_copy_up(dentry);
+       if (attr->ia_valid & ATTR_SIZE) {
+               struct inode *realinode = d_inode(ovl_dentry_real(dentry));
+
+               err = -ETXTBSY;
+               if (atomic_read(&realinode->i_writecount) < 0)
+                       goto out_drop_write;
+
+               /* Truncate should trigger data copy up as well */
+               full_copy_up = true;
+       }
+
+       if (!full_copy_up)
+               err = ovl_copy_up(dentry);
+       else
+               err = ovl_copy_up_with_data(dentry);
        if (!err) {
+               struct inode *winode = NULL;
+
                upperdentry = ovl_dentry_upper(dentry);
 
+               if (attr->ia_valid & ATTR_SIZE) {
+                       winode = d_inode(upperdentry);
+                       err = get_write_access(winode);
+                       if (err)
+                               goto out_drop_write;
+               }
+
                if (attr->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID))
                        attr->ia_valid &= ~ATTR_MODE;
 
@@ -53,7 +68,11 @@ int ovl_setattr(struct dentry *dentry, struct iattr *attr)
                if (!err)
                        ovl_copyattr(upperdentry->d_inode, dentry->d_inode);
                inode_unlock(upperdentry->d_inode);
+
+               if (winode)
+                       put_write_access(winode);
        }
+out_drop_write:
        ovl_drop_write(dentry);
 out:
        return err;
@@ -133,6 +152,9 @@ int ovl_getattr(const struct path *path, struct kstat *stat,
        bool samefs = ovl_same_sb(dentry->d_sb);
        struct ovl_layer *lower_layer = NULL;
        int err;
+       bool metacopy_blocks = false;
+
+       metacopy_blocks = ovl_is_metacopy_dentry(dentry);
 
        type = ovl_path_real(dentry, &realpath);
        old_cred = ovl_override_creds(dentry->d_sb);
@@ -154,7 +176,8 @@ int ovl_getattr(const struct path *path, struct kstat *stat,
                        lower_layer = ovl_layer_lower(dentry);
                } else if (OVL_TYPE_ORIGIN(type)) {
                        struct kstat lowerstat;
-                       u32 lowermask = STATX_INO | (!is_dir ? STATX_NLINK : 0);
+                       u32 lowermask = STATX_INO | STATX_BLOCKS |
+                                       (!is_dir ? STATX_NLINK : 0);
 
                        ovl_path_lower(dentry, &realpath);
                        err = vfs_getattr(&realpath, &lowerstat,
@@ -183,6 +206,35 @@ int ovl_getattr(const struct path *path, struct kstat *stat,
                                stat->ino = lowerstat.ino;
                                lower_layer = ovl_layer_lower(dentry);
                        }
+
+                       /*
+                        * If we are querying a metacopy dentry and lower
+                        * dentry is data dentry, then use the blocks we
+                        * queried just now. We don't have to do additional
+                        * vfs_getattr(). If lower itself is metacopy, then
+                        * additional vfs_getattr() is unavoidable.
+                        */
+                       if (metacopy_blocks &&
+                           realpath.dentry == ovl_dentry_lowerdata(dentry)) {
+                               stat->blocks = lowerstat.blocks;
+                               metacopy_blocks = false;
+                       }
+               }
+
+               if (metacopy_blocks) {
+                       /*
+                        * If lower is not same as lowerdata or if there was
+                        * no origin on upper, we can end up here.
+                        */
+                       struct kstat lowerdatastat;
+                       u32 lowermask = STATX_BLOCKS;
+
+                       ovl_path_lowerdata(dentry, &realpath);
+                       err = vfs_getattr(&realpath, &lowerdatastat,
+                                         lowermask, flags);
+                       if (err)
+                               goto out;
+                       stat->blocks = lowerdatastat.blocks;
                }
        }
 
@@ -304,6 +356,9 @@ int ovl_xattr_set(struct dentry *dentry, struct inode *inode, const char *name,
        }
        revert_creds(old_cred);
 
+       /* copy c/mtime */
+       ovl_copyattr(d_inode(realdentry), inode);
+
 out_drop_write:
        ovl_drop_write(dentry);
 out:
@@ -384,38 +439,6 @@ struct posix_acl *ovl_get_acl(struct inode *inode, int type)
        return acl;
 }
 
-static bool ovl_open_need_copy_up(struct dentry *dentry, int flags)
-{
-       /* Copy up of disconnected dentry does not set upper alias */
-       if (ovl_dentry_upper(dentry) &&
-           (ovl_dentry_has_upper_alias(dentry) ||
-            (dentry->d_flags & DCACHE_DISCONNECTED)))
-               return false;
-
-       if (special_file(d_inode(dentry)->i_mode))
-               return false;
-
-       if (!(OPEN_FMODE(flags) & FMODE_WRITE) && !(flags & O_TRUNC))
-               return false;
-
-       return true;
-}
-
-int ovl_open_maybe_copy_up(struct dentry *dentry, unsigned int file_flags)
-{
-       int err = 0;
-
-       if (ovl_open_need_copy_up(dentry, file_flags)) {
-               err = ovl_want_write(dentry);
-               if (!err) {
-                       err = ovl_copy_up_flags(dentry, file_flags);
-                       ovl_drop_write(dentry);
-               }
-       }
-
-       return err;
-}
-
 int ovl_update_time(struct inode *inode, struct timespec64 *ts, int flags)
 {
        if (flags & S_ATIME) {
@@ -433,6 +456,23 @@ int ovl_update_time(struct inode *inode, struct timespec64 *ts, int flags)
        return 0;
 }
 
+static int ovl_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
+                     u64 start, u64 len)
+{
+       int err;
+       struct inode *realinode = ovl_inode_real(inode);
+       const struct cred *old_cred;
+
+       if (!realinode->i_op->fiemap)
+               return -EOPNOTSUPP;
+
+       old_cred = ovl_override_creds(inode->i_sb);
+       err = realinode->i_op->fiemap(realinode, fieinfo, start, len);
+       revert_creds(old_cred);
+
+       return err;
+}
+
 static const struct inode_operations ovl_file_inode_operations = {
        .setattr        = ovl_setattr,
        .permission     = ovl_permission,
@@ -440,6 +480,7 @@ static const struct inode_operations ovl_file_inode_operations = {
        .listxattr      = ovl_listxattr,
        .get_acl        = ovl_get_acl,
        .update_time    = ovl_update_time,
+       .fiemap         = ovl_fiemap,
 };
 
 static const struct inode_operations ovl_symlink_inode_operations = {
@@ -450,6 +491,15 @@ static const struct inode_operations ovl_symlink_inode_operations = {
        .update_time    = ovl_update_time,
 };
 
+static const struct inode_operations ovl_special_inode_operations = {
+       .setattr        = ovl_setattr,
+       .permission     = ovl_permission,
+       .getattr        = ovl_getattr,
+       .listxattr      = ovl_listxattr,
+       .get_acl        = ovl_get_acl,
+       .update_time    = ovl_update_time,
+};
+
 /*
  * It is possible to stack overlayfs instance on top of another
  * overlayfs instance as lower layer. We need to annonate the
@@ -520,6 +570,7 @@ static void ovl_fill_inode(struct inode *inode, umode_t mode, dev_t rdev,
        switch (mode & S_IFMT) {
        case S_IFREG:
                inode->i_op = &ovl_file_inode_operations;
+               inode->i_fop = &ovl_file_operations;
                break;
 
        case S_IFDIR:
@@ -532,7 +583,7 @@ static void ovl_fill_inode(struct inode *inode, umode_t mode, dev_t rdev,
                break;
 
        default:
-               inode->i_op = &ovl_file_inode_operations;
+               inode->i_op = &ovl_special_inode_operations;
                init_special_inode(inode, mode, rdev);
                break;
        }
@@ -769,8 +820,9 @@ struct inode *ovl_get_inode(struct super_block *sb,
        bool bylower = ovl_hash_bylower(sb, upperdentry, lowerdentry,
                                        oip->index);
        int fsid = bylower ? oip->lowerpath->layer->fsid : 0;
-       bool is_dir;
+       bool is_dir, metacopy = false;
        unsigned long ino = 0;
+       int err = -ENOMEM;
 
        if (!realinode)
                realinode = d_inode(lowerdentry);
@@ -787,7 +839,7 @@ struct inode *ovl_get_inode(struct super_block *sb,
 
                inode = ovl_iget5(sb, oip->newinode, key);
                if (!inode)
-                       goto out_nomem;
+                       goto out_err;
                if (!(inode->i_state & I_NEW)) {
                        /*
                         * Verify that the underlying files stored in the inode
@@ -796,11 +848,12 @@ struct inode *ovl_get_inode(struct super_block *sb,
                        if (!ovl_verify_inode(inode, lowerdentry, upperdentry,
                                              true)) {
                                iput(inode);
-                               inode = ERR_PTR(-ESTALE);
-                               goto out;
+                               err = -ESTALE;
+                               goto out_err;
                        }
 
                        dput(upperdentry);
+                       kfree(oip->redirect);
                        goto out;
                }
 
@@ -812,11 +865,13 @@ struct inode *ovl_get_inode(struct super_block *sb,
        } else {
                /* Lower hardlink that will be broken on copy up */
                inode = new_inode(sb);
-               if (!inode)
-                       goto out_nomem;
+               if (!inode) {
+                       err = -ENOMEM;
+                       goto out_err;
+               }
        }
        ovl_fill_inode(inode, realinode->i_mode, realinode->i_rdev, ino, fsid);
-       ovl_inode_init(inode, upperdentry, lowerdentry);
+       ovl_inode_init(inode, upperdentry, lowerdentry, oip->lowerdata);
 
        if (upperdentry && ovl_is_impuredir(upperdentry))
                ovl_set_flag(OVL_IMPURE, inode);
@@ -824,6 +879,20 @@ struct inode *ovl_get_inode(struct super_block *sb,
        if (oip->index)
                ovl_set_flag(OVL_INDEX, inode);
 
+       if (upperdentry) {
+               err = ovl_check_metacopy_xattr(upperdentry);
+               if (err < 0)
+                       goto out_err;
+               metacopy = err;
+               if (!metacopy)
+                       ovl_set_flag(OVL_UPPERDATA, inode);
+       }
+
+       OVL_I(inode)->redirect = oip->redirect;
+
+       if (bylower)
+               ovl_set_flag(OVL_CONST_INO, inode);
+
        /* Check for non-merge dir that may have whiteouts */
        if (is_dir) {
                if (((upperdentry && lowerdentry) || oip->numlower > 1) ||
@@ -837,7 +906,7 @@ struct inode *ovl_get_inode(struct super_block *sb,
 out:
        return inode;
 
-out_nomem:
-       inode = ERR_PTR(-ENOMEM);
+out_err:
+       inode = ERR_PTR(err);
        goto out;
 }
index c993dd8..f287118 100644 (file)
@@ -24,38 +24,20 @@ struct ovl_lookup_data {
        bool stop;
        bool last;
        char *redirect;
+       bool metacopy;
 };
 
 static int ovl_check_redirect(struct dentry *dentry, struct ovl_lookup_data *d,
                              size_t prelen, const char *post)
 {
        int res;
-       char *s, *next, *buf = NULL;
+       char *buf;
 
-       res = vfs_getxattr(dentry, OVL_XATTR_REDIRECT, NULL, 0);
-       if (res < 0) {
-               if (res == -ENODATA || res == -EOPNOTSUPP)
-                       return 0;
-               goto fail;
-       }
-       buf = kzalloc(prelen + res + strlen(post) + 1, GFP_KERNEL);
-       if (!buf)
-               return -ENOMEM;
+       buf = ovl_get_redirect_xattr(dentry, prelen + strlen(post));
+       if (IS_ERR_OR_NULL(buf))
+               return PTR_ERR(buf);
 
-       if (res == 0)
-               goto invalid;
-
-       res = vfs_getxattr(dentry, OVL_XATTR_REDIRECT, buf, res);
-       if (res < 0)
-               goto fail;
-       if (res == 0)
-               goto invalid;
        if (buf[0] == '/') {
-               for (s = buf; *s++ == '/'; s = next) {
-                       next = strchrnul(s, '/');
-                       if (s == next)
-                               goto invalid;
-               }
                /*
                 * One of the ancestor path elements in an absolute path
                 * lookup in ovl_lookup_layer() could have been opaque and
@@ -66,9 +48,7 @@ static int ovl_check_redirect(struct dentry *dentry, struct ovl_lookup_data *d,
                 */
                d->stop = false;
        } else {
-               if (strchr(buf, '/') != NULL)
-                       goto invalid;
-
+               res = strlen(buf) + 1;
                memmove(buf + prelen, buf, res);
                memcpy(buf, d->name.name, prelen);
        }
@@ -80,16 +60,6 @@ static int ovl_check_redirect(struct dentry *dentry, struct ovl_lookup_data *d,
        d->name.len = strlen(d->redirect);
 
        return 0;
-
-err_free:
-       kfree(buf);
-       return 0;
-fail:
-       pr_warn_ratelimited("overlayfs: failed to get redirect (%i)\n", res);
-       goto err_free;
-invalid:
-       pr_warn_ratelimited("overlayfs: invalid redirect (%s)\n", buf);
-       goto err_free;
 }
 
 static int ovl_acceptable(void *ctx, struct dentry *dentry)
@@ -252,28 +222,39 @@ static int ovl_lookup_single(struct dentry *base, struct ovl_lookup_data *d,
                d->stop = d->opaque = true;
                goto put_and_out;
        }
-       if (!d_can_lookup(this)) {
+       /*
+        * This dentry should be a regular file if previous layer lookup
+        * found a metacopy dentry.
+        */
+       if (last_element && d->metacopy && !d_is_reg(this)) {
                d->stop = true;
-               if (d->is_dir)
-                       goto put_and_out;
-
-               /*
-                * NB: handle failure to lookup non-last element when non-dir
-                * redirects become possible
-                */
-               WARN_ON(!last_element);
-               goto out;
+               goto put_and_out;
        }
-       if (last_element)
-               d->is_dir = true;
-       if (d->last)
-               goto out;
+       if (!d_can_lookup(this)) {
+               if (d->is_dir || !last_element) {
+                       d->stop = true;
+                       goto put_and_out;
+               }
+               err = ovl_check_metacopy_xattr(this);
+               if (err < 0)
+                       goto out_err;
 
-       if (ovl_is_opaquedir(this)) {
-               d->stop = true;
+               d->metacopy = err;
+               d->stop = !d->metacopy;
+               if (!d->metacopy || d->last)
+                       goto out;
+       } else {
                if (last_element)
-                       d->opaque = true;
-               goto out;
+                       d->is_dir = true;
+               if (d->last)
+                       goto out;
+
+               if (ovl_is_opaquedir(this)) {
+                       d->stop = true;
+                       if (last_element)
+                               d->opaque = true;
+                       goto out;
+               }
        }
        err = ovl_check_redirect(this, d, prelen, post);
        if (err)
@@ -823,7 +804,7 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
        struct ovl_fs *ofs = dentry->d_sb->s_fs_info;
        struct ovl_entry *poe = dentry->d_parent->d_fsdata;
        struct ovl_entry *roe = dentry->d_sb->s_root->d_fsdata;
-       struct ovl_path *stack = NULL;
+       struct ovl_path *stack = NULL, *origin_path = NULL;
        struct dentry *upperdir, *upperdentry = NULL;
        struct dentry *origin = NULL;
        struct dentry *index = NULL;
@@ -834,6 +815,7 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
        struct dentry *this;
        unsigned int i;
        int err;
+       bool metacopy = false;
        struct ovl_lookup_data d = {
                .name = dentry->d_name,
                .is_dir = false,
@@ -841,6 +823,7 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
                .stop = false,
                .last = ofs->config.redirect_follow ? false : !poe->numlower,
                .redirect = NULL,
+               .metacopy = false,
        };
 
        if (dentry->d_name.len > ofs->namelen)
@@ -859,7 +842,8 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
                        goto out;
                }
                if (upperdentry && !d.is_dir) {
-                       BUG_ON(!d.stop || d.redirect);
+                       unsigned int origin_ctr = 0;
+
                        /*
                         * Lookup copy up origin by decoding origin file handle.
                         * We may get a disconnected dentry, which is fine,
@@ -870,9 +854,13 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
                         * number - it's the same as if we held a reference
                         * to a dentry in lower layer that was moved under us.
                         */
-                       err = ovl_check_origin(ofs, upperdentry, &stack, &ctr);
+                       err = ovl_check_origin(ofs, upperdentry, &origin_path,
+                                              &origin_ctr);
                        if (err)
                                goto out_put_upper;
+
+                       if (d.metacopy)
+                               metacopy = true;
                }
 
                if (d.redirect) {
@@ -913,7 +901,7 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
                 * If no origin fh is stored in upper of a merge dir, store fh
                 * of lower dir and set upper parent "impure".
                 */
-               if (upperdentry && !ctr && !ofs->noxattr) {
+               if (upperdentry && !ctr && !ofs->noxattr && d.is_dir) {
                        err = ovl_fix_origin(dentry, this, upperdentry);
                        if (err) {
                                dput(this);
@@ -925,18 +913,35 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
                 * When "verify_lower" feature is enabled, do not merge with a
                 * lower dir that does not match a stored origin xattr. In any
                 * case, only verified origin is used for index lookup.
+                *
+                * For non-dir dentry, if index=on, then ensure origin
+                * matches the dentry found using path based lookup,
+                * otherwise error out.
                 */
-               if (upperdentry && !ctr && ovl_verify_lower(dentry->d_sb)) {
+               if (upperdentry && !ctr &&
+                   ((d.is_dir && ovl_verify_lower(dentry->d_sb)) ||
+                    (!d.is_dir && ofs->config.index && origin_path))) {
                        err = ovl_verify_origin(upperdentry, this, false);
                        if (err) {
                                dput(this);
-                               break;
+                               if (d.is_dir)
+                                       break;
+                               goto out_put;
                        }
-
-                       /* Bless lower dir as verified origin */
                        origin = this;
                }
 
+               if (d.metacopy)
+                       metacopy = true;
+               /*
+                * Do not store intermediate metacopy dentries in chain,
+                * except top most lower metacopy dentry
+                */
+               if (d.metacopy && ctr) {
+                       dput(this);
+                       continue;
+               }
+
                stack[ctr].dentry = this;
                stack[ctr].layer = lower.layer;
                ctr++;
@@ -968,13 +973,48 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
                }
        }
 
+       if (metacopy) {
+               /*
+                * Found a metacopy dentry but did not find corresponding
+                * data dentry
+                */
+               if (d.metacopy) {
+                       err = -EIO;
+                       goto out_put;
+               }
+
+               err = -EPERM;
+               if (!ofs->config.metacopy) {
+                       pr_warn_ratelimited("overlay: refusing to follow metacopy origin for (%pd2)\n",
+                                           dentry);
+                       goto out_put;
+               }
+       } else if (!d.is_dir && upperdentry && !ctr && origin_path) {
+               if (WARN_ON(stack != NULL)) {
+                       err = -EIO;
+                       goto out_put;
+               }
+               stack = origin_path;
+               ctr = 1;
+               origin_path = NULL;
+       }
+
        /*
         * Lookup index by lower inode and verify it matches upper inode.
         * We only trust dir index if we verified that lower dir matches
         * origin, otherwise dir index entries may be inconsistent and we
-        * ignore them. Always lookup index of non-dir and non-upper.
+        * ignore them.
+        *
+        * For non-dir upper metacopy dentry, we already set "origin" if we
+        * verified that lower matched upper origin. If upper origin was
+        * not present (because lower layer did not support fh encode/decode),
+        * or indexing is not enabled, do not set "origin" and skip looking up
+        * index. This case should be handled in same way as a non-dir upper
+        * without ORIGIN is handled.
+        *
+        * Always lookup index of non-dir non-metacopy and non-upper.
         */
-       if (ctr && (!upperdentry || !d.is_dir))
+       if (ctr && (!upperdentry || (!d.is_dir && !metacopy)))
                origin = stack[0].dentry;
 
        if (origin && ovl_indexdir(dentry->d_sb) &&
@@ -1000,8 +1040,15 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
 
        if (upperdentry)
                ovl_dentry_set_upper_alias(dentry);
-       else if (index)
+       else if (index) {
                upperdentry = dget(index);
+               upperredirect = ovl_get_redirect_xattr(upperdentry, 0);
+               if (IS_ERR(upperredirect)) {
+                       err = PTR_ERR(upperredirect);
+                       upperredirect = NULL;
+                       goto out_free_oe;
+               }
+       }
 
        if (upperdentry || ctr) {
                struct ovl_inode_params oip = {
@@ -1009,22 +1056,22 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
                        .lowerpath = stack,
                        .index = index,
                        .numlower = ctr,
+                       .redirect = upperredirect,
+                       .lowerdata = (ctr > 1 && !d.is_dir) ?
+                                     stack[ctr - 1].dentry : NULL,
                };
 
                inode = ovl_get_inode(dentry->d_sb, &oip);
                err = PTR_ERR(inode);
                if (IS_ERR(inode))
                        goto out_free_oe;
-
-               /*
-                * NB: handle redirected hard links when non-dir redirects
-                * become possible
-                */
-               WARN_ON(OVL_I(inode)->redirect);
-               OVL_I(inode)->redirect = upperredirect;
        }
 
        revert_creds(old_cred);
+       if (origin_path) {
+               dput(origin_path->dentry);
+               kfree(origin_path);
+       }
        dput(index);
        kfree(stack);
        kfree(d.redirect);
@@ -1039,6 +1086,10 @@ out_put:
                dput(stack[i].dentry);
        kfree(stack);
 out_put_upper:
+       if (origin_path) {
+               dput(origin_path->dentry);
+               kfree(origin_path);
+       }
        dput(upperdentry);
        kfree(upperredirect);
 out:
index 7538b9b..f61839e 100644 (file)
@@ -9,6 +9,7 @@
 
 #include <linux/kernel.h>
 #include <linux/uuid.h>
+#include <linux/fs.h>
 #include "ovl_entry.h"
 
 enum ovl_path_type {
@@ -28,6 +29,7 @@ enum ovl_path_type {
 #define OVL_XATTR_IMPURE OVL_XATTR_PREFIX "impure"
 #define OVL_XATTR_NLINK OVL_XATTR_PREFIX "nlink"
 #define OVL_XATTR_UPPER OVL_XATTR_PREFIX "upper"
+#define OVL_XATTR_METACOPY OVL_XATTR_PREFIX "metacopy"
 
 enum ovl_inode_flag {
        /* Pure upper dir that may contain non pure upper entries */
@@ -35,6 +37,9 @@ enum ovl_inode_flag {
        /* Non-merge dir that may contain whiteout entries */
        OVL_WHITEOUTS,
        OVL_INDEX,
+       OVL_UPPERDATA,
+       /* Inode number will remain constant over copy up. */
+       OVL_CONST_INO,
 };
 
 enum ovl_entry_flag {
@@ -190,6 +195,14 @@ static inline struct dentry *ovl_do_tmpfile(struct dentry *dentry, umode_t mode)
        return ret;
 }
 
+static inline bool ovl_open_flags_need_copy_up(int flags)
+{
+       if (!flags)
+               return false;
+
+       return ((OPEN_FMODE(flags) & FMODE_WRITE) || (flags & O_TRUNC));
+}
+
 /* util.c */
 int ovl_want_write(struct dentry *dentry);
 void ovl_drop_write(struct dentry *dentry);
@@ -206,15 +219,19 @@ bool ovl_dentry_weird(struct dentry *dentry);
 enum ovl_path_type ovl_path_type(struct dentry *dentry);
 void ovl_path_upper(struct dentry *dentry, struct path *path);
 void ovl_path_lower(struct dentry *dentry, struct path *path);
+void ovl_path_lowerdata(struct dentry *dentry, struct path *path);
 enum ovl_path_type ovl_path_real(struct dentry *dentry, struct path *path);
 struct dentry *ovl_dentry_upper(struct dentry *dentry);
 struct dentry *ovl_dentry_lower(struct dentry *dentry);
+struct dentry *ovl_dentry_lowerdata(struct dentry *dentry);
 struct ovl_layer *ovl_layer_lower(struct dentry *dentry);
 struct dentry *ovl_dentry_real(struct dentry *dentry);
 struct dentry *ovl_i_dentry_upper(struct inode *inode);
 struct inode *ovl_inode_upper(struct inode *inode);
 struct inode *ovl_inode_lower(struct inode *inode);
+struct inode *ovl_inode_lowerdata(struct inode *inode);
 struct inode *ovl_inode_real(struct inode *inode);
+struct inode *ovl_inode_realdata(struct inode *inode);
 struct ovl_dir_cache *ovl_dir_cache(struct inode *inode);
 void ovl_set_dir_cache(struct inode *inode, struct ovl_dir_cache *cache);
 void ovl_dentry_set_flag(unsigned long flag, struct dentry *dentry);
@@ -225,18 +242,23 @@ bool ovl_dentry_is_whiteout(struct dentry *dentry);
 void ovl_dentry_set_opaque(struct dentry *dentry);
 bool ovl_dentry_has_upper_alias(struct dentry *dentry);
 void ovl_dentry_set_upper_alias(struct dentry *dentry);
+bool ovl_dentry_needs_data_copy_up(struct dentry *dentry, int flags);
+bool ovl_dentry_needs_data_copy_up_locked(struct dentry *dentry, int flags);
+bool ovl_has_upperdata(struct inode *inode);
+void ovl_set_upperdata(struct inode *inode);
 bool ovl_redirect_dir(struct super_block *sb);
 const char *ovl_dentry_get_redirect(struct dentry *dentry);
 void ovl_dentry_set_redirect(struct dentry *dentry, const char *redirect);
 void ovl_inode_init(struct inode *inode, struct dentry *upperdentry,
-                   struct dentry *lowerdentry);
+                   struct dentry *lowerdentry, struct dentry *lowerdata);
 void ovl_inode_update(struct inode *inode, struct dentry *upperdentry);
-void ovl_dentry_version_inc(struct dentry *dentry, bool impurity);
+void ovl_dir_modified(struct dentry *dentry, bool impurity);
 u64 ovl_dentry_version_get(struct dentry *dentry);
 bool ovl_is_whiteout(struct dentry *dentry);
 struct file *ovl_path_open(struct path *path, int flags);
-int ovl_copy_up_start(struct dentry *dentry);
+int ovl_copy_up_start(struct dentry *dentry, int flags);
 void ovl_copy_up_end(struct dentry *dentry);
+bool ovl_already_copied_up(struct dentry *dentry, int flags);
 bool ovl_check_origin_xattr(struct dentry *dentry);
 bool ovl_check_dir_xattr(struct dentry *dentry, const char *name);
 int ovl_check_setxattr(struct dentry *dentry, struct dentry *upperdentry,
@@ -252,6 +274,9 @@ bool ovl_need_index(struct dentry *dentry);
 int ovl_nlink_start(struct dentry *dentry, bool *locked);
 void ovl_nlink_end(struct dentry *dentry, bool locked);
 int ovl_lock_rename_workdir(struct dentry *workdir, struct dentry *upperdir);
+int ovl_check_metacopy_xattr(struct dentry *dentry);
+bool ovl_is_metacopy_dentry(struct dentry *dentry);
+char *ovl_get_redirect_xattr(struct dentry *dentry, int padding);
 
 static inline bool ovl_is_impuredir(struct dentry *dentry)
 {
@@ -324,7 +349,6 @@ int ovl_xattr_get(struct dentry *dentry, struct inode *inode, const char *name,
                  void *value, size_t size);
 ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size);
 struct posix_acl *ovl_get_acl(struct inode *inode, int type);
-int ovl_open_maybe_copy_up(struct dentry *dentry, unsigned int file_flags);
 int ovl_update_time(struct inode *inode, struct timespec64 *ts, int flags);
 bool ovl_is_private_xattr(const char *name);
 
@@ -334,6 +358,8 @@ struct ovl_inode_params {
        struct ovl_path *lowerpath;
        struct dentry *index;
        unsigned int numlower;
+       char *redirect;
+       struct dentry *lowerdata;
 };
 struct inode *ovl_new_inode(struct super_block *sb, umode_t mode, dev_t rdev);
 struct inode *ovl_lookup_inode(struct super_block *sb, struct dentry *real,
@@ -348,6 +374,14 @@ static inline void ovl_copyattr(struct inode *from, struct inode *to)
        to->i_atime = from->i_atime;
        to->i_mtime = from->i_mtime;
        to->i_ctime = from->i_ctime;
+       i_size_write(to, i_size_read(from));
+}
+
+static inline void ovl_copyflags(struct inode *from, struct inode *to)
+{
+       unsigned int mask = S_SYNC | S_IMMUTABLE | S_APPEND | S_NOATIME;
+
+       inode_set_flags(to, from->i_flags & mask, mask);
 }
 
 /* dir.c */
@@ -368,9 +402,14 @@ struct dentry *ovl_create_real(struct inode *dir, struct dentry *newdentry,
 int ovl_cleanup(struct inode *dir, struct dentry *dentry);
 struct dentry *ovl_create_temp(struct dentry *workdir, struct ovl_cattr *attr);
 
+/* file.c */
+extern const struct file_operations ovl_file_operations;
+
 /* copy_up.c */
 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_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 41655a7..ec23703 100644 (file)
@@ -19,6 +19,7 @@ struct ovl_config {
        bool index;
        bool nfs_export;
        int xino;
+       bool metacopy;
 };
 
 struct ovl_sb {
@@ -88,7 +89,10 @@ static inline struct ovl_entry *OVL_E(struct dentry *dentry)
 }
 
 struct ovl_inode {
-       struct ovl_dir_cache *cache;
+       union {
+               struct ovl_dir_cache *cache;    /* directory */
+               struct inode *lowerdata;        /* regular file */
+       };
        const char *redirect;
        u64 version;
        unsigned long flags;
index ef1fe42..cc8303a 100644 (file)
@@ -668,6 +668,21 @@ static int ovl_fill_real(struct dir_context *ctx, const char *name,
        return orig_ctx->actor(orig_ctx, name, namelen, offset, ino, d_type);
 }
 
+static bool ovl_is_impure_dir(struct file *file)
+{
+       struct ovl_dir_file *od = file->private_data;
+       struct inode *dir = d_inode(file->f_path.dentry);
+
+       /*
+        * Only upper dir can be impure, but if we are in the middle of
+        * iterating a lower real dir, dir could be copied up and marked
+        * impure. We only want the impure cache if we started iterating
+        * a real upper dir to begin with.
+        */
+       return od->is_upper && ovl_test_flag(OVL_IMPURE, dir);
+
+}
+
 static int ovl_iterate_real(struct file *file, struct dir_context *ctx)
 {
        int err;
@@ -696,7 +711,7 @@ static int ovl_iterate_real(struct file *file, struct dir_context *ctx)
                rdt.parent_ino = stat.ino;
        }
 
-       if (ovl_test_flag(OVL_IMPURE, d_inode(dir))) {
+       if (ovl_is_impure_dir(file)) {
                rdt.cache = ovl_cache_get_impure(&file->f_path);
                if (IS_ERR(rdt.cache))
                        return PTR_ERR(rdt.cache);
@@ -727,7 +742,7 @@ static int ovl_iterate(struct file *file, struct dir_context *ctx)
                 */
                if (ovl_xino_bits(dentry->d_sb) ||
                    (ovl_same_sb(dentry->d_sb) &&
-                    (ovl_test_flag(OVL_IMPURE, d_inode(dentry)) ||
+                    (ovl_is_impure_dir(file) ||
                      OVL_TYPE_MERGE(ovl_path_type(dentry->d_parent))))) {
                        return ovl_iterate_real(file, ctx);
                }
index 704b373..2e0fc93 100644 (file)
@@ -64,6 +64,11 @@ static void ovl_entry_stack_free(struct ovl_entry *oe)
                dput(oe->lowerstack[i].dentry);
 }
 
+static bool ovl_metacopy_def = IS_ENABLED(CONFIG_OVERLAY_FS_METACOPY);
+module_param_named(metacopy, ovl_metacopy_def, bool, 0644);
+MODULE_PARM_DESC(ovl_metacopy_def,
+                "Default to on or off for the metadata only copy up feature");
+
 static void ovl_dentry_release(struct dentry *dentry)
 {
        struct ovl_entry *oe = dentry->d_fsdata;
@@ -74,31 +79,14 @@ static void ovl_dentry_release(struct dentry *dentry)
        }
 }
 
-static int ovl_check_append_only(struct inode *inode, int flag)
-{
-       /*
-        * This test was moot in vfs may_open() because overlay inode does
-        * not have the S_APPEND flag, so re-check on real upper inode
-        */
-       if (IS_APPEND(inode)) {
-               if  ((flag & O_ACCMODE) != O_RDONLY && !(flag & O_APPEND))
-                       return -EPERM;
-               if (flag & O_TRUNC)
-                       return -EPERM;
-       }
-
-       return 0;
-}
-
 static struct dentry *ovl_d_real(struct dentry *dentry,
-                                const struct inode *inode,
-                                unsigned int open_flags, unsigned int flags)
+                                const struct inode *inode)
 {
        struct dentry *real;
-       int err;
 
-       if (flags & D_REAL_UPPER)
-               return ovl_dentry_upper(dentry);
+       /* It's an overlay file */
+       if (inode && d_inode(dentry) == inode)
+               return dentry;
 
        if (!d_is_reg(dentry)) {
                if (!inode || inode == d_inode(dentry))
@@ -106,28 +94,19 @@ static struct dentry *ovl_d_real(struct dentry *dentry,
                goto bug;
        }
 
-       if (open_flags) {
-               err = ovl_open_maybe_copy_up(dentry, open_flags);
-               if (err)
-                       return ERR_PTR(err);
-       }
-
        real = ovl_dentry_upper(dentry);
-       if (real && (!inode || inode == d_inode(real))) {
-               if (!inode) {
-                       err = ovl_check_append_only(d_inode(real), open_flags);
-                       if (err)
-                               return ERR_PTR(err);
-               }
+       if (real && (inode == d_inode(real)))
+               return real;
+
+       if (real && !inode && ovl_has_upperdata(d_inode(dentry)))
                return real;
-       }
 
-       real = ovl_dentry_lower(dentry);
+       real = ovl_dentry_lowerdata(dentry);
        if (!real)
                goto bug;
 
        /* Handle recursion */
-       real = d_real(real, inode, open_flags, 0);
+       real = d_real(real, inode);
 
        if (!inode || inode == d_inode(real))
                return real;
@@ -205,6 +184,7 @@ static struct inode *ovl_alloc_inode(struct super_block *sb)
        oi->flags = 0;
        oi->__upperdentry = NULL;
        oi->lower = NULL;
+       oi->lowerdata = NULL;
        mutex_init(&oi->lock);
 
        return &oi->vfs_inode;
@@ -223,8 +203,11 @@ static void ovl_destroy_inode(struct inode *inode)
 
        dput(oi->__upperdentry);
        iput(oi->lower);
+       if (S_ISDIR(inode->i_mode))
+               ovl_dir_cache_free(inode);
+       else
+               iput(oi->lowerdata);
        kfree(oi->redirect);
-       ovl_dir_cache_free(inode);
        mutex_destroy(&oi->lock);
 
        call_rcu(&inode->i_rcu, ovl_i_callback);
@@ -376,6 +359,9 @@ static int ovl_show_options(struct seq_file *m, struct dentry *dentry)
                                                "on" : "off");
        if (ofs->config.xino != ovl_xino_def())
                seq_printf(m, ",xino=%s", ovl_xino_str[ofs->config.xino]);
+       if (ofs->config.metacopy != ovl_metacopy_def)
+               seq_printf(m, ",metacopy=%s",
+                          ofs->config.metacopy ? "on" : "off");
        return 0;
 }
 
@@ -413,6 +399,8 @@ enum {
        OPT_XINO_ON,
        OPT_XINO_OFF,
        OPT_XINO_AUTO,
+       OPT_METACOPY_ON,
+       OPT_METACOPY_OFF,
        OPT_ERR,
 };
 
@@ -429,6 +417,8 @@ static const match_table_t ovl_tokens = {
        {OPT_XINO_ON,                   "xino=on"},
        {OPT_XINO_OFF,                  "xino=off"},
        {OPT_XINO_AUTO,                 "xino=auto"},
+       {OPT_METACOPY_ON,               "metacopy=on"},
+       {OPT_METACOPY_OFF,              "metacopy=off"},
        {OPT_ERR,                       NULL}
 };
 
@@ -481,6 +471,7 @@ static int ovl_parse_redirect_mode(struct ovl_config *config, const char *mode)
 static int ovl_parse_opt(char *opt, struct ovl_config *config)
 {
        char *p;
+       int err;
 
        config->redirect_mode = kstrdup(ovl_redirect_mode_def(), GFP_KERNEL);
        if (!config->redirect_mode)
@@ -555,6 +546,14 @@ static int ovl_parse_opt(char *opt, struct ovl_config *config)
                        config->xino = OVL_XINO_AUTO;
                        break;
 
+               case OPT_METACOPY_ON:
+                       config->metacopy = true;
+                       break;
+
+               case OPT_METACOPY_OFF:
+                       config->metacopy = false;
+                       break;
+
                default:
                        pr_err("overlayfs: unrecognized mount option \"%s\" or missing value\n", p);
                        return -EINVAL;
@@ -569,7 +568,20 @@ static int ovl_parse_opt(char *opt, struct ovl_config *config)
                config->workdir = NULL;
        }
 
-       return ovl_parse_redirect_mode(config, config->redirect_mode);
+       err = ovl_parse_redirect_mode(config, config->redirect_mode);
+       if (err)
+               return err;
+
+       /* metacopy feature with upper requires redirect_dir=on */
+       if (config->upperdir && config->metacopy && !config->redirect_dir) {
+               pr_warn("overlayfs: metadata only copy up requires \"redirect_dir=on\", falling back to metacopy=off.\n");
+               config->metacopy = false;
+       } else if (config->metacopy && !config->redirect_follow) {
+               pr_warn("overlayfs: metadata only copy up requires \"redirect_dir=follow\" on non-upper mount, falling back to metacopy=off.\n");
+               config->metacopy = false;
+       }
+
+       return 0;
 }
 
 #define OVL_WORKDIR_NAME "work"
@@ -1042,7 +1054,8 @@ static int ovl_make_workdir(struct ovl_fs *ofs, struct path *workpath)
        if (err) {
                ofs->noxattr = true;
                ofs->config.index = false;
-               pr_warn("overlayfs: upper fs does not support xattr, falling back to index=off.\n");
+               ofs->config.metacopy = false;
+               pr_warn("overlayfs: upper fs does not support xattr, falling back to index=off and metacopy=off.\n");
                err = 0;
        } else {
                vfs_removexattr(ofs->workdir, OVL_XATTR_OPAQUE);
@@ -1064,7 +1077,6 @@ static int ovl_make_workdir(struct ovl_fs *ofs, struct path *workpath)
                pr_warn("overlayfs: NFS export requires \"index=on\", falling back to nfs_export=off.\n");
                ofs->config.nfs_export = false;
        }
-
 out:
        mnt_drop_write(mnt);
        return err;
@@ -1375,6 +1387,7 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
        ofs->config.index = ovl_index_def;
        ofs->config.nfs_export = ovl_nfs_export_def;
        ofs->config.xino = ovl_xino_def();
+       ofs->config.metacopy = ovl_metacopy_def;
        err = ovl_parse_opt((char *) data, &ofs->config);
        if (err)
                goto out_err;
@@ -1445,6 +1458,11 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
                }
        }
 
+       if (ofs->config.metacopy && ofs->config.nfs_export) {
+               pr_warn("overlayfs: NFS export is not supported with metadata only copy up, falling back to nfs_export=off.\n");
+               ofs->config.nfs_export = false;
+       }
+
        if (ofs->config.nfs_export)
                sb->s_export_op = &ovl_export_operations;
 
@@ -1455,7 +1473,7 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
        sb->s_op = &ovl_super_operations;
        sb->s_xattr = ovl_xattr_handlers;
        sb->s_fs_info = ofs;
-       sb->s_flags |= SB_POSIXACL | SB_NOREMOTELOCK;
+       sb->s_flags |= SB_POSIXACL;
 
        err = -ENOMEM;
        root_dentry = d_make_root(ovl_new_inode(sb, S_IFDIR, 0));
@@ -1474,8 +1492,9 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
        /* Root is always merge -> can have whiteouts */
        ovl_set_flag(OVL_WHITEOUTS, d_inode(root_dentry));
        ovl_dentry_set_flag(OVL_E_CONNECTED, root_dentry);
+       ovl_set_upperdata(d_inode(root_dentry));
        ovl_inode_init(d_inode(root_dentry), upperpath.dentry,
-                      ovl_dentry_lower(root_dentry));
+                      ovl_dentry_lower(root_dentry), NULL);
 
        sb->s_root = root_dentry;
 
index 6f10780..8cfb62c 100644 (file)
@@ -133,8 +133,10 @@ enum ovl_path_type ovl_path_type(struct dentry *dentry)
                 * Non-dir dentry can hold lower dentry of its copy up origin.
                 */
                if (oe->numlower) {
-                       type |= __OVL_PATH_ORIGIN;
-                       if (d_is_dir(dentry))
+                       if (ovl_test_flag(OVL_CONST_INO, d_inode(dentry)))
+                               type |= __OVL_PATH_ORIGIN;
+                       if (d_is_dir(dentry) ||
+                           !ovl_has_upperdata(d_inode(dentry)))
                                type |= __OVL_PATH_MERGE;
                }
        } else {
@@ -164,6 +166,18 @@ void ovl_path_lower(struct dentry *dentry, struct path *path)
        }
 }
 
+void ovl_path_lowerdata(struct dentry *dentry, struct path *path)
+{
+       struct ovl_entry *oe = dentry->d_fsdata;
+
+       if (oe->numlower) {
+               path->mnt = oe->lowerstack[oe->numlower - 1].layer->mnt;
+               path->dentry = oe->lowerstack[oe->numlower - 1].dentry;
+       } else {
+               *path = (struct path) { };
+       }
+}
+
 enum ovl_path_type ovl_path_real(struct dentry *dentry, struct path *path)
 {
        enum ovl_path_type type = ovl_path_type(dentry);
@@ -195,6 +209,19 @@ struct ovl_layer *ovl_layer_lower(struct dentry *dentry)
        return oe->numlower ? oe->lowerstack[0].layer : NULL;
 }
 
+/*
+ * ovl_dentry_lower() could return either a data dentry or metacopy dentry
+ * dependig on what is stored in lowerstack[0]. At times we need to find
+ * lower dentry which has data (and not metacopy dentry). This helper
+ * returns the lower data dentry.
+ */
+struct dentry *ovl_dentry_lowerdata(struct dentry *dentry)
+{
+       struct ovl_entry *oe = dentry->d_fsdata;
+
+       return oe->numlower ? oe->lowerstack[oe->numlower - 1].dentry : NULL;
+}
+
 struct dentry *ovl_dentry_real(struct dentry *dentry)
 {
        return ovl_dentry_upper(dentry) ?: ovl_dentry_lower(dentry);
@@ -222,6 +249,26 @@ struct inode *ovl_inode_real(struct inode *inode)
        return ovl_inode_upper(inode) ?: ovl_inode_lower(inode);
 }
 
+/* Return inode which contains lower data. Do not return metacopy */
+struct inode *ovl_inode_lowerdata(struct inode *inode)
+{
+       if (WARN_ON(!S_ISREG(inode->i_mode)))
+               return NULL;
+
+       return OVL_I(inode)->lowerdata ?: ovl_inode_lower(inode);
+}
+
+/* Return real inode which contains data. Does not return metacopy inode */
+struct inode *ovl_inode_realdata(struct inode *inode)
+{
+       struct inode *upperinode;
+
+       upperinode = ovl_inode_upper(inode);
+       if (upperinode && ovl_has_upperdata(inode))
+               return upperinode;
+
+       return ovl_inode_lowerdata(inode);
+}
 
 struct ovl_dir_cache *ovl_dir_cache(struct inode *inode)
 {
@@ -279,6 +326,62 @@ void ovl_dentry_set_upper_alias(struct dentry *dentry)
        ovl_dentry_set_flag(OVL_E_UPPER_ALIAS, dentry);
 }
 
+static bool ovl_should_check_upperdata(struct inode *inode)
+{
+       if (!S_ISREG(inode->i_mode))
+               return false;
+
+       if (!ovl_inode_lower(inode))
+               return false;
+
+       return true;
+}
+
+bool ovl_has_upperdata(struct inode *inode)
+{
+       if (!ovl_should_check_upperdata(inode))
+               return true;
+
+       if (!ovl_test_flag(OVL_UPPERDATA, inode))
+               return false;
+       /*
+        * Pairs with smp_wmb() in ovl_set_upperdata(). Main user of
+        * ovl_has_upperdata() is ovl_copy_up_meta_inode_data(). Make sure
+        * if setting of OVL_UPPERDATA is visible, then effects of writes
+        * before that are visible too.
+        */
+       smp_rmb();
+       return true;
+}
+
+void ovl_set_upperdata(struct inode *inode)
+{
+       /*
+        * Pairs with smp_rmb() in ovl_has_upperdata(). Make sure
+        * if OVL_UPPERDATA flag is visible, then effects of write operations
+        * before it are visible as well.
+        */
+       smp_wmb();
+       ovl_set_flag(OVL_UPPERDATA, inode);
+}
+
+/* Caller should hold ovl_inode->lock */
+bool ovl_dentry_needs_data_copy_up_locked(struct dentry *dentry, int flags)
+{
+       if (!ovl_open_flags_need_copy_up(flags))
+               return false;
+
+       return !ovl_test_flag(OVL_UPPERDATA, d_inode(dentry));
+}
+
+bool ovl_dentry_needs_data_copy_up(struct dentry *dentry, int flags)
+{
+       if (!ovl_open_flags_need_copy_up(flags))
+               return false;
+
+       return !ovl_has_upperdata(d_inode(dentry));
+}
+
 bool ovl_redirect_dir(struct super_block *sb)
 {
        struct ovl_fs *ofs = sb->s_fs_info;
@@ -300,7 +403,7 @@ void ovl_dentry_set_redirect(struct dentry *dentry, const char *redirect)
 }
 
 void ovl_inode_init(struct inode *inode, struct dentry *upperdentry,
-                   struct dentry *lowerdentry)
+                   struct dentry *lowerdentry, struct dentry *lowerdata)
 {
        struct inode *realinode = d_inode(upperdentry ?: lowerdentry);
 
@@ -308,8 +411,11 @@ void ovl_inode_init(struct inode *inode, struct dentry *upperdentry,
                OVL_I(inode)->__upperdentry = upperdentry;
        if (lowerdentry)
                OVL_I(inode)->lower = igrab(d_inode(lowerdentry));
+       if (lowerdata)
+               OVL_I(inode)->lowerdata = igrab(d_inode(lowerdata));
 
        ovl_copyattr(realinode, inode);
+       ovl_copyflags(realinode, inode);
        if (!inode->i_ino)
                inode->i_ino = realinode->i_ino;
 }
@@ -333,7 +439,7 @@ void ovl_inode_update(struct inode *inode, struct dentry *upperdentry)
        }
 }
 
-void ovl_dentry_version_inc(struct dentry *dentry, bool impurity)
+static void ovl_dentry_version_inc(struct dentry *dentry, bool impurity)
 {
        struct inode *inode = d_inode(dentry);
 
@@ -348,6 +454,14 @@ void ovl_dentry_version_inc(struct dentry *dentry, bool impurity)
                OVL_I(inode)->version++;
 }
 
+void ovl_dir_modified(struct dentry *dentry, bool impurity)
+{
+       /* Copy mtime/ctime */
+       ovl_copyattr(d_inode(ovl_dentry_upper(dentry)), d_inode(dentry));
+
+       ovl_dentry_version_inc(dentry, impurity);
+}
+
 u64 ovl_dentry_version_get(struct dentry *dentry)
 {
        struct inode *inode = d_inode(dentry);
@@ -368,13 +482,51 @@ struct file *ovl_path_open(struct path *path, int flags)
        return dentry_open(path, flags | O_NOATIME, current_cred());
 }
 
-int ovl_copy_up_start(struct dentry *dentry)
+/* Caller should hold ovl_inode->lock */
+static bool ovl_already_copied_up_locked(struct dentry *dentry, int flags)
+{
+       bool disconnected = dentry->d_flags & DCACHE_DISCONNECTED;
+
+       if (ovl_dentry_upper(dentry) &&
+           (ovl_dentry_has_upper_alias(dentry) || disconnected) &&
+           !ovl_dentry_needs_data_copy_up_locked(dentry, flags))
+               return true;
+
+       return false;
+}
+
+bool ovl_already_copied_up(struct dentry *dentry, int flags)
+{
+       bool disconnected = dentry->d_flags & DCACHE_DISCONNECTED;
+
+       /*
+        * Check if copy-up has happened as well as for upper alias (in
+        * case of hard links) is there.
+        *
+        * Both checks are lockless:
+        *  - false negatives: will recheck under oi->lock
+        *  - false positives:
+        *    + ovl_dentry_upper() uses memory barriers to ensure the
+        *      upper dentry is up-to-date
+        *    + ovl_dentry_has_upper_alias() relies on locking of
+        *      upper parent i_rwsem to prevent reordering copy-up
+        *      with rename.
+        */
+       if (ovl_dentry_upper(dentry) &&
+           (ovl_dentry_has_upper_alias(dentry) || disconnected) &&
+           !ovl_dentry_needs_data_copy_up(dentry, flags))
+               return true;
+
+       return false;
+}
+
+int ovl_copy_up_start(struct dentry *dentry, int flags)
 {
        struct ovl_inode *oi = OVL_I(d_inode(dentry));
        int err;
 
        err = mutex_lock_interruptible(&oi->lock);
-       if (!err && ovl_dentry_has_upper_alias(dentry)) {
+       if (!err && ovl_already_copied_up_locked(dentry, flags)) {
                err = 1; /* Already copied up */
                mutex_unlock(&oi->lock);
        }
@@ -675,3 +827,91 @@ err:
        pr_err("overlayfs: failed to lock workdir+upperdir\n");
        return -EIO;
 }
+
+/* err < 0, 0 if no metacopy xattr, 1 if metacopy xattr found */
+int ovl_check_metacopy_xattr(struct dentry *dentry)
+{
+       int res;
+
+       /* Only regular files can have metacopy xattr */
+       if (!S_ISREG(d_inode(dentry)->i_mode))
+               return 0;
+
+       res = vfs_getxattr(dentry, OVL_XATTR_METACOPY, NULL, 0);
+       if (res < 0) {
+               if (res == -ENODATA || res == -EOPNOTSUPP)
+                       return 0;
+               goto out;
+       }
+
+       return 1;
+out:
+       pr_warn_ratelimited("overlayfs: failed to get metacopy (%i)\n", res);
+       return res;
+}
+
+bool ovl_is_metacopy_dentry(struct dentry *dentry)
+{
+       struct ovl_entry *oe = dentry->d_fsdata;
+
+       if (!d_is_reg(dentry))
+               return false;
+
+       if (ovl_dentry_upper(dentry)) {
+               if (!ovl_has_upperdata(d_inode(dentry)))
+                       return true;
+               return false;
+       }
+
+       return (oe->numlower > 1);
+}
+
+char *ovl_get_redirect_xattr(struct dentry *dentry, int padding)
+{
+       int res;
+       char *s, *next, *buf = NULL;
+
+       res = vfs_getxattr(dentry, OVL_XATTR_REDIRECT, NULL, 0);
+       if (res < 0) {
+               if (res == -ENODATA || res == -EOPNOTSUPP)
+                       return NULL;
+               goto fail;
+       }
+
+       buf = kzalloc(res + padding + 1, GFP_KERNEL);
+       if (!buf)
+               return ERR_PTR(-ENOMEM);
+
+       if (res == 0)
+               goto invalid;
+
+       res = vfs_getxattr(dentry, OVL_XATTR_REDIRECT, buf, res);
+       if (res < 0)
+               goto fail;
+       if (res == 0)
+               goto invalid;
+
+       if (buf[0] == '/') {
+               for (s = buf; *s++ == '/'; s = next) {
+                       next = strchrnul(s, '/');
+                       if (s == next)
+                               goto invalid;
+               }
+       } else {
+               if (strchr(buf, '/') != NULL)
+                       goto invalid;
+       }
+
+       return buf;
+
+err_free:
+       kfree(buf);
+       return ERR_PTR(res);
+fail:
+       pr_warn_ratelimited("overlayfs: failed to get redirect (%i)\n", res);
+       goto err_free;
+invalid:
+       pr_warn_ratelimited("overlayfs: invalid redirect (%s)\n", buf);
+       res = -EINVAL;
+       goto err_free;
+}
index 0eaeb41..817c02b 100644 (file)
@@ -31,6 +31,7 @@ config PROC_FS
 config PROC_KCORE
        bool "/proc/kcore support" if !ARM
        depends on PROC_FS && MMU
+       select CRASH_CORE
        help
          Provides a virtual ELF core file of the live kernel.  This can
          be read with gdb and other ELF tools.  No modifications can be
index aaffc0c..ccf86f1 100644 (file)
@@ -463,7 +463,7 @@ static int lstats_show_proc(struct seq_file *m, void *v)
        if (!task)
                return -ESRCH;
        seq_puts(m, "Latency Top version : v0.1\n");
-       for (i = 0; i < 32; i++) {
+       for (i = 0; i < LT_SAVECOUNT; i++) {
                struct latency_record *lr = &task->latency_record[i];
                if (lr->backtrace[0]) {
                        int q;
@@ -1366,10 +1366,8 @@ static ssize_t proc_fail_nth_read(struct file *file, char __user *buf,
        if (!task)
                return -ESRCH;
        len = snprintf(numbuf, sizeof(numbuf), "%u\n", task->fail_nth);
-       len = simple_read_from_buffer(buf, count, ppos, numbuf, len);
        put_task_struct(task);
-
-       return len;
+       return simple_read_from_buffer(buf, count, ppos, numbuf, len);
 }
 
 static const struct file_operations proc_fail_nth_operations = {
@@ -2519,47 +2517,47 @@ static ssize_t proc_pid_attr_write(struct file * file, const char __user * buf,
                                   size_t count, loff_t *ppos)
 {
        struct inode * inode = file_inode(file);
+       struct task_struct *task;
        void *page;
-       ssize_t length;
-       struct task_struct *task = get_proc_task(inode);
-
-       length = -ESRCH;
-       if (!task)
-               goto out_no_task;
+       int rv;
 
+       rcu_read_lock();
+       task = pid_task(proc_pid(inode), PIDTYPE_PID);
+       if (!task) {
+               rcu_read_unlock();
+               return -ESRCH;
+       }
        /* A task may only write its own attributes. */
-       length = -EACCES;
-       if (current != task)
-               goto out;
+       if (current != task) {
+               rcu_read_unlock();
+               return -EACCES;
+       }
+       rcu_read_unlock();
 
        if (count > PAGE_SIZE)
                count = PAGE_SIZE;
 
        /* No partial writes. */
-       length = -EINVAL;
        if (*ppos != 0)
-               goto out;
+               return -EINVAL;
 
        page = memdup_user(buf, count);
        if (IS_ERR(page)) {
-               length = PTR_ERR(page);
+               rv = PTR_ERR(page);
                goto out;
        }
 
        /* Guard against adverse ptrace interaction */
-       length = mutex_lock_interruptible(&current->signal->cred_guard_mutex);
-       if (length < 0)
+       rv = mutex_lock_interruptible(&current->signal->cred_guard_mutex);
+       if (rv < 0)
                goto out_free;
 
-       length = security_setprocattr(file->f_path.dentry->d_name.name,
-                                     page, count);
+       rv = security_setprocattr(file->f_path.dentry->d_name.name, page, count);
        mutex_unlock(&current->signal->cred_guard_mutex);
 out_free:
        kfree(page);
 out:
-       put_task_struct(task);
-out_no_task:
-       return length;
+       return rv;
 }
 
 static const struct file_operations proc_pid_attr_operations = {
@@ -3309,12 +3307,12 @@ static const struct pid_entry tid_base_stuff[] = {
        REG("cmdline",   S_IRUGO, proc_pid_cmdline_ops),
        ONE("stat",      S_IRUGO, proc_tid_stat),
        ONE("statm",     S_IRUGO, proc_pid_statm),
-       REG("maps",      S_IRUGO, proc_tid_maps_operations),
+       REG("maps",      S_IRUGO, proc_pid_maps_operations),
 #ifdef CONFIG_PROC_CHILDREN
        REG("children",  S_IRUGO, proc_tid_children_operations),
 #endif
 #ifdef CONFIG_NUMA
-       REG("numa_maps", S_IRUGO, proc_tid_numa_maps_operations),
+       REG("numa_maps", S_IRUGO, proc_pid_numa_maps_operations),
 #endif
        REG("mem",       S_IRUSR|S_IWUSR, proc_mem_operations),
        LNK("cwd",       proc_cwd_link),
@@ -3324,7 +3322,7 @@ static const struct pid_entry tid_base_stuff[] = {
        REG("mountinfo",  S_IRUGO, proc_mountinfo_operations),
 #ifdef CONFIG_PROC_PAGE_MONITOR
        REG("clear_refs", S_IWUSR, proc_clear_refs_operations),
-       REG("smaps",     S_IRUGO, proc_tid_smaps_operations),
+       REG("smaps",     S_IRUGO, proc_pid_smaps_operations),
        REG("smaps_rollup", S_IRUGO, proc_pid_smaps_rollup_operations),
        REG("pagemap",    S_IRUSR, proc_pagemap_operations),
 #endif
index bb1c162..8ae1094 100644 (file)
@@ -286,9 +286,9 @@ int proc_readdir_de(struct file *file, struct dir_context *ctx,
        if (!dir_emit_dots(file, ctx))
                return 0;
 
+       i = ctx->pos - 2;
        read_lock(&proc_subdir_lock);
        de = pde_subdir_first(de);
-       i = ctx->pos - 2;
        for (;;) {
                if (!de) {
                        read_unlock(&proc_subdir_lock);
@@ -309,8 +309,8 @@ int proc_readdir_de(struct file *file, struct dir_context *ctx,
                        pde_put(de);
                        return 0;
                }
-               read_lock(&proc_subdir_lock);
                ctx->pos++;
+               read_lock(&proc_subdir_lock);
                next = pde_subdir_next(de);
                pde_put(de);
                de = next;
index 85ffbd2..fc5306a 100644 (file)
@@ -105,8 +105,10 @@ void __init proc_init_kmemcache(void)
                kmem_cache_create("pde_opener", sizeof(struct pde_opener), 0,
                                  SLAB_ACCOUNT|SLAB_PANIC, NULL);
        proc_dir_entry_cache = kmem_cache_create_usercopy(
-               "proc_dir_entry", SIZEOF_PDE_SLOT, 0, SLAB_PANIC,
-               OFFSETOF_PDE_NAME, SIZEOF_PDE_INLINE_NAME, NULL);
+               "proc_dir_entry", SIZEOF_PDE, 0, SLAB_PANIC,
+               offsetof(struct proc_dir_entry, inline_name),
+               SIZEOF_PDE_INLINE_NAME, NULL);
+       BUILD_BUG_ON(sizeof(struct proc_dir_entry) >= SIZEOF_PDE);
 }
 
 static int proc_show_options(struct seq_file *seq, struct dentry *root)
index da3dbfa..5185d7f 100644 (file)
@@ -65,16 +65,13 @@ struct proc_dir_entry {
        char inline_name[];
 } __randomize_layout;
 
-#define OFFSETOF_PDE_NAME offsetof(struct proc_dir_entry, inline_name)
-#define SIZEOF_PDE_SLOT                                        \
-       (OFFSETOF_PDE_NAME + 34 <= 64 ? 64 :            \
-        OFFSETOF_PDE_NAME + 34 <= 128 ? 128 :          \
-        OFFSETOF_PDE_NAME + 34 <= 192 ? 192 :          \
-        OFFSETOF_PDE_NAME + 34 <= 256 ? 256 :          \
-        OFFSETOF_PDE_NAME + 34 <= 512 ? 512 :          \
-        0)
-
-#define SIZEOF_PDE_INLINE_NAME (SIZEOF_PDE_SLOT - OFFSETOF_PDE_NAME)
+#define SIZEOF_PDE     (                               \
+       sizeof(struct proc_dir_entry) < 128 ? 128 :     \
+       sizeof(struct proc_dir_entry) < 192 ? 192 :     \
+       sizeof(struct proc_dir_entry) < 256 ? 256 :     \
+       sizeof(struct proc_dir_entry) < 512 ? 512 :     \
+       0)
+#define SIZEOF_PDE_INLINE_NAME (SIZEOF_PDE - sizeof(struct proc_dir_entry))
 
 extern struct kmem_cache *proc_dir_entry_cache;
 void pde_free(struct proc_dir_entry *pde);
@@ -116,12 +113,12 @@ static inline void *__PDE_DATA(const struct inode *inode)
        return PDE(inode)->data;
 }
 
-static inline struct pid *proc_pid(struct inode *inode)
+static inline struct pid *proc_pid(const struct inode *inode)
 {
        return PROC_I(inode)->pid;
 }
 
-static inline struct task_struct *get_proc_task(struct inode *inode)
+static inline struct task_struct *get_proc_task(const struct inode *inode)
 {
        return get_pid_task(proc_pid(inode), PIDTYPE_PID);
 }
@@ -285,7 +282,6 @@ struct proc_maps_private {
        struct inode *inode;
        struct task_struct *task;
        struct mm_struct *mm;
-       struct mem_size_stats *rollup;
 #ifdef CONFIG_MMU
        struct vm_area_struct *tail_vma;
 #endif
@@ -297,12 +293,9 @@ struct proc_maps_private {
 struct mm_struct *proc_mem_open(struct inode *inode, unsigned int mode);
 
 extern const struct file_operations proc_pid_maps_operations;
-extern const struct file_operations proc_tid_maps_operations;
 extern const struct file_operations proc_pid_numa_maps_operations;
-extern const struct file_operations proc_tid_numa_maps_operations;
 extern const struct file_operations proc_pid_smaps_operations;
 extern const struct file_operations proc_pid_smaps_rollup_operations;
-extern const struct file_operations proc_tid_smaps_operations;
 extern const struct file_operations proc_clear_refs_operations;
 extern const struct file_operations proc_pagemap_operations;
 
index e64ecb9..ad72261 100644 (file)
@@ -10,6 +10,7 @@
  *     Safe accesses to vmalloc/direct-mapped discontiguous areas, Kanoj Sarcar <kanoj@sgi.com>
  */
 
+#include <linux/crash_core.h>
 #include <linux/mm.h>
 #include <linux/proc_fs.h>
 #include <linux/kcore.h>
@@ -49,32 +50,23 @@ static struct proc_dir_entry *proc_root_kcore;
 #define        kc_offset_to_vaddr(o) ((o) + PAGE_OFFSET)
 #endif
 
-/* An ELF note in memory */
-struct memelfnote
-{
-       const char *name;
-       int type;
-       unsigned int datasz;
-       void *data;
-};
-
 static LIST_HEAD(kclist_head);
-static DEFINE_RWLOCK(kclist_lock);
+static DECLARE_RWSEM(kclist_lock);
 static int kcore_need_update = 1;
 
-void
-kclist_add(struct kcore_list *new, void *addr, size_t size, int type)
+/* This doesn't grab kclist_lock, so it should only be used at init time. */
+void __init kclist_add(struct kcore_list *new, void *addr, size_t size,
+                      int type)
 {
        new->addr = (unsigned long)addr;
        new->size = size;
        new->type = type;
 
-       write_lock(&kclist_lock);
        list_add_tail(&new->list, &kclist_head);
-       write_unlock(&kclist_lock);
 }
 
-static size_t get_kcore_size(int *nphdr, size_t *elf_buflen)
+static size_t get_kcore_size(int *nphdr, size_t *phdrs_len, size_t *notes_len,
+                            size_t *data_offset)
 {
        size_t try, size;
        struct kcore_list *m;
@@ -88,53 +80,19 @@ static size_t get_kcore_size(int *nphdr, size_t *elf_buflen)
                        size = try;
                *nphdr = *nphdr + 1;
        }
-       *elf_buflen =   sizeof(struct elfhdr) + 
-                       (*nphdr + 2)*sizeof(struct elf_phdr) + 
-                       3 * ((sizeof(struct elf_note)) +
-                            roundup(sizeof(CORE_STR), 4)) +
-                       roundup(sizeof(struct elf_prstatus), 4) +
-                       roundup(sizeof(struct elf_prpsinfo), 4) +
-                       roundup(arch_task_struct_size, 4);
-       *elf_buflen = PAGE_ALIGN(*elf_buflen);
-       return size + *elf_buflen;
-}
-
-static void free_kclist_ents(struct list_head *head)
-{
-       struct kcore_list *tmp, *pos;
 
-       list_for_each_entry_safe(pos, tmp, head, list) {
-               list_del(&pos->list);
-               kfree(pos);
-       }
+       *phdrs_len = *nphdr * sizeof(struct elf_phdr);
+       *notes_len = (4 * sizeof(struct elf_note) +
+                     3 * ALIGN(sizeof(CORE_STR), 4) +
+                     VMCOREINFO_NOTE_NAME_BYTES +
+                     ALIGN(sizeof(struct elf_prstatus), 4) +
+                     ALIGN(sizeof(struct elf_prpsinfo), 4) +
+                     ALIGN(arch_task_struct_size, 4) +
+                     ALIGN(vmcoreinfo_size, 4));
+       *data_offset = PAGE_ALIGN(sizeof(struct elfhdr) + *phdrs_len +
+                                 *notes_len);
+       return *data_offset + size;
 }
-/*
- * Replace all KCORE_RAM/KCORE_VMEMMAP information with passed list.
- */
-static void __kcore_update_ram(struct list_head *list)
-{
-       int nphdr;
-       size_t size;
-       struct kcore_list *tmp, *pos;
-       LIST_HEAD(garbage);
-
-       write_lock(&kclist_lock);
-       if (kcore_need_update) {
-               list_for_each_entry_safe(pos, tmp, &kclist_head, list) {
-                       if (pos->type == KCORE_RAM
-                               || pos->type == KCORE_VMEMMAP)
-                               list_move(&pos->list, &garbage);
-               }
-               list_splice_tail(list, &kclist_head);
-       } else
-               list_splice(list, &garbage);
-       kcore_need_update = 0;
-       proc_root_kcore->size = get_kcore_size(&nphdr, &size);
-       write_unlock(&kclist_lock);
-
-       free_kclist_ents(&garbage);
-}
-
 
 #ifdef CONFIG_HIGHMEM
 /*
@@ -142,11 +100,9 @@ static void __kcore_update_ram(struct list_head *list)
  * because memory hole is not as big as !HIGHMEM case.
  * (HIGHMEM is special because part of memory is _invisible_ from the kernel.)
  */
-static int kcore_update_ram(void)
+static int kcore_ram_list(struct list_head *head)
 {
-       LIST_HEAD(head);
        struct kcore_list *ent;
-       int ret = 0;
 
        ent = kmalloc(sizeof(*ent), GFP_KERNEL);
        if (!ent)
@@ -154,9 +110,8 @@ static int kcore_update_ram(void)
        ent->addr = (unsigned long)__va(0);
        ent->size = max_low_pfn << PAGE_SHIFT;
        ent->type = KCORE_RAM;
-       list_add(&ent->list, &head);
-       __kcore_update_ram(&head);
-       return ret;
+       list_add(&ent->list, head);
+       return 0;
 }
 
 #else /* !CONFIG_HIGHMEM */
@@ -255,11 +210,10 @@ free_out:
        return 1;
 }
 
-static int kcore_update_ram(void)
+static int kcore_ram_list(struct list_head *list)
 {
        int nid, ret;
        unsigned long end_pfn;
-       LIST_HEAD(head);
 
        /* Not inialized....update now */
        /* find out "max pfn" */
@@ -271,258 +225,258 @@ static int kcore_update_ram(void)
                        end_pfn = node_end;
        }
        /* scan 0 to max_pfn */
-       ret = walk_system_ram_range(0, end_pfn, &head, kclist_add_private);
-       if (ret) {
-               free_kclist_ents(&head);
+       ret = walk_system_ram_range(0, end_pfn, list, kclist_add_private);
+       if (ret)
                return -ENOMEM;
-       }
-       __kcore_update_ram(&head);
-       return ret;
+       return 0;
 }
 #endif /* CONFIG_HIGHMEM */
 
-/*****************************************************************************/
-/*
- * determine size of ELF note
- */
-static int notesize(struct memelfnote *en)
-{
-       int sz;
-
-       sz = sizeof(struct elf_note);
-       sz += roundup((strlen(en->name) + 1), 4);
-       sz += roundup(en->datasz, 4);
-
-       return sz;
-} /* end notesize() */
-
-/*****************************************************************************/
-/*
- * store a note in the header buffer
- */
-static char *storenote(struct memelfnote *men, char *bufp)
+static int kcore_update_ram(void)
 {
-       struct elf_note en;
-
-#define DUMP_WRITE(addr,nr) do { memcpy(bufp,addr,nr); bufp += nr; } while(0)
-
-       en.n_namesz = strlen(men->name) + 1;
-       en.n_descsz = men->datasz;
-       en.n_type = men->type;
-
-       DUMP_WRITE(&en, sizeof(en));
-       DUMP_WRITE(men->name, en.n_namesz);
-
-       /* XXX - cast from long long to long to avoid need for libgcc.a */
-       bufp = (char*) roundup((unsigned long)bufp,4);
-       DUMP_WRITE(men->data, men->datasz);
-       bufp = (char*) roundup((unsigned long)bufp,4);
-
-#undef DUMP_WRITE
-
-       return bufp;
-} /* end storenote() */
+       LIST_HEAD(list);
+       LIST_HEAD(garbage);
+       int nphdr;
+       size_t phdrs_len, notes_len, data_offset;
+       struct kcore_list *tmp, *pos;
+       int ret = 0;
 
-/*
- * store an ELF coredump header in the supplied buffer
- * nphdr is the number of elf_phdr to insert
- */
-static void elf_kcore_store_hdr(char *bufp, int nphdr, int dataoff)
-{
-       struct elf_prstatus prstatus;   /* NT_PRSTATUS */
-       struct elf_prpsinfo prpsinfo;   /* NT_PRPSINFO */
-       struct elf_phdr *nhdr, *phdr;
-       struct elfhdr *elf;
-       struct memelfnote notes[3];
-       off_t offset = 0;
-       struct kcore_list *m;
+       down_write(&kclist_lock);
+       if (!xchg(&kcore_need_update, 0))
+               goto out;
 
-       /* setup ELF header */
-       elf = (struct elfhdr *) bufp;
-       bufp += sizeof(struct elfhdr);
-       offset += sizeof(struct elfhdr);
-       memcpy(elf->e_ident, ELFMAG, SELFMAG);
-       elf->e_ident[EI_CLASS]  = ELF_CLASS;
-       elf->e_ident[EI_DATA]   = ELF_DATA;
-       elf->e_ident[EI_VERSION]= EV_CURRENT;
-       elf->e_ident[EI_OSABI] = ELF_OSABI;
-       memset(elf->e_ident+EI_PAD, 0, EI_NIDENT-EI_PAD);
-       elf->e_type     = ET_CORE;
-       elf->e_machine  = ELF_ARCH;
-       elf->e_version  = EV_CURRENT;
-       elf->e_entry    = 0;
-       elf->e_phoff    = sizeof(struct elfhdr);
-       elf->e_shoff    = 0;
-       elf->e_flags    = ELF_CORE_EFLAGS;
-       elf->e_ehsize   = sizeof(struct elfhdr);
-       elf->e_phentsize= sizeof(struct elf_phdr);
-       elf->e_phnum    = nphdr;
-       elf->e_shentsize= 0;
-       elf->e_shnum    = 0;
-       elf->e_shstrndx = 0;
-
-       /* setup ELF PT_NOTE program header */
-       nhdr = (struct elf_phdr *) bufp;
-       bufp += sizeof(struct elf_phdr);
-       offset += sizeof(struct elf_phdr);
-       nhdr->p_type    = PT_NOTE;
-       nhdr->p_offset  = 0;
-       nhdr->p_vaddr   = 0;
-       nhdr->p_paddr   = 0;
-       nhdr->p_filesz  = 0;
-       nhdr->p_memsz   = 0;
-       nhdr->p_flags   = 0;
-       nhdr->p_align   = 0;
-
-       /* setup ELF PT_LOAD program header for every area */
-       list_for_each_entry(m, &kclist_head, list) {
-               phdr = (struct elf_phdr *) bufp;
-               bufp += sizeof(struct elf_phdr);
-               offset += sizeof(struct elf_phdr);
-
-               phdr->p_type    = PT_LOAD;
-               phdr->p_flags   = PF_R|PF_W|PF_X;
-               phdr->p_offset  = kc_vaddr_to_offset(m->addr) + dataoff;
-               phdr->p_vaddr   = (size_t)m->addr;
-               if (m->type == KCORE_RAM || m->type == KCORE_TEXT)
-                       phdr->p_paddr   = __pa(m->addr);
-               else
-                       phdr->p_paddr   = (elf_addr_t)-1;
-               phdr->p_filesz  = phdr->p_memsz = m->size;
-               phdr->p_align   = PAGE_SIZE;
+       ret = kcore_ram_list(&list);
+       if (ret) {
+               /* Couldn't get the RAM list, try again next time. */
+               WRITE_ONCE(kcore_need_update, 1);
+               list_splice_tail(&list, &garbage);
+               goto out;
        }
 
-       /*
-        * Set up the notes in similar form to SVR4 core dumps made
-        * with info from their /proc.
-        */
-       nhdr->p_offset  = offset;
-
-       /* set up the process status */
-       notes[0].name = CORE_STR;
-       notes[0].type = NT_PRSTATUS;
-       notes[0].datasz = sizeof(struct elf_prstatus);
-       notes[0].data = &prstatus;
-
-       memset(&prstatus, 0, sizeof(struct elf_prstatus));
-
-       nhdr->p_filesz  = notesize(&notes[0]);
-       bufp = storenote(&notes[0], bufp);
-
-       /* set up the process info */
-       notes[1].name   = CORE_STR;
-       notes[1].type   = NT_PRPSINFO;
-       notes[1].datasz = sizeof(struct elf_prpsinfo);
-       notes[1].data   = &prpsinfo;
-
-       memset(&prpsinfo, 0, sizeof(struct elf_prpsinfo));
-       prpsinfo.pr_state       = 0;
-       prpsinfo.pr_sname       = 'R';
-       prpsinfo.pr_zomb        = 0;
-
-       strcpy(prpsinfo.pr_fname, "vmlinux");
-       strlcpy(prpsinfo.pr_psargs, saved_command_line, sizeof(prpsinfo.pr_psargs));
-
-       nhdr->p_filesz  += notesize(&notes[1]);
-       bufp = storenote(&notes[1], bufp);
+       list_for_each_entry_safe(pos, tmp, &kclist_head, list) {
+               if (pos->type == KCORE_RAM || pos->type == KCORE_VMEMMAP)
+                       list_move(&pos->list, &garbage);
+       }
+       list_splice_tail(&list, &kclist_head);
 
-       /* set up the task structure */
-       notes[2].name   = CORE_STR;
-       notes[2].type   = NT_TASKSTRUCT;
-       notes[2].datasz = arch_task_struct_size;
-       notes[2].data   = current;
+       proc_root_kcore->size = get_kcore_size(&nphdr, &phdrs_len, &notes_len,
+                                              &data_offset);
 
-       nhdr->p_filesz  += notesize(&notes[2]);
-       bufp = storenote(&notes[2], bufp);
+out:
+       up_write(&kclist_lock);
+       list_for_each_entry_safe(pos, tmp, &garbage, list) {
+               list_del(&pos->list);
+               kfree(pos);
+       }
+       return ret;
+}
 
-} /* end elf_kcore_store_hdr() */
+static void append_kcore_note(char *notes, size_t *i, const char *name,
+                             unsigned int type, const void *desc,
+                             size_t descsz)
+{
+       struct elf_note *note = (struct elf_note *)&notes[*i];
+
+       note->n_namesz = strlen(name) + 1;
+       note->n_descsz = descsz;
+       note->n_type = type;
+       *i += sizeof(*note);
+       memcpy(&notes[*i], name, note->n_namesz);
+       *i = ALIGN(*i + note->n_namesz, 4);
+       memcpy(&notes[*i], desc, descsz);
+       *i = ALIGN(*i + descsz, 4);
+}
 
-/*****************************************************************************/
-/*
- * read from the ELF header and then kernel memory
- */
 static ssize_t
 read_kcore(struct file *file, char __user *buffer, size_t buflen, loff_t *fpos)
 {
        char *buf = file->private_data;
-       ssize_t acc = 0;
-       size_t size, tsz;
-       size_t elf_buflen;
+       size_t phdrs_offset, notes_offset, data_offset;
+       size_t phdrs_len, notes_len;
+       struct kcore_list *m;
+       size_t tsz;
        int nphdr;
        unsigned long start;
+       size_t orig_buflen = buflen;
+       int ret = 0;
 
-       read_lock(&kclist_lock);
-       size = get_kcore_size(&nphdr, &elf_buflen);
+       down_read(&kclist_lock);
+
+       get_kcore_size(&nphdr, &phdrs_len, &notes_len, &data_offset);
+       phdrs_offset = sizeof(struct elfhdr);
+       notes_offset = phdrs_offset + phdrs_len;
+
+       /* ELF file header. */
+       if (buflen && *fpos < sizeof(struct elfhdr)) {
+               struct elfhdr ehdr = {
+                       .e_ident = {
+                               [EI_MAG0] = ELFMAG0,
+                               [EI_MAG1] = ELFMAG1,
+                               [EI_MAG2] = ELFMAG2,
+                               [EI_MAG3] = ELFMAG3,
+                               [EI_CLASS] = ELF_CLASS,
+                               [EI_DATA] = ELF_DATA,
+                               [EI_VERSION] = EV_CURRENT,
+                               [EI_OSABI] = ELF_OSABI,
+                       },
+                       .e_type = ET_CORE,
+                       .e_machine = ELF_ARCH,
+                       .e_version = EV_CURRENT,
+                       .e_phoff = sizeof(struct elfhdr),
+                       .e_flags = ELF_CORE_EFLAGS,
+                       .e_ehsize = sizeof(struct elfhdr),
+                       .e_phentsize = sizeof(struct elf_phdr),
+                       .e_phnum = nphdr,
+               };
+
+               tsz = min_t(size_t, buflen, sizeof(struct elfhdr) - *fpos);
+               if (copy_to_user(buffer, (char *)&ehdr + *fpos, tsz)) {
+                       ret = -EFAULT;
+                       goto out;
+               }
 
-       if (buflen == 0 || *fpos >= size) {
-               read_unlock(&kclist_lock);
-               return 0;
+               buffer += tsz;
+               buflen -= tsz;
+               *fpos += tsz;
        }
 
-       /* trim buflen to not go beyond EOF */
-       if (buflen > size - *fpos)
-               buflen = size - *fpos;
-
-       /* construct an ELF core header if we'll need some of it */
-       if (*fpos < elf_buflen) {
-               char * elf_buf;
-
-               tsz = elf_buflen - *fpos;
-               if (buflen < tsz)
-                       tsz = buflen;
-               elf_buf = kzalloc(elf_buflen, GFP_ATOMIC);
-               if (!elf_buf) {
-                       read_unlock(&kclist_lock);
-                       return -ENOMEM;
+       /* ELF program headers. */
+       if (buflen && *fpos < phdrs_offset + phdrs_len) {
+               struct elf_phdr *phdrs, *phdr;
+
+               phdrs = kzalloc(phdrs_len, GFP_KERNEL);
+               if (!phdrs) {
+                       ret = -ENOMEM;
+                       goto out;
                }
-               elf_kcore_store_hdr(elf_buf, nphdr, elf_buflen);
-               read_unlock(&kclist_lock);
-               if (copy_to_user(buffer, elf_buf + *fpos, tsz)) {
-                       kfree(elf_buf);
-                       return -EFAULT;
+
+               phdrs[0].p_type = PT_NOTE;
+               phdrs[0].p_offset = notes_offset;
+               phdrs[0].p_filesz = notes_len;
+
+               phdr = &phdrs[1];
+               list_for_each_entry(m, &kclist_head, list) {
+                       phdr->p_type = PT_LOAD;
+                       phdr->p_flags = PF_R | PF_W | PF_X;
+                       phdr->p_offset = kc_vaddr_to_offset(m->addr) + data_offset;
+                       if (m->type == KCORE_REMAP)
+                               phdr->p_vaddr = (size_t)m->vaddr;
+                       else
+                               phdr->p_vaddr = (size_t)m->addr;
+                       if (m->type == KCORE_RAM || m->type == KCORE_REMAP)
+                               phdr->p_paddr = __pa(m->addr);
+                       else if (m->type == KCORE_TEXT)
+                               phdr->p_paddr = __pa_symbol(m->addr);
+                       else
+                               phdr->p_paddr = (elf_addr_t)-1;
+                       phdr->p_filesz = phdr->p_memsz = m->size;
+                       phdr->p_align = PAGE_SIZE;
+                       phdr++;
                }
-               kfree(elf_buf);
+
+               tsz = min_t(size_t, buflen, phdrs_offset + phdrs_len - *fpos);
+               if (copy_to_user(buffer, (char *)phdrs + *fpos - phdrs_offset,
+                                tsz)) {
+                       kfree(phdrs);
+                       ret = -EFAULT;
+                       goto out;
+               }
+               kfree(phdrs);
+
+               buffer += tsz;
                buflen -= tsz;
                *fpos += tsz;
-               buffer += tsz;
-               acc += tsz;
+       }
+
+       /* ELF note segment. */
+       if (buflen && *fpos < notes_offset + notes_len) {
+               struct elf_prstatus prstatus = {};
+               struct elf_prpsinfo prpsinfo = {
+                       .pr_sname = 'R',
+                       .pr_fname = "vmlinux",
+               };
+               char *notes;
+               size_t i = 0;
+
+               strlcpy(prpsinfo.pr_psargs, saved_command_line,
+                       sizeof(prpsinfo.pr_psargs));
+
+               notes = kzalloc(notes_len, GFP_KERNEL);
+               if (!notes) {
+                       ret = -ENOMEM;
+                       goto out;
+               }
+
+               append_kcore_note(notes, &i, CORE_STR, NT_PRSTATUS, &prstatus,
+                                 sizeof(prstatus));
+               append_kcore_note(notes, &i, CORE_STR, NT_PRPSINFO, &prpsinfo,
+                                 sizeof(prpsinfo));
+               append_kcore_note(notes, &i, CORE_STR, NT_TASKSTRUCT, current,
+                                 arch_task_struct_size);
+               /*
+                * vmcoreinfo_size is mostly constant after init time, but it
+                * can be changed by crash_save_vmcoreinfo(). Racing here with a
+                * panic on another CPU before the machine goes down is insanely
+                * unlikely, but it's better to not leave potential buffer
+                * overflows lying around, regardless.
+                */
+               append_kcore_note(notes, &i, VMCOREINFO_NOTE_NAME, 0,
+                                 vmcoreinfo_data,
+                                 min(vmcoreinfo_size, notes_len - i));
+
+               tsz = min_t(size_t, buflen, notes_offset + notes_len - *fpos);
+               if (copy_to_user(buffer, notes + *fpos - notes_offset, tsz)) {
+                       kfree(notes);
+                       ret = -EFAULT;
+                       goto out;
+               }
+               kfree(notes);
 
-               /* leave now if filled buffer already */
-               if (buflen == 0)
-                       return acc;
-       } else
-               read_unlock(&kclist_lock);
+               buffer += tsz;
+               buflen -= tsz;
+               *fpos += tsz;
+       }
 
        /*
         * Check to see if our file offset matches with any of
         * the addresses in the elf_phdr on our list.
         */
-       start = kc_offset_to_vaddr(*fpos - elf_buflen);
+       start = kc_offset_to_vaddr(*fpos - data_offset);
        if ((tsz = (PAGE_SIZE - (start & ~PAGE_MASK))) > buflen)
                tsz = buflen;
-               
-       while (buflen) {
-               struct kcore_list *m;
 
-               read_lock(&kclist_lock);
-               list_for_each_entry(m, &kclist_head, list) {
-                       if (start >= m->addr && start < (m->addr+m->size))
-                               break;
+       m = NULL;
+       while (buflen) {
+               /*
+                * If this is the first iteration or the address is not within
+                * the previous entry, search for a matching entry.
+                */
+               if (!m || start < m->addr || start >= m->addr + m->size) {
+                       list_for_each_entry(m, &kclist_head, list) {
+                               if (start >= m->addr &&
+                                   start < m->addr + m->size)
+                                       break;
+                       }
                }
-               read_unlock(&kclist_lock);
 
                if (&m->list == &kclist_head) {
-                       if (clear_user(buffer, tsz))
-                               return -EFAULT;
+                       if (clear_user(buffer, tsz)) {
+                               ret = -EFAULT;
+                               goto out;
+                       }
                } else if (m->type == KCORE_VMALLOC) {
                        vread(buf, (char *)start, tsz);
                        /* we have to zero-fill user buffer even if no read */
-                       if (copy_to_user(buffer, buf, tsz))
-                               return -EFAULT;
+                       if (copy_to_user(buffer, buf, tsz)) {
+                               ret = -EFAULT;
+                               goto out;
+                       }
                } else if (m->type == KCORE_USER) {
                        /* User page is handled prior to normal kernel page: */
-                       if (copy_to_user(buffer, (char *)start, tsz))
-                               return -EFAULT;
+                       if (copy_to_user(buffer, (char *)start, tsz)) {
+                               ret = -EFAULT;
+                               goto out;
+                       }
                } else {
                        if (kern_addr_valid(start)) {
                                /*
@@ -530,29 +484,37 @@ read_kcore(struct file *file, char __user *buffer, size_t buflen, loff_t *fpos)
                                 * hardened user copy kernel text checks.
                                 */
                                if (probe_kernel_read(buf, (void *) start, tsz)) {
-                                       if (clear_user(buffer, tsz))
-                                               return -EFAULT;
+                                       if (clear_user(buffer, tsz)) {
+                                               ret = -EFAULT;
+                                               goto out;
+                                       }
                                } else {
-                                       if (copy_to_user(buffer, buf, tsz))
-                                               return -EFAULT;
+                                       if (copy_to_user(buffer, buf, tsz)) {
+                                               ret = -EFAULT;
+                                               goto out;
+                                       }
                                }
                        } else {
-                               if (clear_user(buffer, tsz))
-                                       return -EFAULT;
+                               if (clear_user(buffer, tsz)) {
+                                       ret = -EFAULT;
+                                       goto out;
+                               }
                        }
                }
                buflen -= tsz;
                *fpos += tsz;
                buffer += tsz;
-               acc += tsz;
                start += tsz;
                tsz = (buflen > PAGE_SIZE ? PAGE_SIZE : buflen);
        }
 
-       return acc;
+out:
+       up_read(&kclist_lock);
+       if (ret)
+               return ret;
+       return orig_buflen - buflen;
 }
 
-
 static int open_kcore(struct inode *inode, struct file *filp)
 {
        if (!capable(CAP_SYS_RAWIO))
@@ -592,9 +554,8 @@ static int __meminit kcore_callback(struct notifier_block *self,
        switch (action) {
        case MEM_ONLINE:
        case MEM_OFFLINE:
-               write_lock(&kclist_lock);
                kcore_need_update = 1;
-               write_unlock(&kclist_lock);
+               break;
        }
        return NOTIFY_OK;
 }
index 2fb0484..edda898 100644 (file)
@@ -7,6 +7,7 @@
 #include <linux/mman.h>
 #include <linux/mmzone.h>
 #include <linux/proc_fs.h>
+#include <linux/percpu.h>
 #include <linux/quicklist.h>
 #include <linux/seq_file.h>
 #include <linux/swap.h>
@@ -121,6 +122,7 @@ static int meminfo_proc_show(struct seq_file *m, void *v)
                   (unsigned long)VMALLOC_TOTAL >> 10);
        show_val_kb(m, "VmallocUsed:    ", 0ul);
        show_val_kb(m, "VmallocChunk:   ", 0ul);
+       show_val_kb(m, "Percpu:         ", pcpu_nr_pages());
 
 #ifdef CONFIG_MEMORY_FAILURE
        seq_printf(m, "HardwareCorrupted: %5lu kB\n",
index 59749df..535eda7 100644 (file)
@@ -183,7 +183,7 @@ static int show_stat(struct seq_file *p, void *v)
 
 static int stat_open(struct inode *inode, struct file *file)
 {
-       size_t size = 1024 + 128 * num_online_cpus();
+       unsigned int size = 1024 + 128 * num_online_cpus();
 
        /* minimum size to display an interrupt count : 2 bytes */
        size += 2 * nr_irqs;
index dfd73a4..5ea1d64 100644 (file)
@@ -247,7 +247,6 @@ static int proc_map_release(struct inode *inode, struct file *file)
        if (priv->mm)
                mmdrop(priv->mm);
 
-       kfree(priv->rollup);
        return seq_release_private(inode, file);
 }
 
@@ -294,7 +293,7 @@ static void show_vma_header_prefix(struct seq_file *m,
 }
 
 static void
-show_map_vma(struct seq_file *m, struct vm_area_struct *vma, int is_pid)
+show_map_vma(struct seq_file *m, struct vm_area_struct *vma)
 {
        struct mm_struct *mm = vma->vm_mm;
        struct file *file = vma->vm_file;
@@ -357,35 +356,18 @@ done:
        seq_putc(m, '\n');
 }
 
-static int show_map(struct seq_file *m, void *v, int is_pid)
+static int show_map(struct seq_file *m, void *v)
 {
-       show_map_vma(m, v, is_pid);
+       show_map_vma(m, v);
        m_cache_vma(m, v);
        return 0;
 }
 
-static int show_pid_map(struct seq_file *m, void *v)
-{
-       return show_map(m, v, 1);
-}
-
-static int show_tid_map(struct seq_file *m, void *v)
-{
-       return show_map(m, v, 0);
-}
-
 static const struct seq_operations proc_pid_maps_op = {
        .start  = m_start,
        .next   = m_next,
        .stop   = m_stop,
-       .show   = show_pid_map
-};
-
-static const struct seq_operations proc_tid_maps_op = {
-       .start  = m_start,
-       .next   = m_next,
-       .stop   = m_stop,
-       .show   = show_tid_map
+       .show   = show_map
 };
 
 static int pid_maps_open(struct inode *inode, struct file *file)
@@ -393,11 +375,6 @@ static int pid_maps_open(struct inode *inode, struct file *file)
        return do_maps_open(inode, file, &proc_pid_maps_op);
 }
 
-static int tid_maps_open(struct inode *inode, struct file *file)
-{
-       return do_maps_open(inode, file, &proc_tid_maps_op);
-}
-
 const struct file_operations proc_pid_maps_operations = {
        .open           = pid_maps_open,
        .read           = seq_read,
@@ -405,13 +382,6 @@ const struct file_operations proc_pid_maps_operations = {
        .release        = proc_map_release,
 };
 
-const struct file_operations proc_tid_maps_operations = {
-       .open           = tid_maps_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = proc_map_release,
-};
-
 /*
  * Proportional Set Size(PSS): my share of RSS.
  *
@@ -433,7 +403,6 @@ const struct file_operations proc_tid_maps_operations = {
 
 #ifdef CONFIG_PROC_PAGE_MONITOR
 struct mem_size_stats {
-       bool first;
        unsigned long resident;
        unsigned long shared_clean;
        unsigned long shared_dirty;
@@ -447,7 +416,6 @@ struct mem_size_stats {
        unsigned long swap;
        unsigned long shared_hugetlb;
        unsigned long private_hugetlb;
-       unsigned long first_vma_start;
        u64 pss;
        u64 pss_locked;
        u64 swap_pss;
@@ -731,14 +699,9 @@ static int smaps_hugetlb_range(pte_t *pte, unsigned long hmask,
 }
 #endif /* HUGETLB_PAGE */
 
-#define SEQ_PUT_DEC(str, val) \
-               seq_put_decimal_ull_width(m, str, (val) >> 10, 8)
-static int show_smap(struct seq_file *m, void *v, int is_pid)
+static void smap_gather_stats(struct vm_area_struct *vma,
+                            struct mem_size_stats *mss)
 {
-       struct proc_maps_private *priv = m->private;
-       struct vm_area_struct *vma = v;
-       struct mem_size_stats mss_stack;
-       struct mem_size_stats *mss;
        struct mm_walk smaps_walk = {
                .pmd_entry = smaps_pte_range,
 #ifdef CONFIG_HUGETLB_PAGE
@@ -746,23 +709,6 @@ static int show_smap(struct seq_file *m, void *v, int is_pid)
 #endif
                .mm = vma->vm_mm,
        };
-       int ret = 0;
-       bool rollup_mode;
-       bool last_vma;
-
-       if (priv->rollup) {
-               rollup_mode = true;
-               mss = priv->rollup;
-               if (mss->first) {
-                       mss->first_vma_start = vma->vm_start;
-                       mss->first = false;
-               }
-               last_vma = !m_next_vma(priv, vma);
-       } else {
-               rollup_mode = false;
-               memset(&mss_stack, 0, sizeof(mss_stack));
-               mss = &mss_stack;
-       }
 
        smaps_walk.private = mss;
 
@@ -794,79 +740,116 @@ static int show_smap(struct seq_file *m, void *v, int is_pid)
        walk_page_vma(vma, &smaps_walk);
        if (vma->vm_flags & VM_LOCKED)
                mss->pss_locked += mss->pss;
+}
 
-       if (!rollup_mode) {
-               show_map_vma(m, vma, is_pid);
-       } else if (last_vma) {
-               show_vma_header_prefix(
-                       m, mss->first_vma_start, vma->vm_end, 0, 0, 0, 0);
-               seq_pad(m, ' ');
-               seq_puts(m, "[rollup]\n");
-       } else {
-               ret = SEQ_SKIP;
-       }
-
-       if (!rollup_mode) {
-               SEQ_PUT_DEC("Size:           ", vma->vm_end - vma->vm_start);
-               SEQ_PUT_DEC(" kB\nKernelPageSize: ", vma_kernel_pagesize(vma));
-               SEQ_PUT_DEC(" kB\nMMUPageSize:    ", vma_mmu_pagesize(vma));
-               seq_puts(m, " kB\n");
-       }
+#define SEQ_PUT_DEC(str, val) \
+               seq_put_decimal_ull_width(m, str, (val) >> 10, 8)
 
-       if (!rollup_mode || last_vma) {
-               SEQ_PUT_DEC("Rss:            ", mss->resident);
-               SEQ_PUT_DEC(" kB\nPss:            ", mss->pss >> PSS_SHIFT);
-               SEQ_PUT_DEC(" kB\nShared_Clean:   ", mss->shared_clean);
-               SEQ_PUT_DEC(" kB\nShared_Dirty:   ", mss->shared_dirty);
-               SEQ_PUT_DEC(" kB\nPrivate_Clean:  ", mss->private_clean);
-               SEQ_PUT_DEC(" kB\nPrivate_Dirty:  ", mss->private_dirty);
-               SEQ_PUT_DEC(" kB\nReferenced:     ", mss->referenced);
-               SEQ_PUT_DEC(" kB\nAnonymous:      ", mss->anonymous);
-               SEQ_PUT_DEC(" kB\nLazyFree:       ", mss->lazyfree);
-               SEQ_PUT_DEC(" kB\nAnonHugePages:  ", mss->anonymous_thp);
-               SEQ_PUT_DEC(" kB\nShmemPmdMapped: ", mss->shmem_thp);
-               SEQ_PUT_DEC(" kB\nShared_Hugetlb: ", mss->shared_hugetlb);
-               seq_put_decimal_ull_width(m, " kB\nPrivate_Hugetlb: ",
-                                         mss->private_hugetlb >> 10, 7);
-               SEQ_PUT_DEC(" kB\nSwap:           ", mss->swap);
-               SEQ_PUT_DEC(" kB\nSwapPss:        ",
-                                               mss->swap_pss >> PSS_SHIFT);
-               SEQ_PUT_DEC(" kB\nLocked:         ",
-                                               mss->pss_locked >> PSS_SHIFT);
-               seq_puts(m, " kB\n");
-       }
-       if (!rollup_mode) {
-               if (arch_pkeys_enabled())
-                       seq_printf(m, "ProtectionKey:  %8u\n", vma_pkey(vma));
-               show_smap_vma_flags(m, vma);
-       }
-       m_cache_vma(m, vma);
-       return ret;
+/* Show the contents common for smaps and smaps_rollup */
+static void __show_smap(struct seq_file *m, const struct mem_size_stats *mss)
+{
+       SEQ_PUT_DEC("Rss:            ", mss->resident);
+       SEQ_PUT_DEC(" kB\nPss:            ", mss->pss >> PSS_SHIFT);
+       SEQ_PUT_DEC(" kB\nShared_Clean:   ", mss->shared_clean);
+       SEQ_PUT_DEC(" kB\nShared_Dirty:   ", mss->shared_dirty);
+       SEQ_PUT_DEC(" kB\nPrivate_Clean:  ", mss->private_clean);
+       SEQ_PUT_DEC(" kB\nPrivate_Dirty:  ", mss->private_dirty);
+       SEQ_PUT_DEC(" kB\nReferenced:     ", mss->referenced);
+       SEQ_PUT_DEC(" kB\nAnonymous:      ", mss->anonymous);
+       SEQ_PUT_DEC(" kB\nLazyFree:       ", mss->lazyfree);
+       SEQ_PUT_DEC(" kB\nAnonHugePages:  ", mss->anonymous_thp);
+       SEQ_PUT_DEC(" kB\nShmemPmdMapped: ", mss->shmem_thp);
+       SEQ_PUT_DEC(" kB\nShared_Hugetlb: ", mss->shared_hugetlb);
+       seq_put_decimal_ull_width(m, " kB\nPrivate_Hugetlb: ",
+                                 mss->private_hugetlb >> 10, 7);
+       SEQ_PUT_DEC(" kB\nSwap:           ", mss->swap);
+       SEQ_PUT_DEC(" kB\nSwapPss:        ",
+                                       mss->swap_pss >> PSS_SHIFT);
+       SEQ_PUT_DEC(" kB\nLocked:         ",
+                                       mss->pss_locked >> PSS_SHIFT);
+       seq_puts(m, " kB\n");
 }
-#undef SEQ_PUT_DEC
 
-static int show_pid_smap(struct seq_file *m, void *v)
+static int show_smap(struct seq_file *m, void *v)
 {
-       return show_smap(m, v, 1);
+       struct vm_area_struct *vma = v;
+       struct mem_size_stats mss;
+
+       memset(&mss, 0, sizeof(mss));
+
+       smap_gather_stats(vma, &mss);
+
+       show_map_vma(m, vma);
+
+       SEQ_PUT_DEC("Size:           ", vma->vm_end - vma->vm_start);
+       SEQ_PUT_DEC(" kB\nKernelPageSize: ", vma_kernel_pagesize(vma));
+       SEQ_PUT_DEC(" kB\nMMUPageSize:    ", vma_mmu_pagesize(vma));
+       seq_puts(m, " kB\n");
+
+       __show_smap(m, &mss);
+
+       if (arch_pkeys_enabled())
+               seq_printf(m, "ProtectionKey:  %8u\n", vma_pkey(vma));
+       show_smap_vma_flags(m, vma);
+
+       m_cache_vma(m, vma);
+
+       return 0;
 }
 
-static int show_tid_smap(struct seq_file *m, void *v)
+static int show_smaps_rollup(struct seq_file *m, void *v)
 {
-       return show_smap(m, v, 0);
+       struct proc_maps_private *priv = m->private;
+       struct mem_size_stats mss;
+       struct mm_struct *mm;
+       struct vm_area_struct *vma;
+       unsigned long last_vma_end = 0;
+       int ret = 0;
+
+       priv->task = get_proc_task(priv->inode);
+       if (!priv->task)
+               return -ESRCH;
+
+       mm = priv->mm;
+       if (!mm || !mmget_not_zero(mm)) {
+               ret = -ESRCH;
+               goto out_put_task;
+       }
+
+       memset(&mss, 0, sizeof(mss));
+
+       down_read(&mm->mmap_sem);
+       hold_task_mempolicy(priv);
+
+       for (vma = priv->mm->mmap; vma; vma = vma->vm_next) {
+               smap_gather_stats(vma, &mss);
+               last_vma_end = vma->vm_end;
+       }
+
+       show_vma_header_prefix(m, priv->mm->mmap->vm_start,
+                              last_vma_end, 0, 0, 0, 0);
+       seq_pad(m, ' ');
+       seq_puts(m, "[rollup]\n");
+
+       __show_smap(m, &mss);
+
+       release_task_mempolicy(priv);
+       up_read(&mm->mmap_sem);
+       mmput(mm);
+
+out_put_task:
+       put_task_struct(priv->task);
+       priv->task = NULL;
+
+       return ret;
 }
+#undef SEQ_PUT_DEC
 
 static const struct seq_operations proc_pid_smaps_op = {
        .start  = m_start,
        .next   = m_next,
        .stop   = m_stop,
-       .show   = show_pid_smap
-};
-
-static const struct seq_operations proc_tid_smaps_op = {
-       .start  = m_start,
-       .next   = m_next,
-       .stop   = m_stop,
-       .show   = show_tid_smap
+       .show   = show_smap
 };
 
 static int pid_smaps_open(struct inode *inode, struct file *file)
@@ -874,28 +857,45 @@ static int pid_smaps_open(struct inode *inode, struct file *file)
        return do_maps_open(inode, file, &proc_pid_smaps_op);
 }
 
-static int pid_smaps_rollup_open(struct inode *inode, struct file *file)
+static int smaps_rollup_open(struct inode *inode, struct file *file)
 {
-       struct seq_file *seq;
+       int ret;
        struct proc_maps_private *priv;
-       int ret = do_maps_open(inode, file, &proc_pid_smaps_op);
-
-       if (ret < 0)
-               return ret;
-       seq = file->private_data;
-       priv = seq->private;
-       priv->rollup = kzalloc(sizeof(*priv->rollup), GFP_KERNEL);
-       if (!priv->rollup) {
-               proc_map_release(inode, file);
+
+       priv = kzalloc(sizeof(*priv), GFP_KERNEL_ACCOUNT);
+       if (!priv)
                return -ENOMEM;
+
+       ret = single_open(file, show_smaps_rollup, priv);
+       if (ret)
+               goto out_free;
+
+       priv->inode = inode;
+       priv->mm = proc_mem_open(inode, PTRACE_MODE_READ);
+       if (IS_ERR(priv->mm)) {
+               ret = PTR_ERR(priv->mm);
+
+               single_release(inode, file);
+               goto out_free;
        }
-       priv->rollup->first = true;
+
        return 0;
+
+out_free:
+       kfree(priv);
+       return ret;
 }
 
-static int tid_smaps_open(struct inode *inode, struct file *file)
+static int smaps_rollup_release(struct inode *inode, struct file *file)
 {
-       return do_maps_open(inode, file, &proc_tid_smaps_op);
+       struct seq_file *seq = file->private_data;
+       struct proc_maps_private *priv = seq->private;
+
+       if (priv->mm)
+               mmdrop(priv->mm);
+
+       kfree(priv);
+       return single_release(inode, file);
 }
 
 const struct file_operations proc_pid_smaps_operations = {
@@ -906,17 +906,10 @@ const struct file_operations proc_pid_smaps_operations = {
 };
 
 const struct file_operations proc_pid_smaps_rollup_operations = {
-       .open           = pid_smaps_rollup_open,
+       .open           = smaps_rollup_open,
        .read           = seq_read,
        .llseek         = seq_lseek,
-       .release        = proc_map_release,
-};
-
-const struct file_operations proc_tid_smaps_operations = {
-       .open           = tid_smaps_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = proc_map_release,
+       .release        = smaps_rollup_release,
 };
 
 enum clear_refs_types {
@@ -1728,7 +1721,7 @@ static int gather_hugetlb_stats(pte_t *pte, unsigned long hmask,
 /*
  * Display pages allocated per node and memory policy via /proc.
  */
-static int show_numa_map(struct seq_file *m, void *v, int is_pid)
+static int show_numa_map(struct seq_file *m, void *v)
 {
        struct numa_maps_private *numa_priv = m->private;
        struct proc_maps_private *proc_priv = &numa_priv->proc_maps;
@@ -1812,45 +1805,17 @@ out:
        return 0;
 }
 
-static int show_pid_numa_map(struct seq_file *m, void *v)
-{
-       return show_numa_map(m, v, 1);
-}
-
-static int show_tid_numa_map(struct seq_file *m, void *v)
-{
-       return show_numa_map(m, v, 0);
-}
-
 static const struct seq_operations proc_pid_numa_maps_op = {
        .start  = m_start,
        .next   = m_next,
        .stop   = m_stop,
-       .show   = show_pid_numa_map,
+       .show   = show_numa_map,
 };
 
-static const struct seq_operations proc_tid_numa_maps_op = {
-       .start  = m_start,
-       .next   = m_next,
-       .stop   = m_stop,
-       .show   = show_tid_numa_map,
-};
-
-static int numa_maps_open(struct inode *inode, struct file *file,
-                         const struct seq_operations *ops)
-{
-       return proc_maps_open(inode, file, ops,
-                               sizeof(struct numa_maps_private));
-}
-
 static int pid_numa_maps_open(struct inode *inode, struct file *file)
 {
-       return numa_maps_open(inode, file, &proc_pid_numa_maps_op);
-}
-
-static int tid_numa_maps_open(struct inode *inode, struct file *file)
-{
-       return numa_maps_open(inode, file, &proc_tid_numa_maps_op);
+       return proc_maps_open(inode, file, &proc_pid_numa_maps_op,
+                               sizeof(struct numa_maps_private));
 }
 
 const struct file_operations proc_pid_numa_maps_operations = {
@@ -1860,10 +1825,4 @@ const struct file_operations proc_pid_numa_maps_operations = {
        .release        = proc_map_release,
 };
 
-const struct file_operations proc_tid_numa_maps_operations = {
-       .open           = tid_numa_maps_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = proc_map_release,
-};
 #endif /* CONFIG_NUMA */
index 5b62f57..0b63d68 100644 (file)
@@ -142,8 +142,7 @@ static int is_stack(struct vm_area_struct *vma)
 /*
  * display a single VMA to a sequenced file
  */
-static int nommu_vma_show(struct seq_file *m, struct vm_area_struct *vma,
-                         int is_pid)
+static int nommu_vma_show(struct seq_file *m, struct vm_area_struct *vma)
 {
        struct mm_struct *mm = vma->vm_mm;
        unsigned long ino = 0;
@@ -189,22 +188,11 @@ static int nommu_vma_show(struct seq_file *m, struct vm_area_struct *vma,
 /*
  * display mapping lines for a particular process's /proc/pid/maps
  */
-static int show_map(struct seq_file *m, void *_p, int is_pid)
+static int show_map(struct seq_file *m, void *_p)
 {
        struct rb_node *p = _p;
 
-       return nommu_vma_show(m, rb_entry(p, struct vm_area_struct, vm_rb),
-                             is_pid);
-}
-
-static int show_pid_map(struct seq_file *m, void *_p)
-{
-       return show_map(m, _p, 1);
-}
-
-static int show_tid_map(struct seq_file *m, void *_p)
-{
-       return show_map(m, _p, 0);
+       return nommu_vma_show(m, rb_entry(p, struct vm_area_struct, vm_rb));
 }
 
 static void *m_start(struct seq_file *m, loff_t *pos)
@@ -260,14 +248,7 @@ static const struct seq_operations proc_pid_maps_ops = {
        .start  = m_start,
        .next   = m_next,
        .stop   = m_stop,
-       .show   = show_pid_map
-};
-
-static const struct seq_operations proc_tid_maps_ops = {
-       .start  = m_start,
-       .next   = m_next,
-       .stop   = m_stop,
-       .show   = show_tid_map
+       .show   = show_map
 };
 
 static int maps_open(struct inode *inode, struct file *file,
@@ -308,11 +289,6 @@ static int pid_maps_open(struct inode *inode, struct file *file)
        return maps_open(inode, file, &proc_pid_maps_ops);
 }
 
-static int tid_maps_open(struct inode *inode, struct file *file)
-{
-       return maps_open(inode, file, &proc_tid_maps_ops);
-}
-
 const struct file_operations proc_pid_maps_operations = {
        .open           = pid_maps_open,
        .read           = seq_read,
@@ -320,10 +296,3 @@ const struct file_operations proc_pid_maps_operations = {
        .release        = map_release,
 };
 
-const struct file_operations proc_tid_maps_operations = {
-       .open           = tid_maps_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = map_release,
-};
-
index 3f723cb..a4c2791 100644 (file)
@@ -9,7 +9,7 @@
 
 static int uptime_proc_show(struct seq_file *m, void *v)
 {
-       struct timespec uptime;
+       struct timespec64 uptime;
        struct timespec64 idle;
        u64 nsec;
        u32 rem;
@@ -19,7 +19,7 @@ static int uptime_proc_show(struct seq_file *m, void *v)
        for_each_possible_cpu(i)
                nsec += (__force u64) kcpustat_cpu(i).cpustat[CPUTIME_IDLE];
 
-       get_monotonic_boottime(&uptime);
+       ktime_get_boottime_ts64(&uptime);
        idle.tv_sec = div_u64_rem(nsec, NSEC_PER_SEC, &rem);
        idle.tv_nsec = rem;
        seq_printf(m, "%lu.%02lu %lu.%02lu\n",
index cfb6674..cbde728 100644 (file)
@@ -225,6 +225,7 @@ out_unlock:
        return ret;
 }
 
+#ifdef CONFIG_MMU
 static int vmcoredd_mmap_dumps(struct vm_area_struct *vma, unsigned long dst,
                               u64 start, size_t size)
 {
@@ -259,6 +260,7 @@ out_unlock:
        mutex_unlock(&vmcoredd_mutex);
        return ret;
 }
+#endif /* CONFIG_MMU */
 #endif /* CONFIG_PROC_VMCORE_DEVICE_DUMP */
 
 /* Read from the ELF header and then the crash dump. On error, negative value is
@@ -379,7 +381,7 @@ static ssize_t read_vmcore(struct file *file, char __user *buffer,
  * On s390 the fault handler is used for memory regions that can't be mapped
  * directly with remap_pfn_range().
  */
-static int mmap_vmcore_fault(struct vm_fault *vmf)
+static vm_fault_t mmap_vmcore_fault(struct vm_fault *vmf)
 {
 #ifdef CONFIG_S390
        struct address_space *mapping = vmf->vma->vm_file->f_mapping;
index 153f8f6..39b4a21 100644 (file)
@@ -1964,6 +1964,44 @@ out_error:
 }
 EXPORT_SYMBOL(vfs_dedupe_file_range_compare);
 
+int vfs_dedupe_file_range_one(struct file *src_file, loff_t src_pos,
+                             struct file *dst_file, loff_t dst_pos, u64 len)
+{
+       s64 ret;
+
+       ret = mnt_want_write_file(dst_file);
+       if (ret)
+               return ret;
+
+       ret = clone_verify_area(dst_file, dst_pos, len, true);
+       if (ret < 0)
+               goto out_drop_write;
+
+       ret = -EINVAL;
+       if (!(capable(CAP_SYS_ADMIN) || (dst_file->f_mode & FMODE_WRITE)))
+               goto out_drop_write;
+
+       ret = -EXDEV;
+       if (src_file->f_path.mnt != dst_file->f_path.mnt)
+               goto out_drop_write;
+
+       ret = -EISDIR;
+       if (S_ISDIR(file_inode(dst_file)->i_mode))
+               goto out_drop_write;
+
+       ret = -EINVAL;
+       if (!dst_file->f_op->dedupe_file_range)
+               goto out_drop_write;
+
+       ret = dst_file->f_op->dedupe_file_range(src_file, src_pos,
+                                               dst_file, dst_pos, len);
+out_drop_write:
+       mnt_drop_write_file(dst_file);
+
+       return ret;
+}
+EXPORT_SYMBOL(vfs_dedupe_file_range_one);
+
 int vfs_dedupe_file_range(struct file *file, struct file_dedupe_range *same)
 {
        struct file_dedupe_range_info *info;
@@ -1972,11 +2010,8 @@ int vfs_dedupe_file_range(struct file *file, struct file_dedupe_range *same)
        u64 len;
        int i;
        int ret;
-       bool is_admin = capable(CAP_SYS_ADMIN);
        u16 count = same->dest_count;
-       struct file *dst_file;
-       loff_t dst_off;
-       ssize_t deduped;
+       int deduped;
 
        if (!(file->f_mode & FMODE_READ))
                return -EINVAL;
@@ -2003,6 +2038,9 @@ int vfs_dedupe_file_range(struct file *file, struct file_dedupe_range *same)
        if (off + len > i_size_read(src))
                return -EINVAL;
 
+       /* Arbitrary 1G limit on a single dedupe request, can be raised. */
+       len = min_t(u64, len, 1 << 30);
+
        /* pre-format output fields to sane values */
        for (i = 0; i < count; i++) {
                same->info[i].bytes_deduped = 0ULL;
@@ -2010,54 +2048,28 @@ int vfs_dedupe_file_range(struct file *file, struct file_dedupe_range *same)
        }
 
        for (i = 0, info = same->info; i < count; i++, info++) {
-               struct inode *dst;
                struct fd dst_fd = fdget(info->dest_fd);
+               struct file *dst_file = dst_fd.file;
 
-               dst_file = dst_fd.file;
                if (!dst_file) {
                        info->status = -EBADF;
                        goto next_loop;
                }
-               dst = file_inode(dst_file);
-
-               ret = mnt_want_write_file(dst_file);
-               if (ret) {
-                       info->status = ret;
-                       goto next_fdput;
-               }
-
-               dst_off = info->dest_offset;
-               ret = clone_verify_area(dst_file, dst_off, len, true);
-               if (ret < 0) {
-                       info->status = ret;
-                       goto next_file;
-               }
-               ret = 0;
 
                if (info->reserved) {
                        info->status = -EINVAL;
-               } else if (!(is_admin || (dst_file->f_mode & FMODE_WRITE))) {
-                       info->status = -EINVAL;
-               } else if (file->f_path.mnt != dst_file->f_path.mnt) {
-                       info->status = -EXDEV;
-               } else if (S_ISDIR(dst->i_mode)) {
-                       info->status = -EISDIR;
-               } else if (dst_file->f_op->dedupe_file_range == NULL) {
-                       info->status = -EINVAL;
-               } else {
-                       deduped = dst_file->f_op->dedupe_file_range(file, off,
-                                                       len, dst_file,
-                                                       info->dest_offset);
-                       if (deduped == -EBADE)
-                               info->status = FILE_DEDUPE_RANGE_DIFFERS;
-                       else if (deduped < 0)
-                               info->status = deduped;
-                       else
-                               info->bytes_deduped += deduped;
+                       goto next_fdput;
                }
 
-next_file:
-               mnt_drop_write_file(dst_file);
+               deduped = vfs_dedupe_file_range_one(file, off, dst_file,
+                                                   info->dest_offset, len);
+               if (deduped == -EBADE)
+                       info->status = FILE_DEDUPE_RANGE_DIFFERS;
+               else if (deduped < 0)
+                       info->status = deduped;
+               else
+                       info->bytes_deduped = len;
+
 next_fdput:
                fdput(dst_fd);
 next_loop:
index e3c558d..3a5a752 100644 (file)
@@ -33,30 +33,22 @@ static int sd_is_left_mergeable(struct reiserfs_key *key, unsigned long bsize)
        return 0;
 }
 
-static char *print_time(time_t t)
-{
-       static char timebuf[256];
-
-       sprintf(timebuf, "%ld", t);
-       return timebuf;
-}
-
 static void sd_print_item(struct item_head *ih, char *item)
 {
        printk("\tmode | size | nlinks | first direct | mtime\n");
        if (stat_data_v1(ih)) {
                struct stat_data_v1 *sd = (struct stat_data_v1 *)item;
 
-               printk("\t0%-6o | %6u | %2u | %d | %s\n", sd_v1_mode(sd),
+               printk("\t0%-6o | %6u | %2u | %d | %u\n", sd_v1_mode(sd),
                       sd_v1_size(sd), sd_v1_nlink(sd),
                       sd_v1_first_direct_byte(sd),
-                      print_time(sd_v1_mtime(sd)));
+                      sd_v1_mtime(sd));
        } else {
                struct stat_data *sd = (struct stat_data *)item;
 
-               printk("\t0%-6o | %6llu | %2u | %d | %s\n", sd_v2_mode(sd),
+               printk("\t0%-6o | %6llu | %2u | %d | %u\n", sd_v2_mode(sd),
                       (unsigned long long)sd_v2_size(sd), sd_v2_nlink(sd),
-                      sd_v2_rdev(sd), print_time(sd_v2_mtime(sd)));
+                      sd_v2_rdev(sd), sd_v2_mtime(sd));
        }
 }
 
index 52eb5d2..8a76f9d 100644 (file)
@@ -2381,7 +2381,7 @@ static int journal_read(struct super_block *sb)
        struct reiserfs_journal_desc *desc;
        unsigned int oldest_trans_id = 0;
        unsigned int oldest_invalid_trans_id = 0;
-       time_t start;
+       time64_t start;
        unsigned long oldest_start = 0;
        unsigned long cur_dblock = 0;
        unsigned long newest_mount_id = 9;
@@ -2395,7 +2395,7 @@ static int journal_read(struct super_block *sb)
        cur_dblock = SB_ONDISK_JOURNAL_1st_BLOCK(sb);
        reiserfs_info(sb, "checking transaction log (%pg)\n",
                      journal->j_dev_bd);
-       start = get_seconds();
+       start = ktime_get_seconds();
 
        /*
         * step 1, read in the journal header block.  Check the transaction
@@ -2556,7 +2556,7 @@ start_log_replay:
        if (replay_count > 0) {
                reiserfs_info(sb,
                              "replayed %d transactions in %lu seconds\n",
-                             replay_count, get_seconds() - start);
+                             replay_count, ktime_get_seconds() - start);
        }
        /* needed to satisfy the locking in _update_journal_header_block */
        reiserfs_write_lock(sb);
@@ -2914,7 +2914,7 @@ int journal_transaction_should_end(struct reiserfs_transaction_handle *th,
                                   int new_alloc)
 {
        struct reiserfs_journal *journal = SB_JOURNAL(th->t_super);
-       time_t now = get_seconds();
+       time64_t now = ktime_get_seconds();
        /* cannot restart while nested */
        BUG_ON(!th->t_trans_id);
        if (th->t_refcount > 1)
@@ -3023,7 +3023,7 @@ static int do_journal_begin_r(struct reiserfs_transaction_handle *th,
                              struct super_block *sb, unsigned long nblocks,
                              int join)
 {
-       time_t now = get_seconds();
+       time64_t now = ktime_get_seconds();
        unsigned int old_trans_id;
        struct reiserfs_journal *journal = SB_JOURNAL(sb);
        struct reiserfs_transaction_handle myth;
@@ -3056,7 +3056,7 @@ relock:
                PROC_INFO_INC(sb, journal.journal_relock_writers);
                goto relock;
        }
-       now = get_seconds();
+       now = ktime_get_seconds();
 
        /*
         * if there is no room in the journal OR
@@ -3119,7 +3119,7 @@ relock:
        }
        /* we are the first writer, set trans_id */
        if (journal->j_trans_start_time == 0) {
-               journal->j_trans_start_time = get_seconds();
+               journal->j_trans_start_time = ktime_get_seconds();
        }
        atomic_inc(&journal->j_wcount);
        journal->j_len_alloc += nblocks;
@@ -3559,11 +3559,11 @@ static void flush_async_commits(struct work_struct *work)
  */
 void reiserfs_flush_old_commits(struct super_block *sb)
 {
-       time_t now;
+       time64_t now;
        struct reiserfs_transaction_handle th;
        struct reiserfs_journal *journal = SB_JOURNAL(sb);
 
-       now = get_seconds();
+       now = ktime_get_seconds();
        /*
         * safety check so we don't flush while we are replaying the log during
         * mount
@@ -3613,7 +3613,7 @@ void reiserfs_flush_old_commits(struct super_block *sb)
 static int check_journal_end(struct reiserfs_transaction_handle *th, int flags)
 {
 
-       time_t now;
+       time64_t now;
        int flush = flags & FLUSH_ALL;
        int commit_now = flags & COMMIT_NOW;
        int wait_on_commit = flags & WAIT;
@@ -3694,7 +3694,7 @@ static int check_journal_end(struct reiserfs_transaction_handle *th, int flags)
        }
 
        /* deal with old transactions where we are the last writers */
-       now = get_seconds();
+       now = ktime_get_seconds();
        if ((now - journal->j_trans_start_time) > journal->j_max_trans_age) {
                commit_now = 1;
                journal->j_next_async_flush = 1;
index e39b391..f2cf344 100644 (file)
@@ -297,6 +297,13 @@ static int show_oidmap(struct seq_file *m, void *unused)
        return 0;
 }
 
+static time64_t ktime_mono_to_real_seconds(time64_t mono)
+{
+       ktime_t kt = ktime_set(mono, NSEC_PER_SEC/2);
+
+       return ktime_divns(ktime_mono_to_real(kt), NSEC_PER_SEC);
+}
+
 static int show_journal(struct seq_file *m, void *unused)
 {
        struct super_block *sb = m->private;
@@ -325,7 +332,7 @@ static int show_journal(struct seq_file *m, void *unused)
                   "j_bcount: \t%lu\n"
                   "j_first_unflushed_offset: \t%lu\n"
                   "j_last_flush_trans_id: \t%u\n"
-                  "j_trans_start_time: \t%li\n"
+                  "j_trans_start_time: \t%lli\n"
                   "j_list_bitmap_index: \t%i\n"
                   "j_must_wait: \t%i\n"
                   "j_next_full_flush: \t%i\n"
@@ -366,7 +373,7 @@ static int show_journal(struct seq_file *m, void *unused)
                   JF(j_bcount),
                   JF(j_first_unflushed_offset),
                   JF(j_last_flush_trans_id),
-                  JF(j_trans_start_time),
+                  ktime_mono_to_real_seconds(JF(j_trans_start_time)),
                   JF(j_list_bitmap_index),
                   JF(j_must_wait),
                   JF(j_next_full_flush),
index ae4811f..e5ca9ed 100644 (file)
@@ -271,7 +271,7 @@ struct reiserfs_journal_list {
 
        struct mutex j_commit_mutex;
        unsigned int j_trans_id;
-       time_t j_timestamp;
+       time64_t j_timestamp; /* write-only but useful for crash dump analysis */
        struct reiserfs_list_bitmap *j_list_bitmap;
        struct buffer_head *j_commit_bh;        /* commit buffer head */
        struct reiserfs_journal_cnode *j_realblock;
@@ -331,7 +331,7 @@ struct reiserfs_journal {
 
        struct buffer_head *j_header_bh;
 
-       time_t j_trans_start_time;      /* time this transaction started */
+       time64_t j_trans_start_time;    /* time this transaction started */
        struct mutex j_mutex;
        struct mutex j_flush_mutex;
 
index ff94fad..48cdfc8 100644 (file)
@@ -792,8 +792,10 @@ static int listxattr_filler(struct dir_context *ctx, const char *name,
                        return 0;
                size = namelen + 1;
                if (b->buf) {
-                       if (size > b->size)
+                       if (b->pos + size > b->size) {
+                               b->pos = -ERANGE;
                                return -ERANGE;
+                       }
                        memcpy(b->buf + b->pos, name, namelen);
                        b->buf[b->pos + namelen] = 0;
                }
index 7429588..f3a8c00 100644 (file)
@@ -981,58 +981,42 @@ void emergency_thaw_all(void)
        }
 }
 
-/*
- * Unnamed block devices are dummy devices used by virtual
- * filesystems which don't use real block-devices.  -- jrs
- */
-
 static DEFINE_IDA(unnamed_dev_ida);
-static DEFINE_SPINLOCK(unnamed_dev_lock);/* protects the above */
-/* Many userspace utilities consider an FSID of 0 invalid.
- * Always return at least 1 from get_anon_bdev.
- */
-static int unnamed_dev_start = 1;
 
+/**
+ * get_anon_bdev - Allocate a block device for filesystems which don't have one.
+ * @p: Pointer to a dev_t.
+ *
+ * Filesystems which don't use real block devices can call this function
+ * to allocate a virtual block device.
+ *
+ * Context: Any context.  Frequently called while holding sb_lock.
+ * Return: 0 on success, -EMFILE if there are no anonymous bdevs left
+ * or -ENOMEM if memory allocation failed.
+ */
 int get_anon_bdev(dev_t *p)
 {
        int dev;
-       int error;
 
- retry:
-       if (ida_pre_get(&unnamed_dev_ida, GFP_ATOMIC) == 0)
-               return -ENOMEM;
-       spin_lock(&unnamed_dev_lock);
-       error = ida_get_new_above(&unnamed_dev_ida, unnamed_dev_start, &dev);
-       if (!error)
-               unnamed_dev_start = dev + 1;
-       spin_unlock(&unnamed_dev_lock);
-       if (error == -EAGAIN)
-               /* We raced and lost with another CPU. */
-               goto retry;
-       else if (error)
-               return -EAGAIN;
-
-       if (dev >= (1 << MINORBITS)) {
-               spin_lock(&unnamed_dev_lock);
-               ida_remove(&unnamed_dev_ida, dev);
-               if (unnamed_dev_start > dev)
-                       unnamed_dev_start = dev;
-               spin_unlock(&unnamed_dev_lock);
-               return -EMFILE;
-       }
-       *p = MKDEV(0, dev & MINORMASK);
+       /*
+        * Many userspace utilities consider an FSID of 0 invalid.
+        * Always return at least 1 from get_anon_bdev.
+        */
+       dev = ida_alloc_range(&unnamed_dev_ida, 1, (1 << MINORBITS) - 1,
+                       GFP_ATOMIC);
+       if (dev == -ENOSPC)
+               dev = -EMFILE;
+       if (dev < 0)
+               return dev;
+
+       *p = MKDEV(0, dev);
        return 0;
 }
 EXPORT_SYMBOL(get_anon_bdev);
 
 void free_anon_bdev(dev_t dev)
 {
-       int slot = MINOR(dev);
-       spin_lock(&unnamed_dev_lock);
-       ida_remove(&unnamed_dev_ida, slot);
-       if (slot < unnamed_dev_start)
-               unnamed_dev_start = slot;
-       spin_unlock(&unnamed_dev_lock);
+       ida_free(&unnamed_dev_ida, MINOR(dev));
 }
 EXPORT_SYMBOL(free_anon_bdev);
 
@@ -1040,7 +1024,6 @@ int set_anon_super(struct super_block *s, void *data)
 {
        return get_anon_bdev(&s->s_dev);
 }
-
 EXPORT_SYMBOL(set_anon_super);
 
 void kill_anon_super(struct super_block *sb)
@@ -1049,7 +1032,6 @@ void kill_anon_super(struct super_block *sb)
        generic_shutdown_super(sb);
        free_anon_bdev(dev);
 }
-
 EXPORT_SYMBOL(kill_anon_super);
 
 void kill_litter_super(struct super_block *sb)
@@ -1058,7 +1040,6 @@ void kill_litter_super(struct super_block *sb)
                d_genocide(sb->s_root);
        kill_anon_super(sb);
 }
-
 EXPORT_SYMBOL(kill_litter_super);
 
 static int ns_test_super(struct super_block *sb, void *data)
index bec9f79..499a20a 100644 (file)
@@ -35,7 +35,7 @@
 static int sysv_sync_fs(struct super_block *sb, int wait)
 {
        struct sysv_sb_info *sbi = SYSV_SB(sb);
-       unsigned long time = get_seconds(), old_time;
+       u32 time = (u32)ktime_get_real_seconds(), old_time;
 
        mutex_lock(&sbi->s_lock);
 
@@ -46,8 +46,8 @@ static int sysv_sync_fs(struct super_block *sb, int wait)
         */
        old_time = fs32_to_cpu(sbi, *sbi->s_sb_time);
        if (sbi->s_type == FSTYPE_SYSV4) {
-               if (*sbi->s_sb_state == cpu_to_fs32(sbi, 0x7c269d38 - old_time))
-                       *sbi->s_sb_state = cpu_to_fs32(sbi, 0x7c269d38 - time);
+               if (*sbi->s_sb_state == cpu_to_fs32(sbi, 0x7c269d38u - old_time))
+                       *sbi->s_sb_state = cpu_to_fs32(sbi, 0x7c269d38u - time);
                *sbi->s_sb_time = cpu_to_fs32(sbi, time);
                mark_buffer_dirty(sbi->s_bh2);
        }
index bea8ad8..7098c49 100644 (file)
@@ -53,7 +53,7 @@ static const struct file_operations tracefs_file_operations = {
 static struct tracefs_dir_ops {
        int (*mkdir)(const char *name);
        int (*rmdir)(const char *name);
-} tracefs_ops;
+} tracefs_ops __ro_after_init;
 
 static char *get_dname(struct dentry *dentry)
 {
@@ -478,7 +478,8 @@ struct dentry *tracefs_create_dir(const char *name, struct dentry *parent)
  *
  * Returns the dentry of the instances directory.
  */
-struct dentry *tracefs_create_instance_dir(const char *name, struct dentry *parent,
+__init struct dentry *tracefs_create_instance_dir(const char *name,
+                                         struct dentry *parent,
                                          int (*mkdir)(const char *name),
                                          int (*rmdir)(const char *name))
 {
index 83a961b..bbc7854 100644 (file)
@@ -51,9 +51,20 @@ config UBIFS_ATIME_SUPPORT
 
          If unsure, say 'N'
 
+config UBIFS_FS_XATTR
+       bool "UBIFS XATTR support"
+       depends on UBIFS_FS
+       default y
+       help
+         Saying Y here includes support for extended attributes (xattrs).
+         Xattrs are name:value pairs associated with inodes by
+         the kernel or by users (see the attr(5) manual page).
+
+         If unsure, say Y.
+
 config UBIFS_FS_ENCRYPTION
        bool "UBIFS Encryption"
-       depends on UBIFS_FS && BLOCK
+       depends on UBIFS_FS && UBIFS_FS_XATTR && BLOCK
        select FS_ENCRYPTION
        default n
        help
@@ -64,7 +75,7 @@ config UBIFS_FS_ENCRYPTION
 
 config UBIFS_FS_SECURITY
        bool "UBIFS Security Labels"
-       depends on UBIFS_FS
+       depends on UBIFS_FS && UBIFS_FS_XATTR
        default y
        help
          Security labels provide an access control facility to support Linux
index 9758f70..6197d7e 100644 (file)
@@ -4,6 +4,7 @@ obj-$(CONFIG_UBIFS_FS) += ubifs.o
 ubifs-y += shrinker.o journal.o file.o dir.o super.o sb.o io.o
 ubifs-y += tnc.o master.o scan.o replay.o log.o commit.o gc.o orphan.o
 ubifs-y += budget.o find.o tnc_commit.o compress.o lpt.o lprops.o
-ubifs-y += recovery.o ioctl.o lpt_commit.o tnc_misc.o xattr.o debug.o
+ubifs-y += recovery.o ioctl.o lpt_commit.o tnc_misc.o debug.o
 ubifs-y += misc.o
 ubifs-$(CONFIG_UBIFS_FS_ENCRYPTION) += crypto.o
+ubifs-$(CONFIG_UBIFS_FS_XATTR) += xattr.o
index 11a11b3..7ef22ba 100644 (file)
@@ -439,16 +439,16 @@ int ubifs_budget_space(struct ubifs_info *c, struct ubifs_budget_req *req)
 {
        int err, idx_growth, data_growth, dd_growth, retried = 0;
 
-       ubifs_assert(req->new_page <= 1);
-       ubifs_assert(req->dirtied_page <= 1);
-       ubifs_assert(req->new_dent <= 1);
-       ubifs_assert(req->mod_dent <= 1);
-       ubifs_assert(req->new_ino <= 1);
-       ubifs_assert(req->new_ino_d <= UBIFS_MAX_INO_DATA);
-       ubifs_assert(req->dirtied_ino <= 4);
-       ubifs_assert(req->dirtied_ino_d <= UBIFS_MAX_INO_DATA * 4);
-       ubifs_assert(!(req->new_ino_d & 7));
-       ubifs_assert(!(req->dirtied_ino_d & 7));
+       ubifs_assert(c, req->new_page <= 1);
+       ubifs_assert(c, req->dirtied_page <= 1);
+       ubifs_assert(c, req->new_dent <= 1);
+       ubifs_assert(c, req->mod_dent <= 1);
+       ubifs_assert(c, req->new_ino <= 1);
+       ubifs_assert(c, req->new_ino_d <= UBIFS_MAX_INO_DATA);
+       ubifs_assert(c, req->dirtied_ino <= 4);
+       ubifs_assert(c, req->dirtied_ino_d <= UBIFS_MAX_INO_DATA * 4);
+       ubifs_assert(c, !(req->new_ino_d & 7));
+       ubifs_assert(c, !(req->dirtied_ino_d & 7));
 
        data_growth = calc_data_growth(c, req);
        dd_growth = calc_dd_growth(c, req);
@@ -458,9 +458,9 @@ int ubifs_budget_space(struct ubifs_info *c, struct ubifs_budget_req *req)
 
 again:
        spin_lock(&c->space_lock);
-       ubifs_assert(c->bi.idx_growth >= 0);
-       ubifs_assert(c->bi.data_growth >= 0);
-       ubifs_assert(c->bi.dd_growth >= 0);
+       ubifs_assert(c, c->bi.idx_growth >= 0);
+       ubifs_assert(c, c->bi.data_growth >= 0);
+       ubifs_assert(c, c->bi.dd_growth >= 0);
 
        if (unlikely(c->bi.nospace) && (c->bi.nospace_rp || !can_use_rp(c))) {
                dbg_budg("no space");
@@ -526,20 +526,20 @@ again:
  */
 void ubifs_release_budget(struct ubifs_info *c, struct ubifs_budget_req *req)
 {
-       ubifs_assert(req->new_page <= 1);
-       ubifs_assert(req->dirtied_page <= 1);
-       ubifs_assert(req->new_dent <= 1);
-       ubifs_assert(req->mod_dent <= 1);
-       ubifs_assert(req->new_ino <= 1);
-       ubifs_assert(req->new_ino_d <= UBIFS_MAX_INO_DATA);
-       ubifs_assert(req->dirtied_ino <= 4);
-       ubifs_assert(req->dirtied_ino_d <= UBIFS_MAX_INO_DATA * 4);
-       ubifs_assert(!(req->new_ino_d & 7));
-       ubifs_assert(!(req->dirtied_ino_d & 7));
+       ubifs_assert(c, req->new_page <= 1);
+       ubifs_assert(c, req->dirtied_page <= 1);
+       ubifs_assert(c, req->new_dent <= 1);
+       ubifs_assert(c, req->mod_dent <= 1);
+       ubifs_assert(c, req->new_ino <= 1);
+       ubifs_assert(c, req->new_ino_d <= UBIFS_MAX_INO_DATA);
+       ubifs_assert(c, req->dirtied_ino <= 4);
+       ubifs_assert(c, req->dirtied_ino_d <= UBIFS_MAX_INO_DATA * 4);
+       ubifs_assert(c, !(req->new_ino_d & 7));
+       ubifs_assert(c, !(req->dirtied_ino_d & 7));
        if (!req->recalculate) {
-               ubifs_assert(req->idx_growth >= 0);
-               ubifs_assert(req->data_growth >= 0);
-               ubifs_assert(req->dd_growth >= 0);
+               ubifs_assert(c, req->idx_growth >= 0);
+               ubifs_assert(c, req->data_growth >= 0);
+               ubifs_assert(c, req->dd_growth >= 0);
        }
 
        if (req->recalculate) {
@@ -561,13 +561,13 @@ void ubifs_release_budget(struct ubifs_info *c, struct ubifs_budget_req *req)
        c->bi.dd_growth -= req->dd_growth;
        c->bi.min_idx_lebs = ubifs_calc_min_idx_lebs(c);
 
-       ubifs_assert(c->bi.idx_growth >= 0);
-       ubifs_assert(c->bi.data_growth >= 0);
-       ubifs_assert(c->bi.dd_growth >= 0);
-       ubifs_assert(c->bi.min_idx_lebs < c->main_lebs);
-       ubifs_assert(!(c->bi.idx_growth & 7));
-       ubifs_assert(!(c->bi.data_growth & 7));
-       ubifs_assert(!(c->bi.dd_growth & 7));
+       ubifs_assert(c, c->bi.idx_growth >= 0);
+       ubifs_assert(c, c->bi.data_growth >= 0);
+       ubifs_assert(c, c->bi.dd_growth >= 0);
+       ubifs_assert(c, c->bi.min_idx_lebs < c->main_lebs);
+       ubifs_assert(c, !(c->bi.idx_growth & 7));
+       ubifs_assert(c, !(c->bi.data_growth & 7));
+       ubifs_assert(c, !(c->bi.dd_growth & 7));
        spin_unlock(&c->space_lock);
 }
 
@@ -680,7 +680,7 @@ long long ubifs_get_free_space_nolock(struct ubifs_info *c)
        int rsvd_idx_lebs, lebs;
        long long available, outstanding, free;
 
-       ubifs_assert(c->bi.min_idx_lebs == ubifs_calc_min_idx_lebs(c));
+       ubifs_assert(c, c->bi.min_idx_lebs == ubifs_calc_min_idx_lebs(c));
        outstanding = c->bi.data_growth + c->bi.dd_growth;
        available = ubifs_calc_available(c, c->bi.min_idx_lebs);
 
index 63f5661..591f2c7 100644 (file)
@@ -91,9 +91,9 @@ static int nothing_to_commit(struct ubifs_info *c)
        if (c->nroot && test_bit(DIRTY_CNODE, &c->nroot->flags))
                return 0;
 
-       ubifs_assert(atomic_long_read(&c->dirty_zn_cnt) == 0);
-       ubifs_assert(c->dirty_pn_cnt == 0);
-       ubifs_assert(c->dirty_nn_cnt == 0);
+       ubifs_assert(c, atomic_long_read(&c->dirty_zn_cnt) == 0);
+       ubifs_assert(c, c->dirty_pn_cnt == 0);
+       ubifs_assert(c, c->dirty_nn_cnt == 0);
 
        return 1;
 }
@@ -113,7 +113,7 @@ static int do_commit(struct ubifs_info *c)
        struct ubifs_lp_stats lst;
 
        dbg_cmt("start");
-       ubifs_assert(!c->ro_media && !c->ro_mount);
+       ubifs_assert(c, !c->ro_media && !c->ro_mount);
 
        if (c->ro_error) {
                err = -EROFS;
index 55c508f..4aaedf2 100644 (file)
@@ -32,7 +32,7 @@ int ubifs_encrypt(const struct inode *inode, struct ubifs_data_node *dn,
        struct page *ret;
        unsigned int pad_len = round_up(in_len, UBIFS_CIPHER_BLOCK_SIZE);
 
-       ubifs_assert(pad_len <= *out_len);
+       ubifs_assert(c, pad_len <= *out_len);
        dn->compr_size = cpu_to_le16(in_len);
 
        /* pad to full block cipher length */
@@ -63,7 +63,7 @@ int ubifs_decrypt(const struct inode *inode, struct ubifs_data_node *dn,
                return -EINVAL;
        }
 
-       ubifs_assert(dlen <= UBIFS_BLOCK_SIZE);
+       ubifs_assert(c, dlen <= UBIFS_BLOCK_SIZE);
        err = fscrypt_decrypt_page(inode, virt_to_page(&dn->data), dlen,
                        offset_in_page(&dn->data), block);
        if (err) {
index 7cd8a7b..564e330 100644 (file)
@@ -134,7 +134,7 @@ const char *dbg_snprintf_key(const struct ubifs_info *c,
                }
        } else
                len -= snprintf(p, len, "bad key format %d", c->key_fmt);
-       ubifs_assert(len > 0);
+       ubifs_assert(c, len > 0);
        return p;
 }
 
@@ -276,7 +276,7 @@ void ubifs_dump_inode(struct ubifs_info *c, const struct inode *inode)
                return;
 
        pr_err("List of directory entries:\n");
-       ubifs_assert(!mutex_is_locked(&c->tnc_mutex));
+       ubifs_assert(c, !mutex_is_locked(&c->tnc_mutex));
 
        lowest_dent_key(c, &key, inode->i_ino);
        while (1) {
@@ -931,7 +931,7 @@ void ubifs_dump_tnc(struct ubifs_info *c)
 
        pr_err("\n");
        pr_err("(pid %d) start dumping TNC tree\n", current->pid);
-       znode = ubifs_tnc_levelorder_next(c->zroot.znode, NULL);
+       znode = ubifs_tnc_levelorder_next(c, c->zroot.znode, NULL);
        level = znode->level;
        pr_err("== Level %d ==\n", level);
        while (znode) {
@@ -940,7 +940,7 @@ void ubifs_dump_tnc(struct ubifs_info *c)
                        pr_err("== Level %d ==\n", level);
                }
                ubifs_dump_znode(c, znode);
-               znode = ubifs_tnc_levelorder_next(c->zroot.znode, znode);
+               znode = ubifs_tnc_levelorder_next(c, c->zroot.znode, znode);
        }
        pr_err("(pid %d) finish dumping TNC tree\n", current->pid);
 }
@@ -1183,7 +1183,7 @@ static int dbg_check_key_order(struct ubifs_info *c, struct ubifs_zbranch *zbr1,
        union ubifs_key key;
        char key_buf[DBG_KEY_BUF_LEN];
 
-       ubifs_assert(!keys_cmp(c, &zbr1->key, &zbr2->key));
+       ubifs_assert(c, !keys_cmp(c, &zbr1->key, &zbr2->key));
        dent1 = kmalloc(UBIFS_MAX_DENT_NODE_SZ, GFP_NOFS);
        if (!dent1)
                return -ENOMEM;
@@ -1479,7 +1479,7 @@ int dbg_check_tnc(struct ubifs_info *c, int extra)
        if (!dbg_is_chk_index(c))
                return 0;
 
-       ubifs_assert(mutex_is_locked(&c->tnc_mutex));
+       ubifs_assert(c, mutex_is_locked(&c->tnc_mutex));
        if (!c->zroot.znode)
                return 0;
 
@@ -1505,7 +1505,7 @@ int dbg_check_tnc(struct ubifs_info *c, int extra)
                }
 
                prev = znode;
-               znode = ubifs_tnc_postorder_next(znode);
+               znode = ubifs_tnc_postorder_next(c, znode);
                if (!znode)
                        break;
 
@@ -2036,7 +2036,7 @@ static int check_leaf(struct ubifs_info *c, struct ubifs_zbranch *zbr,
                long long blk_offs;
                struct ubifs_data_node *dn = node;
 
-               ubifs_assert(zbr->len >= UBIFS_DATA_NODE_SZ);
+               ubifs_assert(c, zbr->len >= UBIFS_DATA_NODE_SZ);
 
                /*
                 * Search the inode node this data node belongs to and insert
@@ -2066,7 +2066,7 @@ static int check_leaf(struct ubifs_info *c, struct ubifs_zbranch *zbr,
                struct ubifs_dent_node *dent = node;
                struct fsck_inode *fscki1;
 
-               ubifs_assert(zbr->len >= UBIFS_DENT_NODE_SZ);
+               ubifs_assert(c, zbr->len >= UBIFS_DENT_NODE_SZ);
 
                err = ubifs_validate_entry(c, dent);
                if (err)
@@ -2461,7 +2461,7 @@ static int power_cut_emulated(struct ubifs_info *c, int lnum, int write)
 {
        struct ubifs_debug_info *d = c->dbg;
 
-       ubifs_assert(dbg_is_tst_rcvry(c));
+       ubifs_assert(c, dbg_is_tst_rcvry(c));
 
        if (!d->pc_cnt) {
                /* First call - decide delay to the power cut */
@@ -3081,6 +3081,28 @@ void dbg_debugfs_exit(void)
                debugfs_remove_recursive(dfs_rootdir);
 }
 
+void ubifs_assert_failed(struct ubifs_info *c, const char *expr,
+                        const char *file, int line)
+{
+       ubifs_err(c, "UBIFS assert failed: %s, in %s:%u", expr, file, line);
+
+       switch (c->assert_action) {
+               case ASSACT_PANIC:
+               BUG();
+               break;
+
+               case ASSACT_RO:
+               ubifs_ro_mode(c, -EINVAL);
+               break;
+
+               case ASSACT_REPORT:
+               default:
+               dump_stack();
+               break;
+
+       }
+}
+
 /**
  * ubifs_debugging_init - initialize UBIFS debugging.
  * @c: UBIFS file-system description object
index e03d517..64c6977 100644 (file)
@@ -148,19 +148,21 @@ struct ubifs_global_debug_info {
        unsigned int tst_rcvry:1;
 };
 
-#define ubifs_assert(expr) do {                                                \
+void ubifs_assert_failed(struct ubifs_info *c, const char *expr,
+       const char *file, int line);
+
+#define ubifs_assert(c, expr) do {                                             \
        if (unlikely(!(expr))) {                                               \
-               pr_crit("UBIFS assert failed in %s at %u (pid %d)\n",          \
-                      __func__, __LINE__, current->pid);                      \
-               dump_stack();                                                  \
+               ubifs_assert_failed((struct ubifs_info *)c, #expr, __FILE__,   \
+                __LINE__);                                                    \
        }                                                                      \
 } while (0)
 
 #define ubifs_assert_cmt_locked(c) do {                                        \
        if (unlikely(down_write_trylock(&(c)->commit_sem))) {                  \
                up_write(&(c)->commit_sem);                                    \
-               pr_crit("commit lock is not locked!\n");                       \
-               ubifs_assert(0);                                               \
+               ubifs_err(c, "commit lock is not locked!\n");                  \
+               ubifs_assert(c, 0);                                            \
        }                                                                      \
 } while (0)
 
index 9da224d..5767b37 100644 (file)
@@ -240,8 +240,8 @@ static struct dentry *ubifs_lookup(struct inode *dir, struct dentry *dentry,
        }
 
        if (nm.hash) {
-               ubifs_assert(fname_len(&nm) == 0);
-               ubifs_assert(fname_name(&nm) == NULL);
+               ubifs_assert(c, fname_len(&nm) == 0);
+               ubifs_assert(c, fname_name(&nm) == NULL);
                dent_key_init_hash(c, &key, dir->i_ino, nm.hash);
                err = ubifs_tnc_lookup_dh(c, &key, dent, nm.minor_hash);
        } else {
@@ -404,7 +404,7 @@ static int do_tmpfile(struct inode *dir, struct dentry *dentry,
 
        if (whiteout) {
                init_special_inode(inode, inode->i_mode, WHITEOUT_DEV);
-               ubifs_assert(inode->i_op == &ubifs_file_inode_operations);
+               ubifs_assert(c, inode->i_op == &ubifs_file_inode_operations);
        }
 
        err = ubifs_init_security(dir, inode, &dentry->d_name);
@@ -421,7 +421,7 @@ static int do_tmpfile(struct inode *dir, struct dentry *dentry,
        } else {
                d_tmpfile(dentry, inode);
        }
-       ubifs_assert(ui->dirty);
+       ubifs_assert(c, ui->dirty);
 
        instantiated = 1;
        mutex_unlock(&ui->ui_mutex);
@@ -556,7 +556,7 @@ static int ubifs_readdir(struct file *file, struct dir_context *ctx)
 
        /* File positions 0 and 1 correspond to "." and ".." */
        if (ctx->pos < 2) {
-               ubifs_assert(!file->private_data);
+               ubifs_assert(c, !file->private_data);
                if (!dir_emit_dots(file, ctx)) {
                        if (encrypted)
                                fscrypt_fname_free_buffer(&fstr);
@@ -597,7 +597,7 @@ static int ubifs_readdir(struct file *file, struct dir_context *ctx)
                dbg_gen("ino %llu, new f_pos %#x",
                        (unsigned long long)le64_to_cpu(dent->inum),
                        key_hash_flash(c, &dent->key));
-               ubifs_assert(le64_to_cpu(dent->ch.sqnum) >
+               ubifs_assert(c, le64_to_cpu(dent->ch.sqnum) >
                             ubifs_inode(dir)->creat_sqnum);
 
                fname_len(&nm) = le16_to_cpu(dent->nlen);
@@ -716,8 +716,8 @@ static int ubifs_link(struct dentry *old_dentry, struct inode *dir,
        dbg_gen("dent '%pd' to ino %lu (nlink %d) in dir ino %lu",
                dentry, inode->i_ino,
                inode->i_nlink, dir->i_ino);
-       ubifs_assert(inode_is_locked(dir));
-       ubifs_assert(inode_is_locked(inode));
+       ubifs_assert(c, inode_is_locked(dir));
+       ubifs_assert(c, inode_is_locked(inode));
 
        err = fscrypt_prepare_link(old_dentry, dir, dentry);
        if (err)
@@ -804,8 +804,8 @@ static int ubifs_unlink(struct inode *dir, struct dentry *dentry)
 
        sz_change = CALC_DENT_SIZE(fname_len(&nm));
 
-       ubifs_assert(inode_is_locked(dir));
-       ubifs_assert(inode_is_locked(inode));
+       ubifs_assert(c, inode_is_locked(dir));
+       ubifs_assert(c, inode_is_locked(inode));
        err = dbg_check_synced_i_size(c, inode);
        if (err)
                goto out_fname;
@@ -896,8 +896,8 @@ static int ubifs_rmdir(struct inode *dir, struct dentry *dentry)
 
        dbg_gen("directory '%pd', ino %lu in dir ino %lu", dentry,
                inode->i_ino, dir->i_ino);
-       ubifs_assert(inode_is_locked(dir));
-       ubifs_assert(inode_is_locked(inode));
+       ubifs_assert(c, inode_is_locked(dir));
+       ubifs_assert(c, inode_is_locked(inode));
        err = ubifs_check_dir_empty(d_inode(dentry));
        if (err)
                return err;
@@ -1123,8 +1123,7 @@ static int ubifs_symlink(struct inode *dir, struct dentry *dentry,
        struct ubifs_inode *ui;
        struct ubifs_inode *dir_ui = ubifs_inode(dir);
        struct ubifs_info *c = dir->i_sb->s_fs_info;
-       int err, len = strlen(symname);
-       int sz_change = CALC_DENT_SIZE(len);
+       int err, sz_change, len = strlen(symname);
        struct fscrypt_str disk_link;
        struct ubifs_budget_req req = { .new_ino = 1, .new_dent = 1,
                                        .new_ino_d = ALIGN(len, 8),
@@ -1151,6 +1150,8 @@ static int ubifs_symlink(struct inode *dir, struct dentry *dentry,
        if (err)
                goto out_budg;
 
+       sz_change = CALC_DENT_SIZE(fname_len(&nm));
+
        inode = ubifs_new_inode(c, dir, S_IFLNK | S_IRWXUGO);
        if (IS_ERR(inode)) {
                err = PTR_ERR(inode);
@@ -1294,7 +1295,7 @@ static int do_rename(struct inode *old_dir, struct dentry *old_dentry,
                new_dentry, new_dir->i_ino, flags);
 
        if (unlink)
-               ubifs_assert(inode_is_locked(new_inode));
+               ubifs_assert(c, inode_is_locked(new_inode));
 
        if (unlink && is_dir) {
                err = ubifs_check_dir_empty(new_inode);
@@ -1348,7 +1349,7 @@ static int do_rename(struct inode *old_dir, struct dentry *old_dentry,
                whiteout_ui = ubifs_inode(whiteout);
                whiteout_ui->data = dev;
                whiteout_ui->data_len = ubifs_encode_dev(dev, MKDEV(0, 0));
-               ubifs_assert(!whiteout_ui->dirty);
+               ubifs_assert(c, !whiteout_ui->dirty);
        }
 
        lock_4_inodes(old_dir, new_dir, new_inode, whiteout);
@@ -1508,7 +1509,7 @@ static int ubifs_xrename(struct inode *old_dir, struct dentry *old_dentry,
        int err;
        struct fscrypt_name fst_nm, snd_nm;
 
-       ubifs_assert(fst_inode && snd_inode);
+       ubifs_assert(c, fst_inode && snd_inode);
 
        err = fscrypt_setup_filename(old_dir, &old_dentry->d_name, 0, &fst_nm);
        if (err)
@@ -1555,12 +1556,13 @@ static int ubifs_rename(struct inode *old_dir, struct dentry *old_dentry,
                        unsigned int flags)
 {
        int err;
+       struct ubifs_info *c = old_dir->i_sb->s_fs_info;
 
        if (flags & ~(RENAME_NOREPLACE | RENAME_WHITEOUT | RENAME_EXCHANGE))
                return -EINVAL;
 
-       ubifs_assert(inode_is_locked(old_dir));
-       ubifs_assert(inode_is_locked(new_dir));
+       ubifs_assert(c, inode_is_locked(old_dir));
+       ubifs_assert(c, inode_is_locked(new_dir));
 
        err = fscrypt_prepare_rename(old_dir, old_dentry, new_dir, new_dentry,
                                     flags);
@@ -1647,7 +1649,9 @@ const struct inode_operations ubifs_dir_inode_operations = {
        .rename      = ubifs_rename,
        .setattr     = ubifs_setattr,
        .getattr     = ubifs_getattr,
+#ifdef CONFIG_UBIFS_FS_XATTR
        .listxattr   = ubifs_listxattr,
+#endif
 #ifdef CONFIG_UBIFS_ATIME_SUPPORT
        .update_time = ubifs_update_time,
 #endif
index fd7eb6f..1b78f2e 100644 (file)
@@ -71,7 +71,7 @@ static int read_block(struct inode *inode, void *addr, unsigned int block,
                return err;
        }
 
-       ubifs_assert(le64_to_cpu(dn->ch.sqnum) >
+       ubifs_assert(c, le64_to_cpu(dn->ch.sqnum) >
                     ubifs_inode(inode)->creat_sqnum);
        len = le32_to_cpu(dn->size);
        if (len <= 0 || len > UBIFS_BLOCK_SIZE)
@@ -115,12 +115,13 @@ static int do_readpage(struct page *page)
        unsigned int block, beyond;
        struct ubifs_data_node *dn;
        struct inode *inode = page->mapping->host;
+       struct ubifs_info *c = inode->i_sb->s_fs_info;
        loff_t i_size = i_size_read(inode);
 
        dbg_gen("ino %lu, pg %lu, i_size %lld, flags %#lx",
                inode->i_ino, page->index, i_size, page->flags);
-       ubifs_assert(!PageChecked(page));
-       ubifs_assert(!PagePrivate(page));
+       ubifs_assert(c, !PageChecked(page));
+       ubifs_assert(c, !PagePrivate(page));
 
        addr = kmap(page);
 
@@ -441,8 +442,8 @@ static int ubifs_write_begin(struct file *file, struct address_space *mapping,
        int skipped_read = 0;
        struct page *page;
 
-       ubifs_assert(ubifs_inode(inode)->ui_size == inode->i_size);
-       ubifs_assert(!c->ro_media && !c->ro_mount);
+       ubifs_assert(c, ubifs_inode(inode)->ui_size == inode->i_size);
+       ubifs_assert(c, !c->ro_media && !c->ro_mount);
 
        if (unlikely(c->ro_error))
                return -EROFS;
@@ -481,7 +482,7 @@ static int ubifs_write_begin(struct file *file, struct address_space *mapping,
 
        err = allocate_budget(c, page, ui, appending);
        if (unlikely(err)) {
-               ubifs_assert(err == -ENOSPC);
+               ubifs_assert(c, err == -ENOSPC);
                /*
                 * If we skipped reading the page because we were going to
                 * write all of it, then it is not up to date.
@@ -498,7 +499,7 @@ static int ubifs_write_begin(struct file *file, struct address_space *mapping,
                 * everything and fall-back to slow-path.
                 */
                if (appending) {
-                       ubifs_assert(mutex_is_locked(&ui->ui_mutex));
+                       ubifs_assert(c, mutex_is_locked(&ui->ui_mutex));
                        mutex_unlock(&ui->ui_mutex);
                }
                unlock_page(page);
@@ -595,7 +596,7 @@ static int ubifs_write_end(struct file *file, struct address_space *mapping,
                 * '__set_page_dirty_nobuffers()'.
                 */
                __mark_inode_dirty(inode, I_DIRTY_DATASYNC);
-               ubifs_assert(mutex_is_locked(&ui->ui_mutex));
+               ubifs_assert(c, mutex_is_locked(&ui->ui_mutex));
                mutex_unlock(&ui->ui_mutex);
        }
 
@@ -648,7 +649,7 @@ static int populate_page(struct ubifs_info *c, struct page *page,
 
                        dn = bu->buf + (bu->zbranch[nn].offs - offs);
 
-                       ubifs_assert(le64_to_cpu(dn->ch.sqnum) >
+                       ubifs_assert(c, le64_to_cpu(dn->ch.sqnum) >
                                     ubifs_inode(inode)->creat_sqnum);
 
                        len = le32_to_cpu(dn->size);
@@ -767,8 +768,8 @@ static int ubifs_do_bulk_read(struct ubifs_info *c, struct bu_info *bu,
                        bu->buf_len = bu->zbranch[bu->cnt - 1].offs +
                                      bu->zbranch[bu->cnt - 1].len -
                                      bu->zbranch[0].offs;
-                       ubifs_assert(bu->buf_len > 0);
-                       ubifs_assert(bu->buf_len <= c->leb_size);
+                       ubifs_assert(c, bu->buf_len > 0);
+                       ubifs_assert(c, bu->buf_len <= c->leb_size);
                        bu->buf = kmalloc(bu->buf_len, GFP_NOFS | __GFP_NOWARN);
                        if (!bu->buf)
                                goto out_bu_off;
@@ -920,7 +921,7 @@ static int do_writepage(struct page *page, int len)
 #ifdef UBIFS_DEBUG
        struct ubifs_inode *ui = ubifs_inode(inode);
        spin_lock(&ui->ui_lock);
-       ubifs_assert(page->index <= ui->synced_i_size >> PAGE_SHIFT);
+       ubifs_assert(c, page->index <= ui->synced_i_size >> PAGE_SHIFT);
        spin_unlock(&ui->ui_lock);
 #endif
 
@@ -949,7 +950,7 @@ static int do_writepage(struct page *page, int len)
                ubifs_ro_mode(c, err);
        }
 
-       ubifs_assert(PagePrivate(page));
+       ubifs_assert(c, PagePrivate(page));
        if (PageChecked(page))
                release_new_page_budget(c);
        else
@@ -1014,6 +1015,7 @@ static int do_writepage(struct page *page, int len)
 static int ubifs_writepage(struct page *page, struct writeback_control *wbc)
 {
        struct inode *inode = page->mapping->host;
+       struct ubifs_info *c = inode->i_sb->s_fs_info;
        struct ubifs_inode *ui = ubifs_inode(inode);
        loff_t i_size =  i_size_read(inode), synced_i_size;
        pgoff_t end_index = i_size >> PAGE_SHIFT;
@@ -1022,7 +1024,7 @@ static int ubifs_writepage(struct page *page, struct writeback_control *wbc)
 
        dbg_gen("ino %lu, pg %lu, pg flags %#lx",
                inode->i_ino, page->index, page->flags);
-       ubifs_assert(PagePrivate(page));
+       ubifs_assert(c, PagePrivate(page));
 
        /* Is the page fully outside @i_size? (truncate in progress) */
        if (page->index > end_index || (page->index == end_index && !len)) {
@@ -1167,7 +1169,7 @@ static int do_truncation(struct ubifs_info *c, struct inode *inode,
                                 * 'ubifs_jnl_truncate()' will see an already
                                 * truncated (and up to date) data node.
                                 */
-                               ubifs_assert(PagePrivate(page));
+                               ubifs_assert(c, PagePrivate(page));
 
                                clear_page_dirty_for_io(page);
                                if (UBIFS_BLOCKS_PER_PAGE_SHIFT)
@@ -1303,7 +1305,7 @@ static void ubifs_invalidatepage(struct page *page, unsigned int offset,
        struct inode *inode = page->mapping->host;
        struct ubifs_info *c = inode->i_sb->s_fs_info;
 
-       ubifs_assert(PagePrivate(page));
+       ubifs_assert(c, PagePrivate(page));
        if (offset || length < PAGE_SIZE)
                /* Partial page remains dirty */
                return;
@@ -1365,11 +1367,10 @@ out:
  * granularity, they are not updated. This is an optimization.
  */
 static inline int mctime_update_needed(const struct inode *inode,
-                                      const struct timespec *now)
+                                      const struct timespec64 *now)
 {
-       struct timespec64 now64 = timespec_to_timespec64(*now);
-       if (!timespec64_equal(&inode->i_mtime, &now64) ||
-           !timespec64_equal(&inode->i_ctime, &now64))
+       if (!timespec64_equal(&inode->i_mtime, now) ||
+           !timespec64_equal(&inode->i_ctime, now))
                return 1;
        return 0;
 }
@@ -1425,7 +1426,7 @@ int ubifs_update_time(struct inode *inode, struct timespec64 *time,
  */
 static int update_mctime(struct inode *inode)
 {
-       struct timespec now = timespec64_to_timespec(current_time(inode));
+       struct timespec64 now = current_time(inode);
        struct ubifs_inode *ui = ubifs_inode(inode);
        struct ubifs_info *c = inode->i_sb->s_fs_info;
 
@@ -1462,13 +1463,15 @@ static ssize_t ubifs_write_iter(struct kiocb *iocb, struct iov_iter *from)
 static int ubifs_set_page_dirty(struct page *page)
 {
        int ret;
+       struct inode *inode = page->mapping->host;
+       struct ubifs_info *c = inode->i_sb->s_fs_info;
 
        ret = __set_page_dirty_nobuffers(page);
        /*
         * An attempt to dirty a page without budgeting for it - should not
         * happen.
         */
-       ubifs_assert(ret == 0);
+       ubifs_assert(c, ret == 0);
        return ret;
 }
 
@@ -1497,14 +1500,17 @@ static int ubifs_migrate_page(struct address_space *mapping,
 
 static int ubifs_releasepage(struct page *page, gfp_t unused_gfp_flags)
 {
+       struct inode *inode = page->mapping->host;
+       struct ubifs_info *c = inode->i_sb->s_fs_info;
+
        /*
         * An attempt to release a dirty page without budgeting for it - should
         * not happen.
         */
        if (PageWriteback(page))
                return 0;
-       ubifs_assert(PagePrivate(page));
-       ubifs_assert(0);
+       ubifs_assert(c, PagePrivate(page));
+       ubifs_assert(c, 0);
        ClearPagePrivate(page);
        ClearPageChecked(page);
        return 1;
@@ -1519,13 +1525,13 @@ static vm_fault_t ubifs_vm_page_mkwrite(struct vm_fault *vmf)
        struct page *page = vmf->page;
        struct inode *inode = file_inode(vmf->vma->vm_file);
        struct ubifs_info *c = inode->i_sb->s_fs_info;
-       struct timespec now = timespec64_to_timespec(current_time(inode));
+       struct timespec64 now = current_time(inode);
        struct ubifs_budget_req req = { .new_page = 1 };
        int err, update_time;
 
        dbg_gen("ino %lu, pg %lu, i_size %lld", inode->i_ino, page->index,
                i_size_read(inode));
-       ubifs_assert(!c->ro_media && !c->ro_mount);
+       ubifs_assert(c, !c->ro_media && !c->ro_mount);
 
        if (unlikely(c->ro_error))
                return VM_FAULT_SIGBUS; /* -EROFS */
@@ -1654,7 +1660,9 @@ const struct address_space_operations ubifs_file_address_operations = {
 const struct inode_operations ubifs_file_inode_operations = {
        .setattr     = ubifs_setattr,
        .getattr     = ubifs_getattr,
+#ifdef CONFIG_UBIFS_FS_XATTR
        .listxattr   = ubifs_listxattr,
+#endif
 #ifdef CONFIG_UBIFS_ATIME_SUPPORT
        .update_time = ubifs_update_time,
 #endif
@@ -1664,7 +1672,9 @@ const struct inode_operations ubifs_symlink_inode_operations = {
        .get_link    = ubifs_get_link,
        .setattr     = ubifs_setattr,
        .getattr     = ubifs_getattr,
+#ifdef CONFIG_UBIFS_FS_XATTR
        .listxattr   = ubifs_listxattr,
+#endif
 #ifdef CONFIG_UBIFS_ATIME_SUPPORT
        .update_time = ubifs_update_time,
 #endif
index 9571616..f964683 100644 (file)
@@ -183,18 +183,18 @@ static const struct ubifs_lprops *scan_for_dirty(struct ubifs_info *c,
                                    &data);
        if (err)
                return ERR_PTR(err);
-       ubifs_assert(data.lnum >= c->main_first && data.lnum < c->leb_cnt);
+       ubifs_assert(c, data.lnum >= c->main_first && data.lnum < c->leb_cnt);
        c->lscan_lnum = data.lnum;
        lprops = ubifs_lpt_lookup_dirty(c, data.lnum);
        if (IS_ERR(lprops))
                return lprops;
-       ubifs_assert(lprops->lnum == data.lnum);
-       ubifs_assert(lprops->free + lprops->dirty >= min_space);
-       ubifs_assert(lprops->dirty >= c->dead_wm ||
+       ubifs_assert(c, lprops->lnum == data.lnum);
+       ubifs_assert(c, lprops->free + lprops->dirty >= min_space);
+       ubifs_assert(c, lprops->dirty >= c->dead_wm ||
                     (pick_free &&
                      lprops->free + lprops->dirty == c->leb_size));
-       ubifs_assert(!(lprops->flags & LPROPS_TAKEN));
-       ubifs_assert(!exclude_index || !(lprops->flags & LPROPS_INDEX));
+       ubifs_assert(c, !(lprops->flags & LPROPS_TAKEN));
+       ubifs_assert(c, !exclude_index || !(lprops->flags & LPROPS_INDEX));
        return lprops;
 }
 
@@ -315,7 +315,7 @@ int ubifs_find_dirty_leb(struct ubifs_info *c, struct ubifs_lprops *ret_lp,
                lp = idx_lp;
 
        if (lp) {
-               ubifs_assert(lp->free + lp->dirty >= c->dead_wm);
+               ubifs_assert(c, lp->free + lp->dirty >= c->dead_wm);
                goto found;
        }
 
@@ -326,7 +326,7 @@ int ubifs_find_dirty_leb(struct ubifs_info *c, struct ubifs_lprops *ret_lp,
                err = PTR_ERR(lp);
                goto out;
        }
-       ubifs_assert(lp->dirty >= c->dead_wm ||
+       ubifs_assert(c, lp->dirty >= c->dead_wm ||
                     (pick_free && lp->free + lp->dirty == c->leb_size));
 
 found:
@@ -462,15 +462,15 @@ const struct ubifs_lprops *do_find_free_space(struct ubifs_info *c,
                                    &data);
        if (err)
                return ERR_PTR(err);
-       ubifs_assert(data.lnum >= c->main_first && data.lnum < c->leb_cnt);
+       ubifs_assert(c, data.lnum >= c->main_first && data.lnum < c->leb_cnt);
        c->lscan_lnum = data.lnum;
        lprops = ubifs_lpt_lookup_dirty(c, data.lnum);
        if (IS_ERR(lprops))
                return lprops;
-       ubifs_assert(lprops->lnum == data.lnum);
-       ubifs_assert(lprops->free >= min_space);
-       ubifs_assert(!(lprops->flags & LPROPS_TAKEN));
-       ubifs_assert(!(lprops->flags & LPROPS_INDEX));
+       ubifs_assert(c, lprops->lnum == data.lnum);
+       ubifs_assert(c, lprops->free >= min_space);
+       ubifs_assert(c, !(lprops->flags & LPROPS_TAKEN));
+       ubifs_assert(c, !(lprops->flags & LPROPS_INDEX));
        return lprops;
 }
 
@@ -574,7 +574,7 @@ int ubifs_find_free_space(struct ubifs_info *c, int min_space, int *offs,
        }
 
        dbg_find("found LEB %d, free %d", lnum, c->leb_size - *offs);
-       ubifs_assert(*offs <= c->leb_size - min_space);
+       ubifs_assert(c, *offs <= c->leb_size - min_space);
        return lnum;
 
 out:
@@ -642,15 +642,15 @@ static const struct ubifs_lprops *scan_for_leb_for_idx(struct ubifs_info *c)
                                    &data);
        if (err)
                return ERR_PTR(err);
-       ubifs_assert(data.lnum >= c->main_first && data.lnum < c->leb_cnt);
+       ubifs_assert(c, data.lnum >= c->main_first && data.lnum < c->leb_cnt);
        c->lscan_lnum = data.lnum;
        lprops = ubifs_lpt_lookup_dirty(c, data.lnum);
        if (IS_ERR(lprops))
                return lprops;
-       ubifs_assert(lprops->lnum == data.lnum);
-       ubifs_assert(lprops->free + lprops->dirty == c->leb_size);
-       ubifs_assert(!(lprops->flags & LPROPS_TAKEN));
-       ubifs_assert(!(lprops->flags & LPROPS_INDEX));
+       ubifs_assert(c, lprops->lnum == data.lnum);
+       ubifs_assert(c, lprops->free + lprops->dirty == c->leb_size);
+       ubifs_assert(c, !(lprops->flags & LPROPS_TAKEN));
+       ubifs_assert(c, !(lprops->flags & LPROPS_INDEX));
        return lprops;
 }
 
@@ -690,7 +690,7 @@ int ubifs_find_free_leb_for_idx(struct ubifs_info *c)
                         */
                        if (c->in_a_category_cnt != c->main_lebs ||
                            c->lst.empty_lebs - c->lst.taken_empty_lebs > 0) {
-                               ubifs_assert(c->freeable_cnt == 0);
+                               ubifs_assert(c, c->freeable_cnt == 0);
                                lprops = scan_for_leb_for_idx(c);
                                if (IS_ERR(lprops)) {
                                        err = PTR_ERR(lprops);
@@ -750,10 +750,7 @@ static int cmp_dirty_idx(const struct ubifs_lprops **a,
 static void swap_dirty_idx(struct ubifs_lprops **a, struct ubifs_lprops **b,
                           int size)
 {
-       struct ubifs_lprops *t = *a;
-
-       *a = *b;
-       *b = t;
+       swap(*a, *b);
 }
 
 /**
@@ -870,15 +867,15 @@ static int find_dirty_idx_leb(struct ubifs_info *c)
        if (err)
                return err;
 found:
-       ubifs_assert(data.lnum >= c->main_first && data.lnum < c->leb_cnt);
+       ubifs_assert(c, data.lnum >= c->main_first && data.lnum < c->leb_cnt);
        c->lscan_lnum = data.lnum;
        lprops = ubifs_lpt_lookup_dirty(c, data.lnum);
        if (IS_ERR(lprops))
                return PTR_ERR(lprops);
-       ubifs_assert(lprops->lnum == data.lnum);
-       ubifs_assert(lprops->free + lprops->dirty >= c->min_idx_node_sz);
-       ubifs_assert(!(lprops->flags & LPROPS_TAKEN));
-       ubifs_assert((lprops->flags & LPROPS_INDEX));
+       ubifs_assert(c, lprops->lnum == data.lnum);
+       ubifs_assert(c, lprops->free + lprops->dirty >= c->min_idx_node_sz);
+       ubifs_assert(c, !(lprops->flags & LPROPS_TAKEN));
+       ubifs_assert(c, (lprops->flags & LPROPS_INDEX));
 
        dbg_find("found dirty LEB %d, free %d, dirty %d, flags %#x",
                 lprops->lnum, lprops->free, lprops->dirty, lprops->flags);
@@ -947,8 +944,8 @@ static int find_dirtiest_idx_leb(struct ubifs_info *c)
        }
        dbg_find("LEB %d, dirty %d and free %d flags %#x", lp->lnum, lp->dirty,
                 lp->free, lp->flags);
-       ubifs_assert(lp->flags & LPROPS_TAKEN);
-       ubifs_assert(lp->flags & LPROPS_INDEX);
+       ubifs_assert(c, lp->flags & LPROPS_TAKEN);
+       ubifs_assert(c, lp->flags & LPROPS_INDEX);
        return lnum;
 }
 
index a03a47c..d2680e0 100644 (file)
@@ -83,7 +83,7 @@ static int switch_gc_head(struct ubifs_info *c)
        int err, gc_lnum = c->gc_lnum;
        struct ubifs_wbuf *wbuf = &c->jheads[GCHD].wbuf;
 
-       ubifs_assert(gc_lnum != -1);
+       ubifs_assert(c, gc_lnum != -1);
        dbg_gc("switch GC head from LEB %d:%d to LEB %d (waste %d bytes)",
               wbuf->lnum, wbuf->offs + wbuf->used, gc_lnum,
               c->leb_size - wbuf->offs - wbuf->used);
@@ -131,10 +131,10 @@ static int data_nodes_cmp(void *priv, struct list_head *a, struct list_head *b)
        sa = list_entry(a, struct ubifs_scan_node, list);
        sb = list_entry(b, struct ubifs_scan_node, list);
 
-       ubifs_assert(key_type(c, &sa->key) == UBIFS_DATA_KEY);
-       ubifs_assert(key_type(c, &sb->key) == UBIFS_DATA_KEY);
-       ubifs_assert(sa->type == UBIFS_DATA_NODE);
-       ubifs_assert(sb->type == UBIFS_DATA_NODE);
+       ubifs_assert(c, key_type(c, &sa->key) == UBIFS_DATA_KEY);
+       ubifs_assert(c, key_type(c, &sb->key) == UBIFS_DATA_KEY);
+       ubifs_assert(c, sa->type == UBIFS_DATA_NODE);
+       ubifs_assert(c, sb->type == UBIFS_DATA_NODE);
 
        inuma = key_inum(c, &sa->key);
        inumb = key_inum(c, &sb->key);
@@ -175,9 +175,9 @@ static int nondata_nodes_cmp(void *priv, struct list_head *a,
        sa = list_entry(a, struct ubifs_scan_node, list);
        sb = list_entry(b, struct ubifs_scan_node, list);
 
-       ubifs_assert(key_type(c, &sa->key) != UBIFS_DATA_KEY &&
+       ubifs_assert(c, key_type(c, &sa->key) != UBIFS_DATA_KEY &&
                     key_type(c, &sb->key) != UBIFS_DATA_KEY);
-       ubifs_assert(sa->type != UBIFS_DATA_NODE &&
+       ubifs_assert(c, sa->type != UBIFS_DATA_NODE &&
                     sb->type != UBIFS_DATA_NODE);
 
        /* Inodes go before directory entries */
@@ -189,13 +189,13 @@ static int nondata_nodes_cmp(void *priv, struct list_head *a,
        if (sb->type == UBIFS_INO_NODE)
                return 1;
 
-       ubifs_assert(key_type(c, &sa->key) == UBIFS_DENT_KEY ||
+       ubifs_assert(c, key_type(c, &sa->key) == UBIFS_DENT_KEY ||
                     key_type(c, &sa->key) == UBIFS_XENT_KEY);
-       ubifs_assert(key_type(c, &sb->key) == UBIFS_DENT_KEY ||
+       ubifs_assert(c, key_type(c, &sb->key) == UBIFS_DENT_KEY ||
                     key_type(c, &sb->key) == UBIFS_XENT_KEY);
-       ubifs_assert(sa->type == UBIFS_DENT_NODE ||
+       ubifs_assert(c, sa->type == UBIFS_DENT_NODE ||
                     sa->type == UBIFS_XENT_NODE);
-       ubifs_assert(sb->type == UBIFS_DENT_NODE ||
+       ubifs_assert(c, sb->type == UBIFS_DENT_NODE ||
                     sb->type == UBIFS_XENT_NODE);
 
        inuma = key_inum(c, &sa->key);
@@ -250,7 +250,7 @@ static int sort_nodes(struct ubifs_info *c, struct ubifs_scan_leb *sleb,
 
        /* Separate data nodes and non-data nodes */
        list_for_each_entry_safe(snod, tmp, &sleb->nodes, list) {
-               ubifs_assert(snod->type == UBIFS_INO_NODE  ||
+               ubifs_assert(c, snod->type == UBIFS_INO_NODE  ||
                             snod->type == UBIFS_DATA_NODE ||
                             snod->type == UBIFS_DENT_NODE ||
                             snod->type == UBIFS_XENT_NODE ||
@@ -266,7 +266,7 @@ static int sort_nodes(struct ubifs_info *c, struct ubifs_scan_leb *sleb,
                        continue;
                }
 
-               ubifs_assert(key_type(c, &snod->key) == UBIFS_DATA_KEY ||
+               ubifs_assert(c, key_type(c, &snod->key) == UBIFS_DATA_KEY ||
                             key_type(c, &snod->key) == UBIFS_INO_KEY  ||
                             key_type(c, &snod->key) == UBIFS_DENT_KEY ||
                             key_type(c, &snod->key) == UBIFS_XENT_KEY);
@@ -469,21 +469,21 @@ int ubifs_garbage_collect_leb(struct ubifs_info *c, struct ubifs_lprops *lp)
        struct ubifs_wbuf *wbuf = &c->jheads[GCHD].wbuf;
        int err = 0, lnum = lp->lnum;
 
-       ubifs_assert(c->gc_lnum != -1 || wbuf->offs + wbuf->used == 0 ||
+       ubifs_assert(c, c->gc_lnum != -1 || wbuf->offs + wbuf->used == 0 ||
                     c->need_recovery);
-       ubifs_assert(c->gc_lnum != lnum);
-       ubifs_assert(wbuf->lnum != lnum);
+       ubifs_assert(c, c->gc_lnum != lnum);
+       ubifs_assert(c, wbuf->lnum != lnum);
 
        if (lp->free + lp->dirty == c->leb_size) {
                /* Special case - a free LEB  */
                dbg_gc("LEB %d is free, return it", lp->lnum);
-               ubifs_assert(!(lp->flags & LPROPS_INDEX));
+               ubifs_assert(c, !(lp->flags & LPROPS_INDEX));
 
                if (lp->free != c->leb_size) {
                        /*
                         * Write buffers must be sync'd before unmapping
                         * freeable LEBs, because one of them may contain data
-                        * which obsoletes something in 'lp->pnum'.
+                        * which obsoletes something in 'lp->lnum'.
                         */
                        err = gc_sync_wbufs(c);
                        if (err)
@@ -513,7 +513,7 @@ int ubifs_garbage_collect_leb(struct ubifs_info *c, struct ubifs_lprops *lp)
        if (IS_ERR(sleb))
                return PTR_ERR(sleb);
 
-       ubifs_assert(!list_empty(&sleb->nodes));
+       ubifs_assert(c, !list_empty(&sleb->nodes));
        snod = list_entry(sleb->nodes.next, struct ubifs_scan_node, list);
 
        if (snod->type == UBIFS_IDX_NODE) {
@@ -525,7 +525,7 @@ int ubifs_garbage_collect_leb(struct ubifs_info *c, struct ubifs_lprops *lp)
                        struct ubifs_idx_node *idx = snod->node;
                        int level = le16_to_cpu(idx->level);
 
-                       ubifs_assert(snod->type == UBIFS_IDX_NODE);
+                       ubifs_assert(c, snod->type == UBIFS_IDX_NODE);
                        key_read(c, ubifs_idx_key(c, idx), &snod->key);
                        err = ubifs_dirty_idx_node(c, &snod->key, level, lnum,
                                                   snod->offs);
@@ -648,7 +648,7 @@ int ubifs_garbage_collect(struct ubifs_info *c, int anyway)
        struct ubifs_wbuf *wbuf = &c->jheads[GCHD].wbuf;
 
        ubifs_assert_cmt_locked(c);
-       ubifs_assert(!c->ro_media && !c->ro_mount);
+       ubifs_assert(c, !c->ro_media && !c->ro_mount);
 
        if (ubifs_gc_should_commit(c))
                return -EAGAIN;
@@ -661,7 +661,7 @@ int ubifs_garbage_collect(struct ubifs_info *c, int anyway)
        }
 
        /* We expect the write-buffer to be empty on entry */
-       ubifs_assert(!wbuf->used);
+       ubifs_assert(c, !wbuf->used);
 
        for (i = 0; ; i++) {
                int space_before, space_after;
@@ -752,7 +752,7 @@ int ubifs_garbage_collect(struct ubifs_info *c, int anyway)
                        continue;
                }
 
-               ubifs_assert(ret == LEB_RETAINED);
+               ubifs_assert(c, ret == LEB_RETAINED);
                space_after = c->leb_size - wbuf->offs - wbuf->used;
                dbg_gc("LEB %d retained, freed %d bytes", lp.lnum,
                       space_after - space_before);
@@ -812,8 +812,8 @@ out_unlock:
        return ret;
 
 out:
-       ubifs_assert(ret < 0);
-       ubifs_assert(ret != -ENOSPC && ret != -EAGAIN);
+       ubifs_assert(c, ret < 0);
+       ubifs_assert(c, ret != -ENOSPC && ret != -EAGAIN);
        ubifs_wbuf_sync_nolock(wbuf);
        ubifs_ro_mode(c, ret);
        mutex_unlock(&wbuf->io_mutex);
@@ -848,8 +848,8 @@ int ubifs_gc_start_commit(struct ubifs_info *c)
                lp = ubifs_fast_find_freeable(c);
                if (!lp)
                        break;
-               ubifs_assert(!(lp->flags & LPROPS_TAKEN));
-               ubifs_assert(!(lp->flags & LPROPS_INDEX));
+               ubifs_assert(c, !(lp->flags & LPROPS_TAKEN));
+               ubifs_assert(c, !(lp->flags & LPROPS_INDEX));
                err = ubifs_leb_unmap(c, lp->lnum);
                if (err)
                        goto out;
@@ -858,8 +858,8 @@ int ubifs_gc_start_commit(struct ubifs_info *c)
                        err = PTR_ERR(lp);
                        goto out;
                }
-               ubifs_assert(!(lp->flags & LPROPS_TAKEN));
-               ubifs_assert(!(lp->flags & LPROPS_INDEX));
+               ubifs_assert(c, !(lp->flags & LPROPS_TAKEN));
+               ubifs_assert(c, !(lp->flags & LPROPS_INDEX));
        }
 
        /* Mark GC'd index LEBs OK to unmap after this commit finishes */
@@ -880,8 +880,8 @@ int ubifs_gc_start_commit(struct ubifs_info *c)
                        err = -ENOMEM;
                        goto out;
                }
-               ubifs_assert(!(lp->flags & LPROPS_TAKEN));
-               ubifs_assert(lp->flags & LPROPS_INDEX);
+               ubifs_assert(c, !(lp->flags & LPROPS_TAKEN));
+               ubifs_assert(c, lp->flags & LPROPS_INDEX);
                /* Don't release the LEB until after the next commit */
                flags = (lp->flags | LPROPS_TAKEN) ^ LPROPS_INDEX;
                lp = ubifs_change_lp(c, lp, c->leb_size, 0, flags, 1);
@@ -890,8 +890,8 @@ int ubifs_gc_start_commit(struct ubifs_info *c)
                        kfree(idx_gc);
                        goto out;
                }
-               ubifs_assert(lp->flags & LPROPS_TAKEN);
-               ubifs_assert(!(lp->flags & LPROPS_INDEX));
+               ubifs_assert(c, lp->flags & LPROPS_TAKEN);
+               ubifs_assert(c, !(lp->flags & LPROPS_INDEX));
                idx_gc->lnum = lp->lnum;
                idx_gc->unmap = 1;
                list_add(&idx_gc->list, &c->idx_gc);
index fe77e96..099bec9 100644 (file)
@@ -119,7 +119,7 @@ int ubifs_leb_write(struct ubifs_info *c, int lnum, const void *buf, int offs,
 {
        int err;
 
-       ubifs_assert(!c->ro_media && !c->ro_mount);
+       ubifs_assert(c, !c->ro_media && !c->ro_mount);
        if (c->ro_error)
                return -EROFS;
        if (!dbg_is_tst_rcvry(c))
@@ -139,7 +139,7 @@ int ubifs_leb_change(struct ubifs_info *c, int lnum, const void *buf, int len)
 {
        int err;
 
-       ubifs_assert(!c->ro_media && !c->ro_mount);
+       ubifs_assert(c, !c->ro_media && !c->ro_mount);
        if (c->ro_error)
                return -EROFS;
        if (!dbg_is_tst_rcvry(c))
@@ -159,7 +159,7 @@ int ubifs_leb_unmap(struct ubifs_info *c, int lnum)
 {
        int err;
 
-       ubifs_assert(!c->ro_media && !c->ro_mount);
+       ubifs_assert(c, !c->ro_media && !c->ro_mount);
        if (c->ro_error)
                return -EROFS;
        if (!dbg_is_tst_rcvry(c))
@@ -178,7 +178,7 @@ int ubifs_leb_map(struct ubifs_info *c, int lnum)
 {
        int err;
 
-       ubifs_assert(!c->ro_media && !c->ro_mount);
+       ubifs_assert(c, !c->ro_media && !c->ro_mount);
        if (c->ro_error)
                return -EROFS;
        if (!dbg_is_tst_rcvry(c))
@@ -241,8 +241,8 @@ int ubifs_check_node(const struct ubifs_info *c, const void *buf, int lnum,
        uint32_t crc, node_crc, magic;
        const struct ubifs_ch *ch = buf;
 
-       ubifs_assert(lnum >= 0 && lnum < c->leb_cnt && offs >= 0);
-       ubifs_assert(!(offs & 7) && offs < c->leb_size);
+       ubifs_assert(c, lnum >= 0 && lnum < c->leb_cnt && offs >= 0);
+       ubifs_assert(c, !(offs & 7) && offs < c->leb_size);
 
        magic = le32_to_cpu(ch->magic);
        if (magic != UBIFS_NODE_MAGIC) {
@@ -319,7 +319,7 @@ void ubifs_pad(const struct ubifs_info *c, void *buf, int pad)
 {
        uint32_t crc;
 
-       ubifs_assert(pad >= 0 && !(pad & 7));
+       ubifs_assert(c, pad >= 0 && !(pad & 7));
 
        if (pad >= UBIFS_PAD_NODE_SZ) {
                struct ubifs_ch *ch = buf;
@@ -382,7 +382,7 @@ void ubifs_prepare_node(struct ubifs_info *c, void *node, int len, int pad)
        struct ubifs_ch *ch = node;
        unsigned long long sqnum = next_sqnum(c);
 
-       ubifs_assert(len >= UBIFS_CH_SZ);
+       ubifs_assert(c, len >= UBIFS_CH_SZ);
 
        ch->magic = cpu_to_le32(UBIFS_NODE_MAGIC);
        ch->len = cpu_to_le32(len);
@@ -415,7 +415,7 @@ void ubifs_prep_grp_node(struct ubifs_info *c, void *node, int len, int last)
        struct ubifs_ch *ch = node;
        unsigned long long sqnum = next_sqnum(c);
 
-       ubifs_assert(len >= UBIFS_CH_SZ);
+       ubifs_assert(c, len >= UBIFS_CH_SZ);
 
        ch->magic = cpu_to_le32(UBIFS_NODE_MAGIC);
        ch->len = cpu_to_le32(len);
@@ -448,9 +448,10 @@ static enum hrtimer_restart wbuf_timer_callback_nolock(struct hrtimer *timer)
 
 /**
  * new_wbuf_timer - start new write-buffer timer.
+ * @c: UBIFS file-system description object
  * @wbuf: write-buffer descriptor
  */
-static void new_wbuf_timer_nolock(struct ubifs_wbuf *wbuf)
+static void new_wbuf_timer_nolock(struct ubifs_info *c, struct ubifs_wbuf *wbuf)
 {
        ktime_t softlimit = ms_to_ktime(dirty_writeback_interval * 10);
        unsigned long long delta = dirty_writeback_interval;
@@ -458,8 +459,8 @@ static void new_wbuf_timer_nolock(struct ubifs_wbuf *wbuf)
        /* centi to milli, milli to nano, then 10% */
        delta *= 10ULL * NSEC_PER_MSEC / 10ULL;
 
-       ubifs_assert(!hrtimer_active(&wbuf->timer));
-       ubifs_assert(delta <= ULONG_MAX);
+       ubifs_assert(c, !hrtimer_active(&wbuf->timer));
+       ubifs_assert(c, delta <= ULONG_MAX);
 
        if (wbuf->no_timer)
                return;
@@ -508,14 +509,14 @@ int ubifs_wbuf_sync_nolock(struct ubifs_wbuf *wbuf)
 
        dbg_io("LEB %d:%d, %d bytes, jhead %s",
               wbuf->lnum, wbuf->offs, wbuf->used, dbg_jhead(wbuf->jhead));
-       ubifs_assert(!(wbuf->avail & 7));
-       ubifs_assert(wbuf->offs + wbuf->size <= c->leb_size);
-       ubifs_assert(wbuf->size >= c->min_io_size);
-       ubifs_assert(wbuf->size <= c->max_write_size);
-       ubifs_assert(wbuf->size % c->min_io_size == 0);
-       ubifs_assert(!c->ro_media && !c->ro_mount);
+       ubifs_assert(c, !(wbuf->avail & 7));
+       ubifs_assert(c, wbuf->offs + wbuf->size <= c->leb_size);
+       ubifs_assert(c, wbuf->size >= c->min_io_size);
+       ubifs_assert(c, wbuf->size <= c->max_write_size);
+       ubifs_assert(c, wbuf->size % c->min_io_size == 0);
+       ubifs_assert(c, !c->ro_media && !c->ro_mount);
        if (c->leb_size - wbuf->offs >= c->max_write_size)
-               ubifs_assert(!((wbuf->offs + wbuf->size) % c->max_write_size));
+               ubifs_assert(c, !((wbuf->offs + wbuf->size) % c->max_write_size));
 
        if (c->ro_error)
                return -EROFS;
@@ -576,11 +577,11 @@ int ubifs_wbuf_seek_nolock(struct ubifs_wbuf *wbuf, int lnum, int offs)
        const struct ubifs_info *c = wbuf->c;
 
        dbg_io("LEB %d:%d, jhead %s", lnum, offs, dbg_jhead(wbuf->jhead));
-       ubifs_assert(lnum >= 0 && lnum < c->leb_cnt);
-       ubifs_assert(offs >= 0 && offs <= c->leb_size);
-       ubifs_assert(offs % c->min_io_size == 0 && !(offs & 7));
-       ubifs_assert(lnum != wbuf->lnum);
-       ubifs_assert(wbuf->used == 0);
+       ubifs_assert(c, lnum >= 0 && lnum < c->leb_cnt);
+       ubifs_assert(c, offs >= 0 && offs <= c->leb_size);
+       ubifs_assert(c, offs % c->min_io_size == 0 && !(offs & 7));
+       ubifs_assert(c, lnum != wbuf->lnum);
+       ubifs_assert(c, wbuf->used == 0);
 
        spin_lock(&wbuf->lock);
        wbuf->lnum = lnum;
@@ -610,7 +611,7 @@ int ubifs_bg_wbufs_sync(struct ubifs_info *c)
 {
        int err, i;
 
-       ubifs_assert(!c->ro_media && !c->ro_mount);
+       ubifs_assert(c, !c->ro_media && !c->ro_mount);
        if (!c->need_wbuf_sync)
                return 0;
        c->need_wbuf_sync = 0;
@@ -686,18 +687,18 @@ int ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len)
        dbg_io("%d bytes (%s) to jhead %s wbuf at LEB %d:%d", len,
               dbg_ntype(((struct ubifs_ch *)buf)->node_type),
               dbg_jhead(wbuf->jhead), wbuf->lnum, wbuf->offs + wbuf->used);
-       ubifs_assert(len > 0 && wbuf->lnum >= 0 && wbuf->lnum < c->leb_cnt);
-       ubifs_assert(wbuf->offs >= 0 && wbuf->offs % c->min_io_size == 0);
-       ubifs_assert(!(wbuf->offs & 7) && wbuf->offs <= c->leb_size);
-       ubifs_assert(wbuf->avail > 0 && wbuf->avail <= wbuf->size);
-       ubifs_assert(wbuf->size >= c->min_io_size);
-       ubifs_assert(wbuf->size <= c->max_write_size);
-       ubifs_assert(wbuf->size % c->min_io_size == 0);
-       ubifs_assert(mutex_is_locked(&wbuf->io_mutex));
-       ubifs_assert(!c->ro_media && !c->ro_mount);
-       ubifs_assert(!c->space_fixup);
+       ubifs_assert(c, len > 0 && wbuf->lnum >= 0 && wbuf->lnum < c->leb_cnt);
+       ubifs_assert(c, wbuf->offs >= 0 && wbuf->offs % c->min_io_size == 0);
+       ubifs_assert(c, !(wbuf->offs & 7) && wbuf->offs <= c->leb_size);
+       ubifs_assert(c, wbuf->avail > 0 && wbuf->avail <= wbuf->size);
+       ubifs_assert(c, wbuf->size >= c->min_io_size);
+       ubifs_assert(c, wbuf->size <= c->max_write_size);
+       ubifs_assert(c, wbuf->size % c->min_io_size == 0);
+       ubifs_assert(c, mutex_is_locked(&wbuf->io_mutex));
+       ubifs_assert(c, !c->ro_media && !c->ro_mount);
+       ubifs_assert(c, !c->space_fixup);
        if (c->leb_size - wbuf->offs >= c->max_write_size)
-               ubifs_assert(!((wbuf->offs + wbuf->size) % c->max_write_size));
+               ubifs_assert(c, !((wbuf->offs + wbuf->size) % c->max_write_size));
 
        if (c->leb_size - wbuf->offs - wbuf->used < aligned_len) {
                err = -ENOSPC;
@@ -834,7 +835,7 @@ exit:
        }
 
        if (wbuf->used)
-               new_wbuf_timer_nolock(wbuf);
+               new_wbuf_timer_nolock(c, wbuf);
 
        return 0;
 
@@ -869,10 +870,10 @@ int ubifs_write_node(struct ubifs_info *c, void *buf, int len, int lnum,
        dbg_io("LEB %d:%d, %s, length %d (aligned %d)",
               lnum, offs, dbg_ntype(((struct ubifs_ch *)buf)->node_type), len,
               buf_len);
-       ubifs_assert(lnum >= 0 && lnum < c->leb_cnt && offs >= 0);
-       ubifs_assert(offs % c->min_io_size == 0 && offs < c->leb_size);
-       ubifs_assert(!c->ro_media && !c->ro_mount);
-       ubifs_assert(!c->space_fixup);
+       ubifs_assert(c, lnum >= 0 && lnum < c->leb_cnt && offs >= 0);
+       ubifs_assert(c, offs % c->min_io_size == 0 && offs < c->leb_size);
+       ubifs_assert(c, !c->ro_media && !c->ro_mount);
+       ubifs_assert(c, !c->space_fixup);
 
        if (c->ro_error)
                return -EROFS;
@@ -909,9 +910,9 @@ int ubifs_read_node_wbuf(struct ubifs_wbuf *wbuf, void *buf, int type, int len,
 
        dbg_io("LEB %d:%d, %s, length %d, jhead %s", lnum, offs,
               dbg_ntype(type), len, dbg_jhead(wbuf->jhead));
-       ubifs_assert(wbuf && lnum >= 0 && lnum < c->leb_cnt && offs >= 0);
-       ubifs_assert(!(offs & 7) && offs < c->leb_size);
-       ubifs_assert(type >= 0 && type < UBIFS_NODE_TYPES_CNT);
+       ubifs_assert(c, wbuf && lnum >= 0 && lnum < c->leb_cnt && offs >= 0);
+       ubifs_assert(c, !(offs & 7) && offs < c->leb_size);
+       ubifs_assert(c, type >= 0 && type < UBIFS_NODE_TYPES_CNT);
 
        spin_lock(&wbuf->lock);
        overlap = (lnum == wbuf->lnum && offs + len > wbuf->offs);
@@ -984,10 +985,10 @@ int ubifs_read_node(const struct ubifs_info *c, void *buf, int type, int len,
        struct ubifs_ch *ch = buf;
 
        dbg_io("LEB %d:%d, %s, length %d", lnum, offs, dbg_ntype(type), len);
-       ubifs_assert(lnum >= 0 && lnum < c->leb_cnt && offs >= 0);
-       ubifs_assert(len >= UBIFS_CH_SZ && offs + len <= c->leb_size);
-       ubifs_assert(!(offs & 7) && offs < c->leb_size);
-       ubifs_assert(type >= 0 && type < UBIFS_NODE_TYPES_CNT);
+       ubifs_assert(c, lnum >= 0 && lnum < c->leb_cnt && offs >= 0);
+       ubifs_assert(c, len >= UBIFS_CH_SZ && offs + len <= c->leb_size);
+       ubifs_assert(c, !(offs & 7) && offs < c->leb_size);
+       ubifs_assert(c, type >= 0 && type < UBIFS_NODE_TYPES_CNT);
 
        err = ubifs_leb_read(c, lnum, buf, offs, len, 0);
        if (err && err != -EBADMSG)
index 07b4956..802565a 100644 (file)
@@ -111,7 +111,7 @@ static int reserve_space(struct ubifs_info *c, int jhead, int len)
         * better to try to allocate space at the ends of eraseblocks. This is
         * what the squeeze parameter does.
         */
-       ubifs_assert(!c->ro_media && !c->ro_mount);
+       ubifs_assert(c, !c->ro_media && !c->ro_mount);
        squeeze = (jhead == BASEHD);
 again:
        mutex_lock_nested(&wbuf->io_mutex, wbuf->jhead);
@@ -215,7 +215,7 @@ out_unlock:
 
 out_return:
        /* An error occurred and the LEB has to be returned to lprops */
-       ubifs_assert(err < 0);
+       ubifs_assert(c, err < 0);
        err1 = ubifs_return_leb(c, lnum);
        if (err1 && err == -EAGAIN)
                /*
@@ -246,7 +246,7 @@ static int write_node(struct ubifs_info *c, int jhead, void *node, int len,
 {
        struct ubifs_wbuf *wbuf = &c->jheads[jhead].wbuf;
 
-       ubifs_assert(jhead != GCHD);
+       ubifs_assert(c, jhead != GCHD);
 
        *lnum = c->jheads[jhead].wbuf.lnum;
        *offs = c->jheads[jhead].wbuf.offs + c->jheads[jhead].wbuf.used;
@@ -278,7 +278,7 @@ static int write_head(struct ubifs_info *c, int jhead, void *buf, int len,
        int err;
        struct ubifs_wbuf *wbuf = &c->jheads[jhead].wbuf;
 
-       ubifs_assert(jhead != GCHD);
+       ubifs_assert(c, jhead != GCHD);
 
        *lnum = c->jheads[jhead].wbuf.lnum;
        *offs = c->jheads[jhead].wbuf.offs + c->jheads[jhead].wbuf.used;
@@ -317,6 +317,7 @@ again:
        down_read(&c->commit_sem);
        err = reserve_space(c, jhead, len);
        if (!err)
+               /* c->commit_sem will get released via finish_reservation(). */
                return 0;
        up_read(&c->commit_sem);
 
@@ -548,7 +549,7 @@ int ubifs_jnl_update(struct ubifs_info *c, const struct inode *dir,
        struct ubifs_ino_node *ino;
        union ubifs_key dent_key, ino_key;
 
-       ubifs_assert(mutex_is_locked(&host_ui->ui_mutex));
+       ubifs_assert(c, mutex_is_locked(&host_ui->ui_mutex));
 
        dlen = UBIFS_DENT_NODE_SZ + fname_len(nm) + 1;
        ilen = UBIFS_INO_NODE_SZ;
@@ -664,6 +665,11 @@ int ubifs_jnl_update(struct ubifs_info *c, const struct inode *dir,
        spin_lock(&ui->ui_lock);
        ui->synced_i_size = ui->ui_size;
        spin_unlock(&ui->ui_lock);
+       if (xent) {
+               spin_lock(&host_ui->ui_lock);
+               host_ui->synced_i_size = host_ui->ui_size;
+               spin_unlock(&host_ui->ui_lock);
+       }
        mark_inode_clean(c, ui);
        mark_inode_clean(c, host_ui);
        return 0;
@@ -707,7 +713,7 @@ int ubifs_jnl_write_data(struct ubifs_info *c, const struct inode *inode,
 
        dbg_jnlk(key, "ino %lu, blk %u, len %d, key ",
                (unsigned long)key_inum(c, key), key_block(c, key), len);
-       ubifs_assert(len <= UBIFS_BLOCK_SIZE);
+       ubifs_assert(c, len <= UBIFS_BLOCK_SIZE);
 
        if (encrypted)
                dlen += UBIFS_CIPHER_BLOCK_SIZE;
@@ -738,7 +744,7 @@ int ubifs_jnl_write_data(struct ubifs_info *c, const struct inode *inode,
 
        out_len = compr_len = dlen - UBIFS_DATA_NODE_SZ;
        ubifs_compress(c, buf, len, &data->data, &compr_len, &compr_type);
-       ubifs_assert(compr_len <= UBIFS_BLOCK_SIZE);
+       ubifs_assert(c, compr_len <= UBIFS_BLOCK_SIZE);
 
        if (encrypted) {
                err = ubifs_encrypt(inode, data, compr_len, &out_len, key_block(c, key));
@@ -898,7 +904,7 @@ int ubifs_jnl_delete_inode(struct ubifs_info *c, const struct inode *inode)
        int err;
        struct ubifs_inode *ui = ubifs_inode(inode);
 
-       ubifs_assert(inode->i_nlink == 0);
+       ubifs_assert(c, inode->i_nlink == 0);
 
        if (ui->del_cmtno != c->cmt_no)
                /* A commit happened for sure */
@@ -953,10 +959,10 @@ int ubifs_jnl_xrename(struct ubifs_info *c, const struct inode *fst_dir,
        int twoparents = (fst_dir != snd_dir);
        void *p;
 
-       ubifs_assert(ubifs_inode(fst_dir)->data_len == 0);
-       ubifs_assert(ubifs_inode(snd_dir)->data_len == 0);
-       ubifs_assert(mutex_is_locked(&ubifs_inode(fst_dir)->ui_mutex));
-       ubifs_assert(mutex_is_locked(&ubifs_inode(snd_dir)->ui_mutex));
+       ubifs_assert(c, ubifs_inode(fst_dir)->data_len == 0);
+       ubifs_assert(c, ubifs_inode(snd_dir)->data_len == 0);
+       ubifs_assert(c, mutex_is_locked(&ubifs_inode(fst_dir)->ui_mutex));
+       ubifs_assert(c, mutex_is_locked(&ubifs_inode(snd_dir)->ui_mutex));
 
        dlen1 = UBIFS_DENT_NODE_SZ + fname_len(snd_nm) + 1;
        dlen2 = UBIFS_DENT_NODE_SZ + fname_len(fst_nm) + 1;
@@ -1096,16 +1102,16 @@ int ubifs_jnl_rename(struct ubifs_info *c, const struct inode *old_dir,
        int move = (old_dir != new_dir);
        struct ubifs_inode *uninitialized_var(new_ui);
 
-       ubifs_assert(ubifs_inode(old_dir)->data_len == 0);
-       ubifs_assert(ubifs_inode(new_dir)->data_len == 0);
-       ubifs_assert(mutex_is_locked(&ubifs_inode(old_dir)->ui_mutex));
-       ubifs_assert(mutex_is_locked(&ubifs_inode(new_dir)->ui_mutex));
+       ubifs_assert(c, ubifs_inode(old_dir)->data_len == 0);
+       ubifs_assert(c, ubifs_inode(new_dir)->data_len == 0);
+       ubifs_assert(c, mutex_is_locked(&ubifs_inode(old_dir)->ui_mutex));
+       ubifs_assert(c, mutex_is_locked(&ubifs_inode(new_dir)->ui_mutex));
 
        dlen1 = UBIFS_DENT_NODE_SZ + fname_len(new_nm) + 1;
        dlen2 = UBIFS_DENT_NODE_SZ + fname_len(old_nm) + 1;
        if (new_inode) {
                new_ui = ubifs_inode(new_inode);
-               ubifs_assert(mutex_is_locked(&new_ui->ui_mutex));
+               ubifs_assert(c, mutex_is_locked(&new_ui->ui_mutex));
                ilen = UBIFS_INO_NODE_SZ;
                if (!last_reference)
                        ilen += new_ui->data_len;
@@ -1282,8 +1288,7 @@ static int truncate_data_node(const struct ubifs_info *c, const struct inode *in
                              int *new_len)
 {
        void *buf;
-       int err, compr_type;
-       u32 dlen, out_len, old_dlen;
+       int err, dlen, compr_type, out_len, old_dlen;
 
        out_len = le32_to_cpu(dn->size);
        buf = kmalloc_array(out_len, WORST_COMPR_FACTOR, GFP_NOFS);
@@ -1319,7 +1324,7 @@ static int truncate_data_node(const struct ubifs_info *c, const struct inode *in
                dn->compr_size = 0;
        }
 
-       ubifs_assert(out_len <= UBIFS_BLOCK_SIZE);
+       ubifs_assert(c, out_len <= UBIFS_BLOCK_SIZE);
        dn->compr_type = cpu_to_le16(compr_type);
        dn->size = cpu_to_le32(*new_len);
        *new_len = UBIFS_DATA_NODE_SZ + out_len;
@@ -1358,9 +1363,9 @@ int ubifs_jnl_truncate(struct ubifs_info *c, const struct inode *inode,
 
        dbg_jnl("ino %lu, size %lld -> %lld",
                (unsigned long)inum, old_size, new_size);
-       ubifs_assert(!ui->data_len);
-       ubifs_assert(S_ISREG(inode->i_mode));
-       ubifs_assert(mutex_is_locked(&ui->ui_mutex));
+       ubifs_assert(c, !ui->data_len);
+       ubifs_assert(c, S_ISREG(inode->i_mode));
+       ubifs_assert(c, mutex_is_locked(&ui->ui_mutex));
 
        sz = UBIFS_TRUN_NODE_SZ + UBIFS_INO_NODE_SZ +
             UBIFS_MAX_DATA_NODE_SZ * WORST_COMPR_FACTOR;
@@ -1388,7 +1393,16 @@ int ubifs_jnl_truncate(struct ubifs_info *c, const struct inode *inode,
                else if (err)
                        goto out_free;
                else {
-                       if (le32_to_cpu(dn->size) <= dlen)
+                       int dn_len = le32_to_cpu(dn->size);
+
+                       if (dn_len <= 0 || dn_len > UBIFS_BLOCK_SIZE) {
+                               ubifs_err(c, "bad data node (block %u, inode %lu)",
+                                         blk, inode->i_ino);
+                               ubifs_dump_node(c, dn);
+                               goto out_free;
+                       }
+
+                       if (dn_len <= dlen)
                                dlen = 0; /* Nothing to do */
                        else {
                                err = truncate_data_node(c, inode, blk, dn, &dlen);
@@ -1488,8 +1502,8 @@ int ubifs_jnl_delete_xattr(struct ubifs_info *c, const struct inode *host,
        int sync = IS_DIRSYNC(host);
        struct ubifs_inode *host_ui = ubifs_inode(host);
 
-       ubifs_assert(inode->i_nlink == 0);
-       ubifs_assert(mutex_is_locked(&host_ui->ui_mutex));
+       ubifs_assert(c, inode->i_nlink == 0);
+       ubifs_assert(c, mutex_is_locked(&host_ui->ui_mutex));
 
        /*
         * Since we are deleting the inode, we do not bother to attach any data
@@ -1598,9 +1612,9 @@ int ubifs_jnl_change_xattr(struct ubifs_info *c, const struct inode *inode,
        int sync = IS_DIRSYNC(host);
 
        dbg_jnl("ino %lu, ino %lu", host->i_ino, inode->i_ino);
-       ubifs_assert(host->i_nlink > 0);
-       ubifs_assert(inode->i_nlink > 0);
-       ubifs_assert(mutex_is_locked(&host_ui->ui_mutex));
+       ubifs_assert(c, host->i_nlink > 0);
+       ubifs_assert(c, inode->i_nlink > 0);
+       ubifs_assert(c, mutex_is_locked(&host_ui->ui_mutex));
 
        len1 = UBIFS_INO_NODE_SZ + host_ui->data_len;
        len2 = UBIFS_INO_NODE_SZ + ubifs_inode(inode)->data_len;
index b1f7c0c..2feff6c 100644 (file)
@@ -161,8 +161,8 @@ static inline void dent_key_init(const struct ubifs_info *c,
 {
        uint32_t hash = c->key_hash(fname_name(nm), fname_len(nm));
 
-       ubifs_assert(!(hash & ~UBIFS_S_KEY_HASH_MASK));
-       ubifs_assert(!nm->hash && !nm->minor_hash);
+       ubifs_assert(c, !(hash & ~UBIFS_S_KEY_HASH_MASK));
+       ubifs_assert(c, !nm->hash && !nm->minor_hash);
        key->u32[0] = inum;
        key->u32[1] = hash | (UBIFS_DENT_KEY << UBIFS_S_KEY_HASH_BITS);
 }
@@ -179,7 +179,7 @@ static inline void dent_key_init_hash(const struct ubifs_info *c,
                                      union ubifs_key *key, ino_t inum,
                                      uint32_t hash)
 {
-       ubifs_assert(!(hash & ~UBIFS_S_KEY_HASH_MASK));
+       ubifs_assert(c, !(hash & ~UBIFS_S_KEY_HASH_MASK));
        key->u32[0] = inum;
        key->u32[1] = hash | (UBIFS_DENT_KEY << UBIFS_S_KEY_HASH_BITS);
 }
@@ -198,7 +198,7 @@ static inline void dent_key_init_flash(const struct ubifs_info *c, void *k,
        union ubifs_key *key = k;
        uint32_t hash = c->key_hash(fname_name(nm), fname_len(nm));
 
-       ubifs_assert(!(hash & ~UBIFS_S_KEY_HASH_MASK));
+       ubifs_assert(c, !(hash & ~UBIFS_S_KEY_HASH_MASK));
        key->j32[0] = cpu_to_le32(inum);
        key->j32[1] = cpu_to_le32(hash |
                                  (UBIFS_DENT_KEY << UBIFS_S_KEY_HASH_BITS));
@@ -231,7 +231,7 @@ static inline void xent_key_init(const struct ubifs_info *c,
 {
        uint32_t hash = c->key_hash(fname_name(nm), fname_len(nm));
 
-       ubifs_assert(!(hash & ~UBIFS_S_KEY_HASH_MASK));
+       ubifs_assert(c, !(hash & ~UBIFS_S_KEY_HASH_MASK));
        key->u32[0] = inum;
        key->u32[1] = hash | (UBIFS_XENT_KEY << UBIFS_S_KEY_HASH_BITS);
 }
@@ -249,7 +249,7 @@ static inline void xent_key_init_flash(const struct ubifs_info *c, void *k,
        union ubifs_key *key = k;
        uint32_t hash = c->key_hash(fname_name(nm), fname_len(nm));
 
-       ubifs_assert(!(hash & ~UBIFS_S_KEY_HASH_MASK));
+       ubifs_assert(c, !(hash & ~UBIFS_S_KEY_HASH_MASK));
        key->j32[0] = cpu_to_le32(inum);
        key->j32[1] = cpu_to_le32(hash |
                                  (UBIFS_XENT_KEY << UBIFS_S_KEY_HASH_BITS));
@@ -280,7 +280,7 @@ static inline void data_key_init(const struct ubifs_info *c,
                                 union ubifs_key *key, ino_t inum,
                                 unsigned int block)
 {
-       ubifs_assert(!(block & ~UBIFS_S_KEY_BLOCK_MASK));
+       ubifs_assert(c, !(block & ~UBIFS_S_KEY_BLOCK_MASK));
        key->u32[0] = inum;
        key->u32[1] = block | (UBIFS_DATA_KEY << UBIFS_S_KEY_BLOCK_BITS);
 }
index 7cffa12..86b0828 100644 (file)
@@ -132,7 +132,7 @@ void ubifs_add_bud(struct ubifs_info *c, struct ubifs_bud *bud)
        while (*p) {
                parent = *p;
                b = rb_entry(parent, struct ubifs_bud, rb);
-               ubifs_assert(bud->lnum != b->lnum);
+               ubifs_assert(c, bud->lnum != b->lnum);
                if (bud->lnum < b->lnum)
                        p = &(*p)->rb_left;
                else
@@ -145,7 +145,7 @@ void ubifs_add_bud(struct ubifs_info *c, struct ubifs_bud *bud)
                jhead = &c->jheads[bud->jhead];
                list_add_tail(&bud->list, &jhead->buds_list);
        } else
-               ubifs_assert(c->replaying && c->ro_mount);
+               ubifs_assert(c, c->replaying && c->ro_mount);
 
        /*
         * Note, although this is a new bud, we anyway account this space now,
@@ -189,7 +189,7 @@ int ubifs_add_bud_to_log(struct ubifs_info *c, int jhead, int lnum, int offs)
        }
 
        mutex_lock(&c->log_mutex);
-       ubifs_assert(!c->ro_media && !c->ro_mount);
+       ubifs_assert(c, !c->ro_media && !c->ro_mount);
        if (c->ro_error) {
                err = -EROFS;
                goto out_unlock;
@@ -244,7 +244,7 @@ int ubifs_add_bud_to_log(struct ubifs_info *c, int jhead, int lnum, int offs)
 
        if (c->lhead_offs > c->leb_size - c->ref_node_alsz) {
                c->lhead_lnum = ubifs_next_log_lnum(c, c->lhead_lnum);
-               ubifs_assert(c->lhead_lnum != c->ltail_lnum);
+               ubifs_assert(c, c->lhead_lnum != c->ltail_lnum);
                c->lhead_offs = 0;
        }
 
@@ -301,7 +301,7 @@ static void remove_buds(struct ubifs_info *c)
 {
        struct rb_node *p;
 
-       ubifs_assert(list_empty(&c->old_buds));
+       ubifs_assert(c, list_empty(&c->old_buds));
        c->cmt_bud_bytes = 0;
        spin_lock(&c->buds_lock);
        p = rb_first(&c->buds);
@@ -409,7 +409,7 @@ int ubifs_log_start_commit(struct ubifs_info *c, int *ltail_lnum)
        /* Switch to the next log LEB */
        if (c->lhead_offs) {
                c->lhead_lnum = ubifs_next_log_lnum(c, c->lhead_lnum);
-               ubifs_assert(c->lhead_lnum != c->ltail_lnum);
+               ubifs_assert(c, c->lhead_lnum != c->ltail_lnum);
                c->lhead_offs = 0;
        }
 
index f5a4684..fa8d775 100644 (file)
@@ -187,9 +187,9 @@ static int add_to_lpt_heap(struct ubifs_info *c, struct ubifs_lprops *lprops,
                /* Compare to some other LEB on the bottom of heap */
                /* Pick a position kind of randomly */
                cpos = (((size_t)lprops >> 4) & b) + b;
-               ubifs_assert(cpos >= b);
-               ubifs_assert(cpos < LPT_HEAP_SZ);
-               ubifs_assert(cpos < heap->cnt);
+               ubifs_assert(c, cpos >= b);
+               ubifs_assert(c, cpos < LPT_HEAP_SZ);
+               ubifs_assert(c, cpos < heap->cnt);
 
                val1 = get_heap_comp_val(lprops, cat);
                val2 = get_heap_comp_val(heap->arr[cpos], cat);
@@ -230,8 +230,8 @@ static void remove_from_lpt_heap(struct ubifs_info *c,
        int hpos = lprops->hpos;
 
        heap = &c->lpt_heap[cat - 1];
-       ubifs_assert(hpos >= 0 && hpos < heap->cnt);
-       ubifs_assert(heap->arr[hpos] == lprops);
+       ubifs_assert(c, hpos >= 0 && hpos < heap->cnt);
+       ubifs_assert(c, heap->arr[hpos] == lprops);
        heap->cnt -= 1;
        if (hpos < heap->cnt) {
                heap->arr[hpos] = heap->arr[heap->cnt];
@@ -296,13 +296,13 @@ void ubifs_add_to_cat(struct ubifs_info *c, struct ubifs_lprops *lprops,
                list_add(&lprops->list, &c->frdi_idx_list);
                break;
        default:
-               ubifs_assert(0);
+               ubifs_assert(c, 0);
        }
 
        lprops->flags &= ~LPROPS_CAT_MASK;
        lprops->flags |= cat;
        c->in_a_category_cnt += 1;
-       ubifs_assert(c->in_a_category_cnt <= c->main_lebs);
+       ubifs_assert(c, c->in_a_category_cnt <= c->main_lebs);
 }
 
 /**
@@ -324,20 +324,20 @@ static void ubifs_remove_from_cat(struct ubifs_info *c,
                break;
        case LPROPS_FREEABLE:
                c->freeable_cnt -= 1;
-               ubifs_assert(c->freeable_cnt >= 0);
+               ubifs_assert(c, c->freeable_cnt >= 0);
                /* Fall through */
        case LPROPS_UNCAT:
        case LPROPS_EMPTY:
        case LPROPS_FRDI_IDX:
-               ubifs_assert(!list_empty(&lprops->list));
+               ubifs_assert(c, !list_empty(&lprops->list));
                list_del(&lprops->list);
                break;
        default:
-               ubifs_assert(0);
+               ubifs_assert(c, 0);
        }
 
        c->in_a_category_cnt -= 1;
-       ubifs_assert(c->in_a_category_cnt >= 0);
+       ubifs_assert(c, c->in_a_category_cnt >= 0);
 }
 
 /**
@@ -369,7 +369,7 @@ void ubifs_replace_cat(struct ubifs_info *c, struct ubifs_lprops *old_lprops,
                list_replace(&old_lprops->list, &new_lprops->list);
                break;
        default:
-               ubifs_assert(0);
+               ubifs_assert(c, 0);
        }
 }
 
@@ -412,7 +412,7 @@ int ubifs_categorize_lprops(const struct ubifs_info *c,
                return LPROPS_UNCAT;
 
        if (lprops->free == c->leb_size) {
-               ubifs_assert(!(lprops->flags & LPROPS_INDEX));
+               ubifs_assert(c, !(lprops->flags & LPROPS_INDEX));
                return LPROPS_EMPTY;
        }
 
@@ -478,7 +478,7 @@ static void change_category(struct ubifs_info *c, struct ubifs_lprops *lprops)
  */
 int ubifs_calc_dark(const struct ubifs_info *c, int spc)
 {
-       ubifs_assert(!(spc & 7));
+       ubifs_assert(c, !(spc & 7));
 
        if (spc < c->dark_wm)
                return spc;
@@ -543,27 +543,27 @@ const struct ubifs_lprops *ubifs_change_lp(struct ubifs_info *c,
        dbg_lp("LEB %d, free %d, dirty %d, flags %d",
               lprops->lnum, free, dirty, flags);
 
-       ubifs_assert(mutex_is_locked(&c->lp_mutex));
-       ubifs_assert(c->lst.empty_lebs >= 0 &&
+       ubifs_assert(c, mutex_is_locked(&c->lp_mutex));
+       ubifs_assert(c, c->lst.empty_lebs >= 0 &&
                     c->lst.empty_lebs <= c->main_lebs);
-       ubifs_assert(c->freeable_cnt >= 0);
-       ubifs_assert(c->freeable_cnt <= c->main_lebs);
-       ubifs_assert(c->lst.taken_empty_lebs >= 0);
-       ubifs_assert(c->lst.taken_empty_lebs <= c->lst.empty_lebs);
-       ubifs_assert(!(c->lst.total_free & 7) && !(c->lst.total_dirty & 7));
-       ubifs_assert(!(c->lst.total_dead & 7) && !(c->lst.total_dark & 7));
-       ubifs_assert(!(c->lst.total_used & 7));
-       ubifs_assert(free == LPROPS_NC || free >= 0);
-       ubifs_assert(dirty == LPROPS_NC || dirty >= 0);
+       ubifs_assert(c, c->freeable_cnt >= 0);
+       ubifs_assert(c, c->freeable_cnt <= c->main_lebs);
+       ubifs_assert(c, c->lst.taken_empty_lebs >= 0);
+       ubifs_assert(c, c->lst.taken_empty_lebs <= c->lst.empty_lebs);
+       ubifs_assert(c, !(c->lst.total_free & 7) && !(c->lst.total_dirty & 7));
+       ubifs_assert(c, !(c->lst.total_dead & 7) && !(c->lst.total_dark & 7));
+       ubifs_assert(c, !(c->lst.total_used & 7));
+       ubifs_assert(c, free == LPROPS_NC || free >= 0);
+       ubifs_assert(c, dirty == LPROPS_NC || dirty >= 0);
 
        if (!is_lprops_dirty(c, lprops)) {
                lprops = ubifs_lpt_lookup_dirty(c, lprops->lnum);
                if (IS_ERR(lprops))
                        return lprops;
        } else
-               ubifs_assert(lprops == ubifs_lpt_lookup_dirty(c, lprops->lnum));
+               ubifs_assert(c, lprops == ubifs_lpt_lookup_dirty(c, lprops->lnum));
 
-       ubifs_assert(!(lprops->free & 7) && !(lprops->dirty & 7));
+       ubifs_assert(c, !(lprops->free & 7) && !(lprops->dirty & 7));
 
        spin_lock(&c->space_lock);
        if ((lprops->flags & LPROPS_TAKEN) && lprops->free == c->leb_size)
@@ -768,15 +768,15 @@ const struct ubifs_lprops *ubifs_fast_find_free(struct ubifs_info *c)
        struct ubifs_lprops *lprops;
        struct ubifs_lpt_heap *heap;
 
-       ubifs_assert(mutex_is_locked(&c->lp_mutex));
+       ubifs_assert(c, mutex_is_locked(&c->lp_mutex));
 
        heap = &c->lpt_heap[LPROPS_FREE - 1];
        if (heap->cnt == 0)
                return NULL;
 
        lprops = heap->arr[0];
-       ubifs_assert(!(lprops->flags & LPROPS_TAKEN));
-       ubifs_assert(!(lprops->flags & LPROPS_INDEX));
+       ubifs_assert(c, !(lprops->flags & LPROPS_TAKEN));
+       ubifs_assert(c, !(lprops->flags & LPROPS_INDEX));
        return lprops;
 }
 
@@ -791,15 +791,15 @@ const struct ubifs_lprops *ubifs_fast_find_empty(struct ubifs_info *c)
 {
        struct ubifs_lprops *lprops;
 
-       ubifs_assert(mutex_is_locked(&c->lp_mutex));
+       ubifs_assert(c, mutex_is_locked(&c->lp_mutex));
 
        if (list_empty(&c->empty_list))
                return NULL;
 
        lprops = list_entry(c->empty_list.next, struct ubifs_lprops, list);
-       ubifs_assert(!(lprops->flags & LPROPS_TAKEN));
-       ubifs_assert(!(lprops->flags & LPROPS_INDEX));
-       ubifs_assert(lprops->free == c->leb_size);
+       ubifs_assert(c, !(lprops->flags & LPROPS_TAKEN));
+       ubifs_assert(c, !(lprops->flags & LPROPS_INDEX));
+       ubifs_assert(c, lprops->free == c->leb_size);
        return lprops;
 }
 
@@ -814,16 +814,16 @@ const struct ubifs_lprops *ubifs_fast_find_freeable(struct ubifs_info *c)
 {
        struct ubifs_lprops *lprops;
 
-       ubifs_assert(mutex_is_locked(&c->lp_mutex));
+       ubifs_assert(c, mutex_is_locked(&c->lp_mutex));
 
        if (list_empty(&c->freeable_list))
                return NULL;
 
        lprops = list_entry(c->freeable_list.next, struct ubifs_lprops, list);
-       ubifs_assert(!(lprops->flags & LPROPS_TAKEN));
-       ubifs_assert(!(lprops->flags & LPROPS_INDEX));
-       ubifs_assert(lprops->free + lprops->dirty == c->leb_size);
-       ubifs_assert(c->freeable_cnt > 0);
+       ubifs_assert(c, !(lprops->flags & LPROPS_TAKEN));
+       ubifs_assert(c, !(lprops->flags & LPROPS_INDEX));
+       ubifs_assert(c, lprops->free + lprops->dirty == c->leb_size);
+       ubifs_assert(c, c->freeable_cnt > 0);
        return lprops;
 }
 
@@ -838,15 +838,15 @@ const struct ubifs_lprops *ubifs_fast_find_frdi_idx(struct ubifs_info *c)
 {
        struct ubifs_lprops *lprops;
 
-       ubifs_assert(mutex_is_locked(&c->lp_mutex));
+       ubifs_assert(c, mutex_is_locked(&c->lp_mutex));
 
        if (list_empty(&c->frdi_idx_list))
                return NULL;
 
        lprops = list_entry(c->frdi_idx_list.next, struct ubifs_lprops, list);
-       ubifs_assert(!(lprops->flags & LPROPS_TAKEN));
-       ubifs_assert((lprops->flags & LPROPS_INDEX));
-       ubifs_assert(lprops->free + lprops->dirty == c->leb_size);
+       ubifs_assert(c, !(lprops->flags & LPROPS_TAKEN));
+       ubifs_assert(c, (lprops->flags & LPROPS_INDEX));
+       ubifs_assert(c, lprops->free + lprops->dirty == c->leb_size);
        return lprops;
 }
 
@@ -1089,10 +1089,6 @@ static int scan_check_cb(struct ubifs_info *c,
                }
        }
 
-       buf = __vmalloc(c->leb_size, GFP_NOFS, PAGE_KERNEL);
-       if (!buf)
-               return -ENOMEM;
-
        /*
         * After an unclean unmount, empty and freeable LEBs
         * may contain garbage - do not scan them.
@@ -1111,6 +1107,10 @@ static int scan_check_cb(struct ubifs_info *c,
                return LPT_SCAN_CONTINUE;
        }
 
+       buf = __vmalloc(c->leb_size, GFP_NOFS, PAGE_KERNEL);
+       if (!buf)
+               return -ENOMEM;
+
        sleb = ubifs_scan(c, lnum, 0, buf, 0);
        if (IS_ERR(sleb)) {
                ret = PTR_ERR(sleb);
index 8e99dad..3139337 100644 (file)
@@ -225,21 +225,22 @@ static int calc_dflt_lpt_geom(struct ubifs_info *c, int *main_lebs,
 
 /**
  * pack_bits - pack bit fields end-to-end.
+ * @c: UBIFS file-system description object
  * @addr: address at which to pack (passed and next address returned)
  * @pos: bit position at which to pack (passed and next position returned)
  * @val: value to pack
  * @nrbits: number of bits of value to pack (1-32)
  */
-static void pack_bits(uint8_t **addr, int *pos, uint32_t val, int nrbits)
+static void pack_bits(const struct ubifs_info *c, uint8_t **addr, int *pos, uint32_t val, int nrbits)
 {
        uint8_t *p = *addr;
        int b = *pos;
 
-       ubifs_assert(nrbits > 0);
-       ubifs_assert(nrbits <= 32);
-       ubifs_assert(*pos >= 0);
-       ubifs_assert(*pos < 8);
-       ubifs_assert((val >> nrbits) == 0 || nrbits == 32);
+       ubifs_assert(c, nrbits > 0);
+       ubifs_assert(c, nrbits <= 32);
+       ubifs_assert(c, *pos >= 0);
+       ubifs_assert(c, *pos < 8);
+       ubifs_assert(c, (val >> nrbits) == 0 || nrbits == 32);
        if (b) {
                *p |= ((uint8_t)val) << b;
                nrbits += b;
@@ -274,13 +275,14 @@ static void pack_bits(uint8_t **addr, int *pos, uint32_t val, int nrbits)
 
 /**
  * ubifs_unpack_bits - unpack bit fields.
+ * @c: UBIFS file-system description object
  * @addr: address at which to unpack (passed and next address returned)
  * @pos: bit position at which to unpack (passed and next position returned)
  * @nrbits: number of bits of value to unpack (1-32)
  *
  * This functions returns the value unpacked.
  */
-uint32_t ubifs_unpack_bits(uint8_t **addr, int *pos, int nrbits)
+uint32_t ubifs_unpack_bits(const struct ubifs_info *c, uint8_t **addr, int *pos, int nrbits)
 {
        const int k = 32 - nrbits;
        uint8_t *p = *addr;
@@ -288,10 +290,10 @@ uint32_t ubifs_unpack_bits(uint8_t **addr, int *pos, int nrbits)
        uint32_t uninitialized_var(val);
        const int bytes = (nrbits + b + 7) >> 3;
 
-       ubifs_assert(nrbits > 0);
-       ubifs_assert(nrbits <= 32);
-       ubifs_assert(*pos >= 0);
-       ubifs_assert(*pos < 8);
+       ubifs_assert(c, nrbits > 0);
+       ubifs_assert(c, nrbits <= 32);
+       ubifs_assert(c, *pos >= 0);
+       ubifs_assert(c, *pos < 8);
        if (b) {
                switch (bytes) {
                case 2:
@@ -337,7 +339,7 @@ uint32_t ubifs_unpack_bits(uint8_t **addr, int *pos, int nrbits)
        p += nrbits >> 3;
        *addr = p;
        *pos = b;
-       ubifs_assert((val >> nrbits) == 0 || nrbits - b == 32);
+       ubifs_assert(c, (val >> nrbits) == 0 || nrbits - b == 32);
        return val;
 }
 
@@ -354,24 +356,24 @@ void ubifs_pack_pnode(struct ubifs_info *c, void *buf,
        int i, pos = 0;
        uint16_t crc;
 
-       pack_bits(&addr, &pos, UBIFS_LPT_PNODE, UBIFS_LPT_TYPE_BITS);
+       pack_bits(c, &addr, &pos, UBIFS_LPT_PNODE, UBIFS_LPT_TYPE_BITS);
        if (c->big_lpt)
-               pack_bits(&addr, &pos, pnode->num, c->pcnt_bits);
+               pack_bits(c, &addr, &pos, pnode->num, c->pcnt_bits);
        for (i = 0; i < UBIFS_LPT_FANOUT; i++) {
-               pack_bits(&addr, &pos, pnode->lprops[i].free >> 3,
+               pack_bits(c, &addr, &pos, pnode->lprops[i].free >> 3,
                          c->space_bits);
-               pack_bits(&addr, &pos, pnode->lprops[i].dirty >> 3,
+               pack_bits(c, &addr, &pos, pnode->lprops[i].dirty >> 3,
                          c->space_bits);
                if (pnode->lprops[i].flags & LPROPS_INDEX)
-                       pack_bits(&addr, &pos, 1, 1);
+                       pack_bits(c, &addr, &pos, 1, 1);
                else
-                       pack_bits(&addr, &pos, 0, 1);
+                       pack_bits(c, &addr, &pos, 0, 1);
        }
        crc = crc16(-1, buf + UBIFS_LPT_CRC_BYTES,
                    c->pnode_sz - UBIFS_LPT_CRC_BYTES);
        addr = buf;
        pos = 0;
-       pack_bits(&addr, &pos, crc, UBIFS_LPT_CRC_BITS);
+       pack_bits(c, &addr, &pos, crc, UBIFS_LPT_CRC_BITS);
 }
 
 /**
@@ -387,23 +389,23 @@ void ubifs_pack_nnode(struct ubifs_info *c, void *buf,
        int i, pos = 0;
        uint16_t crc;
 
-       pack_bits(&addr, &pos, UBIFS_LPT_NNODE, UBIFS_LPT_TYPE_BITS);
+       pack_bits(c, &addr, &pos, UBIFS_LPT_NNODE, UBIFS_LPT_TYPE_BITS);
        if (c->big_lpt)
-               pack_bits(&addr, &pos, nnode->num, c->pcnt_bits);
+               pack_bits(c, &addr, &pos, nnode->num, c->pcnt_bits);
        for (i = 0; i < UBIFS_LPT_FANOUT; i++) {
                int lnum = nnode->nbranch[i].lnum;
 
                if (lnum == 0)
                        lnum = c->lpt_last + 1;
-               pack_bits(&addr, &pos, lnum - c->lpt_first, c->lpt_lnum_bits);
-               pack_bits(&addr, &pos, nnode->nbranch[i].offs,
+               pack_bits(c, &addr, &pos, lnum - c->lpt_first, c->lpt_lnum_bits);
+               pack_bits(c, &addr, &pos, nnode->nbranch[i].offs,
                          c->lpt_offs_bits);
        }
        crc = crc16(-1, buf + UBIFS_LPT_CRC_BYTES,
                    c->nnode_sz - UBIFS_LPT_CRC_BYTES);
        addr = buf;
        pos = 0;
-       pack_bits(&addr, &pos, crc, UBIFS_LPT_CRC_BITS);
+       pack_bits(c, &addr, &pos, crc, UBIFS_LPT_CRC_BITS);
 }
 
 /**
@@ -419,16 +421,16 @@ void ubifs_pack_ltab(struct ubifs_info *c, void *buf,
        int i, pos = 0;
        uint16_t crc;
 
-       pack_bits(&addr, &pos, UBIFS_LPT_LTAB, UBIFS_LPT_TYPE_BITS);
+       pack_bits(c, &addr, &pos, UBIFS_LPT_LTAB, UBIFS_LPT_TYPE_BITS);
        for (i = 0; i < c->lpt_lebs; i++) {
-               pack_bits(&addr, &pos, ltab[i].free, c->lpt_spc_bits);
-               pack_bits(&addr, &pos, ltab[i].dirty, c->lpt_spc_bits);
+               pack_bits(c, &addr, &pos, ltab[i].free, c->lpt_spc_bits);
+               pack_bits(c, &addr, &pos, ltab[i].dirty, c->lpt_spc_bits);
        }
        crc = crc16(-1, buf + UBIFS_LPT_CRC_BYTES,
                    c->ltab_sz - UBIFS_LPT_CRC_BYTES);
        addr = buf;
        pos = 0;
-       pack_bits(&addr, &pos, crc, UBIFS_LPT_CRC_BITS);
+       pack_bits(c, &addr, &pos, crc, UBIFS_LPT_CRC_BITS);
 }
 
 /**
@@ -443,14 +445,14 @@ void ubifs_pack_lsave(struct ubifs_info *c, void *buf, int *lsave)
        int i, pos = 0;
        uint16_t crc;
 
-       pack_bits(&addr, &pos, UBIFS_LPT_LSAVE, UBIFS_LPT_TYPE_BITS);
+       pack_bits(c, &addr, &pos, UBIFS_LPT_LSAVE, UBIFS_LPT_TYPE_BITS);
        for (i = 0; i < c->lsave_cnt; i++)
-               pack_bits(&addr, &pos, lsave[i], c->lnum_bits);
+               pack_bits(c, &addr, &pos, lsave[i], c->lnum_bits);
        crc = crc16(-1, buf + UBIFS_LPT_CRC_BYTES,
                    c->lsave_sz - UBIFS_LPT_CRC_BYTES);
        addr = buf;
        pos = 0;
-       pack_bits(&addr, &pos, crc, UBIFS_LPT_CRC_BITS);
+       pack_bits(c, &addr, &pos, crc, UBIFS_LPT_CRC_BITS);
 }
 
 /**
@@ -465,7 +467,7 @@ void ubifs_add_lpt_dirt(struct ubifs_info *c, int lnum, int dirty)
                return;
        dbg_lp("LEB %d add %d to %d",
               lnum, dirty, c->ltab[lnum - c->lpt_first].dirty);
-       ubifs_assert(lnum >= c->lpt_first && lnum <= c->lpt_last);
+       ubifs_assert(c, lnum >= c->lpt_first && lnum <= c->lpt_last);
        c->ltab[lnum - c->lpt_first].dirty += dirty;
 }
 
@@ -481,7 +483,7 @@ static void set_ltab(struct ubifs_info *c, int lnum, int free, int dirty)
        dbg_lp("LEB %d free %d dirty %d to %d %d",
               lnum, c->ltab[lnum - c->lpt_first].free,
               c->ltab[lnum - c->lpt_first].dirty, free, dirty);
-       ubifs_assert(lnum >= c->lpt_first && lnum <= c->lpt_last);
+       ubifs_assert(c, lnum >= c->lpt_first && lnum <= c->lpt_last);
        c->ltab[lnum - c->lpt_first].free = free;
        c->ltab[lnum - c->lpt_first].dirty = dirty;
 }
@@ -639,7 +641,7 @@ int ubifs_create_dflt_lpt(struct ubifs_info *c, int *main_lebs, int lpt_first,
                goto out;
        }
 
-       ubifs_assert(!c->ltab);
+       ubifs_assert(c, !c->ltab);
        c->ltab = ltab; /* Needed by set_ltab */
 
        /* Initialize LPT's own lprops */
@@ -918,7 +920,7 @@ static int check_lpt_crc(const struct ubifs_info *c, void *buf, int len)
        uint8_t *addr = buf;
        uint16_t crc, calc_crc;
 
-       crc = ubifs_unpack_bits(&addr, &pos, UBIFS_LPT_CRC_BITS);
+       crc = ubifs_unpack_bits(c, &addr, &pos, UBIFS_LPT_CRC_BITS);
        calc_crc = crc16(-1, buf + UBIFS_LPT_CRC_BYTES,
                         len - UBIFS_LPT_CRC_BYTES);
        if (crc != calc_crc) {
@@ -944,7 +946,7 @@ static int check_lpt_type(const struct ubifs_info *c, uint8_t **addr,
 {
        int node_type;
 
-       node_type = ubifs_unpack_bits(addr, pos, UBIFS_LPT_TYPE_BITS);
+       node_type = ubifs_unpack_bits(c, addr, pos, UBIFS_LPT_TYPE_BITS);
        if (node_type != type) {
                ubifs_err(c, "invalid type (%d) in LPT node type %d",
                          node_type, type);
@@ -972,16 +974,16 @@ static int unpack_pnode(const struct ubifs_info *c, void *buf,
        if (err)
                return err;
        if (c->big_lpt)
-               pnode->num = ubifs_unpack_bits(&addr, &pos, c->pcnt_bits);
+               pnode->num = ubifs_unpack_bits(c, &addr, &pos, c->pcnt_bits);
        for (i = 0; i < UBIFS_LPT_FANOUT; i++) {
                struct ubifs_lprops * const lprops = &pnode->lprops[i];
 
-               lprops->free = ubifs_unpack_bits(&addr, &pos, c->space_bits);
+               lprops->free = ubifs_unpack_bits(c, &addr, &pos, c->space_bits);
                lprops->free <<= 3;
-               lprops->dirty = ubifs_unpack_bits(&addr, &pos, c->space_bits);
+               lprops->dirty = ubifs_unpack_bits(c, &addr, &pos, c->space_bits);
                lprops->dirty <<= 3;
 
-               if (ubifs_unpack_bits(&addr, &pos, 1))
+               if (ubifs_unpack_bits(c, &addr, &pos, 1))
                        lprops->flags = LPROPS_INDEX;
                else
                        lprops->flags = 0;
@@ -1009,16 +1011,16 @@ int ubifs_unpack_nnode(const struct ubifs_info *c, void *buf,
        if (err)
                return err;
        if (c->big_lpt)
-               nnode->num = ubifs_unpack_bits(&addr, &pos, c->pcnt_bits);
+               nnode->num = ubifs_unpack_bits(c, &addr, &pos, c->pcnt_bits);
        for (i = 0; i < UBIFS_LPT_FANOUT; i++) {
                int lnum;
 
-               lnum = ubifs_unpack_bits(&addr, &pos, c->lpt_lnum_bits) +
+               lnum = ubifs_unpack_bits(c, &addr, &pos, c->lpt_lnum_bits) +
                       c->lpt_first;
                if (lnum == c->lpt_last + 1)
                        lnum = 0;
                nnode->nbranch[i].lnum = lnum;
-               nnode->nbranch[i].offs = ubifs_unpack_bits(&addr, &pos,
+               nnode->nbranch[i].offs = ubifs_unpack_bits(c, &addr, &pos,
                                                     c->lpt_offs_bits);
        }
        err = check_lpt_crc(c, buf, c->nnode_sz);
@@ -1041,8 +1043,8 @@ static int unpack_ltab(const struct ubifs_info *c, void *buf)
        if (err)
                return err;
        for (i = 0; i < c->lpt_lebs; i++) {
-               int free = ubifs_unpack_bits(&addr, &pos, c->lpt_spc_bits);
-               int dirty = ubifs_unpack_bits(&addr, &pos, c->lpt_spc_bits);
+               int free = ubifs_unpack_bits(c, &addr, &pos, c->lpt_spc_bits);
+               int dirty = ubifs_unpack_bits(c, &addr, &pos, c->lpt_spc_bits);
 
                if (free < 0 || free > c->leb_size || dirty < 0 ||
                    dirty > c->leb_size || free + dirty > c->leb_size)
@@ -1073,7 +1075,7 @@ static int unpack_lsave(const struct ubifs_info *c, void *buf)
        if (err)
                return err;
        for (i = 0; i < c->lsave_cnt; i++) {
-               int lnum = ubifs_unpack_bits(&addr, &pos, c->lnum_bits);
+               int lnum = ubifs_unpack_bits(c, &addr, &pos, c->lnum_bits);
 
                if (lnum < c->main_first || lnum >= c->leb_cnt)
                        return -EINVAL;
@@ -1515,7 +1517,7 @@ static struct ubifs_nnode *dirty_cow_nnode(struct ubifs_info *c,
                        branch->cnode->parent = n;
        }
 
-       ubifs_assert(!test_bit(OBSOLETE_CNODE, &nnode->flags));
+       ubifs_assert(c, !test_bit(OBSOLETE_CNODE, &nnode->flags));
        __set_bit(OBSOLETE_CNODE, &nnode->flags);
 
        c->dirty_nn_cnt += 1;
@@ -1558,7 +1560,7 @@ static struct ubifs_pnode *dirty_cow_pnode(struct ubifs_info *c,
        __clear_bit(COW_CNODE, &p->flags);
        replace_cats(c, pnode, p);
 
-       ubifs_assert(!test_bit(OBSOLETE_CNODE, &pnode->flags));
+       ubifs_assert(c, !test_bit(OBSOLETE_CNODE, &pnode->flags));
        __set_bit(OBSOLETE_CNODE, &pnode->flags);
 
        c->dirty_pn_cnt += 1;
@@ -1613,7 +1615,7 @@ struct ubifs_lprops *ubifs_lpt_lookup_dirty(struct ubifs_info *c, int lnum)
        dbg_lp("LEB %d, free %d, dirty %d, flags %d", lnum,
               pnode->lprops[iip].free, pnode->lprops[iip].dirty,
               pnode->lprops[iip].flags);
-       ubifs_assert(test_bit(DIRTY_CNODE, &pnode->flags));
+       ubifs_assert(c, test_bit(DIRTY_CNODE, &pnode->flags));
        return &pnode->lprops[iip];
 }
 
@@ -1889,9 +1891,9 @@ static struct ubifs_pnode *scan_get_pnode(struct ubifs_info *c,
                        lprops->flags = ubifs_categorize_lprops(c, lprops);
                }
        } else {
-               ubifs_assert(branch->lnum >= c->lpt_first &&
+               ubifs_assert(c, branch->lnum >= c->lpt_first &&
                             branch->lnum <= c->lpt_last);
-               ubifs_assert(branch->offs >= 0 && branch->offs < c->leb_size);
+               ubifs_assert(c, branch->offs >= 0 && branch->offs < c->leb_size);
                err = ubifs_leb_read(c, branch->lnum, buf, branch->offs,
                                     c->pnode_sz, 1);
                if (err)
@@ -1935,8 +1937,8 @@ int ubifs_lpt_scan_nolock(struct ubifs_info *c, int start_lnum, int end_lnum,
                        start_lnum = c->main_first;
        }
 
-       ubifs_assert(start_lnum >= c->main_first && start_lnum < c->leb_cnt);
-       ubifs_assert(end_lnum >= c->main_first && end_lnum < c->leb_cnt);
+       ubifs_assert(c, start_lnum >= c->main_first && start_lnum < c->leb_cnt);
+       ubifs_assert(c, end_lnum >= c->main_first && end_lnum < c->leb_cnt);
 
        if (!c->nroot) {
                err = ubifs_read_nnode(c, NULL, 0);
@@ -2055,7 +2057,7 @@ again:
                iip = pnode->iip;
                while (1) {
                        h -= 1;
-                       ubifs_assert(h >= 0);
+                       ubifs_assert(c, h >= 0);
                        nnode = path[h].ptr.nnode;
                        if (iip + 1 < UBIFS_LPT_FANOUT)
                                break;
@@ -2234,7 +2236,7 @@ int dbg_check_lpt_nodes(struct ubifs_info *c, struct ubifs_cnode *cnode,
                return 0;
 
        while (cnode) {
-               ubifs_assert(row >= 0);
+               ubifs_assert(c, row >= 0);
                nnode = cnode->parent;
                if (cnode->level) {
                        /* cnode is a nnode */
index 78da65b..7ce3099 100644 (file)
@@ -34,13 +34,14 @@ static int dbg_populate_lsave(struct ubifs_info *c);
 
 /**
  * first_dirty_cnode - find first dirty cnode.
+ * @c: UBIFS file-system description object
  * @nnode: nnode at which to start
  *
  * This function returns the first dirty cnode or %NULL if there is not one.
  */
-static struct ubifs_cnode *first_dirty_cnode(struct ubifs_nnode *nnode)
+static struct ubifs_cnode *first_dirty_cnode(const struct ubifs_info *c, struct ubifs_nnode *nnode)
 {
-       ubifs_assert(nnode);
+       ubifs_assert(c, nnode);
        while (1) {
                int i, cont = 0;
 
@@ -64,16 +65,17 @@ static struct ubifs_cnode *first_dirty_cnode(struct ubifs_nnode *nnode)
 
 /**
  * next_dirty_cnode - find next dirty cnode.
+ * @c: UBIFS file-system description object
  * @cnode: cnode from which to begin searching
  *
  * This function returns the next dirty cnode or %NULL if there is not one.
  */
-static struct ubifs_cnode *next_dirty_cnode(struct ubifs_cnode *cnode)
+static struct ubifs_cnode *next_dirty_cnode(const struct ubifs_info *c, struct ubifs_cnode *cnode)
 {
        struct ubifs_nnode *nnode;
        int i;
 
-       ubifs_assert(cnode);
+       ubifs_assert(c, cnode);
        nnode = cnode->parent;
        if (!nnode)
                return NULL;
@@ -83,7 +85,7 @@ static struct ubifs_cnode *next_dirty_cnode(struct ubifs_cnode *cnode)
                        if (cnode->level == 0)
                                return cnode; /* cnode is a pnode */
                        /* cnode is a nnode */
-                       return first_dirty_cnode((struct ubifs_nnode *)cnode);
+                       return first_dirty_cnode(c, (struct ubifs_nnode *)cnode);
                }
        }
        return (struct ubifs_cnode *)nnode;
@@ -106,15 +108,15 @@ static int get_cnodes_to_commit(struct ubifs_info *c)
        if (!test_bit(DIRTY_CNODE, &c->nroot->flags))
                return 0;
 
-       c->lpt_cnext = first_dirty_cnode(c->nroot);
+       c->lpt_cnext = first_dirty_cnode(c, c->nroot);
        cnode = c->lpt_cnext;
        if (!cnode)
                return 0;
        cnt += 1;
        while (1) {
-               ubifs_assert(!test_bit(COW_CNODE, &cnode->flags));
+               ubifs_assert(c, !test_bit(COW_CNODE, &cnode->flags));
                __set_bit(COW_CNODE, &cnode->flags);
-               cnext = next_dirty_cnode(cnode);
+               cnext = next_dirty_cnode(c, cnode);
                if (!cnext) {
                        cnode->cnext = c->lpt_cnext;
                        break;
@@ -125,7 +127,7 @@ static int get_cnodes_to_commit(struct ubifs_info *c)
        }
        dbg_cmt("committing %d cnodes", cnt);
        dbg_lp("committing %d cnodes", cnt);
-       ubifs_assert(cnt == c->dirty_nn_cnt + c->dirty_pn_cnt);
+       ubifs_assert(c, cnt == c->dirty_nn_cnt + c->dirty_pn_cnt);
        return cnt;
 }
 
@@ -141,7 +143,7 @@ static void upd_ltab(struct ubifs_info *c, int lnum, int free, int dirty)
        dbg_lp("LEB %d free %d dirty %d to %d +%d",
               lnum, c->ltab[lnum - c->lpt_first].free,
               c->ltab[lnum - c->lpt_first].dirty, free, dirty);
-       ubifs_assert(lnum >= c->lpt_first && lnum <= c->lpt_last);
+       ubifs_assert(c, lnum >= c->lpt_first && lnum <= c->lpt_last);
        c->ltab[lnum - c->lpt_first].free = free;
        c->ltab[lnum - c->lpt_first].dirty += dirty;
 }
@@ -237,7 +239,7 @@ static int layout_cnodes(struct ubifs_info *c)
                        if (err)
                                goto no_space;
                        offs = 0;
-                       ubifs_assert(lnum >= c->lpt_first &&
+                       ubifs_assert(c, lnum >= c->lpt_first &&
                                     lnum <= c->lpt_last);
                        /* Try to place lsave and ltab nicely */
                        if (!done_lsave) {
@@ -280,7 +282,7 @@ static int layout_cnodes(struct ubifs_info *c)
                        if (err)
                                goto no_space;
                        offs = 0;
-                       ubifs_assert(lnum >= c->lpt_first &&
+                       ubifs_assert(c, lnum >= c->lpt_first &&
                                     lnum <= c->lpt_last);
                }
                done_lsave = 1;
@@ -300,7 +302,7 @@ static int layout_cnodes(struct ubifs_info *c)
                        if (err)
                                goto no_space;
                        offs = 0;
-                       ubifs_assert(lnum >= c->lpt_first &&
+                       ubifs_assert(c, lnum >= c->lpt_first &&
                                     lnum <= c->lpt_last);
                }
                c->ltab_lnum = lnum;
@@ -423,7 +425,7 @@ static int write_cnodes(struct ubifs_info *c)
                        if (err)
                                goto no_space;
                        offs = from = 0;
-                       ubifs_assert(lnum >= c->lpt_first &&
+                       ubifs_assert(c, lnum >= c->lpt_first &&
                                     lnum <= c->lpt_last);
                        err = ubifs_leb_unmap(c, lnum);
                        if (err)
@@ -480,7 +482,7 @@ static int write_cnodes(struct ubifs_info *c)
                        if (err)
                                goto no_space;
                        offs = from = 0;
-                       ubifs_assert(lnum >= c->lpt_first &&
+                       ubifs_assert(c, lnum >= c->lpt_first &&
                                     lnum <= c->lpt_last);
                        err = ubifs_leb_unmap(c, lnum);
                        if (err)
@@ -506,7 +508,7 @@ static int write_cnodes(struct ubifs_info *c)
                        if (err)
                                goto no_space;
                        offs = from = 0;
-                       ubifs_assert(lnum >= c->lpt_first &&
+                       ubifs_assert(c, lnum >= c->lpt_first &&
                                     lnum <= c->lpt_last);
                        err = ubifs_leb_unmap(c, lnum);
                        if (err)
@@ -806,7 +808,7 @@ static void populate_lsave(struct ubifs_info *c)
        struct ubifs_lpt_heap *heap;
        int i, cnt = 0;
 
-       ubifs_assert(c->big_lpt);
+       ubifs_assert(c, c->big_lpt);
        if (!(c->lpt_drty_flgs & LSAVE_DIRTY)) {
                c->lpt_drty_flgs |= LSAVE_DIRTY;
                ubifs_add_lpt_dirt(c, c->lsave_lnum, c->lsave_sz);
@@ -1095,8 +1097,8 @@ static int get_lpt_node_type(const struct ubifs_info *c, uint8_t *buf,
        uint8_t *addr = buf + UBIFS_LPT_CRC_BYTES;
        int pos = 0, node_type;
 
-       node_type = ubifs_unpack_bits(&addr, &pos, UBIFS_LPT_TYPE_BITS);
-       *node_num = ubifs_unpack_bits(&addr, &pos, c->pcnt_bits);
+       node_type = ubifs_unpack_bits(c, &addr, &pos, UBIFS_LPT_TYPE_BITS);
+       *node_num = ubifs_unpack_bits(c, &addr, &pos, c->pcnt_bits);
        return node_type;
 }
 
@@ -1116,7 +1118,7 @@ static int is_a_node(const struct ubifs_info *c, uint8_t *buf, int len)
 
        if (len < UBIFS_LPT_CRC_BYTES + (UBIFS_LPT_TYPE_BITS + 7) / 8)
                return 0;
-       node_type = ubifs_unpack_bits(&addr, &pos, UBIFS_LPT_TYPE_BITS);
+       node_type = ubifs_unpack_bits(c, &addr, &pos, UBIFS_LPT_TYPE_BITS);
        if (node_type == UBIFS_LPT_NOT_A_NODE)
                return 0;
        node_len = get_lpt_node_len(c, node_type);
@@ -1124,7 +1126,7 @@ static int is_a_node(const struct ubifs_info *c, uint8_t *buf, int len)
                return 0;
        pos = 0;
        addr = buf;
-       crc = ubifs_unpack_bits(&addr, &pos, UBIFS_LPT_CRC_BITS);
+       crc = ubifs_unpack_bits(c, &addr, &pos, UBIFS_LPT_CRC_BITS);
        calc_crc = crc16(-1, buf + UBIFS_LPT_CRC_BYTES,
                         node_len - UBIFS_LPT_CRC_BYTES);
        if (crc != calc_crc)
@@ -1170,7 +1172,7 @@ static int lpt_gc_lnum(struct ubifs_info *c, int lnum)
                node_type = get_lpt_node_type(c, buf, &node_num);
                node_len = get_lpt_node_len(c, node_type);
                offs = c->leb_size - len;
-               ubifs_assert(node_len != 0);
+               ubifs_assert(c, node_len != 0);
                mutex_lock(&c->lp_mutex);
                err = make_node_dirty(c, node_type, node_num, lnum, offs);
                mutex_unlock(&c->lp_mutex);
@@ -1195,7 +1197,7 @@ static int lpt_gc(struct ubifs_info *c)
 
        mutex_lock(&c->lp_mutex);
        for (i = 0; i < c->lpt_lebs; i++) {
-               ubifs_assert(!c->ltab[i].tgc);
+               ubifs_assert(c, !c->ltab[i].tgc);
                if (i + c->lpt_first == c->nhead_lnum ||
                    c->ltab[i].free + c->ltab[i].dirty == c->leb_size)
                        continue;
@@ -1271,7 +1273,7 @@ int ubifs_lpt_start_commit(struct ubifs_info *c)
                populate_lsave(c);
 
        cnt = get_cnodes_to_commit(c);
-       ubifs_assert(cnt != 0);
+       ubifs_assert(c, cnt != 0);
 
        err = layout_cnodes(c);
        if (err)
index c6a5e39..9df4a41 100644 (file)
@@ -360,7 +360,7 @@ int ubifs_write_master(struct ubifs_info *c)
 {
        int err, lnum, offs, len;
 
-       ubifs_assert(!c->ro_media && !c->ro_mount);
+       ubifs_assert(c, !c->ro_media && !c->ro_mount);
        if (c->ro_error)
                return -EROFS;
 
index 586fd5b..cd23de0 100644 (file)
@@ -56,3 +56,14 @@ void ubifs_warn(const struct ubifs_info *c, const char *fmt, ...)
 
        va_end(args);
 }
+
+static char *assert_names[] = {
+       [ASSACT_REPORT] = "report",
+       [ASSACT_RO] = "read-only",
+       [ASSACT_PANIC] = "panic",
+};
+
+const char *ubifs_assert_action_name(struct ubifs_info *c)
+{
+       return assert_names[c->assert_action];
+}
index caf83d6..21d35d7 100644 (file)
@@ -105,25 +105,27 @@ static inline struct ubifs_inode *ubifs_inode(const struct inode *inode)
 /**
  * ubifs_compr_present - check if compressor was compiled in.
  * @compr_type: compressor type to check
+ * @c: the UBIFS file-system description object
  *
  * This function returns %1 of compressor of type @compr_type is present, and
  * %0 if not.
  */
-static inline int ubifs_compr_present(int compr_type)
+static inline int ubifs_compr_present(struct ubifs_info *c, int compr_type)
 {
-       ubifs_assert(compr_type >= 0 && compr_type < UBIFS_COMPR_TYPES_CNT);
+       ubifs_assert(c, compr_type >= 0 && compr_type < UBIFS_COMPR_TYPES_CNT);
        return !!ubifs_compressors[compr_type]->capi_name;
 }
 
 /**
  * ubifs_compr_name - get compressor name string by its type.
  * @compr_type: compressor type
+ * @c: the UBIFS file-system description object
  *
  * This function returns compressor type string.
  */
-static inline const char *ubifs_compr_name(int compr_type)
+static inline const char *ubifs_compr_name(struct ubifs_info *c, int compr_type)
 {
-       ubifs_assert(compr_type >= 0 && compr_type < UBIFS_COMPR_TYPES_CNT);
+       ubifs_assert(c, compr_type >= 0 && compr_type < UBIFS_COMPR_TYPES_CNT);
        return ubifs_compressors[compr_type]->name;
 }
 
@@ -262,8 +264,8 @@ static inline void ubifs_get_lprops(struct ubifs_info *c)
  */
 static inline void ubifs_release_lprops(struct ubifs_info *c)
 {
-       ubifs_assert(mutex_is_locked(&c->lp_mutex));
-       ubifs_assert(c->lst.empty_lebs >= 0 &&
+       ubifs_assert(c, mutex_is_locked(&c->lp_mutex));
+       ubifs_assert(c, c->lst.empty_lebs >= 0 &&
                     c->lst.empty_lebs <= c->main_lebs);
        mutex_unlock(&c->lp_mutex);
 }
@@ -285,4 +287,6 @@ static inline int ubifs_next_log_lnum(const struct ubifs_info *c, int lnum)
        return lnum;
 }
 
+const char *ubifs_assert_action_name(struct ubifs_info *c);
+
 #endif /* __UBIFS_MISC_H__ */
index caf2d12..8f70494 100644 (file)
@@ -172,8 +172,8 @@ int ubifs_orphan_start_commit(struct ubifs_info *c)
        spin_lock(&c->orphan_lock);
        last = &c->orph_cnext;
        list_for_each_entry(orphan, &c->orph_new, new_list) {
-               ubifs_assert(orphan->new);
-               ubifs_assert(!orphan->cmt);
+               ubifs_assert(c, orphan->new);
+               ubifs_assert(c, !orphan->cmt);
                orphan->new = 0;
                orphan->cmt = 1;
                *last = orphan;
@@ -244,7 +244,7 @@ static int do_write_orph_node(struct ubifs_info *c, int len, int atomic)
        int err = 0;
 
        if (atomic) {
-               ubifs_assert(c->ohead_offs == 0);
+               ubifs_assert(c, c->ohead_offs == 0);
                ubifs_prepare_node(c, c->orph_buf, len, 1);
                len = ALIGN(len, c->min_io_size);
                err = ubifs_leb_change(c, c->ohead_lnum, c->orph_buf, len);
@@ -276,7 +276,7 @@ static int write_orph_node(struct ubifs_info *c, int atomic)
        struct ubifs_orph_node *orph;
        int gap, err, len, cnt, i;
 
-       ubifs_assert(c->cmt_orphans > 0);
+       ubifs_assert(c, c->cmt_orphans > 0);
        gap = c->leb_size - c->ohead_offs;
        if (gap < UBIFS_ORPH_NODE_SZ + sizeof(__le64)) {
                c->ohead_lnum += 1;
@@ -295,14 +295,14 @@ static int write_orph_node(struct ubifs_info *c, int atomic)
        if (cnt > c->cmt_orphans)
                cnt = c->cmt_orphans;
        len = UBIFS_ORPH_NODE_SZ + cnt * sizeof(__le64);
-       ubifs_assert(c->orph_buf);
+       ubifs_assert(c, c->orph_buf);
        orph = c->orph_buf;
        orph->ch.node_type = UBIFS_ORPH_NODE;
        spin_lock(&c->orphan_lock);
        cnext = c->orph_cnext;
        for (i = 0; i < cnt; i++) {
                orphan = cnext;
-               ubifs_assert(orphan->cmt);
+               ubifs_assert(c, orphan->cmt);
                orph->inos[i] = cpu_to_le64(orphan->inum);
                orphan->cmt = 0;
                cnext = orphan->cnext;
@@ -316,9 +316,9 @@ static int write_orph_node(struct ubifs_info *c, int atomic)
        else
                /* Mark the last node of the commit */
                orph->cmt_no = cpu_to_le64((c->cmt_no) | (1ULL << 63));
-       ubifs_assert(c->ohead_offs + len <= c->leb_size);
-       ubifs_assert(c->ohead_lnum >= c->orph_first);
-       ubifs_assert(c->ohead_lnum <= c->orph_last);
+       ubifs_assert(c, c->ohead_offs + len <= c->leb_size);
+       ubifs_assert(c, c->ohead_lnum >= c->orph_first);
+       ubifs_assert(c, c->ohead_lnum <= c->orph_last);
        err = do_write_orph_node(c, len, atomic);
        c->ohead_offs += ALIGN(len, c->min_io_size);
        c->ohead_offs = ALIGN(c->ohead_offs, 8);
@@ -388,7 +388,7 @@ static int consolidate(struct ubifs_info *c)
                        cnt += 1;
                }
                *last = NULL;
-               ubifs_assert(cnt == c->tot_orphans - c->new_orphans);
+               ubifs_assert(c, cnt == c->tot_orphans - c->new_orphans);
                c->cmt_orphans = cnt;
                c->ohead_lnum = c->orph_first;
                c->ohead_offs = 0;
@@ -415,7 +415,7 @@ static int commit_orphans(struct ubifs_info *c)
 {
        int avail, atomic = 0, err;
 
-       ubifs_assert(c->cmt_orphans > 0);
+       ubifs_assert(c, c->cmt_orphans > 0);
        avail = avail_orphs(c);
        if (avail < c->cmt_orphans) {
                /* Not enough space to write new orphans, so consolidate */
@@ -446,8 +446,8 @@ static void erase_deleted(struct ubifs_info *c)
        while (dnext) {
                orphan = dnext;
                dnext = orphan->dnext;
-               ubifs_assert(!orphan->new);
-               ubifs_assert(orphan->del);
+               ubifs_assert(c, !orphan->new);
+               ubifs_assert(c, orphan->del);
                rb_erase(&orphan->rb, &c->orph_tree);
                list_del(&orphan->list);
                c->tot_orphans -= 1;
index 3af4472..984e30e 100644 (file)
@@ -444,7 +444,7 @@ static void clean_buf(const struct ubifs_info *c, void **buf, int lnum,
 
        dbg_rcvry("cleaning corruption at %d:%d", lnum, *offs);
 
-       ubifs_assert(!(*offs & 7));
+       ubifs_assert(c, !(*offs & 7));
        empty_offs = ALIGN(*offs, c->min_io_size);
        pad_len = empty_offs - *offs;
        ubifs_pad(c, *buf, pad_len);
@@ -644,7 +644,7 @@ struct ubifs_scan_leb *ubifs_recover_leb(struct ubifs_info *c, int lnum,
        if (IS_ERR(sleb))
                return sleb;
 
-       ubifs_assert(len >= 8);
+       ubifs_assert(c, len >= 8);
        while (len >= 8) {
                dbg_scan("look at LEB %d:%d (%d bytes left)",
                         lnum, offs, len);
@@ -966,7 +966,7 @@ int ubifs_recover_inl_heads(struct ubifs_info *c, void *sbuf)
 {
        int err;
 
-       ubifs_assert(!c->ro_mount || c->remounting_rw);
+       ubifs_assert(c, !c->ro_mount || c->remounting_rw);
 
        dbg_rcvry("checking index head at %d:%d", c->ihead_lnum, c->ihead_offs);
        err = recover_head(c, c->ihead_lnum, c->ihead_offs, sbuf);
@@ -1187,8 +1187,8 @@ int ubifs_rcvry_gc_commit(struct ubifs_info *c)
                return grab_empty_leb(c);
        }
 
-       ubifs_assert(!(lp.flags & LPROPS_INDEX));
-       ubifs_assert(lp.free + lp.dirty >= wbuf->offs);
+       ubifs_assert(c, !(lp.flags & LPROPS_INDEX));
+       ubifs_assert(c, lp.free + lp.dirty >= wbuf->offs);
 
        /*
         * We run the commit before garbage collection otherwise subsequent
@@ -1216,7 +1216,7 @@ int ubifs_rcvry_gc_commit(struct ubifs_info *c)
                return err;
        }
 
-       ubifs_assert(err == LEB_RETAINED);
+       ubifs_assert(c, err == LEB_RETAINED);
        if (err != LEB_RETAINED)
                return -EINVAL;
 
@@ -1507,7 +1507,7 @@ int ubifs_recover_size(struct ubifs_info *c)
                                struct inode *inode;
                                struct ubifs_inode *ui;
 
-                               ubifs_assert(!e->inode);
+                               ubifs_assert(c, !e->inode);
 
                                inode = ubifs_iget(c->vfs_sb, e->inum);
                                if (IS_ERR(inode))
index 85c2a43..4844538 100644 (file)
@@ -273,6 +273,7 @@ static int apply_replay_entry(struct ubifs_info *c, struct replay_entry *r)
 static int replay_entries_cmp(void *priv, struct list_head *a,
                              struct list_head *b)
 {
+       struct ubifs_info *c = priv;
        struct replay_entry *ra, *rb;
 
        cond_resched();
@@ -281,7 +282,7 @@ static int replay_entries_cmp(void *priv, struct list_head *a,
 
        ra = list_entry(a, struct replay_entry, list);
        rb = list_entry(b, struct replay_entry, list);
-       ubifs_assert(ra->sqnum != rb->sqnum);
+       ubifs_assert(c, ra->sqnum != rb->sqnum);
        if (ra->sqnum > rb->sqnum)
                return 1;
        return -1;
@@ -668,9 +669,9 @@ static int replay_bud(struct ubifs_info *c, struct bud_entry *b)
                        goto out;
        }
 
-       ubifs_assert(ubifs_search_bud(c, lnum));
-       ubifs_assert(sleb->endpt - offs >= used);
-       ubifs_assert(sleb->endpt % c->min_io_size == 0);
+       ubifs_assert(c, ubifs_search_bud(c, lnum));
+       ubifs_assert(c, sleb->endpt - offs >= used);
+       ubifs_assert(c, sleb->endpt % c->min_io_size == 0);
 
        b->dirty = sleb->endpt - offs - used;
        b->free = c->leb_size - sleb->endpt;
@@ -706,7 +707,7 @@ static int replay_buds(struct ubifs_info *c)
                if (err)
                        return err;
 
-               ubifs_assert(b->sqnum > prev_sqnum);
+               ubifs_assert(c, b->sqnum > prev_sqnum);
                prev_sqnum = b->sqnum;
        }
 
@@ -1067,7 +1068,7 @@ int ubifs_replay_journal(struct ubifs_info *c)
        c->bi.uncommitted_idx = atomic_long_read(&c->dirty_zn_cnt);
        c->bi.uncommitted_idx *= c->max_idx_node_sz;
 
-       ubifs_assert(c->bud_bytes <= c->max_bud_bytes || c->need_recovery);
+       ubifs_assert(c, c->bud_bytes <= c->max_bud_bytes || c->need_recovery);
        dbg_mnt("finished, log head LEB %d:%d, max_sqnum %llu, highest_inum %lu",
                c->lhead_lnum, c->lhead_offs, c->max_sqnum,
                (unsigned long)c->highest_inum);
index 8c25081..bf17f58 100644 (file)
@@ -85,7 +85,7 @@ static int create_default_filesystem(struct ubifs_info *c)
        long long tmp64, main_bytes;
        __le64 tmp_le64;
        __le32 tmp_le32;
-       struct timespec ts;
+       struct timespec64 ts;
 
        /* Some functions called from here depend on the @c->key_len filed */
        c->key_len = UBIFS_SK_LEN;
@@ -301,8 +301,8 @@ static int create_default_filesystem(struct ubifs_info *c)
        ino->creat_sqnum = cpu_to_le64(++c->max_sqnum);
        ino->nlink = cpu_to_le32(2);
 
-       ktime_get_real_ts(&ts);
-       ts = timespec_trunc(ts, DEFAULT_TIME_GRAN);
+       ktime_get_real_ts64(&ts);
+       ts = timespec64_trunc(ts, DEFAULT_TIME_GRAN);
        tmp_le64 = cpu_to_le64(ts.tv_sec);
        ino->atime_sec   = tmp_le64;
        ino->ctime_sec   = tmp_le64;
@@ -563,7 +563,7 @@ int ubifs_read_superblock(struct ubifs_info *c)
         * due to the unavailability of time-travelling equipment.
         */
        if (c->fmt_version > UBIFS_FORMAT_VERSION) {
-               ubifs_assert(!c->ro_media || c->ro_mount);
+               ubifs_assert(c, !c->ro_media || c->ro_mount);
                if (!c->ro_mount ||
                    c->ro_compat_version > UBIFS_RO_COMPAT_VERSION) {
                        ubifs_err(c, "on-flash format version is w%d/r%d, but software only supports up to version w%d/r%d",
@@ -705,9 +705,9 @@ static int fixup_leb(struct ubifs_info *c, int lnum, int len)
 {
        int err;
 
-       ubifs_assert(len >= 0);
-       ubifs_assert(len % c->min_io_size == 0);
-       ubifs_assert(len < c->leb_size);
+       ubifs_assert(c, len >= 0);
+       ubifs_assert(c, len % c->min_io_size == 0);
+       ubifs_assert(c, len < c->leb_size);
 
        if (len == 0) {
                dbg_mnt("unmap empty LEB %d", lnum);
@@ -817,8 +817,8 @@ int ubifs_fixup_free_space(struct ubifs_info *c)
        int err;
        struct ubifs_sb_node *sup;
 
-       ubifs_assert(c->space_fixup);
-       ubifs_assert(!c->ro_mount);
+       ubifs_assert(c, c->space_fixup);
+       ubifs_assert(c, !c->ro_mount);
 
        ubifs_msg(c, "start fixing up free space");
 
index 16f03d9..ea88926 100644 (file)
@@ -176,7 +176,7 @@ void ubifs_end_scan(const struct ubifs_info *c, struct ubifs_scan_leb *sleb,
                    int lnum, int offs)
 {
        dbg_scan("stop scanning LEB %d at offset %d", lnum, offs);
-       ubifs_assert(offs % c->min_io_size == 0);
+       ubifs_assert(c, offs % c->min_io_size == 0);
 
        sleb->endpt = ALIGN(offs, c->min_io_size);
 }
index 9a9fb94..5eb5958 100644 (file)
@@ -71,10 +71,10 @@ static int shrink_tnc(struct ubifs_info *c, int nr, int age, int *contention)
 {
        int total_freed = 0;
        struct ubifs_znode *znode, *zprev;
-       int time = get_seconds();
+       time64_t time = ktime_get_seconds();
 
-       ubifs_assert(mutex_is_locked(&c->umount_mutex));
-       ubifs_assert(mutex_is_locked(&c->tnc_mutex));
+       ubifs_assert(c, mutex_is_locked(&c->umount_mutex));
+       ubifs_assert(c, mutex_is_locked(&c->tnc_mutex));
 
        if (!c->zroot.znode || atomic_long_read(&c->clean_zn_cnt) == 0)
                return 0;
@@ -89,7 +89,7 @@ static int shrink_tnc(struct ubifs_info *c, int nr, int age, int *contention)
         * changed only when the 'c->tnc_mutex' is held.
         */
        zprev = NULL;
-       znode = ubifs_tnc_levelorder_next(c->zroot.znode, NULL);
+       znode = ubifs_tnc_levelorder_next(c, c->zroot.znode, NULL);
        while (znode && total_freed < nr &&
               atomic_long_read(&c->clean_zn_cnt) > 0) {
                int freed;
@@ -125,7 +125,7 @@ static int shrink_tnc(struct ubifs_info *c, int nr, int age, int *contention)
                        else
                                c->zroot.znode = NULL;
 
-                       freed = ubifs_destroy_tnc_subtree(znode);
+                       freed = ubifs_destroy_tnc_subtree(c, znode);
                        atomic_long_sub(freed, &ubifs_clean_zn_cnt);
                        atomic_long_sub(freed, &c->clean_zn_cnt);
                        total_freed += freed;
@@ -136,7 +136,7 @@ static int shrink_tnc(struct ubifs_info *c, int nr, int age, int *contention)
                        break;
 
                zprev = znode;
-               znode = ubifs_tnc_levelorder_next(c->zroot.znode, znode);
+               znode = ubifs_tnc_levelorder_next(c, c->zroot.znode, znode);
                cond_resched();
        }
 
index c5466c7..23e7042 100644 (file)
@@ -89,9 +89,9 @@ static int validate_inode(struct ubifs_info *c, const struct inode *inode)
        if (ui->xattr && !S_ISREG(inode->i_mode))
                return 5;
 
-       if (!ubifs_compr_present(ui->compr_type)) {
+       if (!ubifs_compr_present(c, ui->compr_type)) {
                ubifs_warn(c, "inode %lu uses '%s' compression, but it was not compiled in",
-                          inode->i_ino, ubifs_compr_name(ui->compr_type));
+                          inode->i_ino, ubifs_compr_name(c, ui->compr_type));
        }
 
        err = dbg_check_dir(c, inode);
@@ -296,7 +296,7 @@ static int ubifs_write_inode(struct inode *inode, struct writeback_control *wbc)
        struct ubifs_info *c = inode->i_sb->s_fs_info;
        struct ubifs_inode *ui = ubifs_inode(inode);
 
-       ubifs_assert(!ui->xattr);
+       ubifs_assert(c, !ui->xattr);
        if (is_bad_inode(inode))
                return 0;
 
@@ -349,7 +349,7 @@ static void ubifs_evict_inode(struct inode *inode)
                goto out;
 
        dbg_gen("inode %lu, mode %#x", inode->i_ino, (int)inode->i_mode);
-       ubifs_assert(!atomic_read(&inode->i_count));
+       ubifs_assert(c, !atomic_read(&inode->i_count));
 
        truncate_inode_pages_final(&inode->i_data);
 
@@ -384,9 +384,10 @@ done:
 
 static void ubifs_dirty_inode(struct inode *inode, int flags)
 {
+       struct ubifs_info *c = inode->i_sb->s_fs_info;
        struct ubifs_inode *ui = ubifs_inode(inode);
 
-       ubifs_assert(mutex_is_locked(&ui->ui_mutex));
+       ubifs_assert(c, mutex_is_locked(&ui->ui_mutex));
        if (!ui->dirty) {
                ui->dirty = 1;
                dbg_gen("inode %lu",  inode->i_ino);
@@ -416,7 +417,7 @@ static int ubifs_statfs(struct dentry *dentry, struct kstatfs *buf)
        buf->f_namelen = UBIFS_MAX_NLEN;
        buf->f_fsid.val[0] = le32_to_cpu(uuid[0]) ^ le32_to_cpu(uuid[2]);
        buf->f_fsid.val[1] = le32_to_cpu(uuid[1]) ^ le32_to_cpu(uuid[3]);
-       ubifs_assert(buf->f_bfree <= c->block_cnt);
+       ubifs_assert(c, buf->f_bfree <= c->block_cnt);
        return 0;
 }
 
@@ -441,9 +442,10 @@ static int ubifs_show_options(struct seq_file *s, struct dentry *root)
 
        if (c->mount_opts.override_compr) {
                seq_printf(s, ",compr=%s",
-                          ubifs_compr_name(c->mount_opts.compr_type));
+                          ubifs_compr_name(c, c->mount_opts.compr_type));
        }
 
+       seq_printf(s, ",assert=%s", ubifs_assert_action_name(c));
        seq_printf(s, ",ubi=%d,vol=%d", c->vi.ubi_num, c->vi.vol_id);
 
        return 0;
@@ -921,6 +923,7 @@ static int check_volume_empty(struct ubifs_info *c)
  * Opt_chk_data_crc: check CRCs when reading data nodes
  * Opt_no_chk_data_crc: do not check CRCs when reading data nodes
  * Opt_override_compr: override default compressor
+ * Opt_assert: set ubifs_assert() action
  * Opt_err: just end of array marker
  */
 enum {
@@ -931,6 +934,7 @@ enum {
        Opt_chk_data_crc,
        Opt_no_chk_data_crc,
        Opt_override_compr,
+       Opt_assert,
        Opt_ignore,
        Opt_err,
 };
@@ -945,6 +949,7 @@ static const match_table_t tokens = {
        {Opt_override_compr, "compr=%s"},
        {Opt_ignore, "ubi=%s"},
        {Opt_ignore, "vol=%s"},
+       {Opt_assert, "assert=%s"},
        {Opt_err, NULL},
 };
 
@@ -1045,6 +1050,26 @@ static int ubifs_parse_options(struct ubifs_info *c, char *options,
                        c->default_compr = c->mount_opts.compr_type;
                        break;
                }
+               case Opt_assert:
+               {
+                       char *act = match_strdup(&args[0]);
+
+                       if (!act)
+                               return -ENOMEM;
+                       if (!strcmp(act, "report"))
+                               c->assert_action = ASSACT_REPORT;
+                       else if (!strcmp(act, "read-only"))
+                               c->assert_action = ASSACT_RO;
+                       else if (!strcmp(act, "panic"))
+                               c->assert_action = ASSACT_PANIC;
+                       else {
+                               ubifs_err(c, "unknown assert action \"%s\"", act);
+                               kfree(act);
+                               return -EINVAL;
+                       }
+                       kfree(act);
+                       break;
+               }
                case Opt_ignore:
                        break;
                default:
@@ -1103,7 +1128,7 @@ static void destroy_journal(struct ubifs_info *c)
  */
 static void bu_init(struct ubifs_info *c)
 {
-       ubifs_assert(c->bulk_read == 1);
+       ubifs_assert(c, c->bulk_read == 1);
 
        if (c->bu.buf)
                return; /* Already initialized */
@@ -1134,7 +1159,7 @@ again:
  */
 static int check_free_space(struct ubifs_info *c)
 {
-       ubifs_assert(c->dark_wm > 0);
+       ubifs_assert(c, c->dark_wm > 0);
        if (c->lst.total_free + c->lst.total_dirty < c->dark_wm) {
                ubifs_err(c, "insufficient free space to mount in R/W mode");
                ubifs_dump_budg(c, &c->bi);
@@ -1234,9 +1259,9 @@ static int mount_ubifs(struct ubifs_info *c)
         * Make sure the compressor which is set as default in the superblock
         * or overridden by mount options is actually compiled in.
         */
-       if (!ubifs_compr_present(c->default_compr)) {
+       if (!ubifs_compr_present(c, c->default_compr)) {
                ubifs_err(c, "'compressor \"%s\" is not compiled in",
-                         ubifs_compr_name(c->default_compr));
+                         ubifs_compr_name(c, c->default_compr));
                err = -ENOTSUPP;
                goto out_free;
        }
@@ -1396,10 +1421,10 @@ static int mount_ubifs(struct ubifs_info *c)
                         * the journal head LEBs may also be accounted as
                         * "empty taken" if they are empty.
                         */
-                       ubifs_assert(c->lst.taken_empty_lebs > 0);
+                       ubifs_assert(c, c->lst.taken_empty_lebs > 0);
                }
        } else
-               ubifs_assert(c->lst.taken_empty_lebs > 0);
+               ubifs_assert(c, c->lst.taken_empty_lebs > 0);
 
        err = dbg_check_filesystem(c);
        if (err)
@@ -1429,7 +1454,7 @@ static int mount_ubifs(struct ubifs_info *c)
                  UBIFS_FORMAT_VERSION, UBIFS_RO_COMPAT_VERSION, c->uuid,
                  c->big_lpt ? ", big LPT model" : ", small LPT model");
 
-       dbg_gen("default compressor:  %s", ubifs_compr_name(c->default_compr));
+       dbg_gen("default compressor:  %s", ubifs_compr_name(c, c->default_compr));
        dbg_gen("data journal heads:  %d",
                c->jhead_cnt - NONDATA_JHEADS_CNT);
        dbg_gen("log LEBs:            %d (%d - %d)",
@@ -1610,7 +1635,7 @@ static int ubifs_remount_rw(struct ubifs_info *c)
                        goto out;
        } else {
                /* A readonly mount is not allowed to have orphans */
-               ubifs_assert(c->tot_orphans == 0);
+               ubifs_assert(c, c->tot_orphans == 0);
                err = ubifs_clear_orphans(c);
                if (err)
                        goto out;
@@ -1727,8 +1752,8 @@ static void ubifs_remount_ro(struct ubifs_info *c)
 {
        int i, err;
 
-       ubifs_assert(!c->need_recovery);
-       ubifs_assert(!c->ro_mount);
+       ubifs_assert(c, !c->need_recovery);
+       ubifs_assert(c, !c->ro_mount);
 
        mutex_lock(&c->umount_mutex);
        if (c->bgt) {
@@ -1778,9 +1803,9 @@ static void ubifs_put_super(struct super_block *sb)
         * to write them back because of I/O errors.
         */
        if (!c->ro_error) {
-               ubifs_assert(c->bi.idx_growth == 0);
-               ubifs_assert(c->bi.dd_growth == 0);
-               ubifs_assert(c->bi.data_growth == 0);
+               ubifs_assert(c, c->bi.idx_growth == 0);
+               ubifs_assert(c, c->bi.dd_growth == 0);
+               ubifs_assert(c, c->bi.data_growth == 0);
        }
 
        /*
@@ -1887,7 +1912,7 @@ static int ubifs_remount_fs(struct super_block *sb, int *flags, char *data)
                mutex_unlock(&c->bu_mutex);
        }
 
-       ubifs_assert(c->lst.taken_empty_lebs > 0);
+       ubifs_assert(c, c->lst.taken_empty_lebs > 0);
        return 0;
 }
 
@@ -2002,6 +2027,7 @@ static struct ubifs_info *alloc_ubifs_info(struct ubi_volume_desc *ubi)
                INIT_LIST_HEAD(&c->orph_list);
                INIT_LIST_HEAD(&c->orph_new);
                c->no_chk_data_crc = 1;
+               c->assert_action = ASSACT_RO;
 
                c->highest_inum = UBIFS_FIRST_INO;
                c->lhead_lnum = c->ltail_lnum = UBIFS_LOG_LNUM;
@@ -2053,7 +2079,9 @@ static int ubifs_fill_super(struct super_block *sb, void *data, int silent)
        if (c->max_inode_sz > MAX_LFS_FILESIZE)
                sb->s_maxbytes = c->max_inode_sz = MAX_LFS_FILESIZE;
        sb->s_op = &ubifs_super_operations;
+#ifdef CONFIG_UBIFS_FS_XATTR
        sb->s_xattr = ubifs_xattr_handlers;
+#endif
 #ifdef CONFIG_UBIFS_FS_ENCRYPTION
        sb->s_cop = &ubifs_crypt_operations;
 #endif
@@ -2061,7 +2089,7 @@ static int ubifs_fill_super(struct super_block *sb, void *data, int silent)
        mutex_lock(&c->umount_mutex);
        err = mount_ubifs(c);
        if (err) {
-               ubifs_assert(err < 0);
+               ubifs_assert(c, err < 0);
                goto out_unlock;
        }
 
@@ -2304,8 +2332,8 @@ late_initcall(ubifs_init);
 
 static void __exit ubifs_exit(void)
 {
-       ubifs_assert(list_empty(&ubifs_infos));
-       ubifs_assert(atomic_long_read(&ubifs_clean_zn_cnt) == 0);
+       WARN_ON(list_empty(&ubifs_infos));
+       WARN_ON(atomic_long_read(&ubifs_clean_zn_cnt) == 0);
 
        dbg_debugfs_exit();
        ubifs_compressors_exit();
index 4a21e7f..bf416e5 100644 (file)
@@ -211,7 +211,7 @@ static struct ubifs_znode *copy_znode(struct ubifs_info *c,
        __set_bit(DIRTY_ZNODE, &zn->flags);
        __clear_bit(COW_ZNODE, &zn->flags);
 
-       ubifs_assert(!ubifs_zn_obsolete(znode));
+       ubifs_assert(c, !ubifs_zn_obsolete(znode));
        __set_bit(OBSOLETE_ZNODE, &znode->flags);
 
        if (znode->level != 0) {
@@ -321,9 +321,9 @@ static int lnc_add(struct ubifs_info *c, struct ubifs_zbranch *zbr,
        void *lnc_node;
        const struct ubifs_dent_node *dent = node;
 
-       ubifs_assert(!zbr->leaf);
-       ubifs_assert(zbr->len != 0);
-       ubifs_assert(is_hash_key(c, &zbr->key));
+       ubifs_assert(c, !zbr->leaf);
+       ubifs_assert(c, zbr->len != 0);
+       ubifs_assert(c, is_hash_key(c, &zbr->key));
 
        err = ubifs_validate_entry(c, dent);
        if (err) {
@@ -355,8 +355,8 @@ static int lnc_add_directly(struct ubifs_info *c, struct ubifs_zbranch *zbr,
 {
        int err;
 
-       ubifs_assert(!zbr->leaf);
-       ubifs_assert(zbr->len != 0);
+       ubifs_assert(c, !zbr->leaf);
+       ubifs_assert(c, zbr->len != 0);
 
        err = ubifs_validate_entry(c, node);
        if (err) {
@@ -398,11 +398,11 @@ static int tnc_read_hashed_node(struct ubifs_info *c, struct ubifs_zbranch *zbr,
 {
        int err;
 
-       ubifs_assert(is_hash_key(c, &zbr->key));
+       ubifs_assert(c, is_hash_key(c, &zbr->key));
 
        if (zbr->leaf) {
                /* Read from the leaf node cache */
-               ubifs_assert(zbr->len != 0);
+               ubifs_assert(c, zbr->len != 0);
                memcpy(node, zbr->leaf, zbr->len);
                return 0;
        }
@@ -721,7 +721,7 @@ static int resolve_collision(struct ubifs_info *c, const union ubifs_key *key,
                while (1) {
                        err = tnc_prev(c, zn, n);
                        if (err == -ENOENT) {
-                               ubifs_assert(*n == 0);
+                               ubifs_assert(c, *n == 0);
                                *n = -1;
                                return 0;
                        }
@@ -761,12 +761,12 @@ static int resolve_collision(struct ubifs_info *c, const union ubifs_key *key,
                                        err = tnc_next(c, zn, n);
                                        if (err) {
                                                /* Should be impossible */
-                                               ubifs_assert(0);
+                                               ubifs_assert(c, 0);
                                                if (err == -ENOENT)
                                                        err = -EINVAL;
                                                return err;
                                        }
-                                       ubifs_assert(*n == 0);
+                                       ubifs_assert(c, *n == 0);
                                        *n = -1;
                                }
                                return 0;
@@ -778,7 +778,7 @@ static int resolve_collision(struct ubifs_info *c, const union ubifs_key *key,
                                return 0;
                        if (err == NAME_MATCHES)
                                return 1;
-                       ubifs_assert(err == NAME_GREATER);
+                       ubifs_assert(c, err == NAME_GREATER);
                }
        } else {
                int nn = *n;
@@ -802,7 +802,7 @@ static int resolve_collision(struct ubifs_info *c, const union ubifs_key *key,
                        *n = nn;
                        if (err == NAME_MATCHES)
                                return 1;
-                       ubifs_assert(err == NAME_LESS);
+                       ubifs_assert(c, err == NAME_LESS);
                }
        }
 }
@@ -843,7 +843,7 @@ static int fallible_matches_name(struct ubifs_info *c,
                        err = NOT_ON_MEDIA;
                        goto out_free;
                }
-               ubifs_assert(err == 1);
+               ubifs_assert(c, err == 1);
 
                err = lnc_add_directly(c, zbr, dent);
                if (err)
@@ -923,7 +923,7 @@ static int fallible_resolve_collision(struct ubifs_info *c,
                while (1) {
                        err = tnc_prev(c, zn, n);
                        if (err == -ENOENT) {
-                               ubifs_assert(*n == 0);
+                               ubifs_assert(c, *n == 0);
                                *n = -1;
                                break;
                        }
@@ -935,12 +935,12 @@ static int fallible_resolve_collision(struct ubifs_info *c,
                                        err = tnc_next(c, zn, n);
                                        if (err) {
                                                /* Should be impossible */
-                                               ubifs_assert(0);
+                                               ubifs_assert(c, 0);
                                                if (err == -ENOENT)
                                                        err = -EINVAL;
                                                return err;
                                        }
-                                       ubifs_assert(*n == 0);
+                                       ubifs_assert(c, *n == 0);
                                        *n = -1;
                                }
                                break;
@@ -1100,8 +1100,8 @@ static struct ubifs_znode *dirty_cow_bottom_up(struct ubifs_info *c,
        struct ubifs_znode *zp;
        int *path = c->bottom_up_buf, p = 0;
 
-       ubifs_assert(c->zroot.znode);
-       ubifs_assert(znode);
+       ubifs_assert(c, c->zroot.znode);
+       ubifs_assert(c, znode);
        if (c->zroot.znode->level > BOTTOM_UP_HEIGHT) {
                kfree(c->bottom_up_buf);
                c->bottom_up_buf = kmalloc_array(c->zroot.znode->level,
@@ -1120,7 +1120,7 @@ static struct ubifs_znode *dirty_cow_bottom_up(struct ubifs_info *c,
                        if (!zp)
                                break;
                        n = znode->iip;
-                       ubifs_assert(p < c->zroot.znode->level);
+                       ubifs_assert(c, p < c->zroot.znode->level);
                        path[p++] = n;
                        if (!zp->cnext && ubifs_zn_dirty(znode))
                                break;
@@ -1134,18 +1134,18 @@ static struct ubifs_znode *dirty_cow_bottom_up(struct ubifs_info *c,
 
                zp = znode->parent;
                if (zp) {
-                       ubifs_assert(path[p - 1] >= 0);
-                       ubifs_assert(path[p - 1] < zp->child_cnt);
+                       ubifs_assert(c, path[p - 1] >= 0);
+                       ubifs_assert(c, path[p - 1] < zp->child_cnt);
                        zbr = &zp->zbranch[path[--p]];
                        znode = dirty_cow_znode(c, zbr);
                } else {
-                       ubifs_assert(znode == c->zroot.znode);
+                       ubifs_assert(c, znode == c->zroot.znode);
                        znode = dirty_cow_znode(c, &c->zroot);
                }
                if (IS_ERR(znode) || !p)
                        break;
-               ubifs_assert(path[p - 1] >= 0);
-               ubifs_assert(path[p - 1] < znode->child_cnt);
+               ubifs_assert(c, path[p - 1] >= 0);
+               ubifs_assert(c, path[p - 1] < znode->child_cnt);
                znode = znode->zbranch[path[p - 1]].znode;
        }
 
@@ -1179,10 +1179,10 @@ int ubifs_lookup_level0(struct ubifs_info *c, const union ubifs_key *key,
 {
        int err, exact;
        struct ubifs_znode *znode;
-       unsigned long time = get_seconds();
+       time64_t time = ktime_get_seconds();
 
        dbg_tnck(key, "search key ");
-       ubifs_assert(key_type(c, key) < UBIFS_INVALID_KEY);
+       ubifs_assert(c, key_type(c, key) < UBIFS_INVALID_KEY);
 
        znode = c->zroot.znode;
        if (unlikely(!znode)) {
@@ -1315,7 +1315,7 @@ static int lookup_level0_dirty(struct ubifs_info *c, const union ubifs_key *key,
 {
        int err, exact;
        struct ubifs_znode *znode;
-       unsigned long time = get_seconds();
+       time64_t time = ktime_get_seconds();
 
        dbg_tnck(key, "search and dirty key ");
 
@@ -1658,9 +1658,9 @@ static int read_wbuf(struct ubifs_wbuf *wbuf, void *buf, int len, int lnum,
        int rlen, overlap;
 
        dbg_io("LEB %d:%d, length %d", lnum, offs, len);
-       ubifs_assert(wbuf && lnum >= 0 && lnum < c->leb_cnt && offs >= 0);
-       ubifs_assert(!(offs & 7) && offs < c->leb_size);
-       ubifs_assert(offs + len <= c->leb_size);
+       ubifs_assert(c, wbuf && lnum >= 0 && lnum < c->leb_cnt && offs >= 0);
+       ubifs_assert(c, !(offs & 7) && offs < c->leb_size);
+       ubifs_assert(c, offs + len <= c->leb_size);
 
        spin_lock(&wbuf->lock);
        overlap = (lnum == wbuf->lnum && offs + len > wbuf->offs);
@@ -1824,7 +1824,7 @@ static int do_lookup_nm(struct ubifs_info *c, const union ubifs_key *key,
                goto out_unlock;
        }
 
-       ubifs_assert(n >= 0);
+       ubifs_assert(c, n >= 0);
 
        err = resolve_collision(c, key, &znode, &n, nm);
        dbg_tnc("rc returned %d, znode %p, n %d", err, znode, n);
@@ -1922,7 +1922,7 @@ static int do_lookup_dh(struct ubifs_info *c, const union ubifs_key *key,
        struct ubifs_znode *znode;
        union ubifs_key start_key;
 
-       ubifs_assert(is_hash_key(c, key));
+       ubifs_assert(c, is_hash_key(c, key));
 
        lowest_dent_key(c, &start_key, key_inum(c, key));
 
@@ -1993,8 +1993,8 @@ static void correct_parent_keys(const struct ubifs_info *c,
 {
        union ubifs_key *key, *key1;
 
-       ubifs_assert(znode->parent);
-       ubifs_assert(znode->iip == 0);
+       ubifs_assert(c, znode->parent);
+       ubifs_assert(c, znode->iip == 0);
 
        key = &znode->zbranch[0].key;
        key1 = &znode->parent->zbranch[0].key;
@@ -2011,6 +2011,7 @@ static void correct_parent_keys(const struct ubifs_info *c,
 
 /**
  * insert_zbranch - insert a zbranch into a znode.
+ * @c: UBIFS file-system description object
  * @znode: znode into which to insert
  * @zbr: zbranch to insert
  * @n: slot number to insert to
@@ -2020,12 +2021,12 @@ static void correct_parent_keys(const struct ubifs_info *c,
  * zbranch has to be inserted to the @znode->zbranches[]' array at the @n-th
  * slot, zbranches starting from @n have to be moved right.
  */
-static void insert_zbranch(struct ubifs_znode *znode,
+static void insert_zbranch(struct ubifs_info *c, struct ubifs_znode *znode,
                           const struct ubifs_zbranch *zbr, int n)
 {
        int i;
 
-       ubifs_assert(ubifs_zn_dirty(znode));
+       ubifs_assert(c, ubifs_zn_dirty(znode));
 
        if (znode->level) {
                for (i = znode->child_cnt; i > n; i--) {
@@ -2079,16 +2080,16 @@ static int tnc_insert(struct ubifs_info *c, struct ubifs_znode *znode,
        int i, keep, move, appending = 0;
        union ubifs_key *key = &zbr->key, *key1;
 
-       ubifs_assert(n >= 0 && n <= c->fanout);
+       ubifs_assert(c, n >= 0 && n <= c->fanout);
 
        /* Implement naive insert for now */
 again:
        zp = znode->parent;
        if (znode->child_cnt < c->fanout) {
-               ubifs_assert(n != c->fanout);
+               ubifs_assert(c, n != c->fanout);
                dbg_tnck(key, "inserted at %d level %d, key ", n, znode->level);
 
-               insert_zbranch(znode, zbr, n);
+               insert_zbranch(c, znode, zbr, n);
 
                /* Ensure parent's key is correct */
                if (n == 0 && zp && znode->iip == 0)
@@ -2197,7 +2198,7 @@ do_split:
        /* Insert new key and branch */
        dbg_tnck(key, "inserting at %d level %d, key ", n, zn->level);
 
-       insert_zbranch(zi, zbr, n);
+       insert_zbranch(c, zi, zbr, n);
 
        /* Insert new znode (produced by spitting) into the parent */
        if (zp) {
@@ -2495,8 +2496,8 @@ static int tnc_delete(struct ubifs_info *c, struct ubifs_znode *znode, int n)
        int i, err;
 
        /* Delete without merge for now */
-       ubifs_assert(znode->level == 0);
-       ubifs_assert(n >= 0 && n < c->fanout);
+       ubifs_assert(c, znode->level == 0);
+       ubifs_assert(c, n >= 0 && n < c->fanout);
        dbg_tnck(&znode->zbranch[n].key, "deleting key ");
 
        zbr = &znode->zbranch[n];
@@ -2522,8 +2523,8 @@ static int tnc_delete(struct ubifs_info *c, struct ubifs_znode *znode, int n)
         */
 
        do {
-               ubifs_assert(!ubifs_zn_obsolete(znode));
-               ubifs_assert(ubifs_zn_dirty(znode));
+               ubifs_assert(c, !ubifs_zn_obsolete(znode));
+               ubifs_assert(c, ubifs_zn_dirty(znode));
 
                zp = znode->parent;
                n = znode->iip;
@@ -2545,7 +2546,7 @@ static int tnc_delete(struct ubifs_info *c, struct ubifs_znode *znode, int n)
 
        /* Remove from znode, entry n - 1 */
        znode->child_cnt -= 1;
-       ubifs_assert(znode->level != 0);
+       ubifs_assert(c, znode->level != 0);
        for (i = n; i < znode->child_cnt; i++) {
                znode->zbranch[i] = znode->zbranch[i + 1];
                if (znode->zbranch[i].znode)
@@ -2578,8 +2579,8 @@ static int tnc_delete(struct ubifs_info *c, struct ubifs_znode *znode, int n)
                        c->zroot.offs = zbr->offs;
                        c->zroot.len = zbr->len;
                        c->zroot.znode = znode;
-                       ubifs_assert(!ubifs_zn_obsolete(zp));
-                       ubifs_assert(ubifs_zn_dirty(zp));
+                       ubifs_assert(c, !ubifs_zn_obsolete(zp));
+                       ubifs_assert(c, ubifs_zn_dirty(zp));
                        atomic_long_dec(&c->dirty_zn_cnt);
 
                        if (zp->cnext) {
@@ -2944,7 +2945,7 @@ struct ubifs_dent_node *ubifs_tnc_next_ent(struct ubifs_info *c,
        union ubifs_key *dkey;
 
        dbg_tnck(key, "key ");
-       ubifs_assert(is_hash_key(c, key));
+       ubifs_assert(c, is_hash_key(c, key));
 
        mutex_lock(&c->tnc_mutex);
        err = ubifs_lookup_level0(c, key, &znode, &n);
@@ -3031,7 +3032,7 @@ static void tnc_destroy_cnext(struct ubifs_info *c)
 
        if (!c->cnext)
                return;
-       ubifs_assert(c->cmt_state == COMMIT_BROKEN);
+       ubifs_assert(c, c->cmt_state == COMMIT_BROKEN);
        cnext = c->cnext;
        do {
                struct ubifs_znode *znode = cnext;
@@ -3053,8 +3054,8 @@ void ubifs_tnc_close(struct ubifs_info *c)
                long n, freed;
 
                n = atomic_long_read(&c->clean_zn_cnt);
-               freed = ubifs_destroy_tnc_subtree(c->zroot.znode);
-               ubifs_assert(freed == n);
+               freed = ubifs_destroy_tnc_subtree(c, c->zroot.znode);
+               ubifs_assert(c, freed == n);
                atomic_long_sub(n, &ubifs_clean_zn_cnt);
        }
        kfree(c->gap_lebs);
@@ -3167,7 +3168,7 @@ static struct ubifs_znode *lookup_znode(struct ubifs_info *c,
        struct ubifs_znode *znode, *zn;
        int n, nn;
 
-       ubifs_assert(key_type(c, key) < UBIFS_INVALID_KEY);
+       ubifs_assert(c, key_type(c, key) < UBIFS_INVALID_KEY);
 
        /*
         * The arguments have probably been read off flash, so don't assume
@@ -3206,7 +3207,7 @@ static struct ubifs_znode *lookup_znode(struct ubifs_info *c,
                        if (IS_ERR(znode))
                                return znode;
                        ubifs_search_zbranch(c, znode, key, &n);
-                       ubifs_assert(n >= 0);
+                       ubifs_assert(c, n >= 0);
                }
                if (znode->level == level + 1)
                        break;
@@ -3497,7 +3498,7 @@ int dbg_check_inode_size(struct ubifs_info *c, const struct inode *inode,
        if (err < 0)
                goto out_unlock;
 
-       ubifs_assert(err == 0);
+       ubifs_assert(c, err == 0);
        key = &znode->zbranch[n].key;
        if (!key_in_range(c, key, &from_key, &to_key))
                goto out_unlock;
index a9df94a..dba87d0 100644 (file)
@@ -87,8 +87,8 @@ static int make_idx_node(struct ubifs_info *c, struct ubifs_idx_node *idx,
 
        atomic_long_dec(&c->dirty_zn_cnt);
 
-       ubifs_assert(ubifs_zn_dirty(znode));
-       ubifs_assert(ubifs_zn_cow(znode));
+       ubifs_assert(c, ubifs_zn_dirty(znode));
+       ubifs_assert(c, ubifs_zn_cow(znode));
 
        /*
         * Note, unlike 'write_index()' we do not add memory barriers here
@@ -115,9 +115,9 @@ static int fill_gap(struct ubifs_info *c, int lnum, int gap_start, int gap_end,
 {
        int len, gap_remains, gap_pos, written, pad_len;
 
-       ubifs_assert((gap_start & 7) == 0);
-       ubifs_assert((gap_end & 7) == 0);
-       ubifs_assert(gap_end >= gap_start);
+       ubifs_assert(c, (gap_start & 7) == 0);
+       ubifs_assert(c, (gap_end & 7) == 0);
+       ubifs_assert(c, gap_end >= gap_start);
 
        gap_remains = gap_end - gap_start;
        if (!gap_remains)
@@ -131,7 +131,7 @@ static int fill_gap(struct ubifs_info *c, int lnum, int gap_start, int gap_end,
                        const int alen = ALIGN(len, 8);
                        int err;
 
-                       ubifs_assert(alen <= gap_remains);
+                       ubifs_assert(c, alen <= gap_remains);
                        err = make_idx_node(c, c->ileb_buf + gap_pos, znode,
                                            lnum, gap_pos, len);
                        if (err)
@@ -259,7 +259,7 @@ static int layout_leb_in_gaps(struct ubifs_info *c, int *p)
                struct ubifs_idx_node *idx;
                int in_use, level;
 
-               ubifs_assert(snod->type == UBIFS_IDX_NODE);
+               ubifs_assert(c, snod->type == UBIFS_IDX_NODE);
                idx = snod->node;
                key_read(c, ubifs_idx_key(c, idx), &snod->key);
                level = le16_to_cpu(idx->level);
@@ -373,7 +373,7 @@ static int layout_in_gaps(struct ubifs_info *c, int cnt)
 
        p = c->gap_lebs;
        do {
-               ubifs_assert(p < c->gap_lebs + c->lst.idx_lebs);
+               ubifs_assert(c, p < c->gap_lebs + c->lst.idx_lebs);
                written = layout_leb_in_gaps(c, p);
                if (written < 0) {
                        err = written;
@@ -639,7 +639,7 @@ static int get_znodes_to_commit(struct ubifs_info *c)
        }
        cnt += 1;
        while (1) {
-               ubifs_assert(!ubifs_zn_cow(znode));
+               ubifs_assert(c, !ubifs_zn_cow(znode));
                __set_bit(COW_ZNODE, &znode->flags);
                znode->alt = 0;
                cnext = find_next_dirty(znode);
@@ -652,7 +652,7 @@ static int get_znodes_to_commit(struct ubifs_info *c)
                cnt += 1;
        }
        dbg_cmt("committing %d znodes", cnt);
-       ubifs_assert(cnt == atomic_long_read(&c->dirty_zn_cnt));
+       ubifs_assert(c, cnt == atomic_long_read(&c->dirty_zn_cnt));
        return cnt;
 }
 
@@ -760,7 +760,7 @@ int ubifs_tnc_start_commit(struct ubifs_info *c, struct ubifs_zbranch *zroot)
                err = layout_commit(c, no_space, cnt);
                if (err)
                        goto out_free;
-               ubifs_assert(atomic_long_read(&c->dirty_zn_cnt) == 0);
+               ubifs_assert(c, atomic_long_read(&c->dirty_zn_cnt) == 0);
                err = free_unused_idx_lebs(c);
                if (err)
                        goto out;
@@ -781,7 +781,7 @@ int ubifs_tnc_start_commit(struct ubifs_info *c, struct ubifs_zbranch *zroot)
         * budgeting subsystem to assume the index is already committed,
         * even though it is not.
         */
-       ubifs_assert(c->bi.min_idx_lebs == ubifs_calc_min_idx_lebs(c));
+       ubifs_assert(c, c->bi.min_idx_lebs == ubifs_calc_min_idx_lebs(c));
        c->bi.old_idx_sz = c->calc_idx_sz;
        c->bi.uncommitted_idx = 0;
        c->bi.min_idx_lebs = ubifs_calc_min_idx_lebs(c);
@@ -887,8 +887,8 @@ static int write_index(struct ubifs_info *c)
                /* Grab some stuff from znode while we still can */
                cnext = znode->cnext;
 
-               ubifs_assert(ubifs_zn_dirty(znode));
-               ubifs_assert(ubifs_zn_cow(znode));
+               ubifs_assert(c, ubifs_zn_dirty(znode));
+               ubifs_assert(c, ubifs_zn_cow(znode));
 
                /*
                 * It is important that other threads should see %DIRTY_ZNODE
index 93f5b78..d90ee01 100644 (file)
 
 /**
  * ubifs_tnc_levelorder_next - next TNC tree element in levelorder traversal.
+ * @c: UBIFS file-system description object
  * @zr: root of the subtree to traverse
  * @znode: previous znode
  *
  * This function implements levelorder TNC traversal. The LNC is ignored.
  * Returns the next element or %NULL if @znode is already the last one.
  */
-struct ubifs_znode *ubifs_tnc_levelorder_next(struct ubifs_znode *zr,
+struct ubifs_znode *ubifs_tnc_levelorder_next(const struct ubifs_info *c,
+                                             struct ubifs_znode *zr,
                                              struct ubifs_znode *znode)
 {
        int level, iip, level_search = 0;
        struct ubifs_znode *zn;
 
-       ubifs_assert(zr);
+       ubifs_assert(c, zr);
 
        if (unlikely(!znode))
                return zr;
@@ -58,7 +60,7 @@ struct ubifs_znode *ubifs_tnc_levelorder_next(struct ubifs_znode *zr,
 
        iip = znode->iip;
        while (1) {
-               ubifs_assert(znode->level <= zr->level);
+               ubifs_assert(c, znode->level <= zr->level);
 
                /*
                 * First walk up until there is a znode with next branch to
@@ -85,7 +87,7 @@ struct ubifs_znode *ubifs_tnc_levelorder_next(struct ubifs_znode *zr,
                        level_search = 1;
                        iip = -1;
                        znode = ubifs_tnc_find_child(zr, 0);
-                       ubifs_assert(znode);
+                       ubifs_assert(c, znode);
                }
 
                /* Switch to the next index */
@@ -111,7 +113,7 @@ struct ubifs_znode *ubifs_tnc_levelorder_next(struct ubifs_znode *zr,
                }
 
                if (zn) {
-                       ubifs_assert(zn->level >= 0);
+                       ubifs_assert(c, zn->level >= 0);
                        return zn;
                }
        }
@@ -140,7 +142,7 @@ int ubifs_search_zbranch(const struct ubifs_info *c,
        int uninitialized_var(cmp);
        const struct ubifs_zbranch *zbr = &znode->zbranch[0];
 
-       ubifs_assert(end > beg);
+       ubifs_assert(c, end > beg);
 
        while (end > beg) {
                mid = (beg + end) >> 1;
@@ -158,13 +160,13 @@ int ubifs_search_zbranch(const struct ubifs_info *c,
        *n = end - 1;
 
        /* The insert point is after *n */
-       ubifs_assert(*n >= -1 && *n < znode->child_cnt);
+       ubifs_assert(c, *n >= -1 && *n < znode->child_cnt);
        if (*n == -1)
-               ubifs_assert(keys_cmp(c, key, &zbr[0].key) < 0);
+               ubifs_assert(c, keys_cmp(c, key, &zbr[0].key) < 0);
        else
-               ubifs_assert(keys_cmp(c, key, &zbr[*n].key) > 0);
+               ubifs_assert(c, keys_cmp(c, key, &zbr[*n].key) > 0);
        if (*n + 1 < znode->child_cnt)
-               ubifs_assert(keys_cmp(c, key, &zbr[*n + 1].key) < 0);
+               ubifs_assert(c, keys_cmp(c, key, &zbr[*n + 1].key) < 0);
 
        return 0;
 }
@@ -195,16 +197,18 @@ struct ubifs_znode *ubifs_tnc_postorder_first(struct ubifs_znode *znode)
 
 /**
  * ubifs_tnc_postorder_next - next TNC tree element in postorder traversal.
+ * @c: UBIFS file-system description object
  * @znode: previous znode
  *
  * This function implements postorder TNC traversal. The LNC is ignored.
  * Returns the next element or %NULL if @znode is already the last one.
  */
-struct ubifs_znode *ubifs_tnc_postorder_next(struct ubifs_znode *znode)
+struct ubifs_znode *ubifs_tnc_postorder_next(const struct ubifs_info *c,
+                                            struct ubifs_znode *znode)
 {
        struct ubifs_znode *zn;
 
-       ubifs_assert(znode);
+       ubifs_assert(c, znode);
        if (unlikely(!znode->parent))
                return NULL;
 
@@ -220,18 +224,20 @@ struct ubifs_znode *ubifs_tnc_postorder_next(struct ubifs_znode *znode)
 
 /**
  * ubifs_destroy_tnc_subtree - destroy all znodes connected to a subtree.
+ * @c: UBIFS file-system description object
  * @znode: znode defining subtree to destroy
  *
  * This function destroys subtree of the TNC tree. Returns number of clean
  * znodes in the subtree.
  */
-long ubifs_destroy_tnc_subtree(struct ubifs_znode *znode)
+long ubifs_destroy_tnc_subtree(const struct ubifs_info *c,
+                              struct ubifs_znode *znode)
 {
        struct ubifs_znode *zn = ubifs_tnc_postorder_first(znode);
        long clean_freed = 0;
        int n;
 
-       ubifs_assert(zn);
+       ubifs_assert(c, zn);
        while (1) {
                for (n = 0; n < zn->child_cnt; n++) {
                        if (!zn->zbranch[n].znode)
@@ -252,7 +258,7 @@ long ubifs_destroy_tnc_subtree(struct ubifs_znode *znode)
                        return clean_freed;
                }
 
-               zn = ubifs_tnc_postorder_next(zn);
+               zn = ubifs_tnc_postorder_next(c, zn);
        }
 }
 
@@ -410,7 +416,7 @@ struct ubifs_znode *ubifs_load_znode(struct ubifs_info *c,
        int err;
        struct ubifs_znode *znode;
 
-       ubifs_assert(!zbr->znode);
+       ubifs_assert(c, !zbr->znode);
        /*
         * A slab cache is not presently used for znodes because the znode size
         * depends on the fanout which is stored in the superblock.
@@ -435,7 +441,7 @@ struct ubifs_znode *ubifs_load_znode(struct ubifs_info *c,
 
        zbr->znode = znode;
        znode->parent = parent;
-       znode->time = get_seconds();
+       znode->time = ktime_get_seconds();
        znode->iip = iip;
 
        return znode;
index 04bf84d..4368cde 100644 (file)
@@ -258,6 +258,18 @@ enum {
        LEB_RETAINED,
 };
 
+/*
+ * Action taken upon a failed ubifs_assert().
+ * @ASSACT_REPORT: just report the failed assertion
+ * @ASSACT_RO: switch to read-only mode
+ * @ASSACT_PANIC: call BUG() and possible panic the kernel
+ */
+enum {
+       ASSACT_REPORT = 0,
+       ASSACT_RO,
+       ASSACT_PANIC,
+};
+
 /**
  * struct ubifs_old_idx - index node obsoleted since last commit start.
  * @rb: rb-tree node
@@ -758,7 +770,7 @@ struct ubifs_znode {
        struct ubifs_znode *parent;
        struct ubifs_znode *cnext;
        unsigned long flags;
-       unsigned long time;
+       time64_t time;
        int level;
        int child_cnt;
        int iip;
@@ -1015,6 +1027,7 @@ struct ubifs_debug_info;
  * @bulk_read: enable bulk-reads
  * @default_compr: default compression algorithm (%UBIFS_COMPR_LZO, etc)
  * @rw_incompat: the media is not R/W compatible
+ * @assert_action: action to take when a ubifs_assert() fails
  *
  * @tnc_mutex: protects the Tree Node Cache (TNC), @zroot, @cnext, @enext, and
  *             @calc_idx_sz
@@ -1256,6 +1269,7 @@ struct ubifs_info {
        unsigned int bulk_read:1;
        unsigned int default_compr:2;
        unsigned int rw_incompat:1;
+       unsigned int assert_action:2;
 
        struct mutex tnc_mutex;
        struct ubifs_zbranch zroot;
@@ -1608,14 +1622,17 @@ int ubifs_tnc_get_bu_keys(struct ubifs_info *c, struct bu_info *bu);
 int ubifs_tnc_bulk_read(struct ubifs_info *c, struct bu_info *bu);
 
 /* tnc_misc.c */
-struct ubifs_znode *ubifs_tnc_levelorder_next(struct ubifs_znode *zr,
+struct ubifs_znode *ubifs_tnc_levelorder_next(const struct ubifs_info *c,
+                                             struct ubifs_znode *zr,
                                              struct ubifs_znode *znode);
 int ubifs_search_zbranch(const struct ubifs_info *c,
                         const struct ubifs_znode *znode,
                         const union ubifs_key *key, int *n);
 struct ubifs_znode *ubifs_tnc_postorder_first(struct ubifs_znode *znode);
-struct ubifs_znode *ubifs_tnc_postorder_next(struct ubifs_znode *znode);
-long ubifs_destroy_tnc_subtree(struct ubifs_znode *zr);
+struct ubifs_znode *ubifs_tnc_postorder_next(const struct ubifs_info *c,
+                                            struct ubifs_znode *znode);
+long ubifs_destroy_tnc_subtree(const struct ubifs_info *c,
+                              struct ubifs_znode *zr);
 struct ubifs_znode *ubifs_load_znode(struct ubifs_info *c,
                                     struct ubifs_zbranch *zbr,
                                     struct ubifs_znode *parent, int iip);
@@ -1698,7 +1715,7 @@ struct ubifs_nnode *ubifs_get_nnode(struct ubifs_info *c,
 int ubifs_read_nnode(struct ubifs_info *c, struct ubifs_nnode *parent, int iip);
 void ubifs_add_lpt_dirt(struct ubifs_info *c, int lnum, int dirty);
 void ubifs_add_nnode_dirt(struct ubifs_info *c, struct ubifs_nnode *nnode);
-uint32_t ubifs_unpack_bits(uint8_t **addr, int *pos, int nrbits);
+uint32_t ubifs_unpack_bits(const struct ubifs_info *c, uint8_t **addr, int *pos, int nrbits);
 struct ubifs_nnode *ubifs_first_nnode(struct ubifs_info *c, int *hght);
 /* Needed only in debugging code in lpt_commit.c */
 int ubifs_unpack_nnode(const struct ubifs_info *c, void *buf,
@@ -1755,7 +1772,13 @@ int ubifs_xattr_set(struct inode *host, const char *name, const void *value,
                    size_t size, int flags, bool check_lock);
 ssize_t ubifs_xattr_get(struct inode *host, const char *name, void *buf,
                        size_t size);
+
+#ifdef CONFIG_UBIFS_FS_XATTR
 void ubifs_evict_xattr_inode(struct ubifs_info *c, ino_t xattr_inum);
+#else
+static inline void ubifs_evict_xattr_inode(struct ubifs_info *c,
+                                          ino_t xattr_inum) { }
+#endif
 
 #ifdef CONFIG_UBIFS_FS_SECURITY
 extern int ubifs_init_security(struct inode *dentry, struct inode *inode,
@@ -1812,14 +1835,16 @@ static inline int ubifs_encrypt(const struct inode *inode,
                                unsigned int in_len, unsigned int *out_len,
                                int block)
 {
-       ubifs_assert(0);
+       struct ubifs_info *c = inode->i_sb->s_fs_info;
+       ubifs_assert(c, 0);
        return -EOPNOTSUPP;
 }
 static inline int ubifs_decrypt(const struct inode *inode,
                                struct ubifs_data_node *dn,
                                unsigned int *out_len, int block)
 {
-       ubifs_assert(0);
+       struct ubifs_info *c = inode->i_sb->s_fs_info;
+       ubifs_assert(c, 0);
        return -EOPNOTSUPP;
 }
 #else
index 6f720fd..61afdfe 100644 (file)
@@ -152,6 +152,12 @@ static int create_xattr(struct ubifs_info *c, struct inode *host,
        ui->data_len = size;
 
        mutex_lock(&host_ui->ui_mutex);
+
+       if (!host->i_nlink) {
+               err = -ENOENT;
+               goto out_noent;
+       }
+
        host->i_ctime = current_time(host);
        host_ui->xattr_cnt += 1;
        host_ui->xattr_size += CALC_DENT_SIZE(fname_len(nm));
@@ -184,6 +190,7 @@ out_cancel:
        host_ui->xattr_size -= CALC_XATTR_BYTES(size);
        host_ui->xattr_names -= fname_len(nm);
        host_ui->flags &= ~UBIFS_CRYPT_FL;
+out_noent:
        mutex_unlock(&host_ui->ui_mutex);
 out_free:
        make_bad_inode(inode);
@@ -216,7 +223,7 @@ static int change_xattr(struct ubifs_info *c, struct inode *host,
        struct ubifs_budget_req req = { .dirtied_ino = 2,
                .dirtied_ino_d = ALIGN(size, 8) + ALIGN(host_ui->data_len, 8) };
 
-       ubifs_assert(ui->data_len == inode->i_size);
+       ubifs_assert(c, ui->data_len == inode->i_size);
        err = ubifs_budget_space(c, &req);
        if (err)
                return err;
@@ -235,6 +242,12 @@ static int change_xattr(struct ubifs_info *c, struct inode *host,
        mutex_unlock(&ui->ui_mutex);
 
        mutex_lock(&host_ui->ui_mutex);
+
+       if (!host->i_nlink) {
+               err = -ENOENT;
+               goto out_noent;
+       }
+
        host->i_ctime = current_time(host);
        host_ui->xattr_size -= CALC_XATTR_BYTES(old_size);
        host_ui->xattr_size += CALC_XATTR_BYTES(size);
@@ -256,6 +269,7 @@ static int change_xattr(struct ubifs_info *c, struct inode *host,
 out_cancel:
        host_ui->xattr_size -= CALC_XATTR_BYTES(size);
        host_ui->xattr_size += CALC_XATTR_BYTES(old_size);
+out_noent:
        mutex_unlock(&host_ui->ui_mutex);
        make_bad_inode(inode);
 out_free:
@@ -291,7 +305,7 @@ int ubifs_xattr_set(struct inode *host, const char *name, const void *value,
        int err;
 
        if (check_lock)
-               ubifs_assert(inode_is_locked(host));
+               ubifs_assert(c, inode_is_locked(host));
 
        if (size > UBIFS_MAX_INO_DATA)
                return -ERANGE;
@@ -374,8 +388,8 @@ ssize_t ubifs_xattr_get(struct inode *host, const char *name, void *buf,
        }
 
        ui = ubifs_inode(inode);
-       ubifs_assert(inode->i_size == ui->data_len);
-       ubifs_assert(ubifs_inode(host)->xattr_size > ui->data_len);
+       ubifs_assert(c, inode->i_size == ui->data_len);
+       ubifs_assert(c, ubifs_inode(host)->xattr_size > ui->data_len);
 
        mutex_lock(&ui->ui_mutex);
        if (buf) {
@@ -462,7 +476,7 @@ ssize_t ubifs_listxattr(struct dentry *dentry, char *buffer, size_t size)
                return err;
        }
 
-       ubifs_assert(written <= size);
+       ubifs_assert(c, written <= size);
        return written;
 }
 
@@ -475,13 +489,19 @@ static int remove_xattr(struct ubifs_info *c, struct inode *host,
        struct ubifs_budget_req req = { .dirtied_ino = 2, .mod_dent = 1,
                                .dirtied_ino_d = ALIGN(host_ui->data_len, 8) };
 
-       ubifs_assert(ui->data_len == inode->i_size);
+       ubifs_assert(c, ui->data_len == inode->i_size);
 
        err = ubifs_budget_space(c, &req);
        if (err)
                return err;
 
        mutex_lock(&host_ui->ui_mutex);
+
+       if (!host->i_nlink) {
+               err = -ENOENT;
+               goto out_noent;
+       }
+
        host->i_ctime = current_time(host);
        host_ui->xattr_cnt -= 1;
        host_ui->xattr_size -= CALC_DENT_SIZE(fname_len(nm));
@@ -501,6 +521,7 @@ out_cancel:
        host_ui->xattr_size += CALC_DENT_SIZE(fname_len(nm));
        host_ui->xattr_size += CALC_XATTR_BYTES(ui->data_len);
        host_ui->xattr_names += fname_len(nm);
+out_noent:
        mutex_unlock(&host_ui->ui_mutex);
        ubifs_release_budget(c, &req);
        make_bad_inode(inode);
@@ -538,7 +559,10 @@ static int ubifs_xattr_remove(struct inode *host, const char *name)
        union ubifs_key key;
        int err;
 
-       ubifs_assert(inode_is_locked(host));
+       ubifs_assert(c, inode_is_locked(host));
+
+       if (!host->i_nlink)
+               return -ENOENT;
 
        if (fname_len(&nm) > UBIFS_MAX_NLEN)
                return -ENAMETOOLONG;
@@ -561,7 +585,7 @@ static int ubifs_xattr_remove(struct inode *host, const char *name)
                goto out_free;
        }
 
-       ubifs_assert(inode->i_nlink == 1);
+       ubifs_assert(c, inode->i_nlink == 1);
        clear_nlink(inode);
        err = remove_xattr(c, host, inode, &nm);
        if (err)
index 15c265d..bfa0ec6 100644 (file)
@@ -340,17 +340,15 @@ out:
  * fatal_signal_pending()s, and the mmap_sem must be released before
  * returning it.
  */
-int handle_userfault(struct vm_fault *vmf, unsigned long reason)
+vm_fault_t handle_userfault(struct vm_fault *vmf, unsigned long reason)
 {
        struct mm_struct *mm = vmf->vma->vm_mm;
        struct userfaultfd_ctx *ctx;
        struct userfaultfd_wait_queue uwq;
-       int ret;
+       vm_fault_t ret = VM_FAULT_SIGBUS;
        bool must_wait, return_to_userland;
        long blocking_state;
 
-       ret = VM_FAULT_SIGBUS;
-
        /*
         * We don't do userfault handling for the final child pid update.
         *
@@ -910,7 +908,7 @@ wakeup:
         */
        spin_lock(&ctx->fault_pending_wqh.lock);
        __wake_up_locked_key(&ctx->fault_pending_wqh, TASK_NORMAL, &range);
-       __wake_up_locked_key(&ctx->fault_wqh, TASK_NORMAL, &range);
+       __wake_up(&ctx->fault_wqh, TASK_NORMAL, 1, &range);
        spin_unlock(&ctx->fault_pending_wqh.lock);
 
        /* Flush pending events that may still wait on event_wqh */
@@ -1066,7 +1064,7 @@ static ssize_t userfaultfd_ctx_read(struct userfaultfd_ctx *ctx, int no_wait,
                         * anyway.
                         */
                        list_del(&uwq->wq.entry);
-                       __add_wait_queue(&ctx->fault_wqh, &uwq->wq);
+                       add_wait_queue(&ctx->fault_wqh, &uwq->wq);
 
                        write_seqcount_end(&ctx->refile_seq);
 
@@ -1215,7 +1213,7 @@ static void __wake_userfault(struct userfaultfd_ctx *ctx,
                __wake_up_locked_key(&ctx->fault_pending_wqh, TASK_NORMAL,
                                     range);
        if (waitqueue_active(&ctx->fault_wqh))
-               __wake_up_locked_key(&ctx->fault_wqh, TASK_NORMAL, range);
+               __wake_up(&ctx->fault_wqh, TASK_NORMAL, 1, range);
        spin_unlock(&ctx->fault_pending_wqh.lock);
 }
 
index f9cb1db..daa7325 100644 (file)
@@ -23,7 +23,6 @@
 #include <linux/posix_acl_xattr.h>
 
 #include <linux/uaccess.h>
-#include "internal.h"
 
 static const char *
 strcmp_prefix(const char *a, const char *a_prefix)
@@ -501,10 +500,10 @@ SYSCALL_DEFINE5(fsetxattr, int, fd, const char __user *, name,
        if (!f.file)
                return error;
        audit_file(f.file);
-       error = mnt_want_write_file_path(f.file);
+       error = mnt_want_write_file(f.file);
        if (!error) {
                error = setxattr(f.file->f_path.dentry, name, value, size, flags);
-               mnt_drop_write_file_path(f.file);
+               mnt_drop_write_file(f.file);
        }
        fdput(f);
        return error;
@@ -539,7 +538,7 @@ getxattr(struct dentry *d, const char __user *name, void __user *value,
        if (error > 0) {
                if ((strcmp(kname, XATTR_NAME_POSIX_ACL_ACCESS) == 0) ||
                    (strcmp(kname, XATTR_NAME_POSIX_ACL_DEFAULT) == 0))
-                       posix_acl_fix_xattr_to_user(kvalue, size);
+                       posix_acl_fix_xattr_to_user(kvalue, error);
                if (size && copy_to_user(value, kvalue, error))
                        error = -EFAULT;
        } else if (error == -ERANGE && size >= XATTR_SIZE_MAX) {
@@ -733,10 +732,10 @@ SYSCALL_DEFINE2(fremovexattr, int, fd, const char __user *, name)
        if (!f.file)
                return error;
        audit_file(f.file);
-       error = mnt_want_write_file_path(f.file);
+       error = mnt_want_write_file(f.file);
        if (!error) {
                error = removexattr(f.file->f_path.dentry, name);
-               mnt_drop_write_file_path(f.file);
+               mnt_drop_write_file(f.file);
        }
        fdput(f);
        return error;
index 17cf485..9f08dd9 100644 (file)
@@ -195,8 +195,8 @@ xrep_calc_ag_resblks(
        struct xfs_scrub_metadata       *sm = sc->sm;
        struct xfs_perag                *pag;
        struct xfs_buf                  *bp;
-       xfs_agino_t                     icount = 0;
-       xfs_extlen_t                    aglen = 0;
+       xfs_agino_t                     icount = NULLAGINO;
+       xfs_extlen_t                    aglen = NULLAGBLOCK;
        xfs_extlen_t                    usedlen;
        xfs_extlen_t                    freelen;
        xfs_extlen_t                    bnobt_sz;
@@ -208,20 +208,14 @@ xrep_calc_ag_resblks(
        if (!(sm->sm_flags & XFS_SCRUB_IFLAG_REPAIR))
                return 0;
 
-       /* Use in-core counters if possible. */
        pag = xfs_perag_get(mp, sm->sm_agno);
-       if (pag->pagi_init)
+       if (pag->pagi_init) {
+               /* Use in-core icount if possible. */
                icount = pag->pagi_count;
-
-       /*
-        * Otherwise try to get the actual counters from disk; if not, make
-        * some worst case assumptions.
-        */
-       if (icount == 0) {
+       } else {
+               /* Try to get the actual counters from disk. */
                error = xfs_ialloc_read_agi(mp, NULL, sm->sm_agno, &bp);
-               if (error) {
-                       icount = mp->m_sb.sb_agblocks / mp->m_sb.sb_inopblock;
-               } else {
+               if (!error) {
                        icount = pag->pagi_count;
                        xfs_buf_relse(bp);
                }
@@ -229,18 +223,32 @@ xrep_calc_ag_resblks(
 
        /* Now grab the block counters from the AGF. */
        error = xfs_alloc_read_agf(mp, NULL, sm->sm_agno, 0, &bp);
-       if (error) {
-               aglen = mp->m_sb.sb_agblocks;
-               freelen = aglen;
-               usedlen = aglen;
-       } else {
+       if (!error) {
                aglen = be32_to_cpu(XFS_BUF_TO_AGF(bp)->agf_length);
-               freelen = pag->pagf_freeblks;
+               freelen = be32_to_cpu(XFS_BUF_TO_AGF(bp)->agf_freeblks);
                usedlen = aglen - freelen;
                xfs_buf_relse(bp);
        }
        xfs_perag_put(pag);
 
+       /* If the icount is impossible, make some worst-case assumptions. */
+       if (icount == NULLAGINO ||
+           !xfs_verify_agino(mp, sm->sm_agno, icount)) {
+               xfs_agino_t     first, last;
+
+               xfs_agino_range(mp, sm->sm_agno, &first, &last);
+               icount = last - first + 1;
+       }
+
+       /* If the block counts are impossible, make worst-case assumptions. */
+       if (aglen == NULLAGBLOCK ||
+           aglen != xfs_ag_block_count(mp, sm->sm_agno) ||
+           freelen >= aglen) {
+               aglen = xfs_ag_block_count(mp, sm->sm_agno);
+               freelen = aglen;
+               usedlen = aglen;
+       }
+
        trace_xrep_calc_ag_resblks(mp, sm->sm_agno, icount, aglen,
                        freelen, usedlen);
 
index 5eaef2c..61a5ad2 100644 (file)
@@ -931,31 +931,16 @@ xfs_file_clone_range(
                                     len, false);
 }
 
-STATIC ssize_t
+STATIC int
 xfs_file_dedupe_range(
-       struct file     *src_file,
-       u64             loff,
-       u64             len,
-       struct file     *dst_file,
-       u64             dst_loff)
+       struct file     *file_in,
+       loff_t          pos_in,
+       struct file     *file_out,
+       loff_t          pos_out,
+       u64             len)
 {
-       struct inode    *srci = file_inode(src_file);
-       u64             max_dedupe;
-       int             error;
-
-       /*
-        * Since we have to read all these pages in to compare them, cut
-        * it off at MAX_RW_COUNT/2 rounded down to the nearest block.
-        * That means we won't do more than MAX_RW_COUNT IO per request.
-        */
-       max_dedupe = (MAX_RW_COUNT >> 1) & ~(i_blocksize(srci) - 1);
-       if (len > max_dedupe)
-               len = max_dedupe;
-       error = xfs_reflink_remap_range(src_file, loff, dst_file, dst_loff,
+       return xfs_reflink_remap_range(file_in, pos_in, file_out, pos_out,
                                     len, true);
-       if (error)
-               return error;
-       return len;
 }
 
 STATIC int
index 99db27d..02d1509 100644 (file)
@@ -637,6 +637,7 @@ xfs_check_summary_counts(
         */
        if (XFS_LAST_UNMOUNT_WAS_CLEAN(mp) &&
            (mp->m_sb.sb_fdblocks > mp->m_sb.sb_dblocks ||
+            !xfs_verify_icount(mp, mp->m_sb.sb_icount) ||
             mp->m_sb.sb_ifree > mp->m_sb.sb_icount))
                mp->m_flags |= XFS_MOUNT_BAD_SUMMARY;
 
index 012c55c..e6964e9 100644 (file)
@@ -89,7 +89,7 @@
 
 /* Maximum object reference count (detects object deletion issues) */
 
-#define ACPI_MAX_REFERENCE_COUNT        0x1000
+#define ACPI_MAX_REFERENCE_COUNT        0x4000
 
 /* Default page size for use in mapping memory for operation regions */
 
index 226e5ae..856c56e 100644 (file)
@@ -59,6 +59,12 @@ struct acpi_exception_info {
 
 #define AE_OK                           (acpi_status) 0x0000
 
+#define ACPI_ENV_EXCEPTION(status)      (status & AE_CODE_ENVIRONMENTAL)
+#define ACPI_AML_EXCEPTION(status)      (status & AE_CODE_AML)
+#define ACPI_PROG_EXCEPTION(status)     (status & AE_CODE_PROGRAMMER)
+#define ACPI_TABLE_EXCEPTION(status)    (status & AE_CODE_ACPI_TABLES)
+#define ACPI_CNTL_EXCEPTION(status)     (status & AE_CODE_CONTROL)
+
 /*
  * Environmental exceptions
  */
index 88072c9..9566f99 100644 (file)
@@ -12,7 +12,7 @@
 
 /* Current ACPICA subsystem version in YYYYMMDD format */
 
-#define ACPI_CA_VERSION                 0x20180629
+#define ACPI_CA_VERSION                 0x20180810
 
 #include <acpi/acconfig.h>
 #include <acpi/actypes.h>
index a7613e1..20561a6 100644 (file)
@@ -75,9 +75,19 @@ struct bug_entry {
 
 /*
  * WARN(), WARN_ON(), WARN_ON_ONCE, and so on can be used to report
- * significant issues that need prompt attention if they should ever
- * appear at runtime.  Use the versions with printk format strings
- * to provide better diagnostics.
+ * significant kernel issues that need prompt attention if they should ever
+ * appear at runtime.
+ *
+ * Do not use these macros when checking for invalid external inputs
+ * (e.g. invalid system call arguments, or invalid data coming from
+ * network/devices), and on transient conditions like ENOMEM or EAGAIN.
+ * These macros should be used for recoverable kernel issues only.
+ * For invalid external inputs, transient conditions, etc use
+ * pr_err[_once/_ratelimited]() followed by dump_stack(), if necessary.
+ * Do not include "BUG"/"WARNING" in format strings manually to make these
+ * conditions distinguishable from kernel issues.
+ *
+ * Use the versions with printk format strings to provide better diagnostics.
  */
 #ifndef __WARN_TAINT
 extern __printf(3, 4)
index 68efb95..4d73e6e 100644 (file)
@@ -5,12 +5,10 @@
 #define KSYM_FUNC(x) x
 #endif
 #ifdef CONFIG_64BIT
-#define __put .quad
 #ifndef KSYM_ALIGN
 #define KSYM_ALIGN 8
 #endif
 #else
-#define __put .long
 #ifndef KSYM_ALIGN
 #define KSYM_ALIGN 4
 #endif
 #define KCRC_ALIGN 4
 #endif
 
+.macro __put, val, name
+#ifdef CONFIG_HAVE_ARCH_PREL32_RELOCATIONS
+       .long   \val - ., \name - .
+#elif defined(CONFIG_64BIT)
+       .quad   \val, \name
+#else
+       .long   \val, \name
+#endif
+.endm
+
 /*
  * note on .section use: @progbits vs %progbits nastiness doesn't matter,
  * since we immediately emit into those sections anyway.
index e811ef7..b3353e2 100644 (file)
@@ -15,6 +15,7 @@
 #ifndef _ASM_GENERIC__TLB_H
 #define _ASM_GENERIC__TLB_H
 
+#include <linux/mmu_notifier.h>
 #include <linux/swap.h>
 #include <asm/pgalloc.h>
 #include <asm/tlbflush.h>
@@ -138,6 +139,16 @@ static inline void __tlb_reset_range(struct mmu_gather *tlb)
        }
 }
 
+static inline void tlb_flush_mmu_tlbonly(struct mmu_gather *tlb)
+{
+       if (!tlb->end)
+               return;
+
+       tlb_flush(tlb);
+       mmu_notifier_invalidate_range(tlb->mm, tlb->start, tlb->end);
+       __tlb_reset_range(tlb);
+}
+
 static inline void tlb_remove_page_size(struct mmu_gather *tlb,
                                        struct page *page, int page_size)
 {
@@ -186,10 +197,8 @@ static inline void tlb_remove_check_page_size_change(struct mmu_gather *tlb,
 
 #define __tlb_end_vma(tlb, vma)                                        \
        do {                                                    \
-               if (!tlb->fullmm && tlb->end) {                 \
-                       tlb_flush(tlb);                         \
-                       __tlb_reset_range(tlb);                 \
-               }                                               \
+               if (!tlb->fullmm)                               \
+                       tlb_flush_mmu_tlbonly(tlb);             \
        } while (0)
 
 #ifndef tlb_end_vma
@@ -303,14 +312,4 @@ static inline void tlb_remove_check_page_size_change(struct mmu_gather *tlb,
 
 #define tlb_migrate_finish(mm) do {} while (0)
 
-/*
- * Used to flush the TLB when page tables are removed, when lazy
- * TLB mode may cause a CPU to retain intermediate translations
- * pointing to about-to-be-freed page table memory.
- */
-#ifndef HAVE_TLB_FLUSH_REMOVE_TABLES
-#define tlb_flush_remove_tables(mm) do {} while (0)
-#define tlb_flush_remove_tables_local(mm) do {} while (0)
-#endif
-
 #endif /* _ASM_GENERIC__TLB_H */
index f173b5f..7b75ff6 100644 (file)
@@ -54,8 +54,6 @@
 #define LOAD_OFFSET 0
 #endif
 
-#include <linux/export.h>
-
 /* Align . to a 8 byte boundary equals to maximum function alignment. */
 #define ALIGN_FUNCTION()  . = ALIGN(8)
 
index 2c00537..7138384 100644 (file)
@@ -15,6 +15,8 @@
 /* SmartReflex sysc found on 36xx and later */
 #define SYSC_OMAP3_SR_ENAWAKEUP                (1 << 26)
 
+#define SYSC_DRA7_MCAN_ENAWAKEUP       (1 << 4)
+
 /* SYSCONFIG STANDBYMODE/MIDLEMODE/SIDLEMODE supported by hardware */
 #define SYSC_IDLE_FORCE                        0
 #define SYSC_IDLE_NO                   1
index 5e1061b..d7549c5 100644 (file)
 #define DRA7_COUNTER_32K_CLKCTRL       DRA7_CLKCTRL_INDEX(0x50)
 #define DRA7_UART10_CLKCTRL    DRA7_CLKCTRL_INDEX(0x80)
 #define DRA7_DCAN1_CLKCTRL     DRA7_CLKCTRL_INDEX(0x88)
+#define DRA7_ADC_CLKCTRL       DRA7_CLKCTRL_INDEX(0xa0)
 
 #endif
diff --git a/include/dt-bindings/clock/exynos5440.h b/include/dt-bindings/clock/exynos5440.h
deleted file mode 100644 (file)
index 842cdc0..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (c) 2013 Samsung Electronics Co., Ltd.
- * Author: Andrzej Hajda <a.hajda@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Device Tree binding constants for Exynos5440 clock controller.
-*/
-
-#ifndef _DT_BINDINGS_CLOCK_EXYNOS_5440_H
-#define _DT_BINDINGS_CLOCK_EXYNOS_5440_H
-
-#define CLK_XTAL               1
-#define CLK_ARM_CLK            2
-#define CLK_CPLLA              3
-#define CLK_CPLLB              4
-#define CLK_SPI_BAUD           16
-#define CLK_PB0_250            17
-#define CLK_PR0_250            18
-#define CLK_PR1_250            19
-#define CLK_B_250              20
-#define CLK_B_125              21
-#define CLK_B_200              22
-#define CLK_SATA               23
-#define CLK_USB                        24
-#define CLK_GMAC0              25
-#define CLK_CS250              26
-#define CLK_PB0_250_O          27
-#define CLK_PR0_250_O          28
-#define CLK_PR1_250_O          29
-#define CLK_B_250_O            30
-#define CLK_B_125_O            31
-#define CLK_B_200_O            32
-#define CLK_SATA_O             33
-#define CLK_USB_O              34
-#define CLK_GMAC0_O            35
-#define CLK_CS250_O            36
-
-/* must be greater than maximal clock id */
-#define CLK_NR_CLKS            37
-
-#endif /* _DT_BINDINGS_CLOCK_EXYNOS_5440_H */
diff --git a/include/dt-bindings/memory/mt2712-larb-port.h b/include/dt-bindings/memory/mt2712-larb-port.h
new file mode 100644 (file)
index 0000000..6f9aa73
--- /dev/null
@@ -0,0 +1,95 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2017 MediaTek Inc.
+ * Author: Yong Wu <yong.wu@mediatek.com>
+ */
+#ifndef __DTS_IOMMU_PORT_MT2712_H
+#define __DTS_IOMMU_PORT_MT2712_H
+
+#define MTK_M4U_ID(larb, port)         (((larb) << 5) | (port))
+
+#define M4U_LARB0_ID                   0
+#define M4U_LARB1_ID                   1
+#define M4U_LARB2_ID                   2
+#define M4U_LARB3_ID                   3
+#define M4U_LARB4_ID                   4
+#define M4U_LARB5_ID                   5
+#define M4U_LARB6_ID                   6
+#define M4U_LARB7_ID                   7
+#define M4U_LARB8_ID                   8
+#define M4U_LARB9_ID                   9
+
+/* larb0 */
+#define M4U_PORT_DISP_OVL0             MTK_M4U_ID(M4U_LARB0_ID, 0)
+#define M4U_PORT_DISP_RDMA0            MTK_M4U_ID(M4U_LARB0_ID, 1)
+#define M4U_PORT_DISP_WDMA0            MTK_M4U_ID(M4U_LARB0_ID, 2)
+#define M4U_PORT_DISP_OD_R             MTK_M4U_ID(M4U_LARB0_ID, 3)
+#define M4U_PORT_DISP_OD_W             MTK_M4U_ID(M4U_LARB0_ID, 4)
+#define M4U_PORT_MDP_RDMA0             MTK_M4U_ID(M4U_LARB0_ID, 5)
+#define M4U_PORT_MDP_WDMA              MTK_M4U_ID(M4U_LARB0_ID, 6)
+#define M4U_PORT_DISP_RDMA2            MTK_M4U_ID(M4U_LARB0_ID, 7)
+
+/* larb1 */
+#define M4U_PORT_HW_VDEC_MC_EXT                MTK_M4U_ID(M4U_LARB1_ID, 0)
+#define M4U_PORT_HW_VDEC_PP_EXT                MTK_M4U_ID(M4U_LARB1_ID, 1)
+#define M4U_PORT_HW_VDEC_UFO_EXT       MTK_M4U_ID(M4U_LARB1_ID, 2)
+#define M4U_PORT_HW_VDEC_VLD_EXT       MTK_M4U_ID(M4U_LARB1_ID, 3)
+#define M4U_PORT_HW_VDEC_VLD2_EXT      MTK_M4U_ID(M4U_LARB1_ID, 4)
+#define M4U_PORT_HW_VDEC_AVC_MV_EXT    MTK_M4U_ID(M4U_LARB1_ID, 5)
+#define M4U_PORT_HW_VDEC_PRED_RD_EXT   MTK_M4U_ID(M4U_LARB1_ID, 6)
+#define M4U_PORT_HW_VDEC_PRED_WR_EXT   MTK_M4U_ID(M4U_LARB1_ID, 7)
+#define M4U_PORT_HW_VDEC_PPWRAP_EXT    MTK_M4U_ID(M4U_LARB1_ID, 8)
+#define M4U_PORT_HW_VDEC_TILE          MTK_M4U_ID(M4U_LARB1_ID, 9)
+#define M4U_PORT_HW_IMG_RESZ_EXT       MTK_M4U_ID(M4U_LARB1_ID, 10)
+
+/* larb2 */
+#define M4U_PORT_CAM_DMA0              MTK_M4U_ID(M4U_LARB2_ID, 0)
+#define M4U_PORT_CAM_DMA1              MTK_M4U_ID(M4U_LARB2_ID, 1)
+#define M4U_PORT_CAM_DMA2              MTK_M4U_ID(M4U_LARB2_ID, 2)
+
+/* larb3 */
+#define M4U_PORT_VENC_RCPU             MTK_M4U_ID(M4U_LARB3_ID, 0)
+#define M4U_PORT_VENC_REC              MTK_M4U_ID(M4U_LARB3_ID, 1)
+#define M4U_PORT_VENC_BSDMA            MTK_M4U_ID(M4U_LARB3_ID, 2)
+#define M4U_PORT_VENC_SV_COMV          MTK_M4U_ID(M4U_LARB3_ID, 3)
+#define M4U_PORT_VENC_RD_COMV          MTK_M4U_ID(M4U_LARB3_ID, 4)
+#define M4U_PORT_VENC_CUR_CHROMA       MTK_M4U_ID(M4U_LARB3_ID, 5)
+#define M4U_PORT_VENC_REF_CHROMA       MTK_M4U_ID(M4U_LARB3_ID, 6)
+#define M4U_PORT_VENC_CUR_LUMA         MTK_M4U_ID(M4U_LARB3_ID, 7)
+#define M4U_PORT_VENC_REF_LUMA         MTK_M4U_ID(M4U_LARB3_ID, 8)
+
+/* larb4 */
+#define M4U_PORT_DISP_OVL1             MTK_M4U_ID(M4U_LARB4_ID, 0)
+#define M4U_PORT_DISP_RDMA1            MTK_M4U_ID(M4U_LARB4_ID, 1)
+#define M4U_PORT_DISP_WDMA1            MTK_M4U_ID(M4U_LARB4_ID, 2)
+#define M4U_PORT_DISP_OD1_R            MTK_M4U_ID(M4U_LARB4_ID, 3)
+#define M4U_PORT_DISP_OD1_W            MTK_M4U_ID(M4U_LARB4_ID, 4)
+#define M4U_PORT_MDP_RDMA1             MTK_M4U_ID(M4U_LARB4_ID, 5)
+#define M4U_PORT_MDP_WROT1             MTK_M4U_ID(M4U_LARB4_ID, 6)
+
+/* larb5 */
+#define M4U_PORT_DISP_OVL2             MTK_M4U_ID(M4U_LARB5_ID, 0)
+#define M4U_PORT_DISP_WDMA2            MTK_M4U_ID(M4U_LARB5_ID, 1)
+#define M4U_PORT_MDP_RDMA2             MTK_M4U_ID(M4U_LARB5_ID, 2)
+#define M4U_PORT_MDP_WROT0             MTK_M4U_ID(M4U_LARB5_ID, 3)
+
+/* larb6 */
+#define M4U_PORT_JPGDEC_WDMA_0         MTK_M4U_ID(M4U_LARB6_ID, 0)
+#define M4U_PORT_JPGDEC_WDMA_1         MTK_M4U_ID(M4U_LARB6_ID, 1)
+#define M4U_PORT_JPGDEC_BSDMA_0                MTK_M4U_ID(M4U_LARB6_ID, 2)
+#define M4U_PORT_JPGDEC_BSDMA_1                MTK_M4U_ID(M4U_LARB6_ID, 3)
+
+/* larb7 */
+#define M4U_PORT_MDP_RDMA3             MTK_M4U_ID(M4U_LARB7_ID, 0)
+#define M4U_PORT_MDP_WROT2             MTK_M4U_ID(M4U_LARB7_ID, 1)
+
+/* larb8 */
+#define M4U_PORT_VDO                   MTK_M4U_ID(M4U_LARB8_ID, 0)
+#define M4U_PORT_NR                    MTK_M4U_ID(M4U_LARB8_ID, 1)
+#define M4U_PORT_WR_CHANNEL0           MTK_M4U_ID(M4U_LARB8_ID, 2)
+
+/* larb9 */
+#define M4U_PORT_TVD                   MTK_M4U_ID(M4U_LARB9_ID, 0)
+#define M4U_PORT_WR_CHANNEL1           MTK_M4U_ID(M4U_LARB9_ID, 1)
+
+#endif
diff --git a/include/dt-bindings/reset/amlogic,meson-axg-audio-arb.h b/include/dt-bindings/reset/amlogic,meson-axg-audio-arb.h
new file mode 100644 (file)
index 0000000..05c3636
--- /dev/null
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: (GPL-2.0 OR MIT)
+ *
+ * Copyright (c) 2018 Baylibre SAS.
+ * Author: Jerome Brunet <jbrunet@baylibre.com>
+ */
+
+#ifndef _DT_BINDINGS_AMLOGIC_MESON_AXG_AUDIO_ARB_H
+#define _DT_BINDINGS_AMLOGIC_MESON_AXG_AUDIO_ARB_H
+
+#define AXG_ARB_TODDR_A        0
+#define AXG_ARB_TODDR_B        1
+#define AXG_ARB_TODDR_C        2
+#define AXG_ARB_FRDDR_A        3
+#define AXG_ARB_FRDDR_B        4
+#define AXG_ARB_FRDDR_C        5
+
+#endif /* _DT_BINDINGS_AMLOGIC_MESON_AXG_AUDIO_ARB_H */
diff --git a/include/dt-bindings/reset/qcom,sdm845-aoss.h b/include/dt-bindings/reset/qcom,sdm845-aoss.h
new file mode 100644 (file)
index 0000000..476c5fc
--- /dev/null
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2018 The Linux Foundation. All rights reserved.
+ */
+
+#ifndef _DT_BINDINGS_RESET_AOSS_SDM_845_H
+#define _DT_BINDINGS_RESET_AOSS_SDM_845_H
+
+#define AOSS_CC_MSS_RESTART    0
+#define AOSS_CC_CAMSS_RESTART  1
+#define AOSS_CC_VENUS_RESTART  2
+#define AOSS_CC_GPU_RESTART    3
+#define AOSS_CC_DISPSS_RESTART 4
+#define AOSS_CC_WCSS_RESTART   5
+#define AOSS_CC_LPASS_RESTART  6
+
+#endif
index cfdd248..4f31f96 100644 (file)
@@ -133,6 +133,7 @@ struct vgic_irq {
        u8 source;                      /* GICv2 SGIs only */
        u8 active_source;               /* GICv2 SGIs only */
        u8 priority;
+       u8 group;                       /* 0 == group 0, 1 == group 1 */
        enum vgic_irq_config config;    /* Level or edge */
 
        /*
@@ -217,6 +218,12 @@ struct vgic_dist {
        /* vGIC model the kernel emulates for the guest (GICv2 or GICv3) */
        u32                     vgic_model;
 
+       /* Implementation revision as reported in the GICD_IIDR */
+       u32                     implementation_rev;
+
+       /* Userspace can write to GICv2 IGROUPR */
+       bool                    v2_groups_user_writable;
+
        /* Do injected MSIs require an additional device ID? */
        bool                    msis_require_devid;
 
@@ -366,7 +373,7 @@ void kvm_vgic_sync_hwstate(struct kvm_vcpu *vcpu);
 void kvm_vgic_flush_hwstate(struct kvm_vcpu *vcpu);
 void kvm_vgic_reset_mapped_irq(struct kvm_vcpu *vcpu, u32 vintid);
 
-void vgic_v3_dispatch_sgi(struct kvm_vcpu *vcpu, u64 reg);
+void vgic_v3_dispatch_sgi(struct kvm_vcpu *vcpu, u64 reg, bool allow_group1);
 
 /**
  * kvm_vgic_get_max_vcpus - Get the maximum number of VCPUs allowed by HW
index 1b0a17b..eaedca5 100644 (file)
@@ -30,7 +30,7 @@ void ahci_platform_disable_regulators(struct ahci_host_priv *hpriv);
 int ahci_platform_enable_resources(struct ahci_host_priv *hpriv);
 void ahci_platform_disable_resources(struct ahci_host_priv *hpriv);
 struct ahci_host_priv *ahci_platform_get_resources(
-       struct platform_device *pdev);
+       struct platform_device *pdev, unsigned int flags);
 int ahci_platform_init_host(struct platform_device *pdev,
                            struct ahci_host_priv *hpriv,
                            const struct ata_port_info *pi_template,
@@ -43,4 +43,6 @@ int ahci_platform_resume_host(struct device *dev);
 int ahci_platform_suspend(struct device *dev);
 int ahci_platform_resume(struct device *dev);
 
+#define AHCI_PLATFORM_GET_RESETS       0x01
+
 #endif /* _AHCI_PLATFORM_H */
index 2425176..9a6bc09 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/timer.h>
 #include <linux/workqueue.h>
 #include <linux/kref.h>
+#include <linux/refcount.h>
 
 struct page;
 struct device;
@@ -75,7 +76,7 @@ enum wb_reason {
  */
 struct bdi_writeback_congested {
        unsigned long state;            /* WB_[a]sync_congested flags */
-       atomic_t refcnt;                /* nr of attached wb's and blkg */
+       refcount_t refcnt;              /* nr of attached wb's and blkg */
 
 #ifdef CONFIG_CGROUP_WRITEBACK
        struct backing_dev_info *__bdi; /* the associated bdi, set to NULL
index 72ca0f3..c28a47c 100644 (file)
@@ -404,13 +404,13 @@ static inline bool inode_cgwb_enabled(struct inode *inode)
 static inline struct bdi_writeback_congested *
 wb_congested_get_create(struct backing_dev_info *bdi, int blkcg_id, gfp_t gfp)
 {
-       atomic_inc(&bdi->wb_congested->refcnt);
+       refcount_inc(&bdi->wb_congested->refcnt);
        return bdi->wb_congested;
 }
 
 static inline void wb_congested_put(struct bdi_writeback_congested *congested)
 {
-       if (atomic_dec_and_test(&congested->refcnt))
+       if (refcount_dec_and_test(&congested->refcnt))
                kfree(congested);
 }
 
index 7fbf053..0b58974 100644 (file)
@@ -79,7 +79,6 @@ struct backlight_properties {
        /* Backlight type */
        enum backlight_type type;
        /* Flags used to signal drivers of state changes */
-       /* Upper 4 bits are reserved for driver internal use */
        unsigned int state;
 
 #define BL_CORE_SUSPENDED      (1 << 0)        /* backlight is suspended */
index af41901..7ddb134 100644 (file)
@@ -4,7 +4,8 @@
 #include <asm/types.h>
 #include <linux/bits.h>
 
-#define BITS_TO_LONGS(nr)      DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))
+#define BITS_PER_TYPE(type) (sizeof(type) * BITS_PER_BYTE)
+#define BITS_TO_LONGS(nr)      DIV_ROUND_UP(nr, BITS_PER_TYPE(long))
 
 extern unsigned int __sw_hweight8(unsigned int w);
 extern unsigned int __sw_hweight16(unsigned int w);
index e931da8..6728c2e 100644 (file)
@@ -64,6 +64,10 @@ struct ceph_auth_client_ops {
        /* ensure that an existing authorizer is up to date */
        int (*update_authorizer)(struct ceph_auth_client *ac, int peer_type,
                                 struct ceph_auth_handshake *auth);
+       int (*add_authorizer_challenge)(struct ceph_auth_client *ac,
+                                       struct ceph_authorizer *a,
+                                       void *challenge_buf,
+                                       int challenge_buf_len);
        int (*verify_authorizer_reply)(struct ceph_auth_client *ac,
                                       struct ceph_authorizer *a);
        void (*invalidate_authorizer)(struct ceph_auth_client *ac,
@@ -118,6 +122,10 @@ void ceph_auth_destroy_authorizer(struct ceph_authorizer *a);
 extern int ceph_auth_update_authorizer(struct ceph_auth_client *ac,
                                       int peer_type,
                                       struct ceph_auth_handshake *a);
+int ceph_auth_add_authorizer_challenge(struct ceph_auth_client *ac,
+                                      struct ceph_authorizer *a,
+                                      void *challenge_buf,
+                                      int challenge_buf_len);
 extern int ceph_auth_verify_authorizer_reply(struct ceph_auth_client *ac,
                                             struct ceph_authorizer *a);
 extern void ceph_auth_invalidate_authorizer(struct ceph_auth_client *ac,
index 3901927..6b92b33 100644 (file)
@@ -165,9 +165,9 @@ DEFINE_CEPH_FEATURE(58, 1, FS_FILE_LAYOUT_V2) // overlap
 DEFINE_CEPH_FEATURE(59, 1, FS_BTIME)
 DEFINE_CEPH_FEATURE(59, 1, FS_CHANGE_ATTR) // overlap
 DEFINE_CEPH_FEATURE(59, 1, MSG_ADDR2) // overlap
-DEFINE_CEPH_FEATURE(60, 1, BLKIN_TRACING)  // *do not share this bit*
+DEFINE_CEPH_FEATURE(60, 1, OSD_RECOVERY_DELETES) // *do not share this bit*
+DEFINE_CEPH_FEATURE(61, 1, CEPHX_V2)             // *do not share this bit*
 
-DEFINE_CEPH_FEATURE(61, 1, RESERVED2)          // unused, but slow down!
 DEFINE_CEPH_FEATURE(62, 1, RESERVED)           // do not use; used as a sentinal
 DEFINE_CEPH_FEATURE_DEPRECATED(63, 1, RESERVED_BROKEN, LUMINOUS) // client-facing
 
@@ -210,7 +210,8 @@ DEFINE_CEPH_FEATURE_DEPRECATED(63, 1, RESERVED_BROKEN, LUMINOUS) // client-facin
         CEPH_FEATURE_SERVER_JEWEL |            \
         CEPH_FEATURE_MON_STATEFUL_SUB |        \
         CEPH_FEATURE_CRUSH_TUNABLES5 |         \
-        CEPH_FEATURE_NEW_OSDOPREPLY_ENCODING)
+        CEPH_FEATURE_NEW_OSDOPREPLY_ENCODING | \
+        CEPH_FEATURE_CEPHX_V2)
 
 #define CEPH_FEATURES_REQUIRED_DEFAULT   \
        (CEPH_FEATURE_NOSRCADDR |        \
index d143ac8..a6c2a48 100644 (file)
@@ -194,16 +194,22 @@ ceph_decode_skip_n(p, end, sizeof(u8), bad)
        } while (0)
 
 /*
- * struct ceph_timespec <-> struct timespec
+ * struct ceph_timespec <-> struct timespec64
  */
-static inline void ceph_decode_timespec(struct timespec *ts,
-                                       const struct ceph_timespec *tv)
+static inline void ceph_decode_timespec64(struct timespec64 *ts,
+                                         const struct ceph_timespec *tv)
 {
-       ts->tv_sec = (__kernel_time_t)le32_to_cpu(tv->tv_sec);
+       /*
+        * This will still overflow in year 2106.  We could extend
+        * the protocol to steal two more bits from tv_nsec to
+        * add three more 136 year epochs after that the way ext4
+        * does if necessary.
+        */
+       ts->tv_sec = (time64_t)le32_to_cpu(tv->tv_sec);
        ts->tv_nsec = (long)le32_to_cpu(tv->tv_nsec);
 }
-static inline void ceph_encode_timespec(struct ceph_timespec *tv,
-                                       const struct timespec *ts)
+static inline void ceph_encode_timespec64(struct ceph_timespec *tv,
+                                         const struct timespec64 *ts)
 {
        tv->tv_sec = cpu_to_le32((u32)ts->tv_sec);
        tv->tv_nsec = cpu_to_le32((u32)ts->tv_nsec);
index c7dfcb8..fc2b449 100644 (file)
@@ -31,6 +31,9 @@ struct ceph_connection_operations {
        struct ceph_auth_handshake *(*get_authorizer) (
                                struct ceph_connection *con,
                               int *proto, int force_new);
+       int (*add_authorizer_challenge)(struct ceph_connection *con,
+                                       void *challenge_buf,
+                                       int challenge_buf_len);
        int (*verify_authorizer_reply) (struct ceph_connection *con);
        int (*invalidate_authorizer)(struct ceph_connection *con);
 
@@ -286,9 +289,8 @@ struct ceph_connection {
                                 attempt for this connection, client */
        u32 peer_global_seq;  /* peer's global seq for this connection */
 
+       struct ceph_auth_handshake *auth;
        int auth_retry;       /* true if we need a newer authorizer */
-       void *auth_reply_buf;   /* where to put the authorizer reply */
-       int auth_reply_buf_len;
 
        struct mutex mutex;
 
@@ -330,7 +332,7 @@ struct ceph_connection {
        int in_base_pos;     /* bytes read */
        __le64 in_temp_ack;  /* for reading an ack */
 
-       struct timespec last_keepalive_ack; /* keepalive2 ack stamp */
+       struct timespec64 last_keepalive_ack; /* keepalive2 ack stamp */
 
        struct delayed_work work;           /* send|recv work */
        unsigned long       delay;          /* current delay interval */
index 73ae2a9..9e50aed 100644 (file)
@@ -91,7 +91,7 @@ struct ceph_entity_inst {
 #define CEPH_MSGR_TAG_SEQ           13 /* 64-bit int follows with seen seq number */
 #define CEPH_MSGR_TAG_KEEPALIVE2    14 /* keepalive2 byte + ceph_timespec */
 #define CEPH_MSGR_TAG_KEEPALIVE2_ACK 15 /* keepalive2 reply */
-
+#define CEPH_MSGR_TAG_CHALLENGE_AUTHORIZER 16  /* cephx v2 doing server challenge */
 
 /*
  * connection negotiation
index 0d6ee04..02096da 100644 (file)
@@ -199,7 +199,7 @@ struct ceph_osd_request {
        /* set by submitter */
        u64 r_snapid;                         /* for reads, CEPH_NOSNAP o/w */
        struct ceph_snap_context *r_snapc;    /* for writes */
-       struct timespec r_mtime;              /* ditto */
+       struct timespec64 r_mtime;            /* ditto */
        u64 r_data_offset;                    /* ditto */
        bool r_linger;                        /* don't resend on failure */
 
@@ -253,7 +253,7 @@ struct ceph_osd_linger_request {
        struct ceph_osd_request_target t;
        u32 map_dne_bound;
 
-       struct timespec mtime;
+       struct timespec64 mtime;
 
        struct kref kref;
        struct mutex lock;
@@ -508,7 +508,7 @@ extern int ceph_osdc_writepages(struct ceph_osd_client *osdc,
                                struct ceph_snap_context *sc,
                                u64 off, u64 len,
                                u32 truncate_seq, u64 truncate_size,
-                               struct timespec *mtime,
+                               struct timespec64 *mtime,
                                struct page **pages, int nr_pages);
 
 /* watch/notify */
@@ -528,12 +528,12 @@ int ceph_osdc_notify_ack(struct ceph_osd_client *osdc,
                         u64 notify_id,
                         u64 cookie,
                         void *payload,
-                        size_t payload_len);
+                        u32 payload_len);
 int ceph_osdc_notify(struct ceph_osd_client *osdc,
                     struct ceph_object_id *oid,
                     struct ceph_object_locator *oloc,
                     void *payload,
-                    size_t payload_len,
+                    u32 payload_len,
                     u32 timeout,
                     struct page ***preply_pages,
                     size_t *preply_len);
index 7edcded..d022336 100644 (file)
@@ -68,7 +68,7 @@ static inline int ceph_pagelist_encode_8(struct ceph_pagelist *pl, u8 v)
        return ceph_pagelist_append(pl, &v, 1);
 }
 static inline int ceph_pagelist_encode_string(struct ceph_pagelist *pl,
-                                             char *s, size_t len)
+                                             char *s, u32 len)
 {
        int ret = ceph_pagelist_encode_32(pl, len);
        if (ret)
index 6aca5ce..931ab05 100644 (file)
 #define        AT91_CKGR_MOR           0x20                    /* Main Oscillator Register [not on SAM9RL] */
 #define                AT91_PMC_MOSCEN         (1    <<  0)            /* Main Oscillator Enable */
 #define                AT91_PMC_OSCBYPASS      (1    <<  1)            /* Oscillator Bypass */
+#define                AT91_PMC_WAITMODE       (1    <<  2)            /* Wait Mode Command */
 #define                AT91_PMC_MOSCRCEN       (1    <<  3)            /* Main On-Chip RC Oscillator Enable [some SAM9] */
 #define                AT91_PMC_OSCOUNT        (0xff <<  8)            /* Main Oscillator Start-up Time */
+#define                AT91_PMC_KEY_MASK       (0xff << 16)
 #define                AT91_PMC_KEY            (0x37 << 16)            /* MOR Writing Key */
 #define                AT91_PMC_MOSCSEL        (1    << 24)            /* Main Oscillator Selection [some SAM9] */
 #define                AT91_PMC_CFDEN          (1    << 25)            /* Clock Failure Detector Enable [some SAM9] */
 #define                AT91_PMC_GCKRDY         (1 << 24)               /* Generated Clocks */
 #define        AT91_PMC_IMR            0x6c                    /* Interrupt Mask Register */
 
+#define AT91_PMC_FSMR          0x70            /* Fast Startup Mode Register */
+#define AT91_PMC_FSTT(n)       BIT(n)
+#define AT91_PMC_RTCAL         BIT(17)         /* RTC Alarm Enable */
+#define AT91_PMC_USBAL         BIT(18)         /* USB Resume Enable */
+#define AT91_PMC_SDMMC_CD      BIT(19)         /* SDMMC Card Detect Enable */
+#define AT91_PMC_LPM           BIT(20)         /* Low-power Mode */
+#define AT91_PMC_RXLP_MCE      BIT(24)         /* Backup UART Receive Enable */
+#define AT91_PMC_ACC_CE                BIT(25)         /* ACC Enable */
+
+#define AT91_PMC_FSPR          0x74            /* Fast Startup Polarity Reg */
+
+#define AT91_PMC_FS_INPUT_MASK  0x7ff
+
 #define AT91_PMC_PLLICPR       0x80                    /* PLL Charge Pump Current Register */
 
 #define AT91_PMC_PROT          0xe4                    /* Write Protect Mode Register [some SAM9] */
index 7087446..b1ce500 100644 (file)
@@ -6,11 +6,7 @@
 /* Some compiler specific definitions are overwritten here
  * for Clang compiler
  */
-
-#ifdef uninitialized_var
-#undef uninitialized_var
 #define uninitialized_var(x) x = *(&(x))
-#endif
 
 /* same as gcc, this was present in clang-2.6 so we can assume it works
  * with any version that can compile the kernel
 #define __SANITIZE_ADDRESS__
 #endif
 
-#undef __no_sanitize_address
 #define __no_sanitize_address __attribute__((no_sanitize("address")))
 
-/* Clang doesn't have a way to turn it off per-function, yet. */
-#ifdef __noretpoline
-#undef __noretpoline
-#endif
-
 /*
  * Not all versions of clang implement the the type-generic versions
  * of the builtin overflow checkers. Fortunately, clang implements
  * checks. Unfortunately, we don't know which version of gcc clang
  * pretends to be, so the macro may or may not be defined.
  */
-#undef COMPILER_HAS_GENERIC_BUILTIN_OVERFLOW
 #if __has_builtin(__builtin_mul_overflow) && \
     __has_builtin(__builtin_add_overflow) && \
     __has_builtin(__builtin_sub_overflow)
 #define COMPILER_HAS_GENERIC_BUILTIN_OVERFLOW 1
 #endif
+
+/* The following are for compatibility with GCC, from compiler-gcc.h,
+ * and may be redefined here because they should not be shared with other
+ * compilers, like ICC.
+ */
+#define barrier() __asm__ __volatile__("" : : : "memory")
+#define __must_be_array(a) BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0]))
+#define __assume_aligned(a, ...)       \
+       __attribute__((__assume_aligned__(a, ## __VA_ARGS__)))
index 3e70b7d..763bbad 100644 (file)
                     + __GNUC_MINOR__ * 100     \
                     + __GNUC_PATCHLEVEL__)
 
+#if GCC_VERSION < 40600
+# error Sorry, your compiler is too old - please upgrade it.
+#endif
+
 /* Optimization barrier */
 
 /* The "volatile" is due to gcc bugs */
 #define OPTIMIZER_HIDE_VAR(var)                                                \
        __asm__ ("" : "=r" (var) : "0" (var))
 
+/*
+ * A trick to suppress uninitialized variable warning without generating any
+ * code
+ */
+#define uninitialized_var(x) x = x
+
 #ifdef __CHECKER__
 #define __must_be_array(a)     0
 #else
 #define __must_be_array(a)     BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0]))
 #endif
 
-/*
- * Feature detection for gnu_inline (gnu89 extern inline semantics). Either
- * __GNUC_STDC_INLINE__ is defined (not using gnu89 extern inline semantics,
- * and we opt in to the gnu89 semantics), or __GNUC_STDC_INLINE__ is not
- * defined so the gnu89 semantics are the default.
- */
-#ifdef __GNUC_STDC_INLINE__
-# define __gnu_inline  __attribute__((gnu_inline))
-#else
-# define __gnu_inline
-#endif
-
-/*
- * Force always-inline if the user requests it so via the .config,
- * or if gcc is too old.
- * GCC does not warn about unused static inline functions for
- * -Wunused-function.  This turns out to avoid the need for complex #ifdef
- * directives.  Suppress the warning in clang as well by using "unused"
- * function attribute, which is redundant but not harmful for gcc.
- * Prefer gnu_inline, so that extern inline functions do not emit an
- * externally visible function. This makes extern inline behave as per gnu89
- * semantics rather than c99. This prevents multiple symbol definition errors
- * of extern inline functions at link time.
- * A lot of inline functions can cause havoc with function tracing.
- */
-#if !defined(CONFIG_ARCH_SUPPORTS_OPTIMIZED_INLINING) ||               \
-    !defined(CONFIG_OPTIMIZE_INLINING) || (__GNUC__ < 4)
-#define inline \
-       inline __attribute__((always_inline, unused)) notrace __gnu_inline
-#else
-#define inline inline          __attribute__((unused)) notrace __gnu_inline
-#endif
-
-#define __inline__ inline
-#define __inline inline
-#define __always_inline        inline __attribute__((always_inline))
-#define  noinline      __attribute__((noinline))
-
-#define __packed       __attribute__((packed))
-#define __weak         __attribute__((weak))
-#define __alias(symbol)        __attribute__((alias(#symbol)))
-
 #ifdef RETPOLINE
 #define __noretpoline __attribute__((indirect_branch("keep")))
 #endif
  */
 #define __naked                __attribute__((naked)) noinline __noclone notrace
 
-#define __noreturn     __attribute__((noreturn))
-
-/*
- * From the GCC manual:
- *
- * Many functions have no effects except the return value and their
- * return value depends only on the parameters and/or global
- * variables.  Such a function can be subject to common subexpression
- * elimination and loop optimization just as an arithmetic operator
- * would be.
- * [...]
- */
-#define __pure                 __attribute__((pure))
-#define __aligned(x)           __attribute__((aligned(x)))
-#define __aligned_largest      __attribute__((aligned))
-#define __printf(a, b)         __attribute__((format(printf, a, b)))
-#define __scanf(a, b)          __attribute__((format(scanf, a, b)))
-#define __attribute_const__    __attribute__((__const__))
-#define __maybe_unused         __attribute__((unused))
-#define __always_unused                __attribute__((unused))
-#define __mode(x)               __attribute__((mode(x)))
-
-/* gcc version specific checks */
-
-#if GCC_VERSION < 30200
-# error Sorry, your compiler is too old - please upgrade it.
-#endif
-
-#if GCC_VERSION < 30300
-# define __used                        __attribute__((__unused__))
-#else
-# define __used                        __attribute__((__used__))
-#endif
-
-#ifdef CONFIG_GCOV_KERNEL
-# if GCC_VERSION < 30400
-#   error "GCOV profiling support for gcc versions below 3.4 not included"
-# endif /* __GNUC_MINOR__ */
-#endif /* CONFIG_GCOV_KERNEL */
-
-#if GCC_VERSION >= 30400
-#define __must_check           __attribute__((warn_unused_result))
-#define __malloc               __attribute__((__malloc__))
-#endif
-
-#if GCC_VERSION >= 40000
-
-/* GCC 4.1.[01] miscompiles __weak */
-#ifdef __KERNEL__
-# if GCC_VERSION >= 40100 &&  GCC_VERSION <= 40101
-#  error Your version of gcc miscompiles the __weak directive
-# endif
-#endif
-
-#define __used                 __attribute__((__used__))
-#define __compiler_offsetof(a, b)                                      \
-       __builtin_offsetof(a, b)
-
-#if GCC_VERSION >= 40100
-# define __compiletime_object_size(obj) __builtin_object_size(obj, 0)
-#endif
-
-#if GCC_VERSION >= 40300
-/* Mark functions as cold. gcc will assume any path leading to a call
- * to them will be unlikely.  This means a lot of manual unlikely()s
- * are unnecessary now for any paths leading to the usual suspects
- * like BUG(), printk(), panic() etc. [but let's keep them for now for
- * older compilers]
- *
- * Early snapshots of gcc 4.3 don't support this and we can't detect this
- * in the preprocessor, but we can live with this because they're unreleased.
- * Maketime probing would be overkill here.
- *
- * gcc also has a __attribute__((__hot__)) to move hot functions into
- * a special section, but I don't see any sense in this right now in
- * the kernel context
- */
-#define __cold                 __attribute__((__cold__))
-
 #define __UNIQUE_ID(prefix) __PASTE(__PASTE(__UNIQUE_ID_, prefix), __COUNTER__)
 
-#ifndef __CHECKER__
-# define __compiletime_warning(message) __attribute__((warning(message)))
-# define __compiletime_error(message) __attribute__((error(message)))
-#endif /* __CHECKER__ */
-#endif /* GCC_VERSION >= 40300 */
-
-#if GCC_VERSION >= 40400
 #define __optimize(level)      __attribute__((__optimize__(level)))
-#define __nostackprotector     __optimize("no-stack-protector")
-#endif /* GCC_VERSION >= 40400 */
 
-#if GCC_VERSION >= 40500
+#define __compiletime_object_size(obj) __builtin_object_size(obj, 0)
 
 #ifndef __CHECKER__
+#define __compiletime_warning(message) __attribute__((warning(message)))
+#define __compiletime_error(message) __attribute__((error(message)))
+
 #ifdef LATENT_ENTROPY_PLUGIN
 #define __latent_entropy __attribute__((latent_entropy))
 #endif
-#endif
+#endif /* __CHECKER__ */
 
 /*
  * calling noreturn functions, __builtin_unreachable() and __builtin_trap()
 #define randomized_struct_fields_end   } __randomize_layout;
 #endif
 
-#endif /* GCC_VERSION >= 40500 */
-
-#if GCC_VERSION >= 40600
-
 /*
  * When used with Link Time Optimization, gcc can optimize away C functions or
  * variables which are referenced only from assembly code.  __visible tells the
  */
 #define __visible      __attribute__((externally_visible))
 
-#endif /* GCC_VERSION >= 40600 */
-
+/* gcc version specific checks */
 
 #if GCC_VERSION >= 40900 && !defined(__CHECKER__)
 /*
  * folding in __builtin_bswap*() (yet), so don't set these for it.
  */
 #if defined(CONFIG_ARCH_USE_BUILTIN_BSWAP) && !defined(__CHECKER__)
-#if GCC_VERSION >= 40400
 #define __HAVE_BUILTIN_BSWAP32__
 #define __HAVE_BUILTIN_BSWAP64__
-#endif
 #if GCC_VERSION >= 40800
 #define __HAVE_BUILTIN_BSWAP16__
 #endif
  * https://gcc.gnu.org/onlinedocs/gcc/Designated-Inits.html
  */
 #define __designated_init __attribute__((designated_init))
+#define COMPILER_HAS_GENERIC_BUILTIN_OVERFLOW 1
 #endif
 
-#endif /* gcc version >= 40000 specific checks */
-
 #if !defined(__noclone)
 #define __noclone      /* not needed */
 #endif
 #endif
 
 /*
- * A trick to suppress uninitialized variable warning without generating any
- * code
- */
-#define uninitialized_var(x) x = x
-
-#if GCC_VERSION >= 50100
-#define COMPILER_HAS_GENERIC_BUILTIN_OVERFLOW 1
-#endif
-
-/*
  * Turn individual warnings and errors on and off locally, depending
  * on version.
  */
 #define __diag_GCC_warn                warning
 #define __diag_GCC_error       error
 
-/* Compilers before gcc-4.6 do not understand "#pragma GCC diagnostic push" */
-#if GCC_VERSION >= 40600
 #define __diag_str1(s)         #s
 #define __diag_str(s)          __diag_str1(s)
 #define __diag(s)              _Pragma(__diag_str(GCC diagnostic s))
-#endif
 
 #if GCC_VERSION >= 80000
 #define __diag_GCC_8(s)                __diag(s)
index 547cdc9..4c7f9be 100644 (file)
 /* Intel ECC compiler doesn't support gcc specific asm stmts.
  * It uses intrinsics to do the equivalent things.
  */
-#undef barrier
-#undef barrier_data
-#undef RELOC_HIDE
-#undef OPTIMIZER_HIDE_VAR
 
 #define barrier() __memory_barrier()
 #define barrier_data(ptr) barrier()
 
 #endif
 
-#ifndef __HAVE_BUILTIN_BSWAP16__
 /* icc has this, but it's called _bswap16 */
 #define __HAVE_BUILTIN_BSWAP16__
 #define __builtin_bswap16 _bswap16
-#endif
 
-/*
- * icc defines __GNUC__, but does not implement the builtin overflow checkers.
+/* The following are for compatibility with GCC, from compiler-gcc.h,
+ * and may be redefined here because they should not be shared with other
+ * compilers, like clang.
  */
-#undef COMPILER_HAS_GENERIC_BUILTIN_OVERFLOW
+#define __visible      __attribute__((externally_visible))
index 42506e4..681d866 100644 (file)
@@ -280,6 +280,25 @@ unsigned long read_word_at_a_time(const void *addr)
 
 #endif /* __KERNEL__ */
 
+/*
+ * Force the compiler to emit 'sym' as a symbol, so that we can reference
+ * it from inline assembler. Necessary in case 'sym' could be inlined
+ * otherwise, or eliminated entirely due to lack of references that are
+ * visible to the compiler.
+ */
+#define __ADDRESSABLE(sym) \
+       static void * __attribute__((section(".discard.addressable"), used)) \
+               __PASTE(__addressable_##sym, __LINE__) = (void *)&sym;
+
+/**
+ * offset_to_ptr - convert a relative memory offset to an absolute pointer
+ * @off:       the address of the 32-bit offset value
+ */
+static inline void *offset_to_ptr(const int *off)
+{
+       return (void *)((unsigned long)off + *off);
+}
+
 #endif /* __ASSEMBLY__ */
 
 #ifndef __optimize
@@ -313,7 +332,7 @@ unsigned long read_word_at_a_time(const void *addr)
 #ifdef __OPTIMIZE__
 # define __compiletime_assert(condition, msg, prefix, suffix)          \
        do {                                                            \
-               bool __cond = !(condition);                             \
+               int __cond = !(condition);                              \
                extern void prefix ## suffix(void) __compiletime_error(msg); \
                if (__cond)                                             \
                        prefix ## suffix();                             \
index fbf3379..3525c17 100644 (file)
@@ -54,32 +54,32 @@ extern void __chk_io_ptr(const volatile void __iomem *);
 
 #ifdef __KERNEL__
 
-#ifdef __GNUC__
+/* Compiler specific macros. */
+#ifdef __clang__
+#include <linux/compiler-clang.h>
+#elif defined(__INTEL_COMPILER)
+#include <linux/compiler-intel.h>
+#elif defined(__GNUC__)
+/* The above compilers also define __GNUC__, so order is important here. */
 #include <linux/compiler-gcc.h>
-#endif
-
-#if defined(CC_USING_HOTPATCH) && !defined(__CHECKER__)
-#define notrace __attribute__((hotpatch(0,0)))
 #else
-#define notrace __attribute__((no_instrument_function))
+#error "Unknown compiler"
 #endif
 
-/* Intel compiler defines __GNUC__. So we will overwrite implementations
- * coming from above header files here
- */
-#ifdef __INTEL_COMPILER
-# include <linux/compiler-intel.h>
-#endif
-
-/* Clang compiler defines __GNUC__. So we will overwrite implementations
- * coming from above header files here
+/*
+ * Some architectures need to provide custom definitions of macros provided
+ * by linux/compiler-*.h, and can do so using asm/compiler.h. We include that
+ * conditionally rather than using an asm-generic wrapper in order to avoid
+ * build failures if any C compilation, which will include this file via an
+ * -include argument in c_flags, occurs prior to the asm-generic wrappers being
+ * generated.
  */
-#ifdef __clang__
-#include <linux/compiler-clang.h>
+#ifdef CONFIG_HAVE_ARCH_COMPILER_H
+#include <asm/compiler.h>
 #endif
 
 /*
- * Generic compiler-dependent macros required for kernel
+ * Generic compiler-independent macros required for kernel
  * build go below this comment. Actual compiler/compiler version
  * specific implementations come from the above header files
  */
@@ -106,93 +106,19 @@ struct ftrace_likely_data {
        unsigned long                   constant;
 };
 
-#endif /* __KERNEL__ */
-
-#endif /* __ASSEMBLY__ */
-
-#ifdef __KERNEL__
-
 /* Don't. Just don't. */
 #define __deprecated
 #define __deprecated_for_modules
 
-#ifndef __must_check
-#define __must_check
-#endif
-
-#ifndef CONFIG_ENABLE_MUST_CHECK
-#undef __must_check
-#define __must_check
-#endif
-
-#ifndef __malloc
-#define __malloc
-#endif
-
-/*
- * Allow us to avoid 'defined but not used' warnings on functions and data,
- * as well as force them to be emitted to the assembly file.
- *
- * As of gcc 3.4, static functions that are not marked with attribute((used))
- * may be elided from the assembly file.  As of gcc 3.4, static data not so
- * marked will not be elided, but this may change in a future gcc version.
- *
- * NOTE: Because distributions shipped with a backported unit-at-a-time
- * compiler in gcc 3.3, we must define __used to be __attribute__((used))
- * for gcc >=3.3 instead of 3.4.
- *
- * In prior versions of gcc, such functions and data would be emitted, but
- * would be warned about except with attribute((unused)).
- *
- * Mark functions that are referenced only in inline assembly as __used so
- * the code is emitted even though it appears to be unreferenced.
- */
-#ifndef __used
-# define __used                        /* unimplemented */
-#endif
-
-#ifndef __maybe_unused
-# define __maybe_unused                /* unimplemented */
-#endif
-
-#ifndef __always_unused
-# define __always_unused       /* unimplemented */
-#endif
-
-#ifndef noinline
-#define noinline
-#endif
-
-/*
- * Rather then using noinline to prevent stack consumption, use
- * noinline_for_stack instead.  For documentation reasons.
- */
-#define noinline_for_stack noinline
-
-#ifndef __always_inline
-#define __always_inline inline
-#endif
-
 #endif /* __KERNEL__ */
 
+#endif /* __ASSEMBLY__ */
+
 /*
- * From the GCC manual:
- *
- * Many functions do not examine any values except their arguments,
- * and have no effects except the return value.  Basically this is
- * just slightly more strict class than the `pure' attribute above,
- * since function is not allowed to read global memory.
- *
- * Note that a function that has pointer arguments and examines the
- * data pointed to must _not_ be declared `const'.  Likewise, a
- * function that calls a non-`const' function usually must not be
- * `const'.  It does not make sense for a `const' function to return
- * `void'.
+ * The below symbols may be defined for one or more, but not ALL, of the above
+ * compilers. We don't consider that to be an error, so set them to nothing.
+ * For example, some of them are for compiler specific plugins.
  */
-#ifndef __attribute_const__
-# define __attribute_const__   /* unimplemented */
-#endif
-
 #ifndef __designated_init
 # define __designated_init
 #endif
@@ -214,28 +140,10 @@ struct ftrace_likely_data {
 # define randomized_struct_fields_end
 #endif
 
-/*
- * Tell gcc if a function is cold. The compiler will assume any path
- * directly leading to the call is unlikely.
- */
-
-#ifndef __cold
-#define __cold
-#endif
-
-/* Simple shorthand for a section definition */
-#ifndef __section
-# define __section(S) __attribute__ ((__section__(#S)))
-#endif
-
 #ifndef __visible
 #define __visible
 #endif
 
-#ifndef __nostackprotector
-# define __nostackprotector
-#endif
-
 /*
  * Assume alignment of return value.
  */
@@ -243,17 +151,23 @@ struct ftrace_likely_data {
 #define __assume_aligned(a, ...)
 #endif
 
-
 /* Are two types/vars the same type (ignoring qualifiers)? */
-#ifndef __same_type
-# define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))
-#endif
+#define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))
 
 /* Is this type a native word size -- useful for atomic operations */
-#ifndef __native_word
-# define __native_word(t) (sizeof(t) == sizeof(char) || sizeof(t) == sizeof(short) || sizeof(t) == sizeof(int) || sizeof(t) == sizeof(long))
+#define __native_word(t) \
+       (sizeof(t) == sizeof(char) || sizeof(t) == sizeof(short) || \
+        sizeof(t) == sizeof(int) || sizeof(t) == sizeof(long))
+
+#ifndef __attribute_const__
+#define __attribute_const__    __attribute__((__const__))
 #endif
 
+#ifndef __noclone
+#define __noclone
+#endif
+
+/* Helpers for emitting diagnostics in pragmas. */
 #ifndef __diag
 #define __diag(string)
 #endif
@@ -272,4 +186,92 @@ struct ftrace_likely_data {
 #define __diag_error(compiler, version, option, comment) \
        __diag_ ## compiler(version, error, option)
 
+/*
+ * From the GCC manual:
+ *
+ * Many functions have no effects except the return value and their
+ * return value depends only on the parameters and/or global
+ * variables.  Such a function can be subject to common subexpression
+ * elimination and loop optimization just as an arithmetic operator
+ * would be.
+ * [...]
+ */
+#define __pure                 __attribute__((pure))
+#define __aligned(x)           __attribute__((aligned(x)))
+#define __aligned_largest      __attribute__((aligned))
+#define __printf(a, b)         __attribute__((format(printf, a, b)))
+#define __scanf(a, b)          __attribute__((format(scanf, a, b)))
+#define __maybe_unused         __attribute__((unused))
+#define __always_unused                __attribute__((unused))
+#define __mode(x)              __attribute__((mode(x)))
+#define __malloc               __attribute__((__malloc__))
+#define __used                 __attribute__((__used__))
+#define __noreturn             __attribute__((noreturn))
+#define __packed               __attribute__((packed))
+#define __weak                 __attribute__((weak))
+#define __alias(symbol)                __attribute__((alias(#symbol)))
+#define __cold                 __attribute__((cold))
+#define __section(S)           __attribute__((__section__(#S)))
+
+
+#ifdef CONFIG_ENABLE_MUST_CHECK
+#define __must_check           __attribute__((warn_unused_result))
+#else
+#define __must_check
+#endif
+
+#if defined(CC_USING_HOTPATCH) && !defined(__CHECKER__)
+#define notrace                        __attribute__((hotpatch(0, 0)))
+#else
+#define notrace                        __attribute__((no_instrument_function))
+#endif
+
+#define __compiler_offsetof(a, b)      __builtin_offsetof(a, b)
+
+/*
+ * Feature detection for gnu_inline (gnu89 extern inline semantics). Either
+ * __GNUC_STDC_INLINE__ is defined (not using gnu89 extern inline semantics,
+ * and we opt in to the gnu89 semantics), or __GNUC_STDC_INLINE__ is not
+ * defined so the gnu89 semantics are the default.
+ */
+#ifdef __GNUC_STDC_INLINE__
+# define __gnu_inline  __attribute__((gnu_inline))
+#else
+# define __gnu_inline
+#endif
+
+/*
+ * Force always-inline if the user requests it so via the .config.
+ * GCC does not warn about unused static inline functions for
+ * -Wunused-function.  This turns out to avoid the need for complex #ifdef
+ * directives.  Suppress the warning in clang as well by using "unused"
+ * function attribute, which is redundant but not harmful for gcc.
+ * Prefer gnu_inline, so that extern inline functions do not emit an
+ * externally visible function. This makes extern inline behave as per gnu89
+ * semantics rather than c99. This prevents multiple symbol definition errors
+ * of extern inline functions at link time.
+ * A lot of inline functions can cause havoc with function tracing.
+ */
+#if !defined(CONFIG_ARCH_SUPPORTS_OPTIMIZED_INLINING) || \
+       !defined(CONFIG_OPTIMIZE_INLINING)
+#define inline \
+       inline __attribute__((always_inline, unused)) notrace __gnu_inline
+#else
+#define inline inline  __attribute__((unused)) notrace __gnu_inline
+#endif
+
+#define __inline__ inline
+#define __inline inline
+#define noinline       __attribute__((noinline))
+
+#ifndef __always_inline
+#define __always_inline inline __attribute__((always_inline))
+#endif
+
+/*
+ * Rather then using noinline to prevent stack consumption, use
+ * noinline_for_stack instead.  For documentation reasons.
+ */
+#define noinline_for_stack noinline
+
 #endif /* __LINUX_COMPILER_TYPES_H */
index f59f3db..ec9bdb3 100644 (file)
@@ -14,6 +14,7 @@
 #ifndef _LINUX_CONSOLE_H_
 #define _LINUX_CONSOLE_H_ 1
 
+#include <linux/atomic.h>
 #include <linux/types.h>
 
 struct vc_data;
@@ -201,11 +202,14 @@ void vcs_make_sysfs(int index);
 void vcs_remove_sysfs(int index);
 
 /* Some debug stub to catch some of the obvious races in the VT code */
-#if 1
-#define WARN_CONSOLE_UNLOCKED()        WARN_ON(!is_console_locked() && !oops_in_progress)
-#else
-#define WARN_CONSOLE_UNLOCKED()
-#endif
+#define WARN_CONSOLE_UNLOCKED()                                                \
+       WARN_ON(!atomic_read(&ignore_console_lock_warning) &&           \
+               !is_console_locked() && !oops_in_progress)
+/*
+ * Increment ignore_console_lock_warning if you need to quiet
+ * WARN_CONSOLE_UNLOCKED() for debugging purposes.
+ */
+extern atomic_t ignore_console_lock_warning;
 
 /* VESA Blanking Levels */
 #define VESA_NO_BLANKING        0
index c49843c..caf40ad 100644 (file)
@@ -144,6 +144,7 @@ enum cpuhp_state {
        CPUHP_AP_SMPBOOT_THREADS,
        CPUHP_AP_X86_VDSO_VMA_ONLINE,
        CPUHP_AP_IRQ_AFFINITY_ONLINE,
+       CPUHP_AP_ARM_MVEBU_SYNC_CLOCKS,
        CPUHP_AP_PERF_ONLINE,
        CPUHP_AP_PERF_X86_ONLINE,
        CPUHP_AP_PERF_X86_UNCORE_ONLINE,
index b511f6d..525510a 100644 (file)
@@ -60,6 +60,8 @@ phys_addr_t paddr_vmcoreinfo_note(void);
 #define VMCOREINFO_CONFIG(name) \
        vmcoreinfo_append_str("CONFIG_%s=y\n", #name)
 
+extern unsigned char *vmcoreinfo_data;
+extern size_t vmcoreinfo_size;
 extern u32 *vmcoreinfo_note;
 
 Elf_Word *append_elf_note(Elf_Word *buf, char *name, unsigned int type,
diff --git a/include/linux/crc64.h b/include/linux/crc64.h
new file mode 100644 (file)
index 0000000..c756e65
--- /dev/null
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * See lib/crc64.c for the related specification and polynomial arithmetic.
+ */
+#ifndef _LINUX_CRC64_H
+#define _LINUX_CRC64_H
+
+#include <linux/types.h>
+
+u64 __pure crc64_be(u64 crc, const void *p, size_t len);
+#endif /* _LINUX_CRC64_H */
index deb0f66..450b28d 100644 (file)
@@ -88,6 +88,8 @@ int dax_writeback_mapping_range(struct address_space *mapping,
                struct block_device *bdev, struct writeback_control *wbc);
 
 struct page *dax_layout_busy_page(struct address_space *mapping);
+bool dax_lock_mapping_entry(struct page *page);
+void dax_unlock_mapping_entry(struct page *page);
 #else
 static inline bool bdev_dax_supported(struct block_device *bdev,
                int blocksize)
@@ -119,6 +121,17 @@ static inline int dax_writeback_mapping_range(struct address_space *mapping,
 {
        return -EOPNOTSUPP;
 }
+
+static inline bool dax_lock_mapping_entry(struct page *page)
+{
+       if (IS_DAX(page->mapping->host))
+               return true;
+       return false;
+}
+
+static inline void dax_unlock_mapping_entry(struct page *page)
+{
+}
 #endif
 
 int dax_read_lock(void);
index d32957b..ef4b70f 100644 (file)
@@ -145,8 +145,7 @@ struct dentry_operations {
        char *(*d_dname)(struct dentry *, char *, int);
        struct vfsmount *(*d_automount)(struct path *);
        int (*d_manage)(const struct path *, bool);
-       struct dentry *(*d_real)(struct dentry *, const struct inode *,
-                                unsigned int, unsigned int);
+       struct dentry *(*d_real)(struct dentry *, const struct inode *);
 } ____cacheline_aligned;
 
 /*
@@ -561,15 +560,10 @@ static inline struct dentry *d_backing_dentry(struct dentry *upper)
        return upper;
 }
 
-/* d_real() flags */
-#define D_REAL_UPPER   0x2     /* return upper dentry or NULL if non-upper */
-
 /**
  * d_real - Return the real dentry
  * @dentry: the dentry to query
  * @inode: inode to select the dentry from multiple layers (can be NULL)
- * @open_flags: open flags to control copy-up behavior
- * @flags: flags to control what is returned by this function
  *
  * If dentry is on a union/overlay, then return the underlying, real dentry.
  * Otherwise return the dentry itself.
@@ -577,11 +571,10 @@ static inline struct dentry *d_backing_dentry(struct dentry *upper)
  * See also: Documentation/filesystems/vfs.txt
  */
 static inline struct dentry *d_real(struct dentry *dentry,
-                                   const struct inode *inode,
-                                   unsigned int open_flags, unsigned int flags)
+                                   const struct inode *inode)
 {
        if (unlikely(dentry->d_flags & DCACHE_OP_REAL))
-               return dentry->d_op->d_real(dentry, inode, open_flags, flags);
+               return dentry->d_op->d_real(dentry, inode);
        else
                return dentry;
 }
@@ -596,7 +589,7 @@ static inline struct dentry *d_real(struct dentry *dentry,
 static inline struct inode *d_real_inode(const struct dentry *dentry)
 {
        /* This usage of d_real() results in const dentry */
-       return d_backing_inode(d_real((struct dentry *) dentry, NULL, 0, 0));
+       return d_backing_inode(d_real((struct dentry *) dentry, NULL));
 }
 
 struct name_snapshot {
index e2433bc..843a41b 100644 (file)
@@ -265,11 +265,6 @@ static inline void dmar_copy_shared_irte(struct irte *dst, struct irte *src)
 #define PDA_LOW_BIT    26
 #define PDA_HIGH_BIT   32
 
-enum {
-       IRQ_REMAP_XAPIC_MODE,
-       IRQ_REMAP_X2APIC_MODE,
-};
-
 /* Can't use the common MSI interrupt functions
  * since DMAR is not a pci device
  */
index b768d6d..ce764a5 100644 (file)
  * hackers place grumpy comments in header files.
  */
 
-#define __VMLINUX_SYMBOL(x) x
-#define __VMLINUX_SYMBOL_STR(x) #x
-
-/* Indirect, so macros are expanded before pasting. */
-#define VMLINUX_SYMBOL(x) __VMLINUX_SYMBOL(x)
-#define VMLINUX_SYMBOL_STR(x) __VMLINUX_SYMBOL_STR(x)
-
 #ifndef __ASSEMBLY__
-struct kernel_symbol
-{
-       unsigned long value;
-       const char *name;
-};
-
 #ifdef MODULE
 extern struct module __this_module;
 #define THIS_MODULE (&__this_module)
@@ -54,19 +41,58 @@ extern struct module __this_module;
 #define __CRC_SYMBOL(sym, sec)
 #endif
 
+#ifdef CONFIG_HAVE_ARCH_PREL32_RELOCATIONS
+#include <linux/compiler.h>
+/*
+ * Emit the ksymtab entry as a pair of relative references: this reduces
+ * the size by half on 64-bit architectures, and eliminates the need for
+ * absolute relocations that require runtime processing on relocatable
+ * kernels.
+ */
+#define __KSYMTAB_ENTRY(sym, sec)                                      \
+       __ADDRESSABLE(sym)                                              \
+       asm("   .section \"___ksymtab" sec "+" #sym "\", \"a\"  \n"     \
+           "   .balign 8                                       \n"     \
+           "__ksymtab_" #sym ":                                \n"     \
+           "   .long   " #sym "- .                             \n"     \
+           "   .long   __kstrtab_" #sym "- .                   \n"     \
+           "   .previous                                       \n")
+
+struct kernel_symbol {
+       int value_offset;
+       int name_offset;
+};
+#else
+#define __KSYMTAB_ENTRY(sym, sec)                                      \
+       static const struct kernel_symbol __ksymtab_##sym               \
+       __attribute__((section("___ksymtab" sec "+" #sym), used))       \
+       = { (unsigned long)&sym, __kstrtab_##sym }
+
+struct kernel_symbol {
+       unsigned long value;
+       const char *name;
+};
+#endif
+
 /* For every exported symbol, place a struct in the __ksymtab section */
 #define ___EXPORT_SYMBOL(sym, sec)                                     \
        extern typeof(sym) sym;                                         \
        __CRC_SYMBOL(sym, sec)                                          \
        static const char __kstrtab_##sym[]                             \
-       __attribute__((section("__ksymtab_strings"), aligned(1)))       \
+       __attribute__((section("__ksymtab_strings"), used, aligned(1))) \
        = #sym;                                                         \
-       static const struct kernel_symbol __ksymtab_##sym               \
-       __used                                                          \
-       __attribute__((section("___ksymtab" sec "+" #sym), used))       \
-       = { (unsigned long)&sym, __kstrtab_##sym }
+       __KSYMTAB_ENTRY(sym, sec)
+
+#if defined(__DISABLE_EXPORTS)
+
+/*
+ * Allow symbol exports to be disabled completely so that C code may
+ * be reused in other execution contexts such as the UEFI stub or the
+ * decompressor.
+ */
+#define __EXPORT_SYMBOL(sym, sec)
 
-#if defined(__KSYM_DEPS__)
+#elif defined(__KSYM_DEPS__)
 
 /*
  * For fine grained build dependencies, we want to tell the build system
index aa5db8b..f70f8ac 100644 (file)
@@ -304,11 +304,6 @@ struct f2fs_node {
  * For NAT entries
  */
 #define NAT_ENTRY_PER_BLOCK (PAGE_SIZE / sizeof(struct f2fs_nat_entry))
-#define NAT_ENTRY_BITMAP_SIZE  ((NAT_ENTRY_PER_BLOCK + 7) / 8)
-#define NAT_ENTRY_BITMAP_SIZE_ALIGNED                          \
-       ((NAT_ENTRY_BITMAP_SIZE + BITS_PER_LONG - 1) /          \
-       BITS_PER_LONG * BITS_PER_LONG)
-
 
 struct f2fs_nat_entry {
        __u8 version;           /* latest version of cached nat entry */
index aa74a22..3e7e753 100644 (file)
@@ -126,7 +126,7 @@ struct fb_cursor_user {
 
 /*     The resolution of the passed in fb_info about to change */ 
 #define FB_EVENT_MODE_CHANGE           0x01
-/*     The display on this fb_info is beeing suspended, no access to the
+/*     The display on this fb_info is being suspended, no access to the
  *     framebuffer is allowed any more after that call returns
  */
 #define FB_EVENT_SUSPEND               0x02
@@ -159,9 +159,9 @@ struct fb_cursor_user {
 #define FB_EVENT_FB_UNBIND              0x0E
 /*      CONSOLE-SPECIFIC: remap all consoles to new fb - for vga_switcheroo */
 #define FB_EVENT_REMAP_ALL_CONSOLE      0x0F
-/*      A hardware display blank early change occured */
+/*      A hardware display blank early change occurred */
 #define FB_EARLY_EVENT_BLANK           0x10
-/*      A hardware display blank revert early change occured */
+/*      A hardware display blank revert early change occurred */
 #define FB_R_EARLY_EVENT_BLANK         0x11
 
 struct fb_event {
@@ -650,6 +650,10 @@ extern struct fb_info *registered_fb[FB_MAX];
 extern int num_registered_fb;
 extern struct class *fb_class;
 
+#define for_each_registered_fb(i)              \
+       for (i = 0; i < FB_MAX; i++)            \
+               if (!registered_fb[i]) {} else
+
 extern int lock_fb_info(struct fb_info *info);
 
 static inline void unlock_fb_info(struct fb_info *info)
index a9242f3..3332270 100644 (file)
@@ -74,6 +74,8 @@ extern struct inodes_stat_t inodes_stat;
 extern int leases_enable, lease_break_time;
 extern int sysctl_protected_symlinks;
 extern int sysctl_protected_hardlinks;
+extern int sysctl_protected_fifos;
+extern int sysctl_protected_regular;
 
 typedef __kernel_rwf_t rwf_t;
 
@@ -157,6 +159,9 @@ typedef int (dio_iodone_t)(struct kiocb *iocb, loff_t offset,
 /* File is capable of returning -EAGAIN if I/O will block */
 #define FMODE_NOWAIT   ((__force fmode_t)0x8000000)
 
+/* File does not contribute to nr_files count */
+#define FMODE_NOACCOUNT        ((__force fmode_t)0x20000000)
+
 /*
  * Flag for rw_copy_check_uvector and compat_rw_copy_check_uvector
  * that indicates that they should check the contents of the iovec are
@@ -1067,17 +1072,7 @@ struct file_lock_context {
 
 extern void send_sigio(struct fown_struct *fown, int fd, int band);
 
-/*
- * Return the inode to use for locking
- *
- * For overlayfs this should be the overlay inode, not the real inode returned
- * by file_inode().  For any other fs file_inode(filp) and locks_inode(filp) are
- * equal.
- */
-static inline struct inode *locks_inode(const struct file *f)
-{
-       return f->f_path.dentry->d_inode;
-}
+#define locks_inode(f) file_inode(f)
 
 #ifdef CONFIG_FILE_LOCKING
 extern int fcntl_getlk(struct file *, unsigned int, struct flock *);
@@ -1262,7 +1257,7 @@ static inline struct inode *file_inode(const struct file *f)
 
 static inline struct dentry *file_dentry(const struct file *file)
 {
-       return d_real(file->f_path.dentry, file_inode(file), 0, 0);
+       return d_real(file->f_path.dentry, file_inode(file));
 }
 
 static inline int locks_lock_file_wait(struct file *filp, struct file_lock *fl)
@@ -1318,7 +1313,6 @@ extern int send_sigurg(struct fown_struct *fown);
 
 /* These sb flags are internal to the kernel */
 #define SB_SUBMOUNT     (1<<26)
-#define SB_NOREMOTELOCK        (1<<27)
 #define SB_NOSEC       (1<<28)
 #define SB_BORN                (1<<29)
 #define SB_ACTIVE      (1<<30)
@@ -1647,6 +1641,8 @@ int vfs_mkobj(struct dentry *, umode_t,
                int (*f)(struct dentry *, umode_t, void *),
                void *);
 
+extern long vfs_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
+
 /*
  * VFS file helper functions.
  */
@@ -1765,7 +1761,7 @@ struct file_operations {
                        loff_t, size_t, unsigned int);
        int (*clone_file_range)(struct file *, loff_t, struct file *, loff_t,
                        u64);
-       ssize_t (*dedupe_file_range)(struct file *, u64, u64, struct file *,
+       int (*dedupe_file_range)(struct file *, loff_t, struct file *, loff_t,
                        u64);
 } __randomize_layout;
 
@@ -1838,6 +1834,10 @@ extern int vfs_dedupe_file_range_compare(struct inode *src, loff_t srcoff,
                                         loff_t len, bool *is_same);
 extern int vfs_dedupe_file_range(struct file *file,
                                 struct file_dedupe_range *same);
+extern int vfs_dedupe_file_range_one(struct file *src_file, loff_t src_pos,
+                                    struct file *dst_file, loff_t dst_pos,
+                                    u64 len);
+
 
 struct super_operations {
        struct inode *(*alloc_inode)(struct super_block *sb);
@@ -2096,6 +2096,7 @@ enum file_time_flags {
        S_VERSION = 8,
 };
 
+extern bool atime_needs_update(const struct path *, struct inode *);
 extern void touch_atime(const struct path *);
 static inline void file_accessed(struct file *file)
 {
@@ -2441,6 +2442,8 @@ extern struct file *filp_open(const char *, int, umode_t);
 extern struct file *file_open_root(struct dentry *, struct vfsmount *,
                                   const char *, int, umode_t);
 extern struct file * dentry_open(const struct path *, int, const struct cred *);
+extern struct file * open_with_fake_path(const struct path *, int,
+                                        struct inode*, const struct cred *);
 static inline struct file *file_clone_open(struct file *file)
 {
        return dentry_open(&file->f_path, file->f_flags, file->f_cred);
index bdaf225..fd1ce10 100644 (file)
@@ -30,11 +30,7 @@ static inline int fsnotify_parent(const struct path *path, struct dentry *dentry
 static inline int fsnotify_perm(struct file *file, int mask)
 {
        const struct path *path = &file->f_path;
-       /*
-        * Do not use file_inode() here or anywhere in this file to get the
-        * inode.  That would break *notity on overlayfs.
-        */
-       struct inode *inode = path->dentry->d_inode;
+       struct inode *inode = file_inode(file);
        __u32 fsnotify_mask = 0;
        int ret;
 
@@ -178,7 +174,7 @@ static inline void fsnotify_mkdir(struct inode *inode, struct dentry *dentry)
 static inline void fsnotify_access(struct file *file)
 {
        const struct path *path = &file->f_path;
-       struct inode *inode = path->dentry->d_inode;
+       struct inode *inode = file_inode(file);
        __u32 mask = FS_ACCESS;
 
        if (S_ISDIR(inode->i_mode))
@@ -196,7 +192,7 @@ static inline void fsnotify_access(struct file *file)
 static inline void fsnotify_modify(struct file *file)
 {
        const struct path *path = &file->f_path;
-       struct inode *inode = path->dentry->d_inode;
+       struct inode *inode = file_inode(file);
        __u32 mask = FS_MODIFY;
 
        if (S_ISDIR(inode->i_mode))
@@ -214,7 +210,7 @@ static inline void fsnotify_modify(struct file *file)
 static inline void fsnotify_open(struct file *file)
 {
        const struct path *path = &file->f_path;
-       struct inode *inode = path->dentry->d_inode;
+       struct inode *inode = file_inode(file);
        __u32 mask = FS_OPEN;
 
        if (S_ISDIR(inode->i_mode))
@@ -230,7 +226,7 @@ static inline void fsnotify_open(struct file *file)
 static inline void fsnotify_close(struct file *file)
 {
        const struct path *path = &file->f_path;
-       struct inode *inode = path->dentry->d_inode;
+       struct inode *inode = file_inode(file);
        fmode_t mode = file->f_mode;
        __u32 mask = (mode & FMODE_WRITE) ? FS_CLOSE_WRITE : FS_CLOSE_NOWRITE;
 
index ebb7767..a397907 100644 (file)
@@ -234,10 +234,6 @@ extern void ftrace_stub(unsigned long a0, unsigned long a1,
  */
 #define register_ftrace_function(ops) ({ 0; })
 #define unregister_ftrace_function(ops) ({ 0; })
-static inline int ftrace_nr_registered_ops(void)
-{
-       return 0;
-}
 static inline void ftrace_kill(void) { }
 static inline void ftrace_free_init_mem(void) { }
 static inline void ftrace_free_mem(struct module *mod, void *start, void *end) { }
@@ -328,8 +324,6 @@ struct seq_file;
 
 extern int ftrace_text_reserved(const void *start, const void *end);
 
-extern int ftrace_nr_registered_ops(void);
-
 struct ftrace_ops *ftrace_ops_trampoline(unsigned long addr);
 
 bool is_ftrace_trampoline(unsigned long addr);
@@ -707,16 +701,7 @@ static inline unsigned long get_lock_parent_ip(void)
        return CALLER_ADDR2;
 }
 
-#ifdef CONFIG_IRQSOFF_TRACER
-  extern void time_hardirqs_on(unsigned long a0, unsigned long a1);
-  extern void time_hardirqs_off(unsigned long a0, unsigned long a1);
-#else
-  static inline void time_hardirqs_on(unsigned long a0, unsigned long a1) { }
-  static inline void time_hardirqs_off(unsigned long a0, unsigned long a1) { }
-#endif
-
-#if defined(CONFIG_PREEMPT_TRACER) || \
-       (defined(CONFIG_DEBUG_PREEMPT) && defined(CONFIG_PREEMPTIRQ_EVENTS))
+#ifdef CONFIG_TRACE_PREEMPT_TOGGLE
   extern void trace_preempt_on(unsigned long a0, unsigned long a1);
   extern void trace_preempt_off(unsigned long a0, unsigned long a1);
 #else
index a6afcec..24bcc5e 100644 (file)
@@ -59,29 +59,32 @@ struct vm_area_struct;
 #define __GFP_MOVABLE  ((__force gfp_t)___GFP_MOVABLE)  /* ZONE_MOVABLE allowed */
 #define GFP_ZONEMASK   (__GFP_DMA|__GFP_HIGHMEM|__GFP_DMA32|__GFP_MOVABLE)
 
-/*
+/**
+ * DOC: Page mobility and placement hints
+ *
  * Page mobility and placement hints
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  *
  * These flags provide hints about how mobile the page is. Pages with similar
  * mobility are placed within the same pageblocks to minimise problems due
  * to external fragmentation.
  *
- * __GFP_MOVABLE (also a zone modifier) indicates that the page can be
- *   moved by page migration during memory compaction or can be reclaimed.
+ * %__GFP_MOVABLE (also a zone modifier) indicates that the page can be
+ * moved by page migration during memory compaction or can be reclaimed.
  *
- * __GFP_RECLAIMABLE is used for slab allocations that specify
- *   SLAB_RECLAIM_ACCOUNT and whose pages can be freed via shrinkers.
+ * %__GFP_RECLAIMABLE is used for slab allocations that specify
+ * SLAB_RECLAIM_ACCOUNT and whose pages can be freed via shrinkers.
  *
- * __GFP_WRITE indicates the caller intends to dirty the page. Where possible,
- *   these pages will be spread between local zones to avoid all the dirty
- *   pages being in one zone (fair zone allocation policy).
+ * %__GFP_WRITE indicates the caller intends to dirty the page. Where possible,
+ * these pages will be spread between local zones to avoid all the dirty
+ * pages being in one zone (fair zone allocation policy).
  *
- * __GFP_HARDWALL enforces the cpuset memory allocation policy.
+ * %__GFP_HARDWALL enforces the cpuset memory allocation policy.
  *
- * __GFP_THISNODE forces the allocation to be satisified from the requested
- *   node with no fallbacks or placement policy enforcements.
+ * %__GFP_THISNODE forces the allocation to be satisified from the requested
+ * node with no fallbacks or placement policy enforcements.
  *
- * __GFP_ACCOUNT causes the allocation to be accounted to kmemcg.
+ * %__GFP_ACCOUNT causes the allocation to be accounted to kmemcg.
  */
 #define __GFP_RECLAIMABLE ((__force gfp_t)___GFP_RECLAIMABLE)
 #define __GFP_WRITE    ((__force gfp_t)___GFP_WRITE)
@@ -89,54 +92,60 @@ struct vm_area_struct;
 #define __GFP_THISNODE ((__force gfp_t)___GFP_THISNODE)
 #define __GFP_ACCOUNT  ((__force gfp_t)___GFP_ACCOUNT)
 
-/*
+/**
+ * DOC: Watermark modifiers
+ *
  * Watermark modifiers -- controls access to emergency reserves
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  *
- * __GFP_HIGH indicates that the caller is high-priority and that granting
- *   the request is necessary before the system can make forward progress.
- *   For example, creating an IO context to clean pages.
+ * %__GFP_HIGH indicates that the caller is high-priority and that granting
+ * the request is necessary before the system can make forward progress.
+ * For example, creating an IO context to clean pages.
  *
- * __GFP_ATOMIC indicates that the caller cannot reclaim or sleep and is
- *   high priority. Users are typically interrupt handlers. This may be
- *   used in conjunction with __GFP_HIGH
+ * %__GFP_ATOMIC indicates that the caller cannot reclaim or sleep and is
+ * high priority. Users are typically interrupt handlers. This may be
+ * used in conjunction with %__GFP_HIGH
  *
- * __GFP_MEMALLOC allows access to all memory. This should only be used when
- *   the caller guarantees the allocation will allow more memory to be freed
- *   very shortly e.g. process exiting or swapping. Users either should
- *   be the MM or co-ordinating closely with the VM (e.g. swap over NFS).
+ * %__GFP_MEMALLOC allows access to all memory. This should only be used when
+ * the caller guarantees the allocation will allow more memory to be freed
+ * very shortly e.g. process exiting or swapping. Users either should
+ * be the MM or co-ordinating closely with the VM (e.g. swap over NFS).
  *
- * __GFP_NOMEMALLOC is used to explicitly forbid access to emergency reserves.
- *   This takes precedence over the __GFP_MEMALLOC flag if both are set.
+ * %__GFP_NOMEMALLOC is used to explicitly forbid access to emergency reserves.
+ * This takes precedence over the %__GFP_MEMALLOC flag if both are set.
  */
 #define __GFP_ATOMIC   ((__force gfp_t)___GFP_ATOMIC)
 #define __GFP_HIGH     ((__force gfp_t)___GFP_HIGH)
 #define __GFP_MEMALLOC ((__force gfp_t)___GFP_MEMALLOC)
 #define __GFP_NOMEMALLOC ((__force gfp_t)___GFP_NOMEMALLOC)
 
-/*
+/**
+ * DOC: Reclaim modifiers
+ *
  * Reclaim modifiers
+ * ~~~~~~~~~~~~~~~~~
  *
- * __GFP_IO can start physical IO.
+ * %__GFP_IO can start physical IO.
  *
- * __GFP_FS can call down to the low-level FS. Clearing the flag avoids the
- *   allocator recursing into the filesystem which might already be holding
- *   locks.
+ * %__GFP_FS can call down to the low-level FS. Clearing the flag avoids the
+ * allocator recursing into the filesystem which might already be holding
+ * locks.
  *
- * __GFP_DIRECT_RECLAIM indicates that the caller may enter direct reclaim.
- *   This flag can be cleared to avoid unnecessary delays when a fallback
- *   option is available.
+ * %__GFP_DIRECT_RECLAIM indicates that the caller may enter direct reclaim.
+ * This flag can be cleared to avoid unnecessary delays when a fallback
+ * option is available.
  *
- * __GFP_KSWAPD_RECLAIM indicates that the caller wants to wake kswapd when
- *   the low watermark is reached and have it reclaim pages until the high
- *   watermark is reached. A caller may wish to clear this flag when fallback
- *   options are available and the reclaim is likely to disrupt the system. The
- *   canonical example is THP allocation where a fallback is cheap but
- *   reclaim/compaction may cause indirect stalls.
+ * %__GFP_KSWAPD_RECLAIM indicates that the caller wants to wake kswapd when
+ * the low watermark is reached and have it reclaim pages until the high
+ * watermark is reached. A caller may wish to clear this flag when fallback
+ * options are available and the reclaim is likely to disrupt the system. The
+ * canonical example is THP allocation where a fallback is cheap but
+ * reclaim/compaction may cause indirect stalls.
  *
- * __GFP_RECLAIM is shorthand to allow/forbid both direct and kswapd reclaim.
+ * %__GFP_RECLAIM is shorthand to allow/forbid both direct and kswapd reclaim.
  *
  * The default allocator behavior depends on the request size. We have a concept
- * of so called costly allocations (with order > PAGE_ALLOC_COSTLY_ORDER).
+ * of so called costly allocations (with order > %PAGE_ALLOC_COSTLY_ORDER).
  * !costly allocations are too essential to fail so they are implicitly
  * non-failing by default (with some exceptions like OOM victims might fail so
  * the caller still has to check for failures) while costly requests try to be
@@ -144,40 +153,40 @@ struct vm_area_struct;
  * The following three modifiers might be used to override some of these
  * implicit rules
  *
- * __GFP_NORETRY: The VM implementation will try only very lightweight
- *   memory direct reclaim to get some memory under memory pressure (thus
- *   it can sleep). It will avoid disruptive actions like OOM killer. The
- *   caller must handle the failure which is quite likely to happen under
- *   heavy memory pressure. The flag is suitable when failure can easily be
- *   handled at small cost, such as reduced throughput
- *
- * __GFP_RETRY_MAYFAIL: The VM implementation will retry memory reclaim
- *   procedures that have previously failed if there is some indication
- *   that progress has been made else where.  It can wait for other
- *   tasks to attempt high level approaches to freeing memory such as
- *   compaction (which removes fragmentation) and page-out.
- *   There is still a definite limit to the number of retries, but it is
- *   a larger limit than with __GFP_NORETRY.
- *   Allocations with this flag may fail, but only when there is
- *   genuinely little unused memory. While these allocations do not
- *   directly trigger the OOM killer, their failure indicates that
- *   the system is likely to need to use the OOM killer soon.  The
- *   caller must handle failure, but can reasonably do so by failing
- *   a higher-level request, or completing it only in a much less
- *   efficient manner.
- *   If the allocation does fail, and the caller is in a position to
- *   free some non-essential memory, doing so could benefit the system
- *   as a whole.
- *
- * __GFP_NOFAIL: The VM implementation _must_ retry infinitely: the caller
- *   cannot handle allocation failures. The allocation could block
- *   indefinitely but will never return with failure. Testing for
- *   failure is pointless.
- *   New users should be evaluated carefully (and the flag should be
- *   used only when there is no reasonable failure policy) but it is
- *   definitely preferable to use the flag rather than opencode endless
- *   loop around allocator.
- *   Using this flag for costly allocations is _highly_ discouraged.
+ * %__GFP_NORETRY: The VM implementation will try only very lightweight
+ * memory direct reclaim to get some memory under memory pressure (thus
+ * it can sleep). It will avoid disruptive actions like OOM killer. The
+ * caller must handle the failure which is quite likely to happen under
+ * heavy memory pressure. The flag is suitable when failure can easily be
+ * handled at small cost, such as reduced throughput
+ *
+ * %__GFP_RETRY_MAYFAIL: The VM implementation will retry memory reclaim
+ * procedures that have previously failed if there is some indication
+ * that progress has been made else where.  It can wait for other
+ * tasks to attempt high level approaches to freeing memory such as
+ * compaction (which removes fragmentation) and page-out.
+ * There is still a definite limit to the number of retries, but it is
+ * a larger limit than with %__GFP_NORETRY.
+ * Allocations with this flag may fail, but only when there is
+ * genuinely little unused memory. While these allocations do not
+ * directly trigger the OOM killer, their failure indicates that
+ * the system is likely to need to use the OOM killer soon.  The
+ * caller must handle failure, but can reasonably do so by failing
+ * a higher-level request, or completing it only in a much less
+ * efficient manner.
+ * If the allocation does fail, and the caller is in a position to
+ * free some non-essential memory, doing so could benefit the system
+ * as a whole.
+ *
+ * %__GFP_NOFAIL: The VM implementation _must_ retry infinitely: the caller
+ * cannot handle allocation failures. The allocation could block
+ * indefinitely but will never return with failure. Testing for
+ * failure is pointless.
+ * New users should be evaluated carefully (and the flag should be
+ * used only when there is no reasonable failure policy) but it is
+ * definitely preferable to use the flag rather than opencode endless
+ * loop around allocator.
+ * Using this flag for costly allocations is _highly_ discouraged.
  */
 #define __GFP_IO       ((__force gfp_t)___GFP_IO)
 #define __GFP_FS       ((__force gfp_t)___GFP_FS)
@@ -188,14 +197,17 @@ struct vm_area_struct;
 #define __GFP_NOFAIL   ((__force gfp_t)___GFP_NOFAIL)
 #define __GFP_NORETRY  ((__force gfp_t)___GFP_NORETRY)
 
-/*
+/**
+ * DOC: Action modifiers
+ *
  * Action modifiers
+ * ~~~~~~~~~~~~~~~~
  *
- * __GFP_NOWARN suppresses allocation failure reports.
+ * %__GFP_NOWARN suppresses allocation failure reports.
  *
- * __GFP_COMP address compound page metadata.
+ * %__GFP_COMP address compound page metadata.
  *
- * __GFP_ZERO returns a zeroed page on success.
+ * %__GFP_ZERO returns a zeroed page on success.
  */
 #define __GFP_NOWARN   ((__force gfp_t)___GFP_NOWARN)
 #define __GFP_COMP     ((__force gfp_t)___GFP_COMP)
@@ -208,66 +220,71 @@ struct vm_area_struct;
 #define __GFP_BITS_SHIFT (23 + IS_ENABLED(CONFIG_LOCKDEP))
 #define __GFP_BITS_MASK ((__force gfp_t)((1 << __GFP_BITS_SHIFT) - 1))
 
-/*
+/**
+ * DOC: Useful GFP flag combinations
+ *
+ * Useful GFP flag combinations
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
  * Useful GFP flag combinations that are commonly used. It is recommended
  * that subsystems start with one of these combinations and then set/clear
- * __GFP_FOO flags as necessary.
- *
- * GFP_ATOMIC users can not sleep and need the allocation to succeed. A lower
- *   watermark is applied to allow access to "atomic reserves"
- *
- * GFP_KERNEL is typical for kernel-internal allocations. The caller requires
- *   ZONE_NORMAL or a lower zone for direct access but can direct reclaim.
- *
- * GFP_KERNEL_ACCOUNT is the same as GFP_KERNEL, except the allocation is
- *   accounted to kmemcg.
- *
- * GFP_NOWAIT is for kernel allocations that should not stall for direct
- *   reclaim, start physical IO or use any filesystem callback.
- *
- * GFP_NOIO will use direct reclaim to discard clean pages or slab pages
- *   that do not require the starting of any physical IO.
- *   Please try to avoid using this flag directly and instead use
- *   memalloc_noio_{save,restore} to mark the whole scope which cannot
- *   perform any IO with a short explanation why. All allocation requests
- *   will inherit GFP_NOIO implicitly.
- *
- * GFP_NOFS will use direct reclaim but will not use any filesystem interfaces.
- *   Please try to avoid using this flag directly and instead use
- *   memalloc_nofs_{save,restore} to mark the whole scope which cannot/shouldn't
- *   recurse into the FS layer with a short explanation why. All allocation
- *   requests will inherit GFP_NOFS implicitly.
- *
- * GFP_USER is for userspace allocations that also need to be directly
- *   accessibly by the kernel or hardware. It is typically used by hardware
- *   for buffers that are mapped to userspace (e.g. graphics) that hardware
- *   still must DMA to. cpuset limits are enforced for these allocations.
- *
- * GFP_DMA exists for historical reasons and should be avoided where possible.
- *   The flags indicates that the caller requires that the lowest zone be
- *   used (ZONE_DMA or 16M on x86-64). Ideally, this would be removed but
- *   it would require careful auditing as some users really require it and
- *   others use the flag to avoid lowmem reserves in ZONE_DMA and treat the
- *   lowest zone as a type of emergency reserve.
- *
- * GFP_DMA32 is similar to GFP_DMA except that the caller requires a 32-bit
- *   address.
- *
- * GFP_HIGHUSER is for userspace allocations that may be mapped to userspace,
- *   do not need to be directly accessible by the kernel but that cannot
- *   move once in use. An example may be a hardware allocation that maps
- *   data directly into userspace but has no addressing limitations.
- *
- * GFP_HIGHUSER_MOVABLE is for userspace allocations that the kernel does not
- *   need direct access to but can use kmap() when access is required. They
- *   are expected to be movable via page reclaim or page migration. Typically,
- *   pages on the LRU would also be allocated with GFP_HIGHUSER_MOVABLE.
- *
- * GFP_TRANSHUGE and GFP_TRANSHUGE_LIGHT are used for THP allocations. They are
- *   compound allocations that will generally fail quickly if memory is not
- *   available and will not wake kswapd/kcompactd on failure. The _LIGHT
- *   version does not attempt reclaim/compaction at all and is by default used
- *   in page fault path, while the non-light is used by khugepaged.
+ * %__GFP_FOO flags as necessary.
+ *
+ * %GFP_ATOMIC users can not sleep and need the allocation to succeed. A lower
+ * watermark is applied to allow access to "atomic reserves"
+ *
+ * %GFP_KERNEL is typical for kernel-internal allocations. The caller requires
+ * %ZONE_NORMAL or a lower zone for direct access but can direct reclaim.
+ *
+ * %GFP_KERNEL_ACCOUNT is the same as GFP_KERNEL, except the allocation is
+ * accounted to kmemcg.
+ *
+ * %GFP_NOWAIT is for kernel allocations that should not stall for direct
+ * reclaim, start physical IO or use any filesystem callback.
+ *
+ * %GFP_NOIO will use direct reclaim to discard clean pages or slab pages
+ * that do not require the starting of any physical IO.
+ * Please try to avoid using this flag directly and instead use
+ * memalloc_noio_{save,restore} to mark the whole scope which cannot
+ * perform any IO with a short explanation why. All allocation requests
+ * will inherit GFP_NOIO implicitly.
+ *
+ * %GFP_NOFS will use direct reclaim but will not use any filesystem interfaces.
+ * Please try to avoid using this flag directly and instead use
+ * memalloc_nofs_{save,restore} to mark the whole scope which cannot/shouldn't
+ * recurse into the FS layer with a short explanation why. All allocation
+ * requests will inherit GFP_NOFS implicitly.
+ *
+ * %GFP_USER is for userspace allocations that also need to be directly
+ * accessibly by the kernel or hardware. It is typically used by hardware
+ * for buffers that are mapped to userspace (e.g. graphics) that hardware
+ * still must DMA to. cpuset limits are enforced for these allocations.
+ *
+ * %GFP_DMA exists for historical reasons and should be avoided where possible.
+ * The flags indicates that the caller requires that the lowest zone be
+ * used (%ZONE_DMA or 16M on x86-64). Ideally, this would be removed but
+ * it would require careful auditing as some users really require it and
+ * others use the flag to avoid lowmem reserves in %ZONE_DMA and treat the
+ * lowest zone as a type of emergency reserve.
+ *
+ * %GFP_DMA32 is similar to %GFP_DMA except that the caller requires a 32-bit
+ * address.
+ *
+ * %GFP_HIGHUSER is for userspace allocations that may be mapped to userspace,
+ * do not need to be directly accessible by the kernel but that cannot
+ * move once in use. An example may be a hardware allocation that maps
+ * data directly into userspace but has no addressing limitations.
+ *
+ * %GFP_HIGHUSER_MOVABLE is for userspace allocations that the kernel does not
+ * need direct access to but can use kmap() when access is required. They
+ * are expected to be movable via page reclaim or page migration. Typically,
+ * pages on the LRU would also be allocated with %GFP_HIGHUSER_MOVABLE.
+ *
+ * %GFP_TRANSHUGE and %GFP_TRANSHUGE_LIGHT are used for THP allocations. They
+ * are compound allocations that will generally fail quickly if memory is not
+ * available and will not wake kswapd/kcompactd on failure. The _LIGHT
+ * version does not attempt reclaim/compaction at all and is by default used
+ * in page fault path, while the non-light is used by khugepaged.
  */
 #define GFP_ATOMIC     (__GFP_HIGH|__GFP_ATOMIC|__GFP_KSWAPD_RECLAIM)
 #define GFP_KERNEL     (__GFP_RECLAIM | __GFP_IO | __GFP_FS)
index 773bcb1..834e646 100644 (file)
@@ -190,6 +190,12 @@ struct hid_item {
  * http://www.usb.org/developers/hidpage/HUTRR40RadioHIDUsagesFinal.pdf
  */
 #define HID_GD_WIRELESS_RADIO_CTLS     0x0001000c
+/*
+ * System Multi-Axis, see:
+ * http://www.usb.org/developers/hidpage/HUTRR62_-_Generic_Desktop_CA_for_System_Multi-Axis_Controllers.txt
+ */
+#define HID_GD_SYSTEM_MULTIAXIS        0x0001000e
+
 #define HID_GD_X               0x00010030
 #define HID_GD_Y               0x00010031
 #define HID_GD_Z               0x00010032
@@ -638,12 +644,13 @@ static inline void hid_set_drvdata(struct hid_device *hdev, void *data)
 struct hid_parser {
        struct hid_global     global;
        struct hid_global     global_stack[HID_GLOBAL_STACK_SIZE];
-       unsigned              global_stack_ptr;
+       unsigned int          global_stack_ptr;
        struct hid_local      local;
-       unsigned              collection_stack[HID_COLLECTION_STACK_SIZE];
-       unsigned              collection_stack_ptr;
+       unsigned int         *collection_stack;
+       unsigned int          collection_stack_ptr;
+       unsigned int          collection_stack_size;
        struct hid_device    *device;
-       unsigned              scan_flags;
+       unsigned int          scan_flags;
 };
 
 struct hid_class_descriptor {
@@ -894,6 +901,8 @@ const struct hid_device_id *hid_match_id(const struct hid_device *hdev,
                                         const struct hid_device_id *id);
 const struct hid_device_id *hid_match_device(struct hid_device *hdev,
                                             struct hid_driver *hdrv);
+bool hid_compare_device_paths(struct hid_device *hdev_a,
+                             struct hid_device *hdev_b, char separator);
 s32 hid_snto32(__u32 value, unsigned n);
 __u32 hid_field_extract(const struct hid_device *hid, __u8 *report,
                     unsigned offset, unsigned n);
index a8a1262..99c19b0 100644 (file)
@@ -3,10 +3,11 @@
 #define _LINUX_HUGE_MM_H
 
 #include <linux/sched/coredump.h>
+#include <linux/mm_types.h>
 
 #include <linux/fs.h> /* only for vma_is_dax() */
 
-extern int do_huge_pmd_anonymous_page(struct vm_fault *vmf);
+extern vm_fault_t do_huge_pmd_anonymous_page(struct vm_fault *vmf);
 extern int copy_huge_pmd(struct mm_struct *dst_mm, struct mm_struct *src_mm,
                         pmd_t *dst_pmd, pmd_t *src_pmd, unsigned long addr,
                         struct vm_area_struct *vma);
@@ -23,7 +24,7 @@ static inline void huge_pud_set_accessed(struct vm_fault *vmf, pud_t orig_pud)
 }
 #endif
 
-extern int do_huge_pmd_wp_page(struct vm_fault *vmf, pmd_t orig_pmd);
+extern vm_fault_t do_huge_pmd_wp_page(struct vm_fault *vmf, pmd_t orig_pmd);
 extern struct page *follow_trans_huge_pmd(struct vm_area_struct *vma,
                                          unsigned long addr,
                                          pmd_t *pmd,
@@ -46,9 +47,9 @@ 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);
-int vmf_insert_pfn_pmd(struct vm_area_struct *vma, unsigned long addr,
+vm_fault_t vmf_insert_pfn_pmd(struct vm_area_struct *vma, unsigned long addr,
                        pmd_t *pmd, pfn_t pfn, bool write);
-int vmf_insert_pfn_pud(struct vm_area_struct *vma, unsigned long addr,
+vm_fault_t vmf_insert_pfn_pud(struct vm_area_struct *vma, unsigned long addr,
                        pud_t *pud, pfn_t pfn, bool write);
 enum transparent_hugepage_flag {
        TRANSPARENT_HUGEPAGE_FLAG,
@@ -216,7 +217,7 @@ struct page *follow_devmap_pmd(struct vm_area_struct *vma, unsigned long addr,
 struct page *follow_devmap_pud(struct vm_area_struct *vma, unsigned long addr,
                pud_t *pud, int flags);
 
-extern int do_huge_pmd_numa_page(struct vm_fault *vmf, pmd_t orig_pmd);
+extern vm_fault_t do_huge_pmd_numa_page(struct vm_fault *vmf, pmd_t orig_pmd);
 
 extern struct page *huge_zero_page;
 
@@ -321,7 +322,8 @@ static inline spinlock_t *pud_trans_huge_lock(pud_t *pud,
        return NULL;
 }
 
-static inline int do_huge_pmd_numa_page(struct vm_fault *vmf, pmd_t orig_pmd)
+static inline vm_fault_t do_huge_pmd_numa_page(struct vm_fault *vmf,
+               pmd_t orig_pmd)
 {
        return 0;
 }
index c39d917..6b68e34 100644 (file)
@@ -105,7 +105,7 @@ void hugetlb_report_meminfo(struct seq_file *);
 int hugetlb_report_node_meminfo(int, char *);
 void hugetlb_show_meminfo(void);
 unsigned long hugetlb_total_pages(void);
-int hugetlb_fault(struct mm_struct *mm, struct vm_area_struct *vma,
+vm_fault_t hugetlb_fault(struct mm_struct *mm, struct vm_area_struct *vma,
                        unsigned long address, unsigned int flags);
 int hugetlb_mcopy_atomic_pte(struct mm_struct *dst_mm, pte_t *dst_pte,
                                struct vm_area_struct *dst_vma,
index 465afb0..b79387f 100644 (file)
@@ -231,7 +231,6 @@ enum i2c_alert_protocol {
 /**
  * struct i2c_driver - represent an I2C device driver
  * @class: What kind of i2c device we instantiate (for detect)
- * @attach_adapter: Callback for bus addition (deprecated)
  * @probe: Callback for device binding - soon to be deprecated
  * @probe_new: New callback for device binding
  * @remove: Callback for device unbinding
@@ -268,11 +267,6 @@ enum i2c_alert_protocol {
 struct i2c_driver {
        unsigned int class;
 
-       /* Notifies the driver that a new bus has appeared. You should avoid
-        * using this, it will be removed in a near future.
-        */
-       int (*attach_adapter)(struct i2c_adapter *) __deprecated;
-
        /* Standard driver model interfaces */
        int (*probe)(struct i2c_client *, const struct i2c_device_id *);
        int (*remove)(struct i2c_client *);
@@ -564,6 +558,7 @@ struct i2c_lock_operations {
  * @scl_fall_ns: time SCL signal takes to fall in ns; t(f) in the I2C specification
  * @scl_int_delay_ns: time IP core additionally needs to setup SCL in ns
  * @sda_fall_ns: time SDA signal takes to fall in ns; t(f) in the I2C specification
+ * @sda_hold_ns: time IP core additionally needs to hold SDA in ns
  */
 struct i2c_timings {
        u32 bus_freq_hz;
@@ -571,6 +566,7 @@ struct i2c_timings {
        u32 scl_fall_ns;
        u32 scl_int_delay_ns;
        u32 sda_fall_ns;
+       u32 sda_hold_ns;
 };
 
 /**
@@ -581,12 +577,14 @@ struct i2c_timings {
  *      recovery. Populated internally for generic GPIO recovery.
  * @set_scl: This sets/clears the SCL line. Mandatory for generic SCL recovery.
  *      Populated internally for generic GPIO recovery.
- * @get_sda: This gets current value of SDA line. Optional for generic SCL
- *      recovery. Populated internally, if sda_gpio is a valid GPIO, for generic
- *      GPIO recovery.
- * @set_sda: This sets/clears the SDA line. Optional for generic SCL recovery.
- *     Populated internally, if sda_gpio is a valid GPIO, for generic GPIO
- *     recovery.
+ * @get_sda: This gets current value of SDA line. This or set_sda() is mandatory
+ *     for generic SCL recovery. Populated internally, if sda_gpio is a valid
+ *     GPIO, for generic GPIO recovery.
+ * @set_sda: This sets/clears the SDA line. This or get_sda() is mandatory for
+ *     generic SCL recovery. Populated internally, if sda_gpio is a valid GPIO,
+ *     for generic GPIO recovery.
+ * @get_bus_free: Returns the bus free state as seen from the IP core in case it
+ *     has a more complex internal logic than just reading SDA. Optional.
  * @prepare_recovery: This will be called before starting recovery. Platform may
  *     configure padmux here for SDA/SCL line or something else they want.
  * @unprepare_recovery: This will be called after completing recovery. Platform
@@ -601,6 +599,7 @@ struct i2c_bus_recovery_info {
        void (*set_scl)(struct i2c_adapter *adap, int val);
        int (*get_sda)(struct i2c_adapter *adap);
        void (*set_sda)(struct i2c_adapter *adap, int val);
+       int (*get_bus_free)(struct i2c_adapter *adap);
 
        void (*prepare_recovery)(struct i2c_adapter *adap);
        void (*unprepare_recovery)(struct i2c_adapter *adap);
@@ -658,6 +657,10 @@ struct i2c_adapter_quirks {
                                         I2C_AQ_COMB_READ_SECOND | I2C_AQ_COMB_SAME_ADDR)
 /* clock stretching is not supported */
 #define I2C_AQ_NO_CLK_STRETCH          BIT(4)
+/* message cannot have length of 0 */
+#define I2C_AQ_NO_ZERO_LEN_READ                BIT(5)
+#define I2C_AQ_NO_ZERO_LEN_WRITE       BIT(6)
+#define I2C_AQ_NO_ZERO_LEN             (I2C_AQ_NO_ZERO_LEN_READ | I2C_AQ_NO_ZERO_LEN_WRITE)
 
 /*
  * i2c_adapter is the structure used to identify a physical i2c bus along
@@ -759,18 +762,6 @@ i2c_unlock_bus(struct i2c_adapter *adapter, unsigned int flags)
        adapter->lock_ops->unlock_bus(adapter, flags);
 }
 
-static inline void
-i2c_lock_adapter(struct i2c_adapter *adapter)
-{
-       i2c_lock_bus(adapter, I2C_LOCK_ROOT_ADAPTER);
-}
-
-static inline void
-i2c_unlock_adapter(struct i2c_adapter *adapter)
-{
-       i2c_unlock_bus(adapter, I2C_LOCK_ROOT_ADAPTER);
-}
-
 /*flags for the client struct: */
 #define I2C_CLIENT_PEC         0x04    /* Use Packet Error Checking */
 #define I2C_CLIENT_TEN         0x10    /* we have a ten bit chip address */
index 3e8215b..3ec8628 100644 (file)
@@ -236,34 +236,74 @@ struct ida {
 }
 #define DEFINE_IDA(name)       struct ida name = IDA_INIT(name)
 
-int ida_pre_get(struct ida *ida, gfp_t gfp_mask);
-int ida_get_new_above(struct ida *ida, int starting_id, int *p_id);
-void ida_remove(struct ida *ida, int id);
+int ida_alloc_range(struct ida *, unsigned int min, unsigned int max, gfp_t);
+void ida_free(struct ida *, unsigned int id);
 void ida_destroy(struct ida *ida);
 
-int ida_simple_get(struct ida *ida, unsigned int start, unsigned int end,
-                  gfp_t gfp_mask);
-void ida_simple_remove(struct ida *ida, unsigned int id);
+/**
+ * ida_alloc() - Allocate an unused ID.
+ * @ida: IDA handle.
+ * @gfp: Memory allocation flags.
+ *
+ * Allocate an ID between 0 and %INT_MAX, inclusive.
+ *
+ * Context: Any context.
+ * Return: The allocated ID, or %-ENOMEM if memory could not be allocated,
+ * or %-ENOSPC if there are no free IDs.
+ */
+static inline int ida_alloc(struct ida *ida, gfp_t gfp)
+{
+       return ida_alloc_range(ida, 0, ~0, gfp);
+}
 
-static inline void ida_init(struct ida *ida)
+/**
+ * ida_alloc_min() - Allocate an unused ID.
+ * @ida: IDA handle.
+ * @min: Lowest ID to allocate.
+ * @gfp: Memory allocation flags.
+ *
+ * Allocate an ID between @min and %INT_MAX, inclusive.
+ *
+ * Context: Any context.
+ * Return: The allocated ID, or %-ENOMEM if memory could not be allocated,
+ * or %-ENOSPC if there are no free IDs.
+ */
+static inline int ida_alloc_min(struct ida *ida, unsigned int min, gfp_t gfp)
 {
-       INIT_RADIX_TREE(&ida->ida_rt, IDR_RT_MARKER | GFP_NOWAIT);
+       return ida_alloc_range(ida, min, ~0, gfp);
 }
 
 /**
- * ida_get_new - allocate new ID
- * @ida:       idr handle
- * @p_id:      pointer to the allocated handle
+ * ida_alloc_max() - Allocate an unused ID.
+ * @ida: IDA handle.
+ * @max: Highest ID to allocate.
+ * @gfp: Memory allocation flags.
+ *
+ * Allocate an ID between 0 and @max, inclusive.
  *
- * Simple wrapper around ida_get_new_above() w/ @starting_id of zero.
+ * Context: Any context.
+ * Return: The allocated ID, or %-ENOMEM if memory could not be allocated,
+ * or %-ENOSPC if there are no free IDs.
  */
-static inline int ida_get_new(struct ida *ida, int *p_id)
+static inline int ida_alloc_max(struct ida *ida, unsigned int max, gfp_t gfp)
 {
-       return ida_get_new_above(ida, 0, p_id);
+       return ida_alloc_range(ida, 0, max, gfp);
 }
 
+static inline void ida_init(struct ida *ida)
+{
+       INIT_RADIX_TREE(&ida->ida_rt, IDR_RT_MARKER | GFP_NOWAIT);
+}
+
+#define ida_simple_get(ida, start, end, gfp)   \
+                       ida_alloc_range(ida, start, (end) - 1, gfp)
+#define ida_simple_remove(ida, id)     ida_free(ida, id)
+
 static inline bool ida_is_empty(const struct ida *ida)
 {
        return radix_tree_empty(&ida->ida_rt);
 }
+
+/* in lib/radix-tree.c */
+int ida_pre_get(struct ida *ida, gfp_t gfp_mask);
 #endif /* __IDR_H__ */
index bc27cf0..2538d17 100644 (file)
 typedef int (*initcall_t)(void);
 typedef void (*exitcall_t)(void);
 
-extern initcall_t __con_initcall_start[], __con_initcall_end[];
-extern initcall_t __security_initcall_start[], __security_initcall_end[];
+#ifdef CONFIG_HAVE_ARCH_PREL32_RELOCATIONS
+typedef int initcall_entry_t;
+
+static inline initcall_t initcall_from_entry(initcall_entry_t *entry)
+{
+       return offset_to_ptr(entry);
+}
+#else
+typedef initcall_t initcall_entry_t;
+
+static inline initcall_t initcall_from_entry(initcall_entry_t *entry)
+{
+       return *entry;
+}
+#endif
+
+extern initcall_entry_t __con_initcall_start[], __con_initcall_end[];
+extern initcall_entry_t __security_initcall_start[], __security_initcall_end[];
 
 /* Used for contructor calls. */
 typedef void (*ctor_fn_t)(void);
@@ -167,9 +183,20 @@ extern bool initcall_debug;
  * as KEEP() in the linker script.
  */
 
-#define __define_initcall(fn, id) \
+#ifdef CONFIG_HAVE_ARCH_PREL32_RELOCATIONS
+#define ___define_initcall(fn, id, __sec)                      \
+       __ADDRESSABLE(fn)                                       \
+       asm(".section   \"" #__sec ".init\", \"a\"      \n"     \
+       "__initcall_" #fn #id ":                        \n"     \
+           ".long      " #fn " - .                     \n"     \
+           ".previous                                  \n");
+#else
+#define ___define_initcall(fn, id, __sec) \
        static initcall_t __initcall_##fn##id __used \
-       __attribute__((__section__(".initcall" #id ".init"))) = fn;
+               __attribute__((__section__(#__sec ".init"))) = fn;
+#endif
+
+#define __define_initcall(fn, id) ___define_initcall(fn, id, .initcall##id)
 
 /*
  * Early initcalls run before initializing SMP.
@@ -208,13 +235,8 @@ extern bool initcall_debug;
 #define __exitcall(fn)                                         \
        static exitcall_t __exitcall_##fn __exit_call = fn
 
-#define console_initcall(fn)                                   \
-       static initcall_t __initcall_##fn                       \
-       __used __section(.con_initcall.init) = fn
-
-#define security_initcall(fn)                                  \
-       static initcall_t __initcall_##fn                       \
-       __used __section(.security_initcall.init) = fn
+#define console_initcall(fn)   ___define_initcall(fn,, .con_initcall)
+#define security_initcall(fn)  ___define_initcall(fn,, .security_initcall)
 
 struct obs_kernel_param {
        const char *str;
index a454b8a..a7083a4 100644 (file)
@@ -46,15 +46,6 @@ extern struct cred init_cred;
 #define INIT_CPU_TIMERS(s)
 #endif
 
-#define INIT_PID_LINK(type)                                    \
-{                                                              \
-       .node = {                                               \
-               .next = NULL,                                   \
-               .pprev = NULL,                                  \
-       },                                                      \
-       .pid = &init_struct_pid,                                \
-}
-
 #define INIT_TASK_COMM "swapper"
 
 /* Attach to the init_task data structure for proper alignment */
index ef169d6..28004d7 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/list.h>
 #include <linux/iommu.h>
 #include <linux/io-64-nonatomic-lo-hi.h>
+#include <linux/dmar.h>
 
 #include <asm/cacheflush.h>
 #include <asm/iommu.h>
  * Extended Capability Register
  */
 
+#define ecap_dit(e)            ((e >> 41) & 0x1)
 #define ecap_pasid(e)          ((e >> 40) & 0x1)
 #define ecap_pss(e)            ((e >> 35) & 0x1f)
 #define ecap_eafs(e)           ((e >> 34) & 0x1)
@@ -284,6 +286,7 @@ enum {
 #define QI_DEV_IOTLB_SID(sid)  ((u64)((sid) & 0xffff) << 32)
 #define QI_DEV_IOTLB_QDEP(qdep)        (((qdep) & 0x1f) << 16)
 #define QI_DEV_IOTLB_ADDR(addr)        ((u64)(addr) & VTD_PAGE_MASK)
+#define QI_DEV_IOTLB_PFSID(pfsid) (((u64)(pfsid & 0xf) << 12) | ((u64)(pfsid & 0xfff) << 52))
 #define QI_DEV_IOTLB_SIZE      1
 #define QI_DEV_IOTLB_MAX_INVS  32
 
@@ -308,6 +311,7 @@ enum {
 #define QI_DEV_EIOTLB_PASID(p) (((u64)p) << 32)
 #define QI_DEV_EIOTLB_SID(sid) ((u64)((sid) & 0xffff) << 16)
 #define QI_DEV_EIOTLB_QDEP(qd) ((u64)((qd) & 0x1f) << 4)
+#define QI_DEV_EIOTLB_PFSID(pfsid) (((u64)(pfsid & 0xf) << 12) | ((u64)(pfsid & 0xfff) << 52))
 #define QI_DEV_EIOTLB_MAX_INVS 32
 
 #define QI_PGRP_IDX(idx)       (((u64)(idx)) << 55)
@@ -385,6 +389,42 @@ struct pasid_entry;
 struct pasid_state_entry;
 struct page_req_dsc;
 
+struct dmar_domain {
+       int     nid;                    /* node id */
+
+       unsigned        iommu_refcnt[DMAR_UNITS_SUPPORTED];
+                                       /* Refcount of devices per iommu */
+
+
+       u16             iommu_did[DMAR_UNITS_SUPPORTED];
+                                       /* Domain ids per IOMMU. Use u16 since
+                                        * domain ids are 16 bit wide according
+                                        * to VT-d spec, section 9.3 */
+
+       bool has_iotlb_device;
+       struct list_head devices;       /* all devices' list */
+       struct iova_domain iovad;       /* iova's that belong to this domain */
+
+       struct dma_pte  *pgd;           /* virtual address */
+       int             gaw;            /* max guest address width */
+
+       /* adjusted guest address width, 0 is level 2 30-bit */
+       int             agaw;
+
+       int             flags;          /* flags to find out type of domain */
+
+       int             iommu_coherency;/* indicate coherency of iommu access */
+       int             iommu_snooping; /* indicate snooping control feature*/
+       int             iommu_count;    /* reference count of iommu */
+       int             iommu_superpage;/* Level of superpages supported:
+                                          0 == 4KiB (no superpages), 1 == 2MiB,
+                                          2 == 1GiB, 3 == 512GiB, 4 == 1TiB */
+       u64             max_addr;       /* maximum mapped address */
+
+       struct iommu_domain domain;     /* generic domain data structure for
+                                          iommu core */
+};
+
 struct intel_iommu {
        void __iomem    *reg; /* Pointer to hardware regs, virtual addr */
        u64             reg_phys; /* physical address of hw register set */
@@ -414,11 +454,9 @@ struct intel_iommu {
         * devices away to userspace processes (e.g. for DPDK) and don't
         * want to trust that userspace will use *only* the PASID it was
         * told to. But while it's all driver-arbitrated, we're fine. */
-       struct pasid_entry *pasid_table;
        struct pasid_state_entry *pasid_state_table;
        struct page_req_dsc *prq;
        unsigned char prq_name[16];    /* Name for PRQ interrupt */
-       struct idr pasid_idr;
        u32 pasid_max;
 #endif
        struct q_inval  *qi;            /* Queued invalidation info */
@@ -434,6 +472,27 @@ struct intel_iommu {
        u32             flags;      /* Software defined flags */
 };
 
+/* PCI domain-device relationship */
+struct device_domain_info {
+       struct list_head link;  /* link to domain siblings */
+       struct list_head global; /* link to global list */
+       struct list_head table; /* link to pasid table */
+       u8 bus;                 /* PCI bus number */
+       u8 devfn;               /* PCI devfn number */
+       u16 pfsid;              /* SRIOV physical function source ID */
+       u8 pasid_supported:3;
+       u8 pasid_enabled:1;
+       u8 pri_supported:1;
+       u8 pri_enabled:1;
+       u8 ats_supported:1;
+       u8 ats_enabled:1;
+       u8 ats_qdep;
+       struct device *dev; /* it's NULL for PCIe-to-PCI bridge */
+       struct intel_iommu *iommu; /* IOMMU used by this device */
+       struct dmar_domain *domain; /* pointer to domain */
+       struct pasid_table *pasid_table; /* pasid table */
+};
+
 static inline void __iommu_flush_cache(
        struct intel_iommu *iommu, void *addr, int size)
 {
@@ -453,16 +512,22 @@ extern void qi_flush_context(struct intel_iommu *iommu, u16 did, u16 sid,
                             u8 fm, u64 type);
 extern void qi_flush_iotlb(struct intel_iommu *iommu, u16 did, u64 addr,
                          unsigned int size_order, u64 type);
-extern void qi_flush_dev_iotlb(struct intel_iommu *iommu, u16 sid, u16 qdep,
-                              u64 addr, unsigned mask);
-
+extern void qi_flush_dev_iotlb(struct intel_iommu *iommu, u16 sid, u16 pfsid,
+                       u16 qdep, u64 addr, unsigned mask);
 extern int qi_submit_sync(struct qi_desc *desc, struct intel_iommu *iommu);
 
 extern int dmar_ir_support(void);
 
+struct dmar_domain *get_valid_domain_for_dev(struct device *dev);
+void *alloc_pgtable_page(int node);
+void free_pgtable_page(void *vaddr);
+struct intel_iommu *domain_get_iommu(struct dmar_domain *domain);
+int for_each_device_domain(int (*fn)(struct device_domain_info *info,
+                                    void *data), void *data);
+
 #ifdef CONFIG_INTEL_IOMMU_SVM
-extern int intel_svm_alloc_pasid_tables(struct intel_iommu *iommu);
-extern int intel_svm_free_pasid_tables(struct intel_iommu *iommu);
+int intel_svm_init(struct intel_iommu *iommu);
+int intel_svm_exit(struct intel_iommu *iommu);
 extern int intel_svm_enable_prq(struct intel_iommu *iommu);
 extern int intel_svm_finish_prq(struct intel_iommu *iommu);
 
@@ -486,6 +551,7 @@ struct intel_svm {
        int flags;
        int pasid;
        struct list_head devs;
+       struct list_head list;
 };
 
 extern int intel_iommu_enable_pasid(struct intel_iommu *iommu, struct intel_svm_dev *sdev);
index 19938ee..87994c2 100644 (file)
@@ -166,8 +166,6 @@ struct iommu_resv_region {
  * @detach_dev: detach device from an iommu domain
  * @map: map a physically contiguous memory region to an iommu domain
  * @unmap: unmap a physically contiguous memory region from an iommu domain
- * @map_sg: map a scatter-gather list of physically contiguous memory chunks
- *          to an iommu domain
  * @flush_tlb_all: Synchronously flush all hardware TLBs for this domain
  * @tlb_range_add: Add a given iova range to the flush queue for this domain
  * @tlb_sync: Flush all queued ranges from the hardware TLBs and empty flush
@@ -201,8 +199,6 @@ struct iommu_ops {
                   phys_addr_t paddr, size_t size, int prot);
        size_t (*unmap)(struct iommu_domain *domain, unsigned long iova,
                     size_t size);
-       size_t (*map_sg)(struct iommu_domain *domain, unsigned long iova,
-                        struct scatterlist *sg, unsigned int nents, int prot);
        void (*flush_iotlb_all)(struct iommu_domain *domain);
        void (*iotlb_range_add)(struct iommu_domain *domain,
                                unsigned long iova, size_t size);
@@ -303,9 +299,8 @@ extern size_t iommu_unmap(struct iommu_domain *domain, unsigned long iova,
                          size_t size);
 extern size_t iommu_unmap_fast(struct iommu_domain *domain,
                               unsigned long iova, size_t size);
-extern size_t default_iommu_map_sg(struct iommu_domain *domain, unsigned long iova,
-                               struct scatterlist *sg,unsigned int nents,
-                               int prot);
+extern size_t iommu_map_sg(struct iommu_domain *domain, unsigned long iova,
+                          struct scatterlist *sg,unsigned int nents, int prot);
 extern phys_addr_t iommu_iova_to_phys(struct iommu_domain *domain, dma_addr_t iova);
 extern void iommu_set_fault_handler(struct iommu_domain *domain,
                        iommu_fault_handler_t handler, void *token);
@@ -378,13 +373,6 @@ static inline void iommu_tlb_sync(struct iommu_domain *domain)
                domain->ops->iotlb_sync(domain);
 }
 
-static inline size_t iommu_map_sg(struct iommu_domain *domain,
-                                 unsigned long iova, struct scatterlist *sg,
-                                 unsigned int nents, int prot)
-{
-       return domain->ops->map_sg(domain, iova, sg, nents, prot);
-}
-
 /* PCI device grouping function */
 extern struct iommu_group *pci_device_group(struct device *dev);
 /* Generic device grouping function */
@@ -698,4 +686,11 @@ const struct iommu_ops *iommu_ops_from_fwnode(struct fwnode_handle *fwnode)
 
 #endif /* CONFIG_IOMMU_API */
 
+#ifdef CONFIG_IOMMU_DEBUGFS
+extern struct dentry *iommu_debugfs_dir;
+void iommu_debugfs_setup(void);
+#else
+static inline void iommu_debugfs_setup(void) {}
+#endif
+
 #endif /* __LINUX_IOMMU_H */
index 6cea726..6ab8c1b 100644 (file)
@@ -16,10 +16,9 @@ struct user_namespace;
 struct ipc_ids {
        int in_use;
        unsigned short seq;
-       bool tables_initialized;
        struct rw_semaphore rwsem;
        struct idr ipcs_idr;
-       int max_id;
+       int max_idx;
 #ifdef CONFIG_CHECKPOINT_RESTORE
        int next_id;
 #endif
index 9d2ea3e..8bdbb5f 100644 (file)
 #define GICD_CTLR_ENABLE_G1A           (1U << 1)
 #define GICD_CTLR_ENABLE_G1            (1U << 0)
 
+#define GICD_IIDR_IMPLEMENTER_SHIFT    0
+#define GICD_IIDR_IMPLEMENTER_MASK     (0xfff << GICD_IIDR_IMPLEMENTER_SHIFT)
+#define GICD_IIDR_REVISION_SHIFT       12
+#define GICD_IIDR_REVISION_MASK                (0xf << GICD_IIDR_REVISION_SHIFT)
+#define GICD_IIDR_VARIANT_SHIFT                16
+#define GICD_IIDR_VARIANT_MASK         (0xf << GICD_IIDR_VARIANT_SHIFT)
+#define GICD_IIDR_PRODUCT_ID_SHIFT     24
+#define GICD_IIDR_PRODUCT_ID_MASK      (0xff << GICD_IIDR_PRODUCT_ID_SHIFT)
+
+
 /*
  * In systems with a single security state (what we emulate in KVM)
  * the meaning of the interrupt group enable bits is slightly different
index 68d8b1f..6c4aaf0 100644 (file)
                                        (GICD_INT_DEF_PRI << 8) |\
                                        GICD_INT_DEF_PRI)
 
+#define GICD_IIDR_IMPLEMENTER_SHIFT    0
+#define GICD_IIDR_IMPLEMENTER_MASK     (0xfff << GICD_IIDR_IMPLEMENTER_SHIFT)
+#define GICD_IIDR_REVISION_SHIFT       12
+#define GICD_IIDR_REVISION_MASK                (0xf << GICD_IIDR_REVISION_SHIFT)
+#define GICD_IIDR_VARIANT_SHIFT                16
+#define GICD_IIDR_VARIANT_MASK         (0xf << GICD_IIDR_VARIANT_SHIFT)
+#define GICD_IIDR_PRODUCT_ID_SHIFT     24
+#define GICD_IIDR_PRODUCT_ID_MASK      (0xff << GICD_IIDR_PRODUCT_ID_SHIFT)
+
+
 #define GICH_HCR                       0x0
 #define GICH_VTR                       0x4
 #define GICH_VMCR                      0x8
 #define GICH_LR_PENDING_BIT            (1 << 28)
 #define GICH_LR_ACTIVE_BIT             (1 << 29)
 #define GICH_LR_EOI                    (1 << 19)
+#define GICH_LR_GROUP1                 (1 << 30)
 #define GICH_LR_HW                     (1 << 31)
 
 #define GICH_VMCR_ENABLE_GRP0_SHIFT    0
index 9700f00..21619c9 100644 (file)
 #include <linux/typecheck.h>
 #include <asm/irqflags.h>
 
-#ifdef CONFIG_TRACE_IRQFLAGS
+/* Currently trace_softirqs_on/off is used only by lockdep */
+#ifdef CONFIG_PROVE_LOCKING
   extern void trace_softirqs_on(unsigned long ip);
   extern void trace_softirqs_off(unsigned long ip);
+  extern void lockdep_hardirqs_on(unsigned long ip);
+  extern void lockdep_hardirqs_off(unsigned long ip);
+#else
+  static inline void trace_softirqs_on(unsigned long ip) { }
+  static inline void trace_softirqs_off(unsigned long ip) { }
+  static inline void lockdep_hardirqs_on(unsigned long ip) { }
+  static inline void lockdep_hardirqs_off(unsigned long ip) { }
+#endif
+
+#ifdef CONFIG_TRACE_IRQFLAGS
   extern void trace_hardirqs_on(void);
   extern void trace_hardirqs_off(void);
 # define trace_hardirq_context(p)      ((p)->hardirq_context)
@@ -43,8 +54,6 @@ do {                                          \
 #else
 # define trace_hardirqs_on()           do { } while (0)
 # define trace_hardirqs_off()          do { } while (0)
-# define trace_softirqs_on(ip)         do { } while (0)
-# define trace_softirqs_off(ip)                do { } while (0)
 # define trace_hardirq_context(p)      0
 # define trace_softirq_context(p)      0
 # define trace_hardirqs_enabled(p)     0
index 8de55e4..8c3f8c1 100644 (file)
@@ -12,11 +12,13 @@ enum kcore_type {
        KCORE_VMEMMAP,
        KCORE_USER,
        KCORE_OTHER,
+       KCORE_REMAP,
 };
 
 struct kcore_list {
        struct list_head list;
        unsigned long addr;
+       unsigned long vaddr;
        size_t size;
        int type;
 };
@@ -35,12 +37,23 @@ struct vmcoredd_node {
 };
 
 #ifdef CONFIG_PROC_KCORE
-extern void kclist_add(struct kcore_list *, void *, size_t, int type);
+void __init kclist_add(struct kcore_list *, void *, size_t, int type);
+static inline
+void kclist_add_remap(struct kcore_list *m, void *addr, void *vaddr, size_t sz)
+{
+       m->vaddr = (unsigned long)vaddr;
+       kclist_add(m, addr, sz, KCORE_REMAP);
+}
 #else
 static inline
 void kclist_add(struct kcore_list *new, void *addr, size_t size, int type)
 {
 }
+
+static inline
+void kclist_add_remap(struct kcore_list *m, void *addr, void *vaddr, size_t sz)
+{
+}
 #endif
 
 #endif /* _LINUX_KCORE_H */
index 941dc0a..d6aac75 100644 (file)
  * arguments just once each.
  */
 #define __round_mask(x, y) ((__typeof__(x))((y)-1))
+/**
+ * round_up - round up to next specified power of 2
+ * @x: the value to round
+ * @y: multiple to round up to (must be a power of 2)
+ *
+ * Rounds @x up to next multiple of @y (which must be a power of 2).
+ * To perform arbitrary rounding up, use roundup() below.
+ */
 #define round_up(x, y) ((((x)-1) | __round_mask(x, y))+1)
+/**
+ * round_down - round down to next specified power of 2
+ * @x: the value to round
+ * @y: multiple to round down to (must be a power of 2)
+ *
+ * Rounds @x down to next multiple of @y (which must be a power of 2).
+ * To perform arbitrary rounding down, use rounddown() below.
+ */
 #define round_down(x, y) ((x) & ~__round_mask(x, y))
 
 /**
 # define DIV_ROUND_UP_SECTOR_T(ll,d) DIV_ROUND_UP(ll,d)
 #endif
 
-/* The `const' in roundup() prevents gcc-3.3 from calling __divdi3 */
+/**
+ * roundup - round up to the next specified multiple
+ * @x: the value to up
+ * @y: multiple to round up to
+ *
+ * Rounds @x up to next multiple of @y. If @y will always be a power
+ * of 2, consider using the faster round_up().
+ *
+ * The `const' here prevents gcc-3.3 from calling __divdi3
+ */
 #define roundup(x, y) (                                        \
 {                                                      \
        const typeof(y) __y = y;                        \
        (((x) + (__y - 1)) / __y) * __y;                \
 }                                                      \
 )
+/**
+ * rounddown - round down to next specified multiple
+ * @x: the value to round
+ * @y: multiple to round down to
+ *
+ * Rounds @x down to next multiple of @y. If @y will always be a power
+ * of 2, consider using the faster round_down().
+ */
 #define rounddown(x, y) (                              \
 {                                                      \
        typeof(x) __x = (x);                            \
index 7c7362d..0205aee 100644 (file)
@@ -1289,8 +1289,8 @@ static inline long kvm_arch_vcpu_async_ioctl(struct file *filp,
 }
 #endif /* CONFIG_HAVE_KVM_VCPU_ASYNC_IOCTL */
 
-void kvm_arch_mmu_notifier_invalidate_range(struct kvm *kvm,
-               unsigned long start, unsigned long end);
+int kvm_arch_mmu_notifier_invalidate_range(struct kvm *kvm,
+               unsigned long start, unsigned long end, bool blockable);
 
 #ifdef CONFIG_HAVE_KVM_VCPU_RUN_PID_CHANGE
 int kvm_arch_vcpu_run_pid_change(struct kvm_vcpu *vcpu);
index bc4f87c..38c95d6 100644 (file)
@@ -523,7 +523,8 @@ enum ata_lpm_policy {
        ATA_LPM_MAX_POWER,
        ATA_LPM_MED_POWER,
        ATA_LPM_MED_POWER_WITH_DIPM, /* Med power + DIPM as win IRST does */
-       ATA_LPM_MIN_POWER,
+       ATA_LPM_MIN_POWER_WITH_PARTIAL, /* Min Power + partial and slumber */
+       ATA_LPM_MIN_POWER, /* Min power + no partial (slumber only) */
 };
 
 enum ata_lpm_hints {
@@ -1858,8 +1859,6 @@ extern unsigned int ata_sff_data_xfer(struct ata_queued_cmd *qc,
                        unsigned char *buf, unsigned int buflen, int rw);
 extern unsigned int ata_sff_data_xfer32(struct ata_queued_cmd *qc,
                        unsigned char *buf, unsigned int buflen, int rw);
-extern unsigned int ata_sff_data_xfer_noirq(struct ata_queued_cmd *qc,
-                       unsigned char *buf, unsigned int buflen, int rw);
 extern void ata_sff_irq_on(struct ata_port *ap);
 extern void ata_sff_irq_clear(struct ata_port *ap);
 extern int ata_sff_hsm_move(struct ata_port *ap, struct ata_queued_cmd *qc,
index 4fd95db..b065ef4 100644 (file)
@@ -299,7 +299,7 @@ int           nlmsvc_unlock_all_by_ip(struct sockaddr *server_addr);
 
 static inline struct inode *nlmsvc_file_inode(struct nlm_file *file)
 {
-       return file_inode(file->f_file);
+       return locks_inode(file->f_file);
 }
 
 static inline int __nlm_privileged_request4(const struct sockaddr *sap)
@@ -359,7 +359,7 @@ static inline int nlm_privileged_requester(const struct svc_rqst *rqstp)
 static inline int nlm_compare_locks(const struct file_lock *fl1,
                                    const struct file_lock *fl2)
 {
-       return file_inode(fl1->fl_file) == file_inode(fl2->fl_file)
+       return locks_inode(fl1->fl_file) == locks_inode(fl2->fl_file)
             && fl1->fl_pid   == fl2->fl_pid
             && fl1->fl_owner == fl2->fl_owner
             && fl1->fl_start == fl2->fl_start
index 6fc77d4..b0d0b51 100644 (file)
@@ -266,7 +266,7 @@ struct held_lock {
 /*
  * Initialization, self-test and debugging-output methods:
  */
-extern void lockdep_info(void);
+extern void lockdep_init(void);
 extern void lockdep_reset(void);
 extern void lockdep_reset_lock(struct lockdep_map *lock);
 extern void lockdep_free_key_range(void *start, unsigned long size);
@@ -406,7 +406,7 @@ static inline void lockdep_on(void)
 # define lock_downgrade(l, i)                  do { } while (0)
 # define lock_set_class(l, n, k, s, i)         do { } while (0)
 # define lock_set_subclass(l, s, i)            do { } while (0)
-# define lockdep_info()                                do { } while (0)
+# define lockdep_init()                                do { } while (0)
 # define lockdep_init_map(lock, name, key, sub) \
                do { (void)(name); (void)(key); } while (0)
 # define lockdep_set_class(lock, key)          do { (void)(key); } while (0)
@@ -532,7 +532,7 @@ do {                                                                \
 
 #endif /* CONFIG_LOCKDEP */
 
-#ifdef CONFIG_TRACE_IRQFLAGS
+#ifdef CONFIG_PROVE_LOCKING
 extern void print_irqtrace_events(struct task_struct *curr);
 #else
 static inline void print_irqtrace_events(struct task_struct *curr)
index 0e6c515..652f602 100644 (file)
@@ -225,6 +225,11 @@ struct mem_cgroup {
         */
        bool use_hierarchy;
 
+       /*
+        * Should the OOM killer kill all belonging tasks, had it kill one?
+        */
+       bool oom_group;
+
        /* protected by memcg_oom_lock */
        bool            oom_lock;
        int             under_oom;
@@ -542,6 +547,9 @@ static inline bool task_in_memcg_oom(struct task_struct *p)
 }
 
 bool mem_cgroup_oom_synchronize(bool wait);
+struct mem_cgroup *mem_cgroup_get_oom_group(struct task_struct *victim,
+                                           struct mem_cgroup *oom_domain);
+void mem_cgroup_print_oom_group(struct mem_cgroup *memcg);
 
 #ifdef CONFIG_MEMCG_SWAP
 extern int do_swap_account;
@@ -1001,6 +1009,16 @@ static inline bool mem_cgroup_oom_synchronize(bool wait)
        return false;
 }
 
+static inline struct mem_cgroup *mem_cgroup_get_oom_group(
+       struct task_struct *victim, struct mem_cgroup *oom_domain)
+{
+       return NULL;
+}
+
+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)
 {
index 4e9828c..34a2822 100644 (file)
@@ -319,6 +319,7 @@ static inline int offline_pages(unsigned long start_pfn, unsigned long nr_pages)
 static inline void remove_memory(int nid, u64 start, u64 size) {}
 #endif /* CONFIG_MEMORY_HOTREMOVE */
 
+extern void __ref free_area_init_core_hotplug(int nid);
 extern int walk_memory_range(unsigned long start_pfn, unsigned long end_pfn,
                void *arg, int (*func)(struct memory_block *, void *));
 extern int add_memory(int nid, u64 start, u64 size);
index 51e6f94..b404a5a 100644 (file)
 #define AS3722_ADC1_CONV_NOTREADY                      BIT(7)
 #define AS3722_ADC1_SOURCE_SELECT_MASK                 0x1F
 
+#define AS3722_CTRL_SEQU1_AC_OK_PWR_ON                 BIT(0)
+
 /* GPIO modes */
 #define AS3722_GPIO_MODE_MASK                          0x07
 #define AS3722_GPIO_MODE_INPUT                         0x00
@@ -391,6 +393,7 @@ struct as3722 {
        unsigned long irq_flags;
        bool en_intern_int_pullup;
        bool en_intern_i2c_pullup;
+       bool en_ac_ok_pwr_on;
        struct regmap_irq_chip_data *irq_data;
 };
 
index 32421df..20949dd 100644 (file)
@@ -147,7 +147,7 @@ struct cros_ec_device {
        bool mkbp_event_supported;
        struct blocking_notifier_head event_notifier;
 
-       struct ec_response_get_next_event event_data;
+       struct ec_response_get_next_event_v1 event_data;
        int event_size;
        u32 host_event_wake_mask;
 };
index f2edd99..6e1ab9b 100644 (file)
@@ -804,6 +804,8 @@ enum ec_feature_code {
        EC_FEATURE_MOTION_SENSE_FIFO = 24,
        /* EC has RTC feature that can be controlled by host commands */
        EC_FEATURE_RTC = 27,
+       /* EC supports CEC commands */
+       EC_FEATURE_CEC = 35,
 };
 
 #define EC_FEATURE_MASK_0(event_code) (1UL << (event_code % 32))
@@ -2078,6 +2080,12 @@ enum ec_mkbp_event {
        /* EC sent a sysrq command */
        EC_MKBP_EVENT_SYSRQ = 6,
 
+       /* Notify the AP that something happened on CEC */
+       EC_MKBP_EVENT_CEC_EVENT = 8,
+
+       /* Send an incoming CEC message to the AP */
+       EC_MKBP_EVENT_CEC_MESSAGE = 9,
+
        /* Number of MKBP events */
        EC_MKBP_EVENT_COUNT,
 };
@@ -2093,12 +2101,28 @@ union ec_response_get_next_data {
        uint32_t   sysrq;
 } __packed;
 
+union ec_response_get_next_data_v1 {
+       uint8_t key_matrix[16];
+       uint32_t host_event;
+       uint32_t buttons;
+       uint32_t switches;
+       uint32_t sysrq;
+       uint32_t cec_events;
+       uint8_t cec_message[16];
+} __packed;
+
 struct ec_response_get_next_event {
        uint8_t event_type;
        /* Followed by event data if any */
        union ec_response_get_next_data data;
 } __packed;
 
+struct ec_response_get_next_event_v1 {
+       uint8_t event_type;
+       /* Followed by event data if any */
+       union ec_response_get_next_data_v1 data;
+} __packed;
+
 /* Bit indices for buttons and switches.*/
 /* Buttons */
 #define EC_MKBP_POWER_BUTTON   0
@@ -2593,14 +2617,18 @@ struct ec_params_current_limit {
 } __packed;
 
 /*
- * Set maximum external power current.
+ * Set maximum external voltage / current.
  */
-#define EC_CMD_EXT_POWER_CURRENT_LIMIT 0xa2
+#define EC_CMD_EXTERNAL_POWER_LIMIT 0x00A2
 
-struct ec_params_ext_power_current_limit {
-       uint32_t limit; /* in mA */
+/* Command v0 is used only on Spring and is obsolete + unsupported */
+struct ec_params_external_power_limit_v1 {
+       uint16_t current_lim; /* in mA, or EC_POWER_LIMIT_NONE to clear limit */
+       uint16_t voltage_lim; /* in mV, or EC_POWER_LIMIT_NONE to clear limit */
 } __packed;
 
+#define EC_POWER_LIMIT_NONE 0xffff
+
 /* Inform the EC when entering a sleep state */
 #define EC_CMD_HOST_SLEEP_EVENT 0xa9
 
@@ -2831,6 +2859,79 @@ struct ec_params_reboot_ec {
 
 /*****************************************************************************/
 /*
+ * HDMI CEC commands
+ *
+ * These commands are for sending and receiving message via HDMI CEC
+ */
+#define EC_MAX_CEC_MSG_LEN 16
+
+/* CEC message from the AP to be written on the CEC bus */
+#define EC_CMD_CEC_WRITE_MSG 0x00B8
+
+/**
+ * struct ec_params_cec_write - Message to write to the CEC bus
+ * @msg: message content to write to the CEC bus
+ */
+struct ec_params_cec_write {
+       uint8_t msg[EC_MAX_CEC_MSG_LEN];
+} __packed;
+
+/* Set various CEC parameters */
+#define EC_CMD_CEC_SET 0x00BA
+
+/**
+ * struct ec_params_cec_set - CEC parameters set
+ * @cmd: parameter type, can be CEC_CMD_ENABLE or CEC_CMD_LOGICAL_ADDRESS
+ * @val: in case cmd is CEC_CMD_ENABLE, this field can be 0 to disable CEC
+ *     or 1 to enable CEC functionality, in case cmd is CEC_CMD_LOGICAL_ADDRESS,
+ *     this field encodes the requested logical address between 0 and 15
+ *     or 0xff to unregister
+ */
+struct ec_params_cec_set {
+       uint8_t cmd; /* enum cec_command */
+       uint8_t val;
+} __packed;
+
+/* Read various CEC parameters */
+#define EC_CMD_CEC_GET 0x00BB
+
+/**
+ * struct ec_params_cec_get - CEC parameters get
+ * @cmd: parameter type, can be CEC_CMD_ENABLE or CEC_CMD_LOGICAL_ADDRESS
+ */
+struct ec_params_cec_get {
+       uint8_t cmd; /* enum cec_command */
+} __packed;
+
+/**
+ * struct ec_response_cec_get - CEC parameters get response
+ * @val: in case cmd was CEC_CMD_ENABLE, this field will 0 if CEC is
+ *     disabled or 1 if CEC functionality is enabled,
+ *     in case cmd was CEC_CMD_LOGICAL_ADDRESS, this will encode the
+ *     configured logical address between 0 and 15 or 0xff if unregistered
+ */
+struct ec_response_cec_get {
+       uint8_t val;
+} __packed;
+
+/* CEC parameters command */
+enum ec_cec_command {
+       /* CEC reading, writing and events enable */
+       CEC_CMD_ENABLE,
+       /* CEC logical address  */
+       CEC_CMD_LOGICAL_ADDRESS,
+};
+
+/* Events from CEC to AP */
+enum mkbp_cec_event {
+       /* Outgoing message was acknowledged by a follower */
+       EC_MKBP_CEC_SEND_OK                     = BIT(0),
+       /* Outgoing message was not acknowledged */
+       EC_MKBP_CEC_SEND_FAILED                 = BIT(1),
+};
+
+/*****************************************************************************/
+/*
  * Special commands
  *
  * These do not follow the normal rules for commands.  See each command for
@@ -2974,6 +3075,12 @@ enum usb_chg_type {
        USB_CHG_TYPE_VBUS,
        USB_CHG_TYPE_UNKNOWN,
 };
+enum usb_power_roles {
+       USB_PD_PORT_POWER_DISCONNECTED,
+       USB_PD_PORT_POWER_SOURCE,
+       USB_PD_PORT_POWER_SINK,
+       USB_PD_PORT_POWER_SINK_NOT_CHARGING,
+};
 
 struct usb_chg_measures {
        uint16_t voltage_max;
@@ -2991,6 +3098,120 @@ struct ec_response_usb_pd_power_info {
        uint32_t max_power;
 } __packed;
 
+struct ec_params_usb_pd_info_request {
+       uint8_t port;
+} __packed;
+
+/* Read USB-PD Device discovery info */
+#define EC_CMD_USB_PD_DISCOVERY 0x0113
+struct ec_params_usb_pd_discovery_entry {
+       uint16_t vid;  /* USB-IF VID */
+       uint16_t pid;  /* USB-IF PID */
+       uint8_t ptype; /* product type (hub,periph,cable,ama) */
+} __packed;
+
+/* Override default charge behavior */
+#define EC_CMD_PD_CHARGE_PORT_OVERRIDE 0x0114
+
+/* Negative port parameters have special meaning */
+enum usb_pd_override_ports {
+       OVERRIDE_DONT_CHARGE = -2,
+       OVERRIDE_OFF = -1,
+       /* [0, CONFIG_USB_PD_PORT_COUNT): Port# */
+};
+
+struct ec_params_charge_port_override {
+       int16_t override_port; /* Override port# */
+} __packed;
+
+/* Read (and delete) one entry of PD event log */
+#define EC_CMD_PD_GET_LOG_ENTRY 0x0115
+
+struct ec_response_pd_log {
+       uint32_t timestamp; /* relative timestamp in milliseconds */
+       uint8_t type;       /* event type : see PD_EVENT_xx below */
+       uint8_t size_port;  /* [7:5] port number [4:0] payload size in bytes */
+       uint16_t data;      /* type-defined data payload */
+       uint8_t payload[0]; /* optional additional data payload: 0..16 bytes */
+} __packed;
+
+/* The timestamp is the microsecond counter shifted to get about a ms. */
+#define PD_LOG_TIMESTAMP_SHIFT 10 /* 1 LSB = 1024us */
+
+#define PD_LOG_SIZE_MASK  0x1f
+#define PD_LOG_PORT_MASK  0xe0
+#define PD_LOG_PORT_SHIFT    5
+#define PD_LOG_PORT_SIZE(port, size) (((port) << PD_LOG_PORT_SHIFT) | \
+                                     ((size) & PD_LOG_SIZE_MASK))
+#define PD_LOG_PORT(size_port) ((size_port) >> PD_LOG_PORT_SHIFT)
+#define PD_LOG_SIZE(size_port) ((size_port) & PD_LOG_SIZE_MASK)
+
+/* PD event log : entry types */
+/* PD MCU events */
+#define PD_EVENT_MCU_BASE       0x00
+#define PD_EVENT_MCU_CHARGE             (PD_EVENT_MCU_BASE+0)
+#define PD_EVENT_MCU_CONNECT            (PD_EVENT_MCU_BASE+1)
+/* Reserved for custom board event */
+#define PD_EVENT_MCU_BOARD_CUSTOM       (PD_EVENT_MCU_BASE+2)
+/* PD generic accessory events */
+#define PD_EVENT_ACC_BASE       0x20
+#define PD_EVENT_ACC_RW_FAIL   (PD_EVENT_ACC_BASE+0)
+#define PD_EVENT_ACC_RW_ERASE  (PD_EVENT_ACC_BASE+1)
+/* PD power supply events */
+#define PD_EVENT_PS_BASE        0x40
+#define PD_EVENT_PS_FAULT      (PD_EVENT_PS_BASE+0)
+/* PD video dongles events */
+#define PD_EVENT_VIDEO_BASE     0x60
+#define PD_EVENT_VIDEO_DP_MODE (PD_EVENT_VIDEO_BASE+0)
+#define PD_EVENT_VIDEO_CODEC   (PD_EVENT_VIDEO_BASE+1)
+/* Returned in the "type" field, when there is no entry available */
+#define PD_EVENT_NO_ENTRY       0xff
+
+/*
+ * PD_EVENT_MCU_CHARGE event definition :
+ * the payload is "struct usb_chg_measures"
+ * the data field contains the port state flags as defined below :
+ */
+/* Port partner is a dual role device */
+#define CHARGE_FLAGS_DUAL_ROLE         BIT(15)
+/* Port is the pending override port */
+#define CHARGE_FLAGS_DELAYED_OVERRIDE  BIT(14)
+/* Port is the override port */
+#define CHARGE_FLAGS_OVERRIDE          BIT(13)
+/* Charger type */
+#define CHARGE_FLAGS_TYPE_SHIFT               3
+#define CHARGE_FLAGS_TYPE_MASK       (0xf << CHARGE_FLAGS_TYPE_SHIFT)
+/* Power delivery role */
+#define CHARGE_FLAGS_ROLE_MASK         (7 <<  0)
+
+/*
+ * PD_EVENT_PS_FAULT data field flags definition :
+ */
+#define PS_FAULT_OCP                          1
+#define PS_FAULT_FAST_OCP                     2
+#define PS_FAULT_OVP                          3
+#define PS_FAULT_DISCH                        4
+
+/*
+ * PD_EVENT_VIDEO_CODEC payload is "struct mcdp_info".
+ */
+struct mcdp_version {
+       uint8_t major;
+       uint8_t minor;
+       uint16_t build;
+} __packed;
+
+struct mcdp_info {
+       uint8_t family[2];
+       uint8_t chipid[2];
+       struct mcdp_version irom;
+       struct mcdp_version fw;
+} __packed;
+
+/* struct mcdp_info field decoding */
+#define MCDP_CHIPID(chipid) ((chipid[0] << 8) | chipid[1])
+#define MCDP_FAMILY(family) ((family[0] << 8) | family[1])
+
 /* Get info about USB-C SS muxes */
 #define EC_CMD_USB_PD_MUX_INFO 0x11a
 
index f3ae65d..71b0915 100644 (file)
 #define DA9063_DRVNAME_RTC             "da9063-rtc"
 #define DA9063_DRVNAME_VIBRATION       "da9063-vibration"
 
-enum da9063_models {
-       PMIC_DA9063 = 0x61,
+#define PMIC_CHIP_ID_DA9063            0x61
+
+enum da9063_type {
+       PMIC_TYPE_DA9063 = 0,
+       PMIC_TYPE_DA9063L,
 };
 
 enum da9063_variant_codes {
@@ -72,13 +75,10 @@ enum da9063_irqs {
        DA9063_IRQ_GPI15,
 };
 
-#define DA9063_IRQ_BASE_OFFSET 0
-#define DA9063_NUM_IRQ         (DA9063_IRQ_GPI15 + 1 - DA9063_IRQ_BASE_OFFSET)
-
 struct da9063 {
        /* Device */
        struct device   *dev;
-       unsigned short  model;
+       enum da9063_type type;
        unsigned char   variant_code;
        unsigned int    flags;
 
@@ -94,7 +94,4 @@ struct da9063 {
 int da9063_device_init(struct da9063 *da9063, unsigned int irq);
 int da9063_irq_init(struct da9063 *da9063);
 
-void da9063_device_exit(struct da9063 *da9063);
-void da9063_irq_exit(struct da9063 *da9063);
-
 #endif /* __MFD_DA9063_CORE_H__ */
diff --git a/include/linux/mfd/madera/core.h b/include/linux/mfd/madera/core.h
new file mode 100644 (file)
index 0000000..c332681
--- /dev/null
@@ -0,0 +1,187 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * MFD internals for Cirrus Logic Madera codecs
+ *
+ * Copyright (C) 2015-2018 Cirrus Logic
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2.
+ */
+
+#ifndef MADERA_CORE_H
+#define MADERA_CORE_H
+
+#include <linux/gpio/consumer.h>
+#include <linux/interrupt.h>
+#include <linux/mfd/madera/pdata.h>
+#include <linux/notifier.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+
+enum madera_type {
+       /* 0 is reserved for indicating failure to identify */
+       CS47L35 = 1,
+       CS47L85 = 2,
+       CS47L90 = 3,
+       CS47L91 = 4,
+       WM1840 = 7,
+};
+
+#define MADERA_MAX_CORE_SUPPLIES       2
+#define MADERA_MAX_GPIOS               40
+
+#define CS47L35_NUM_GPIOS              16
+#define CS47L85_NUM_GPIOS              40
+#define CS47L90_NUM_GPIOS              38
+
+#define MADERA_MAX_MICBIAS             4
+
+/* Notifier events */
+#define MADERA_NOTIFY_VOICE_TRIGGER    0x1
+#define MADERA_NOTIFY_HPDET            0x2
+#define MADERA_NOTIFY_MICDET           0x4
+
+/* GPIO Function Definitions */
+#define MADERA_GP_FN_ALTERNATE         0x00
+#define MADERA_GP_FN_GPIO              0x01
+#define MADERA_GP_FN_DSP_GPIO          0x02
+#define MADERA_GP_FN_IRQ1              0x03
+#define MADERA_GP_FN_IRQ2              0x04
+#define MADERA_GP_FN_FLL1_CLOCK                0x10
+#define MADERA_GP_FN_FLL2_CLOCK                0x11
+#define MADERA_GP_FN_FLL3_CLOCK                0x12
+#define MADERA_GP_FN_FLLAO_CLOCK       0x13
+#define MADERA_GP_FN_FLL1_LOCK         0x18
+#define MADERA_GP_FN_FLL2_LOCK         0x19
+#define MADERA_GP_FN_FLL3_LOCK         0x1A
+#define MADERA_GP_FN_FLLAO_LOCK                0x1B
+#define MADERA_GP_FN_OPCLK_OUT         0x40
+#define MADERA_GP_FN_OPCLK_ASYNC_OUT   0x41
+#define MADERA_GP_FN_PWM1              0x48
+#define MADERA_GP_FN_PWM2              0x49
+#define MADERA_GP_FN_SPDIF_OUT         0x4C
+#define MADERA_GP_FN_HEADPHONE_DET     0x50
+#define MADERA_GP_FN_MIC_DET           0x58
+#define MADERA_GP_FN_DRC1_SIGNAL_DETECT        0x80
+#define MADERA_GP_FN_DRC2_SIGNAL_DETECT        0x81
+#define MADERA_GP_FN_ASRC1_IN1_LOCK    0x88
+#define MADERA_GP_FN_ASRC1_IN2_LOCK    0x89
+#define MADERA_GP_FN_ASRC2_IN1_LOCK    0x8A
+#define MADERA_GP_FN_ASRC2_IN2_LOCK    0x8B
+#define MADERA_GP_FN_DSP_IRQ1          0xA0
+#define MADERA_GP_FN_DSP_IRQ2          0xA1
+#define MADERA_GP_FN_DSP_IRQ3          0xA2
+#define MADERA_GP_FN_DSP_IRQ4          0xA3
+#define MADERA_GP_FN_DSP_IRQ5          0xA4
+#define MADERA_GP_FN_DSP_IRQ6          0xA5
+#define MADERA_GP_FN_DSP_IRQ7          0xA6
+#define MADERA_GP_FN_DSP_IRQ8          0xA7
+#define MADERA_GP_FN_DSP_IRQ9          0xA8
+#define MADERA_GP_FN_DSP_IRQ10         0xA9
+#define MADERA_GP_FN_DSP_IRQ11         0xAA
+#define MADERA_GP_FN_DSP_IRQ12         0xAB
+#define MADERA_GP_FN_DSP_IRQ13         0xAC
+#define MADERA_GP_FN_DSP_IRQ14         0xAD
+#define MADERA_GP_FN_DSP_IRQ15         0xAE
+#define MADERA_GP_FN_DSP_IRQ16         0xAF
+#define MADERA_GP_FN_HPOUT1L_SC                0xB0
+#define MADERA_GP_FN_HPOUT1R_SC                0xB1
+#define MADERA_GP_FN_HPOUT2L_SC                0xB2
+#define MADERA_GP_FN_HPOUT2R_SC                0xB3
+#define MADERA_GP_FN_HPOUT3L_SC                0xB4
+#define MADERA_GP_FN_HPOUT4R_SC                0xB5
+#define MADERA_GP_FN_SPKOUTL_SC                0xB6
+#define MADERA_GP_FN_SPKOUTR_SC                0xB7
+#define MADERA_GP_FN_HPOUT1L_ENA       0xC0
+#define MADERA_GP_FN_HPOUT1R_ENA       0xC1
+#define MADERA_GP_FN_HPOUT2L_ENA       0xC2
+#define MADERA_GP_FN_HPOUT2R_ENA       0xC3
+#define MADERA_GP_FN_HPOUT3L_ENA       0xC4
+#define MADERA_GP_FN_HPOUT4R_ENA       0xC5
+#define MADERA_GP_FN_SPKOUTL_ENA       0xC6
+#define MADERA_GP_FN_SPKOUTR_ENA       0xC7
+#define MADERA_GP_FN_HPOUT1L_DIS       0xD0
+#define MADERA_GP_FN_HPOUT1R_DIS       0xD1
+#define MADERA_GP_FN_HPOUT2L_DIS       0xD2
+#define MADERA_GP_FN_HPOUT2R_DIS       0xD3
+#define MADERA_GP_FN_HPOUT3L_DIS       0xD4
+#define MADERA_GP_FN_HPOUT4R_DIS       0xD5
+#define MADERA_GP_FN_SPKOUTL_DIS       0xD6
+#define MADERA_GP_FN_SPKOUTR_DIS       0xD7
+#define MADERA_GP_FN_SPK_SHUTDOWN      0xE0
+#define MADERA_GP_FN_SPK_OVH_SHUTDOWN  0xE1
+#define MADERA_GP_FN_SPK_OVH_WARN      0xE2
+#define MADERA_GP_FN_TIMER1_STATUS     0x140
+#define MADERA_GP_FN_TIMER2_STATUS     0x141
+#define MADERA_GP_FN_TIMER3_STATUS     0x142
+#define MADERA_GP_FN_TIMER4_STATUS     0x143
+#define MADERA_GP_FN_TIMER5_STATUS     0x144
+#define MADERA_GP_FN_TIMER6_STATUS     0x145
+#define MADERA_GP_FN_TIMER7_STATUS     0x146
+#define MADERA_GP_FN_TIMER8_STATUS     0x147
+#define MADERA_GP_FN_EVENTLOG1_FIFO_STS        0x150
+#define MADERA_GP_FN_EVENTLOG2_FIFO_STS        0x151
+#define MADERA_GP_FN_EVENTLOG3_FIFO_STS        0x152
+#define MADERA_GP_FN_EVENTLOG4_FIFO_STS        0x153
+#define MADERA_GP_FN_EVENTLOG5_FIFO_STS        0x154
+#define MADERA_GP_FN_EVENTLOG6_FIFO_STS        0x155
+#define MADERA_GP_FN_EVENTLOG7_FIFO_STS        0x156
+#define MADERA_GP_FN_EVENTLOG8_FIFO_STS        0x157
+
+struct snd_soc_dapm_context;
+
+/*
+ * struct madera - internal data shared by the set of Madera drivers
+ *
+ * This should not be used by anything except child drivers of the Madera MFD
+ *
+ * @regmap:            pointer to the regmap instance for 16-bit registers
+ * @regmap_32bit:      pointer to the regmap instance for 32-bit registers
+ * @dev:               pointer to the MFD device
+ * @type:              type of codec
+ * @rev:               silicon revision
+ * @type_name:         display name of this codec
+ * @num_core_supplies: number of core supply regulators
+ * @core_supplies:     list of core supplies that are always required
+ * @dcvdd:             pointer to DCVDD regulator
+ * @internal_dcvdd:    true if DCVDD is supplied from the internal LDO1
+ * @pdata:             our pdata
+ * @irq_dev:           the irqchip child driver device
+ * @irq:               host irq number from SPI or I2C configuration
+ * @out_clamp:         indicates output clamp state for each analogue output
+ * @out_shorted:       indicates short circuit state for each analogue output
+ * @hp_ena:            bitflags of enable state for the headphone outputs
+ * @num_micbias:       number of MICBIAS outputs
+ * @num_childbias:     number of child biases for each MICBIAS
+ * @dapm:              pointer to codec driver DAPM context
+ * @notifier:          notifier for signalling events to ASoC machine driver
+ */
+struct madera {
+       struct regmap *regmap;
+       struct regmap *regmap_32bit;
+
+       struct device *dev;
+
+       enum madera_type type;
+       unsigned int rev;
+       const char *type_name;
+
+       int num_core_supplies;
+       struct regulator_bulk_data core_supplies[MADERA_MAX_CORE_SUPPLIES];
+       struct regulator *dcvdd;
+       bool internal_dcvdd;
+
+       struct madera_pdata pdata;
+
+       struct device *irq_dev;
+       int irq;
+
+       unsigned int num_micbias;
+       unsigned int num_childbias[MADERA_MAX_MICBIAS];
+
+       struct snd_soc_dapm_context *dapm;
+
+       struct blocking_notifier_head notifier;
+};
+#endif
diff --git a/include/linux/mfd/madera/pdata.h b/include/linux/mfd/madera/pdata.h
new file mode 100644 (file)
index 0000000..0b311f3
--- /dev/null
@@ -0,0 +1,59 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Platform data for Cirrus Logic Madera codecs
+ *
+ * Copyright (C) 2015-2018 Cirrus Logic
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2.
+ */
+
+#ifndef MADERA_PDATA_H
+#define MADERA_PDATA_H
+
+#include <linux/kernel.h>
+#include <linux/regulator/arizona-ldo1.h>
+#include <linux/regulator/arizona-micsupp.h>
+#include <linux/regulator/machine.h>
+
+#define MADERA_MAX_MICBIAS             4
+#define MADERA_MAX_CHILD_MICBIAS       4
+
+#define MADERA_MAX_GPSW                        2
+
+struct gpio_desc;
+struct pinctrl_map;
+struct madera_irqchip_pdata;
+struct madera_codec_pdata;
+
+/**
+ * struct madera_pdata - Configuration data for Madera devices
+ *
+ * @reset:         GPIO controlling /RESET (NULL = none)
+ * @ldo1:          Substruct of pdata for the LDO1 regulator
+ * @micvdd:        Substruct of pdata for the MICVDD regulator
+ * @irq_flags:     Mode for primary IRQ (defaults to active low)
+ * @gpio_base:     Base GPIO number
+ * @gpio_configs:   Array of GPIO configurations (See Documentation/pinctrl.txt)
+ * @n_gpio_configs: Number of entries in gpio_configs
+ * @gpsw:          General purpose switch mode setting. Depends on the external
+ *                 hardware connected to the switch. (See the SW1_MODE field
+ *                 in the datasheet for the available values for your codec)
+ */
+struct madera_pdata {
+       struct gpio_desc *reset;
+
+       struct arizona_ldo1_pdata ldo1;
+       struct arizona_micsupp_pdata micvdd;
+
+       unsigned int irq_flags;
+       int gpio_base;
+
+       const struct pinctrl_map *gpio_configs;
+       int n_gpio_configs;
+
+       u32 gpsw[MADERA_MAX_GPSW];
+};
+
+#endif
diff --git a/include/linux/mfd/madera/registers.h b/include/linux/mfd/madera/registers.h
new file mode 100644 (file)
index 0000000..977e061
--- /dev/null
@@ -0,0 +1,3968 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Madera register definitions
+ *
+ * Copyright (C) 2015-2018 Cirrus Logic
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2.
+ */
+
+#ifndef MADERA_REGISTERS_H
+#define MADERA_REGISTERS_H
+
+/*
+ * Register Addresses.
+ */
+#define MADERA_SOFTWARE_RESET                          0x00
+#define MADERA_HARDWARE_REVISION                       0x01
+#define MADERA_CTRL_IF_CFG_1                           0x08
+#define MADERA_CTRL_IF_CFG_2                           0x09
+#define MADERA_CTRL_IF_CFG_3                           0x0A
+#define MADERA_WRITE_SEQUENCER_CTRL_0                  0x16
+#define MADERA_WRITE_SEQUENCER_CTRL_1                  0x17
+#define MADERA_WRITE_SEQUENCER_CTRL_2                  0x18
+#define MADERA_TONE_GENERATOR_1                                0x20
+#define MADERA_TONE_GENERATOR_2                                0x21
+#define MADERA_TONE_GENERATOR_3                                0x22
+#define MADERA_TONE_GENERATOR_4                                0x23
+#define MADERA_TONE_GENERATOR_5                                0x24
+#define MADERA_PWM_DRIVE_1                             0x30
+#define MADERA_PWM_DRIVE_2                             0x31
+#define MADERA_PWM_DRIVE_3                             0x32
+#define MADERA_SEQUENCE_CONTROL                                0x41
+#define MADERA_SAMPLE_RATE_SEQUENCE_SELECT_1           0x61
+#define MADERA_SAMPLE_RATE_SEQUENCE_SELECT_2           0x62
+#define MADERA_SAMPLE_RATE_SEQUENCE_SELECT_3           0x63
+#define MADERA_SAMPLE_RATE_SEQUENCE_SELECT_4           0x64
+#define MADERA_ALWAYS_ON_TRIGGERS_SEQUENCE_SELECT_1    0x66
+#define MADERA_ALWAYS_ON_TRIGGERS_SEQUENCE_SELECT_2    0x67
+#define MADERA_HAPTICS_CONTROL_1                       0x90
+#define MADERA_HAPTICS_CONTROL_2                       0x91
+#define MADERA_HAPTICS_PHASE_1_INTENSITY               0x92
+#define MADERA_HAPTICS_PHASE_1_DURATION                        0x93
+#define MADERA_HAPTICS_PHASE_2_INTENSITY               0x94
+#define MADERA_HAPTICS_PHASE_2_DURATION                        0x95
+#define MADERA_HAPTICS_PHASE_3_INTENSITY               0x96
+#define MADERA_HAPTICS_PHASE_3_DURATION                        0x97
+#define MADERA_HAPTICS_STATUS                          0x98
+#define MADERA_COMFORT_NOISE_GENERATOR                 0xA0
+#define MADERA_CLOCK_32K_1                             0x100
+#define MADERA_SYSTEM_CLOCK_1                          0x101
+#define MADERA_SAMPLE_RATE_1                           0x102
+#define MADERA_SAMPLE_RATE_2                           0x103
+#define MADERA_SAMPLE_RATE_3                           0x104
+#define MADERA_SAMPLE_RATE_1_STATUS                    0x10A
+#define MADERA_SAMPLE_RATE_2_STATUS                    0x10B
+#define MADERA_SAMPLE_RATE_3_STATUS                    0x10C
+#define MADERA_ASYNC_CLOCK_1                           0x112
+#define MADERA_ASYNC_SAMPLE_RATE_1                     0x113
+#define MADERA_ASYNC_SAMPLE_RATE_2                     0x114
+#define MADERA_ASYNC_SAMPLE_RATE_1_STATUS              0x11B
+#define MADERA_ASYNC_SAMPLE_RATE_2_STATUS              0x11C
+#define MADERA_DSP_CLOCK_1                             0x120
+#define MADERA_DSP_CLOCK_2                             0x122
+#define MADERA_OUTPUT_SYSTEM_CLOCK                     0x149
+#define MADERA_OUTPUT_ASYNC_CLOCK                      0x14A
+#define MADERA_RATE_ESTIMATOR_1                                0x152
+#define MADERA_RATE_ESTIMATOR_2                                0x153
+#define MADERA_RATE_ESTIMATOR_3                                0x154
+#define MADERA_RATE_ESTIMATOR_4                                0x155
+#define MADERA_RATE_ESTIMATOR_5                                0x156
+#define MADERA_FLL1_CONTROL_1                          0x171
+#define MADERA_FLL1_CONTROL_2                          0x172
+#define MADERA_FLL1_CONTROL_3                          0x173
+#define MADERA_FLL1_CONTROL_4                          0x174
+#define MADERA_FLL1_CONTROL_5                          0x175
+#define MADERA_FLL1_CONTROL_6                          0x176
+#define MADERA_FLL1_LOOP_FILTER_TEST_1                 0x177
+#define MADERA_FLL1_NCO_TEST_0                         0x178
+#define MADERA_FLL1_CONTROL_7                          0x179
+#define MADERA_FLL1_EFS_2                              0x17A
+#define CS47L35_FLL1_SYNCHRONISER_1                    0x17F
+#define CS47L35_FLL1_SYNCHRONISER_2                    0x180
+#define CS47L35_FLL1_SYNCHRONISER_3                    0x181
+#define CS47L35_FLL1_SYNCHRONISER_4                    0x182
+#define CS47L35_FLL1_SYNCHRONISER_5                    0x183
+#define CS47L35_FLL1_SYNCHRONISER_6                    0x184
+#define CS47L35_FLL1_SYNCHRONISER_7                    0x185
+#define CS47L35_FLL1_SPREAD_SPECTRUM                   0x187
+#define CS47L35_FLL1_GPIO_CLOCK                                0x188
+#define MADERA_FLL1_SYNCHRONISER_1                     0x181
+#define MADERA_FLL1_SYNCHRONISER_2                     0x182
+#define MADERA_FLL1_SYNCHRONISER_3                     0x183
+#define MADERA_FLL1_SYNCHRONISER_4                     0x184
+#define MADERA_FLL1_SYNCHRONISER_5                     0x185
+#define MADERA_FLL1_SYNCHRONISER_6                     0x186
+#define MADERA_FLL1_SYNCHRONISER_7                     0x187
+#define MADERA_FLL1_SPREAD_SPECTRUM                    0x189
+#define MADERA_FLL1_GPIO_CLOCK                         0x18A
+#define MADERA_FLL2_CONTROL_1                          0x191
+#define MADERA_FLL2_CONTROL_2                          0x192
+#define MADERA_FLL2_CONTROL_3                          0x193
+#define MADERA_FLL2_CONTROL_4                          0x194
+#define MADERA_FLL2_CONTROL_5                          0x195
+#define MADERA_FLL2_CONTROL_6                          0x196
+#define MADERA_FLL2_LOOP_FILTER_TEST_1                 0x197
+#define MADERA_FLL2_NCO_TEST_0                         0x198
+#define MADERA_FLL2_CONTROL_7                          0x199
+#define MADERA_FLL2_EFS_2                              0x19A
+#define MADERA_FLL2_SYNCHRONISER_1                     0x1A1
+#define MADERA_FLL2_SYNCHRONISER_2                     0x1A2
+#define MADERA_FLL2_SYNCHRONISER_3                     0x1A3
+#define MADERA_FLL2_SYNCHRONISER_4                     0x1A4
+#define MADERA_FLL2_SYNCHRONISER_5                     0x1A5
+#define MADERA_FLL2_SYNCHRONISER_6                     0x1A6
+#define MADERA_FLL2_SYNCHRONISER_7                     0x1A7
+#define MADERA_FLL2_SPREAD_SPECTRUM                    0x1A9
+#define MADERA_FLL2_GPIO_CLOCK                         0x1AA
+#define MADERA_FLL3_CONTROL_1                          0x1B1
+#define MADERA_FLL3_CONTROL_2                          0x1B2
+#define MADERA_FLL3_CONTROL_3                          0x1B3
+#define MADERA_FLL3_CONTROL_4                          0x1B4
+#define MADERA_FLL3_CONTROL_5                          0x1B5
+#define MADERA_FLL3_CONTROL_6                          0x1B6
+#define MADERA_FLL3_LOOP_FILTER_TEST_1                 0x1B7
+#define MADERA_FLL3_NCO_TEST_0                         0x1B8
+#define MADERA_FLL3_CONTROL_7                          0x1B9
+#define MADERA_FLL3_SYNCHRONISER_1                     0x1C1
+#define MADERA_FLL3_SYNCHRONISER_2                     0x1C2
+#define MADERA_FLL3_SYNCHRONISER_3                     0x1C3
+#define MADERA_FLL3_SYNCHRONISER_4                     0x1C4
+#define MADERA_FLL3_SYNCHRONISER_5                     0x1C5
+#define MADERA_FLL3_SYNCHRONISER_6                     0x1C6
+#define MADERA_FLL3_SYNCHRONISER_7                     0x1C7
+#define MADERA_FLL3_SPREAD_SPECTRUM                    0x1C9
+#define MADERA_FLL3_GPIO_CLOCK                         0x1CA
+#define MADERA_FLLAO_CONTROL_1                         0x1D1
+#define MADERA_FLLAO_CONTROL_2                         0x1D2
+#define MADERA_FLLAO_CONTROL_3                         0x1D3
+#define MADERA_FLLAO_CONTROL_4                         0x1D4
+#define MADERA_FLLAO_CONTROL_5                         0x1D5
+#define MADERA_FLLAO_CONTROL_6                         0x1D6
+#define MADERA_FLLAO_CONTROL_7                         0x1D8
+#define MADERA_FLLAO_CONTROL_8                         0x1DA
+#define MADERA_FLLAO_CONTROL_9                         0x1DB
+#define MADERA_FLLAO_CONTROL_10                                0x1DC
+#define MADERA_FLLAO_CONTROL_11                                0x1DD
+#define MADERA_MIC_CHARGE_PUMP_1                       0x200
+#define MADERA_HP_CHARGE_PUMP_8                                0x20B
+#define MADERA_LDO1_CONTROL_1                          0x210
+#define MADERA_LDO2_CONTROL_1                          0x213
+#define MADERA_MIC_BIAS_CTRL_1                         0x218
+#define MADERA_MIC_BIAS_CTRL_2                         0x219
+#define MADERA_MIC_BIAS_CTRL_3                         0x21A
+#define MADERA_MIC_BIAS_CTRL_4                         0x21B
+#define MADERA_MIC_BIAS_CTRL_5                         0x21C
+#define MADERA_MIC_BIAS_CTRL_6                         0x21E
+#define MADERA_HP_CTRL_1L                              0x225
+#define MADERA_HP_CTRL_1R                              0x226
+#define MADERA_HP_CTRL_2L                              0x227
+#define MADERA_HP_CTRL_2R                              0x228
+#define MADERA_HP_CTRL_3L                              0x229
+#define MADERA_HP_CTRL_3R                              0x22A
+#define MADERA_DCS_HP1L_CONTROL                                0x232
+#define MADERA_DCS_HP1R_CONTROL                                0x238
+#define MADERA_EDRE_HP_STEREO_CONTROL                  0x27E
+#define MADERA_ACCESSORY_DETECT_MODE_1                 0x293
+#define MADERA_HEADPHONE_DETECT_0                      0x299
+#define MADERA_HEADPHONE_DETECT_1                      0x29B
+#define MADERA_HEADPHONE_DETECT_2                      0x29C
+#define MADERA_HEADPHONE_DETECT_3                      0x29D
+#define MADERA_HEADPHONE_DETECT_4                      0x29E
+#define MADERA_HEADPHONE_DETECT_5                      0x29F
+#define MADERA_MIC_DETECT_1_CONTROL_0                  0x2A2
+#define MADERA_MIC_DETECT_1_CONTROL_1                  0x2A3
+#define MADERA_MIC_DETECT_1_CONTROL_2                  0x2A4
+#define MADERA_MIC_DETECT_1_CONTROL_3                  0x2A5
+#define MADERA_MIC_DETECT_1_LEVEL_1                    0x2A6
+#define MADERA_MIC_DETECT_1_LEVEL_2                    0x2A7
+#define MADERA_MIC_DETECT_1_LEVEL_3                    0x2A8
+#define MADERA_MIC_DETECT_1_LEVEL_4                    0x2A9
+#define MADERA_MIC_DETECT_1_CONTROL_4                  0x2AB
+#define MADERA_MIC_DETECT_2_CONTROL_0                  0x2B2
+#define MADERA_MIC_DETECT_2_CONTROL_1                  0x2B3
+#define MADERA_MIC_DETECT_2_CONTROL_2                  0x2B4
+#define MADERA_MIC_DETECT_2_CONTROL_3                  0x2B5
+#define MADERA_MIC_DETECT_2_LEVEL_1                    0x2B6
+#define MADERA_MIC_DETECT_2_LEVEL_2                    0x2B7
+#define MADERA_MIC_DETECT_2_LEVEL_3                    0x2B8
+#define MADERA_MIC_DETECT_2_LEVEL_4                    0x2B9
+#define MADERA_MIC_DETECT_2_CONTROL_4                  0x2BB
+#define MADERA_MICD_CLAMP_CONTROL                      0x2C6
+#define MADERA_GP_SWITCH_1                             0x2C8
+#define MADERA_JACK_DETECT_ANALOGUE                    0x2D3
+#define MADERA_INPUT_ENABLES                           0x300
+#define MADERA_INPUT_ENABLES_STATUS                    0x301
+#define MADERA_INPUT_RATE                              0x308
+#define MADERA_INPUT_VOLUME_RAMP                       0x309
+#define MADERA_HPF_CONTROL                             0x30C
+#define MADERA_IN1L_CONTROL                            0x310
+#define MADERA_ADC_DIGITAL_VOLUME_1L                   0x311
+#define MADERA_DMIC1L_CONTROL                          0x312
+#define MADERA_IN1L_RATE_CONTROL                       0x313
+#define MADERA_IN1R_CONTROL                            0x314
+#define MADERA_ADC_DIGITAL_VOLUME_1R                   0x315
+#define MADERA_DMIC1R_CONTROL                          0x316
+#define MADERA_IN1R_RATE_CONTROL                       0x317
+#define MADERA_IN2L_CONTROL                            0x318
+#define MADERA_ADC_DIGITAL_VOLUME_2L                   0x319
+#define MADERA_DMIC2L_CONTROL                          0x31A
+#define MADERA_IN2L_RATE_CONTROL                       0x31B
+#define MADERA_IN2R_CONTROL                            0x31C
+#define MADERA_ADC_DIGITAL_VOLUME_2R                   0x31D
+#define MADERA_DMIC2R_CONTROL                          0x31E
+#define MADERA_IN2R_RATE_CONTROL                       0x31F
+#define MADERA_IN3L_CONTROL                            0x320
+#define MADERA_ADC_DIGITAL_VOLUME_3L                   0x321
+#define MADERA_DMIC3L_CONTROL                          0x322
+#define MADERA_IN3L_RATE_CONTROL                       0x323
+#define MADERA_IN3R_CONTROL                            0x324
+#define MADERA_ADC_DIGITAL_VOLUME_3R                   0x325
+#define MADERA_DMIC3R_CONTROL                          0x326
+#define MADERA_IN3R_RATE_CONTROL                       0x327
+#define MADERA_IN4L_CONTROL                            0x328
+#define MADERA_ADC_DIGITAL_VOLUME_4L                   0x329
+#define MADERA_DMIC4L_CONTROL                          0x32A
+#define MADERA_IN4L_RATE_CONTROL                       0x32B
+#define MADERA_IN4R_CONTROL                            0x32C
+#define MADERA_ADC_DIGITAL_VOLUME_4R                   0x32D
+#define MADERA_DMIC4R_CONTROL                          0x32E
+#define MADERA_IN4R_RATE_CONTROL                       0x32F
+#define MADERA_IN5L_CONTROL                            0x330
+#define MADERA_ADC_DIGITAL_VOLUME_5L                   0x331
+#define MADERA_DMIC5L_CONTROL                          0x332
+#define MADERA_IN5L_RATE_CONTROL                       0x333
+#define MADERA_IN5R_CONTROL                            0x334
+#define MADERA_ADC_DIGITAL_VOLUME_5R                   0x335
+#define MADERA_DMIC5R_CONTROL                          0x336
+#define MADERA_IN5R_RATE_CONTROL                       0x337
+#define MADERA_IN6L_CONTROL                            0x338
+#define MADERA_ADC_DIGITAL_VOLUME_6L                   0x339
+#define MADERA_DMIC6L_CONTROL                          0x33A
+#define MADERA_IN6R_CONTROL                            0x33C
+#define MADERA_ADC_DIGITAL_VOLUME_6R                   0x33D
+#define MADERA_DMIC6R_CONTROL                          0x33E
+#define MADERA_OUTPUT_ENABLES_1                                0x400
+#define MADERA_OUTPUT_STATUS_1                         0x401
+#define MADERA_RAW_OUTPUT_STATUS_1                     0x406
+#define MADERA_OUTPUT_RATE_1                           0x408
+#define MADERA_OUTPUT_VOLUME_RAMP                      0x409
+#define MADERA_OUTPUT_PATH_CONFIG_1L                   0x410
+#define MADERA_DAC_DIGITAL_VOLUME_1L                   0x411
+#define MADERA_OUTPUT_PATH_CONFIG_1                    0x412
+#define MADERA_NOISE_GATE_SELECT_1L                    0x413
+#define MADERA_OUTPUT_PATH_CONFIG_1R                   0x414
+#define MADERA_DAC_DIGITAL_VOLUME_1R                   0x415
+#define MADERA_NOISE_GATE_SELECT_1R                    0x417
+#define MADERA_OUTPUT_PATH_CONFIG_2L                   0x418
+#define MADERA_DAC_DIGITAL_VOLUME_2L                   0x419
+#define MADERA_OUTPUT_PATH_CONFIG_2                    0x41A
+#define MADERA_NOISE_GATE_SELECT_2L                    0x41B
+#define MADERA_OUTPUT_PATH_CONFIG_2R                   0x41C
+#define MADERA_DAC_DIGITAL_VOLUME_2R                   0x41D
+#define MADERA_NOISE_GATE_SELECT_2R                    0x41F
+#define MADERA_OUTPUT_PATH_CONFIG_3L                   0x420
+#define MADERA_DAC_DIGITAL_VOLUME_3L                   0x421
+#define MADERA_NOISE_GATE_SELECT_3L                    0x423
+#define MADERA_OUTPUT_PATH_CONFIG_3R                   0x424
+#define MADERA_DAC_DIGITAL_VOLUME_3R                   0x425
+#define MADERA_NOISE_GATE_SELECT_3R                    0x427
+#define MADERA_OUTPUT_PATH_CONFIG_4L                   0x428
+#define MADERA_DAC_DIGITAL_VOLUME_4L                   0x429
+#define MADERA_NOISE_GATE_SELECT_4L                    0x42B
+#define MADERA_OUTPUT_PATH_CONFIG_4R                   0x42C
+#define MADERA_DAC_DIGITAL_VOLUME_4R                   0x42D
+#define MADERA_NOISE_GATE_SELECT_4R                    0x42F
+#define MADERA_OUTPUT_PATH_CONFIG_5L                   0x430
+#define MADERA_DAC_DIGITAL_VOLUME_5L                   0x431
+#define MADERA_NOISE_GATE_SELECT_5L                    0x433
+#define MADERA_OUTPUT_PATH_CONFIG_5R                   0x434
+#define MADERA_DAC_DIGITAL_VOLUME_5R                   0x435
+#define MADERA_NOISE_GATE_SELECT_5R                    0x437
+#define MADERA_OUTPUT_PATH_CONFIG_6L                   0x438
+#define MADERA_DAC_DIGITAL_VOLUME_6L                   0x439
+#define MADERA_NOISE_GATE_SELECT_6L                    0x43B
+#define MADERA_OUTPUT_PATH_CONFIG_6R                   0x43C
+#define MADERA_DAC_DIGITAL_VOLUME_6R                   0x43D
+#define MADERA_NOISE_GATE_SELECT_6R                    0x43F
+#define MADERA_DRE_ENABLE                              0x440
+#define MADERA_EDRE_ENABLE                             0x448
+#define MADERA_EDRE_MANUAL                             0x44A
+#define MADERA_DAC_AEC_CONTROL_1                       0x450
+#define MADERA_DAC_AEC_CONTROL_2                       0x451
+#define MADERA_NOISE_GATE_CONTROL                      0x458
+#define MADERA_PDM_SPK1_CTRL_1                         0x490
+#define MADERA_PDM_SPK1_CTRL_2                         0x491
+#define MADERA_PDM_SPK2_CTRL_1                         0x492
+#define MADERA_PDM_SPK2_CTRL_2                         0x493
+#define MADERA_HP1_SHORT_CIRCUIT_CTRL                  0x4A0
+#define MADERA_HP2_SHORT_CIRCUIT_CTRL                  0x4A1
+#define MADERA_HP3_SHORT_CIRCUIT_CTRL                  0x4A2
+#define MADERA_HP_TEST_CTRL_1                          0x4A4
+#define MADERA_HP_TEST_CTRL_5                          0x4A8
+#define MADERA_HP_TEST_CTRL_6                          0x4A9
+#define MADERA_AIF1_BCLK_CTRL                          0x500
+#define MADERA_AIF1_TX_PIN_CTRL                                0x501
+#define MADERA_AIF1_RX_PIN_CTRL                                0x502
+#define MADERA_AIF1_RATE_CTRL                          0x503
+#define MADERA_AIF1_FORMAT                             0x504
+#define MADERA_AIF1_RX_BCLK_RATE                       0x506
+#define MADERA_AIF1_FRAME_CTRL_1                       0x507
+#define MADERA_AIF1_FRAME_CTRL_2                       0x508
+#define MADERA_AIF1_FRAME_CTRL_3                       0x509
+#define MADERA_AIF1_FRAME_CTRL_4                       0x50A
+#define MADERA_AIF1_FRAME_CTRL_5                       0x50B
+#define MADERA_AIF1_FRAME_CTRL_6                       0x50C
+#define MADERA_AIF1_FRAME_CTRL_7                       0x50D
+#define MADERA_AIF1_FRAME_CTRL_8                       0x50E
+#define MADERA_AIF1_FRAME_CTRL_9                       0x50F
+#define MADERA_AIF1_FRAME_CTRL_10                      0x510
+#define MADERA_AIF1_FRAME_CTRL_11                      0x511
+#define MADERA_AIF1_FRAME_CTRL_12                      0x512
+#define MADERA_AIF1_FRAME_CTRL_13                      0x513
+#define MADERA_AIF1_FRAME_CTRL_14                      0x514
+#define MADERA_AIF1_FRAME_CTRL_15                      0x515
+#define MADERA_AIF1_FRAME_CTRL_16                      0x516
+#define MADERA_AIF1_FRAME_CTRL_17                      0x517
+#define MADERA_AIF1_FRAME_CTRL_18                      0x518
+#define MADERA_AIF1_TX_ENABLES                         0x519
+#define MADERA_AIF1_RX_ENABLES                         0x51A
+#define MADERA_AIF1_FORCE_WRITE                                0x51B
+#define MADERA_AIF2_BCLK_CTRL                          0x540
+#define MADERA_AIF2_TX_PIN_CTRL                                0x541
+#define MADERA_AIF2_RX_PIN_CTRL                                0x542
+#define MADERA_AIF2_RATE_CTRL                          0x543
+#define MADERA_AIF2_FORMAT                             0x544
+#define MADERA_AIF2_RX_BCLK_RATE                       0x546
+#define MADERA_AIF2_FRAME_CTRL_1                       0x547
+#define MADERA_AIF2_FRAME_CTRL_2                       0x548
+#define MADERA_AIF2_FRAME_CTRL_3                       0x549
+#define MADERA_AIF2_FRAME_CTRL_4                       0x54A
+#define MADERA_AIF2_FRAME_CTRL_5                       0x54B
+#define MADERA_AIF2_FRAME_CTRL_6                       0x54C
+#define MADERA_AIF2_FRAME_CTRL_7                       0x54D
+#define MADERA_AIF2_FRAME_CTRL_8                       0x54E
+#define MADERA_AIF2_FRAME_CTRL_9                       0x54F
+#define MADERA_AIF2_FRAME_CTRL_10                      0x550
+#define MADERA_AIF2_FRAME_CTRL_11                      0x551
+#define MADERA_AIF2_FRAME_CTRL_12                      0x552
+#define MADERA_AIF2_FRAME_CTRL_13                      0x553
+#define MADERA_AIF2_FRAME_CTRL_14                      0x554
+#define MADERA_AIF2_FRAME_CTRL_15                      0x555
+#define MADERA_AIF2_FRAME_CTRL_16                      0x556
+#define MADERA_AIF2_FRAME_CTRL_17                      0x557
+#define MADERA_AIF2_FRAME_CTRL_18                      0x558
+#define MADERA_AIF2_TX_ENABLES                         0x559
+#define MADERA_AIF2_RX_ENABLES                         0x55A
+#define MADERA_AIF2_FORCE_WRITE                                0x55B
+#define MADERA_AIF3_BCLK_CTRL                          0x580
+#define MADERA_AIF3_TX_PIN_CTRL                                0x581
+#define MADERA_AIF3_RX_PIN_CTRL                                0x582
+#define MADERA_AIF3_RATE_CTRL                          0x583
+#define MADERA_AIF3_FORMAT                             0x584
+#define MADERA_AIF3_RX_BCLK_RATE                       0x586
+#define MADERA_AIF3_FRAME_CTRL_1                       0x587
+#define MADERA_AIF3_FRAME_CTRL_2                       0x588
+#define MADERA_AIF3_FRAME_CTRL_3                       0x589
+#define MADERA_AIF3_FRAME_CTRL_4                       0x58A
+#define MADERA_AIF3_FRAME_CTRL_11                      0x591
+#define MADERA_AIF3_FRAME_CTRL_12                      0x592
+#define MADERA_AIF3_TX_ENABLES                         0x599
+#define MADERA_AIF3_RX_ENABLES                         0x59A
+#define MADERA_AIF3_FORCE_WRITE                                0x59B
+#define MADERA_AIF4_BCLK_CTRL                          0x5A0
+#define MADERA_AIF4_TX_PIN_CTRL                                0x5A1
+#define MADERA_AIF4_RX_PIN_CTRL                                0x5A2
+#define MADERA_AIF4_RATE_CTRL                          0x5A3
+#define MADERA_AIF4_FORMAT                             0x5A4
+#define MADERA_AIF4_RX_BCLK_RATE                       0x5A6
+#define MADERA_AIF4_FRAME_CTRL_1                       0x5A7
+#define MADERA_AIF4_FRAME_CTRL_2                       0x5A8
+#define MADERA_AIF4_FRAME_CTRL_3                       0x5A9
+#define MADERA_AIF4_FRAME_CTRL_4                       0x5AA
+#define MADERA_AIF4_FRAME_CTRL_11                      0x5B1
+#define MADERA_AIF4_FRAME_CTRL_12                      0x5B2
+#define MADERA_AIF4_TX_ENABLES                         0x5B9
+#define MADERA_AIF4_RX_ENABLES                         0x5BA
+#define MADERA_AIF4_FORCE_WRITE                                0x5BB
+#define MADERA_SPD1_TX_CONTROL                         0x5C2
+#define MADERA_SPD1_TX_CHANNEL_STATUS_1                        0x5C3
+#define MADERA_SPD1_TX_CHANNEL_STATUS_2                        0x5C4
+#define MADERA_SPD1_TX_CHANNEL_STATUS_3                        0x5C5
+#define MADERA_SLIMBUS_FRAMER_REF_GEAR                 0x5E3
+#define MADERA_SLIMBUS_RATES_1                         0x5E5
+#define MADERA_SLIMBUS_RATES_2                         0x5E6
+#define MADERA_SLIMBUS_RATES_3                         0x5E7
+#define MADERA_SLIMBUS_RATES_4                         0x5E8
+#define MADERA_SLIMBUS_RATES_5                         0x5E9
+#define MADERA_SLIMBUS_RATES_6                         0x5EA
+#define MADERA_SLIMBUS_RATES_7                         0x5EB
+#define MADERA_SLIMBUS_RATES_8                         0x5EC
+#define MADERA_SLIMBUS_RX_CHANNEL_ENABLE               0x5F5
+#define MADERA_SLIMBUS_TX_CHANNEL_ENABLE               0x5F6
+#define MADERA_SLIMBUS_RX_PORT_STATUS                  0x5F7
+#define MADERA_SLIMBUS_TX_PORT_STATUS                  0x5F8
+#define MADERA_PWM1MIX_INPUT_1_SOURCE                  0x640
+#define MADERA_PWM1MIX_INPUT_1_VOLUME                  0x641
+#define MADERA_PWM1MIX_INPUT_2_SOURCE                  0x642
+#define MADERA_PWM1MIX_INPUT_2_VOLUME                  0x643
+#define MADERA_PWM1MIX_INPUT_3_SOURCE                  0x644
+#define MADERA_PWM1MIX_INPUT_3_VOLUME                  0x645
+#define MADERA_PWM1MIX_INPUT_4_SOURCE                  0x646
+#define MADERA_PWM1MIX_INPUT_4_VOLUME                  0x647
+#define MADERA_PWM2MIX_INPUT_1_SOURCE                  0x648
+#define MADERA_PWM2MIX_INPUT_1_VOLUME                  0x649
+#define MADERA_PWM2MIX_INPUT_2_SOURCE                  0x64A
+#define MADERA_PWM2MIX_INPUT_2_VOLUME                  0x64B
+#define MADERA_PWM2MIX_INPUT_3_SOURCE                  0x64C
+#define MADERA_PWM2MIX_INPUT_3_VOLUME                  0x64D
+#define MADERA_PWM2MIX_INPUT_4_SOURCE                  0x64E
+#define MADERA_PWM2MIX_INPUT_4_VOLUME                  0x64F
+#define MADERA_OUT1LMIX_INPUT_1_SOURCE                 0x680
+#define MADERA_OUT1LMIX_INPUT_1_VOLUME                 0x681
+#define MADERA_OUT1LMIX_INPUT_2_SOURCE                 0x682
+#define MADERA_OUT1LMIX_INPUT_2_VOLUME                 0x683
+#define MADERA_OUT1LMIX_INPUT_3_SOURCE                 0x684
+#define MADERA_OUT1LMIX_INPUT_3_VOLUME                 0x685
+#define MADERA_OUT1LMIX_INPUT_4_SOURCE                 0x686
+#define MADERA_OUT1LMIX_INPUT_4_VOLUME                 0x687
+#define MADERA_OUT1RMIX_INPUT_1_SOURCE                 0x688
+#define MADERA_OUT1RMIX_INPUT_1_VOLUME                 0x689
+#define MADERA_OUT1RMIX_INPUT_2_SOURCE                 0x68A
+#define MADERA_OUT1RMIX_INPUT_2_VOLUME                 0x68B
+#define MADERA_OUT1RMIX_INPUT_3_SOURCE                 0x68C
+#define MADERA_OUT1RMIX_INPUT_3_VOLUME                 0x68D
+#define MADERA_OUT1RMIX_INPUT_4_SOURCE                 0x68E
+#define MADERA_OUT1RMIX_INPUT_4_VOLUME                 0x68F
+#define MADERA_OUT2LMIX_INPUT_1_SOURCE                 0x690
+#define MADERA_OUT2LMIX_INPUT_1_VOLUME                 0x691
+#define MADERA_OUT2LMIX_INPUT_2_SOURCE                 0x692
+#define MADERA_OUT2LMIX_INPUT_2_VOLUME                 0x693
+#define MADERA_OUT2LMIX_INPUT_3_SOURCE                 0x694
+#define MADERA_OUT2LMIX_INPUT_3_VOLUME                 0x695
+#define MADERA_OUT2LMIX_INPUT_4_SOURCE                 0x696
+#define MADERA_OUT2LMIX_INPUT_4_VOLUME                 0x697
+#define MADERA_OUT2RMIX_INPUT_1_SOURCE                 0x698
+#define MADERA_OUT2RMIX_INPUT_1_VOLUME                 0x699
+#define MADERA_OUT2RMIX_INPUT_2_SOURCE                 0x69A
+#define MADERA_OUT2RMIX_INPUT_2_VOLUME                 0x69B
+#define MADERA_OUT2RMIX_INPUT_3_SOURCE                 0x69C
+#define MADERA_OUT2RMIX_INPUT_3_VOLUME                 0x69D
+#define MADERA_OUT2RMIX_INPUT_4_SOURCE                 0x69E
+#define MADERA_OUT2RMIX_INPUT_4_VOLUME                 0x69F
+#define MADERA_OUT3LMIX_INPUT_1_SOURCE                 0x6A0
+#define MADERA_OUT3LMIX_INPUT_1_VOLUME                 0x6A1
+#define MADERA_OUT3LMIX_INPUT_2_SOURCE                 0x6A2
+#define MADERA_OUT3LMIX_INPUT_2_VOLUME                 0x6A3
+#define MADERA_OUT3LMIX_INPUT_3_SOURCE                 0x6A4
+#define MADERA_OUT3LMIX_INPUT_3_VOLUME                 0x6A5
+#define MADERA_OUT3LMIX_INPUT_4_SOURCE                 0x6A6
+#define MADERA_OUT3LMIX_INPUT_4_VOLUME                 0x6A7
+#define MADERA_OUT3RMIX_INPUT_1_SOURCE                 0x6A8
+#define MADERA_OUT3RMIX_INPUT_1_VOLUME                 0x6A9
+#define MADERA_OUT3RMIX_INPUT_2_SOURCE                 0x6AA
+#define MADERA_OUT3RMIX_INPUT_2_VOLUME                 0x6AB
+#define MADERA_OUT3RMIX_INPUT_3_SOURCE                 0x6AC
+#define MADERA_OUT3RMIX_INPUT_3_VOLUME                 0x6AD
+#define MADERA_OUT3RMIX_INPUT_4_SOURCE                 0x6AE
+#define MADERA_OUT3RMIX_INPUT_4_VOLUME                 0x6AF
+#define MADERA_OUT4LMIX_INPUT_1_SOURCE                 0x6B0
+#define MADERA_OUT4LMIX_INPUT_1_VOLUME                 0x6B1
+#define MADERA_OUT4LMIX_INPUT_2_SOURCE                 0x6B2
+#define MADERA_OUT4LMIX_INPUT_2_VOLUME                 0x6B3
+#define MADERA_OUT4LMIX_INPUT_3_SOURCE                 0x6B4
+#define MADERA_OUT4LMIX_INPUT_3_VOLUME                 0x6B5
+#define MADERA_OUT4LMIX_INPUT_4_SOURCE                 0x6B6
+#define MADERA_OUT4LMIX_INPUT_4_VOLUME                 0x6B7
+#define MADERA_OUT4RMIX_INPUT_1_SOURCE                 0x6B8
+#define MADERA_OUT4RMIX_INPUT_1_VOLUME                 0x6B9
+#define MADERA_OUT4RMIX_INPUT_2_SOURCE                 0x6BA
+#define MADERA_OUT4RMIX_INPUT_2_VOLUME                 0x6BB
+#define MADERA_OUT4RMIX_INPUT_3_SOURCE                 0x6BC
+#define MADERA_OUT4RMIX_INPUT_3_VOLUME                 0x6BD
+#define MADERA_OUT4RMIX_INPUT_4_SOURCE                 0x6BE
+#define MADERA_OUT4RMIX_INPUT_4_VOLUME                 0x6BF
+#define MADERA_OUT5LMIX_INPUT_1_SOURCE                 0x6C0
+#define MADERA_OUT5LMIX_INPUT_1_VOLUME                 0x6C1
+#define MADERA_OUT5LMIX_INPUT_2_SOURCE                 0x6C2
+#define MADERA_OUT5LMIX_INPUT_2_VOLUME                 0x6C3
+#define MADERA_OUT5LMIX_INPUT_3_SOURCE                 0x6C4
+#define MADERA_OUT5LMIX_INPUT_3_VOLUME                 0x6C5
+#define MADERA_OUT5LMIX_INPUT_4_SOURCE                 0x6C6
+#define MADERA_OUT5LMIX_INPUT_4_VOLUME                 0x6C7
+#define MADERA_OUT5RMIX_INPUT_1_SOURCE                 0x6C8
+#define MADERA_OUT5RMIX_INPUT_1_VOLUME                 0x6C9
+#define MADERA_OUT5RMIX_INPUT_2_SOURCE                 0x6CA
+#define MADERA_OUT5RMIX_INPUT_2_VOLUME                 0x6CB
+#define MADERA_OUT5RMIX_INPUT_3_SOURCE                 0x6CC
+#define MADERA_OUT5RMIX_INPUT_3_VOLUME                 0x6CD
+#define MADERA_OUT5RMIX_INPUT_4_SOURCE                 0x6CE
+#define MADERA_OUT5RMIX_INPUT_4_VOLUME                 0x6CF
+#define MADERA_OUT6LMIX_INPUT_1_SOURCE                 0x6D0
+#define MADERA_OUT6LMIX_INPUT_1_VOLUME                 0x6D1
+#define MADERA_OUT6LMIX_INPUT_2_SOURCE                 0x6D2
+#define MADERA_OUT6LMIX_INPUT_2_VOLUME                 0x6D3
+#define MADERA_OUT6LMIX_INPUT_3_SOURCE                 0x6D4
+#define MADERA_OUT6LMIX_INPUT_3_VOLUME                 0x6D5
+#define MADERA_OUT6LMIX_INPUT_4_SOURCE                 0x6D6
+#define MADERA_OUT6LMIX_INPUT_4_VOLUME                 0x6D7
+#define MADERA_OUT6RMIX_INPUT_1_SOURCE                 0x6D8
+#define MADERA_OUT6RMIX_INPUT_1_VOLUME                 0x6D9
+#define MADERA_OUT6RMIX_INPUT_2_SOURCE                 0x6DA
+#define MADERA_OUT6RMIX_INPUT_2_VOLUME                 0x6DB
+#define MADERA_OUT6RMIX_INPUT_3_SOURCE                 0x6DC
+#define MADERA_OUT6RMIX_INPUT_3_VOLUME                 0x6DD
+#define MADERA_OUT6RMIX_INPUT_4_SOURCE                 0x6DE
+#define MADERA_OUT6RMIX_INPUT_4_VOLUME                 0x6DF
+#define MADERA_AIF1TX1MIX_INPUT_1_SOURCE               0x700
+#define MADERA_AIF1TX1MIX_INPUT_1_VOLUME               0x701
+#define MADERA_AIF1TX1MIX_INPUT_2_SOURCE               0x702
+#define MADERA_AIF1TX1MIX_INPUT_2_VOLUME               0x703
+#define MADERA_AIF1TX1MIX_INPUT_3_SOURCE               0x704
+#define MADERA_AIF1TX1MIX_INPUT_3_VOLUME               0x705
+#define MADERA_AIF1TX1MIX_INPUT_4_SOURCE               0x706
+#define MADERA_AIF1TX1MIX_INPUT_4_VOLUME               0x707
+#define MADERA_AIF1TX2MIX_INPUT_1_SOURCE               0x708
+#define MADERA_AIF1TX2MIX_INPUT_1_VOLUME               0x709
+#define MADERA_AIF1TX2MIX_INPUT_2_SOURCE               0x70A
+#define MADERA_AIF1TX2MIX_INPUT_2_VOLUME               0x70B
+#define MADERA_AIF1TX2MIX_INPUT_3_SOURCE               0x70C
+#define MADERA_AIF1TX2MIX_INPUT_3_VOLUME               0x70D
+#define MADERA_AIF1TX2MIX_INPUT_4_SOURCE               0x70E
+#define MADERA_AIF1TX2MIX_INPUT_4_VOLUME               0x70F
+#define MADERA_AIF1TX3MIX_INPUT_1_SOURCE               0x710
+#define MADERA_AIF1TX3MIX_INPUT_1_VOLUME               0x711
+#define MADERA_AIF1TX3MIX_INPUT_2_SOURCE               0x712
+#define MADERA_AIF1TX3MIX_INPUT_2_VOLUME               0x713
+#define MADERA_AIF1TX3MIX_INPUT_3_SOURCE               0x714
+#define MADERA_AIF1TX3MIX_INPUT_3_VOLUME               0x715
+#define MADERA_AIF1TX3MIX_INPUT_4_SOURCE               0x716
+#define MADERA_AIF1TX3MIX_INPUT_4_VOLUME               0x717
+#define MADERA_AIF1TX4MIX_INPUT_1_SOURCE               0x718
+#define MADERA_AIF1TX4MIX_INPUT_1_VOLUME               0x719
+#define MADERA_AIF1TX4MIX_INPUT_2_SOURCE               0x71A
+#define MADERA_AIF1TX4MIX_INPUT_2_VOLUME               0x71B
+#define MADERA_AIF1TX4MIX_INPUT_3_SOURCE               0x71C
+#define MADERA_AIF1TX4MIX_INPUT_3_VOLUME               0x71D
+#define MADERA_AIF1TX4MIX_INPUT_4_SOURCE               0x71E
+#define MADERA_AIF1TX4MIX_INPUT_4_VOLUME               0x71F
+#define MADERA_AIF1TX5MIX_INPUT_1_SOURCE               0x720
+#define MADERA_AIF1TX5MIX_INPUT_1_VOLUME               0x721
+#define MADERA_AIF1TX5MIX_INPUT_2_SOURCE               0x722
+#define MADERA_AIF1TX5MIX_INPUT_2_VOLUME               0x723
+#define MADERA_AIF1TX5MIX_INPUT_3_SOURCE               0x724
+#define MADERA_AIF1TX5MIX_INPUT_3_VOLUME               0x725
+#define MADERA_AIF1TX5MIX_INPUT_4_SOURCE               0x726
+#define MADERA_AIF1TX5MIX_INPUT_4_VOLUME               0x727
+#define MADERA_AIF1TX6MIX_INPUT_1_SOURCE               0x728
+#define MADERA_AIF1TX6MIX_INPUT_1_VOLUME               0x729
+#define MADERA_AIF1TX6MIX_INPUT_2_SOURCE               0x72A
+#define MADERA_AIF1TX6MIX_INPUT_2_VOLUME               0x72B
+#define MADERA_AIF1TX6MIX_INPUT_3_SOURCE               0x72C
+#define MADERA_AIF1TX6MIX_INPUT_3_VOLUME               0x72D
+#define MADERA_AIF1TX6MIX_INPUT_4_SOURCE               0x72E
+#define MADERA_AIF1TX6MIX_INPUT_4_VOLUME               0x72F
+#define MADERA_AIF1TX7MIX_INPUT_1_SOURCE               0x730
+#define MADERA_AIF1TX7MIX_INPUT_1_VOLUME               0x731
+#define MADERA_AIF1TX7MIX_INPUT_2_SOURCE               0x732
+#define MADERA_AIF1TX7MIX_INPUT_2_VOLUME               0x733
+#define MADERA_AIF1TX7MIX_INPUT_3_SOURCE               0x734
+#define MADERA_AIF1TX7MIX_INPUT_3_VOLUME               0x735
+#define MADERA_AIF1TX7MIX_INPUT_4_SOURCE               0x736
+#define MADERA_AIF1TX7MIX_INPUT_4_VOLUME               0x737
+#define MADERA_AIF1TX8MIX_INPUT_1_SOURCE               0x738
+#define MADERA_AIF1TX8MIX_INPUT_1_VOLUME               0x739
+#define MADERA_AIF1TX8MIX_INPUT_2_SOURCE               0x73A
+#define MADERA_AIF1TX8MIX_INPUT_2_VOLUME               0x73B
+#define MADERA_AIF1TX8MIX_INPUT_3_SOURCE               0x73C
+#define MADERA_AIF1TX8MIX_INPUT_3_VOLUME               0x73D
+#define MADERA_AIF1TX8MIX_INPUT_4_SOURCE               0x73E
+#define MADERA_AIF1TX8MIX_INPUT_4_VOLUME               0x73F
+#define MADERA_AIF2TX1MIX_INPUT_1_SOURCE               0x740
+#define MADERA_AIF2TX1MIX_INPUT_1_VOLUME               0x741
+#define MADERA_AIF2TX1MIX_INPUT_2_SOURCE               0x742
+#define MADERA_AIF2TX1MIX_INPUT_2_VOLUME               0x743
+#define MADERA_AIF2TX1MIX_INPUT_3_SOURCE               0x744
+#define MADERA_AIF2TX1MIX_INPUT_3_VOLUME               0x745
+#define MADERA_AIF2TX1MIX_INPUT_4_SOURCE               0x746
+#define MADERA_AIF2TX1MIX_INPUT_4_VOLUME               0x747
+#define MADERA_AIF2TX2MIX_INPUT_1_SOURCE               0x748
+#define MADERA_AIF2TX2MIX_INPUT_1_VOLUME               0x749
+#define MADERA_AIF2TX2MIX_INPUT_2_SOURCE               0x74A
+#define MADERA_AIF2TX2MIX_INPUT_2_VOLUME               0x74B
+#define MADERA_AIF2TX2MIX_INPUT_3_SOURCE               0x74C
+#define MADERA_AIF2TX2MIX_INPUT_3_VOLUME               0x74D
+#define MADERA_AIF2TX2MIX_INPUT_4_SOURCE               0x74E
+#define MADERA_AIF2TX2MIX_INPUT_4_VOLUME               0x74F
+#define MADERA_AIF2TX3MIX_INPUT_1_SOURCE               0x750
+#define MADERA_AIF2TX3MIX_INPUT_1_VOLUME               0x751
+#define MADERA_AIF2TX3MIX_INPUT_2_SOURCE               0x752
+#define MADERA_AIF2TX3MIX_INPUT_2_VOLUME               0x753
+#define MADERA_AIF2TX3MIX_INPUT_3_SOURCE               0x754
+#define MADERA_AIF2TX3MIX_INPUT_3_VOLUME               0x755
+#define MADERA_AIF2TX3MIX_INPUT_4_SOURCE               0x756
+#define MADERA_AIF2TX3MIX_INPUT_4_VOLUME               0x757
+#define MADERA_AIF2TX4MIX_INPUT_1_SOURCE               0x758
+#define MADERA_AIF2TX4MIX_INPUT_1_VOLUME               0x759
+#define MADERA_AIF2TX4MIX_INPUT_2_SOURCE               0x75A
+#define MADERA_AIF2TX4MIX_INPUT_2_VOLUME               0x75B
+#define MADERA_AIF2TX4MIX_INPUT_3_SOURCE               0x75C
+#define MADERA_AIF2TX4MIX_INPUT_3_VOLUME               0x75D
+#define MADERA_AIF2TX4MIX_INPUT_4_SOURCE               0x75E
+#define MADERA_AIF2TX4MIX_INPUT_4_VOLUME               0x75F
+#define MADERA_AIF2TX5MIX_INPUT_1_SOURCE               0x760
+#define MADERA_AIF2TX5MIX_INPUT_1_VOLUME               0x761
+#define MADERA_AIF2TX5MIX_INPUT_2_SOURCE               0x762
+#define MADERA_AIF2TX5MIX_INPUT_2_VOLUME               0x763
+#define MADERA_AIF2TX5MIX_INPUT_3_SOURCE               0x764
+#define MADERA_AIF2TX5MIX_INPUT_3_VOLUME               0x765
+#define MADERA_AIF2TX5MIX_INPUT_4_SOURCE               0x766
+#define MADERA_AIF2TX5MIX_INPUT_4_VOLUME               0x767
+#define MADERA_AIF2TX6MIX_INPUT_1_SOURCE               0x768
+#define MADERA_AIF2TX6MIX_INPUT_1_VOLUME               0x769
+#define MADERA_AIF2TX6MIX_INPUT_2_SOURCE               0x76A
+#define MADERA_AIF2TX6MIX_INPUT_2_VOLUME               0x76B
+#define MADERA_AIF2TX6MIX_INPUT_3_SOURCE               0x76C
+#define MADERA_AIF2TX6MIX_INPUT_3_VOLUME               0x76D
+#define MADERA_AIF2TX6MIX_INPUT_4_SOURCE               0x76E
+#define MADERA_AIF2TX6MIX_INPUT_4_VOLUME               0x76F
+#define MADERA_AIF2TX7MIX_INPUT_1_SOURCE               0x770
+#define MADERA_AIF2TX7MIX_INPUT_1_VOLUME               0x771
+#define MADERA_AIF2TX7MIX_INPUT_2_SOURCE               0x772
+#define MADERA_AIF2TX7MIX_INPUT_2_VOLUME               0x773
+#define MADERA_AIF2TX7MIX_INPUT_3_SOURCE               0x774
+#define MADERA_AIF2TX7MIX_INPUT_3_VOLUME               0x775
+#define MADERA_AIF2TX7MIX_INPUT_4_SOURCE               0x776
+#define MADERA_AIF2TX7MIX_INPUT_4_VOLUME               0x777
+#define MADERA_AIF2TX8MIX_INPUT_1_SOURCE               0x778
+#define MADERA_AIF2TX8MIX_INPUT_1_VOLUME               0x779
+#define MADERA_AIF2TX8MIX_INPUT_2_SOURCE               0x77A
+#define MADERA_AIF2TX8MIX_INPUT_2_VOLUME               0x77B
+#define MADERA_AIF2TX8MIX_INPUT_3_SOURCE               0x77C
+#define MADERA_AIF2TX8MIX_INPUT_3_VOLUME               0x77D
+#define MADERA_AIF2TX8MIX_INPUT_4_SOURCE               0x77E
+#define MADERA_AIF2TX8MIX_INPUT_4_VOLUME               0x77F
+#define MADERA_AIF3TX1MIX_INPUT_1_SOURCE               0x780
+#define MADERA_AIF3TX1MIX_INPUT_1_VOLUME               0x781
+#define MADERA_AIF3TX1MIX_INPUT_2_SOURCE               0x782
+#define MADERA_AIF3TX1MIX_INPUT_2_VOLUME               0x783
+#define MADERA_AIF3TX1MIX_INPUT_3_SOURCE               0x784
+#define MADERA_AIF3TX1MIX_INPUT_3_VOLUME               0x785
+#define MADERA_AIF3TX1MIX_INPUT_4_SOURCE               0x786
+#define MADERA_AIF3TX1MIX_INPUT_4_VOLUME               0x787
+#define MADERA_AIF3TX2MIX_INPUT_1_SOURCE               0x788
+#define MADERA_AIF3TX2MIX_INPUT_1_VOLUME               0x789
+#define MADERA_AIF3TX2MIX_INPUT_2_SOURCE               0x78A
+#define MADERA_AIF3TX2MIX_INPUT_2_VOLUME               0x78B
+#define MADERA_AIF3TX2MIX_INPUT_3_SOURCE               0x78C
+#define MADERA_AIF3TX2MIX_INPUT_3_VOLUME               0x78D
+#define MADERA_AIF3TX2MIX_INPUT_4_SOURCE               0x78E
+#define MADERA_AIF3TX2MIX_INPUT_4_VOLUME               0x78F
+#define MADERA_AIF4TX1MIX_INPUT_1_SOURCE               0x7A0
+#define MADERA_AIF4TX1MIX_INPUT_1_VOLUME               0x7A1
+#define MADERA_AIF4TX1MIX_INPUT_2_SOURCE               0x7A2
+#define MADERA_AIF4TX1MIX_INPUT_2_VOLUME               0x7A3
+#define MADERA_AIF4TX1MIX_INPUT_3_SOURCE               0x7A4
+#define MADERA_AIF4TX1MIX_INPUT_3_VOLUME               0x7A5
+#define MADERA_AIF4TX1MIX_INPUT_4_SOURCE               0x7A6
+#define MADERA_AIF4TX1MIX_INPUT_4_VOLUME               0x7A7
+#define MADERA_AIF4TX2MIX_INPUT_1_SOURCE               0x7A8
+#define MADERA_AIF4TX2MIX_INPUT_1_VOLUME               0x7A9
+#define MADERA_AIF4TX2MIX_INPUT_2_SOURCE               0x7AA
+#define MADERA_AIF4TX2MIX_INPUT_2_VOLUME               0x7AB
+#define MADERA_AIF4TX2MIX_INPUT_3_SOURCE               0x7AC
+#define MADERA_AIF4TX2MIX_INPUT_3_VOLUME               0x7AD
+#define MADERA_AIF4TX2MIX_INPUT_4_SOURCE               0x7AE
+#define MADERA_AIF4TX2MIX_INPUT_4_VOLUME               0x7AF
+#define MADERA_SLIMTX1MIX_INPUT_1_SOURCE               0x7C0
+#define MADERA_SLIMTX1MIX_INPUT_1_VOLUME               0x7C1
+#define MADERA_SLIMTX1MIX_INPUT_2_SOURCE               0x7C2
+#define MADERA_SLIMTX1MIX_INPUT_2_VOLUME               0x7C3
+#define MADERA_SLIMTX1MIX_INPUT_3_SOURCE               0x7C4
+#define MADERA_SLIMTX1MIX_INPUT_3_VOLUME               0x7C5
+#define MADERA_SLIMTX1MIX_INPUT_4_SOURCE               0x7C6
+#define MADERA_SLIMTX1MIX_INPUT_4_VOLUME               0x7C7
+#define MADERA_SLIMTX2MIX_INPUT_1_SOURCE               0x7C8
+#define MADERA_SLIMTX2MIX_INPUT_1_VOLUME               0x7C9
+#define MADERA_SLIMTX2MIX_INPUT_2_SOURCE               0x7CA
+#define MADERA_SLIMTX2MIX_INPUT_2_VOLUME               0x7CB
+#define MADERA_SLIMTX2MIX_INPUT_3_SOURCE               0x7CC
+#define MADERA_SLIMTX2MIX_INPUT_3_VOLUME               0x7CD
+#define MADERA_SLIMTX2MIX_INPUT_4_SOURCE               0x7CE
+#define MADERA_SLIMTX2MIX_INPUT_4_VOLUME               0x7CF
+#define MADERA_SLIMTX3MIX_INPUT_1_SOURCE               0x7D0
+#define MADERA_SLIMTX3MIX_INPUT_1_VOLUME               0x7D1
+#define MADERA_SLIMTX3MIX_INPUT_2_SOURCE               0x7D2
+#define MADERA_SLIMTX3MIX_INPUT_2_VOLUME               0x7D3
+#define MADERA_SLIMTX3MIX_INPUT_3_SOURCE               0x7D4
+#define MADERA_SLIMTX3MIX_INPUT_3_VOLUME               0x7D5
+#define MADERA_SLIMTX3MIX_INPUT_4_SOURCE               0x7D6
+#define MADERA_SLIMTX3MIX_INPUT_4_VOLUME               0x7D7
+#define MADERA_SLIMTX4MIX_INPUT_1_SOURCE               0x7D8
+#define MADERA_SLIMTX4MIX_INPUT_1_VOLUME               0x7D9
+#define MADERA_SLIMTX4MIX_INPUT_2_SOURCE               0x7DA
+#define MADERA_SLIMTX4MIX_INPUT_2_VOLUME               0x7DB
+#define MADERA_SLIMTX4MIX_INPUT_3_SOURCE               0x7DC
+#define MADERA_SLIMTX4MIX_INPUT_3_VOLUME               0x7DD
+#define MADERA_SLIMTX4MIX_INPUT_4_SOURCE               0x7DE
+#define MADERA_SLIMTX4MIX_INPUT_4_VOLUME               0x7DF
+#define MADERA_SLIMTX5MIX_INPUT_1_SOURCE               0x7E0
+#define MADERA_SLIMTX5MIX_INPUT_1_VOLUME               0x7E1
+#define MADERA_SLIMTX5MIX_INPUT_2_SOURCE               0x7E2
+#define MADERA_SLIMTX5MIX_INPUT_2_VOLUME               0x7E3
+#define MADERA_SLIMTX5MIX_INPUT_3_SOURCE               0x7E4
+#define MADERA_SLIMTX5MIX_INPUT_3_VOLUME               0x7E5
+#define MADERA_SLIMTX5MIX_INPUT_4_SOURCE               0x7E6
+#define MADERA_SLIMTX5MIX_INPUT_4_VOLUME               0x7E7
+#define MADERA_SLIMTX6MIX_INPUT_1_SOURCE               0x7E8
+#define MADERA_SLIMTX6MIX_INPUT_1_VOLUME               0x7E9
+#define MADERA_SLIMTX6MIX_INPUT_2_SOURCE               0x7EA
+#define MADERA_SLIMTX6MIX_INPUT_2_VOLUME               0x7EB
+#define MADERA_SLIMTX6MIX_INPUT_3_SOURCE               0x7EC
+#define MADERA_SLIMTX6MIX_INPUT_3_VOLUME               0x7ED
+#define MADERA_SLIMTX6MIX_INPUT_4_SOURCE               0x7EE
+#define MADERA_SLIMTX6MIX_INPUT_4_VOLUME               0x7EF
+#define MADERA_SLIMTX7MIX_INPUT_1_SOURCE               0x7F0
+#define MADERA_SLIMTX7MIX_INPUT_1_VOLUME               0x7F1
+#define MADERA_SLIMTX7MIX_INPUT_2_SOURCE               0x7F2
+#define MADERA_SLIMTX7MIX_INPUT_2_VOLUME               0x7F3
+#define MADERA_SLIMTX7MIX_INPUT_3_SOURCE               0x7F4
+#define MADERA_SLIMTX7MIX_INPUT_3_VOLUME               0x7F5
+#define MADERA_SLIMTX7MIX_INPUT_4_SOURCE               0x7F6
+#define MADERA_SLIMTX7MIX_INPUT_4_VOLUME               0x7F7
+#define MADERA_SLIMTX8MIX_INPUT_1_SOURCE               0x7F8
+#define MADERA_SLIMTX8MIX_INPUT_1_VOLUME               0x7F9
+#define MADERA_SLIMTX8MIX_INPUT_2_SOURCE               0x7FA
+#define MADERA_SLIMTX8MIX_INPUT_2_VOLUME               0x7FB
+#define MADERA_SLIMTX8MIX_INPUT_3_SOURCE               0x7FC
+#define MADERA_SLIMTX8MIX_INPUT_3_VOLUME               0x7FD
+#define MADERA_SLIMTX8MIX_INPUT_4_SOURCE               0x7FE
+#define MADERA_SLIMTX8MIX_INPUT_4_VOLUME               0x7FF
+#define MADERA_SPDIF1TX1MIX_INPUT_1_SOURCE             0x800
+#define MADERA_SPDIF1TX1MIX_INPUT_1_VOLUME             0x801
+#define MADERA_SPDIF1TX2MIX_INPUT_1_SOURCE             0x808
+#define MADERA_SPDIF1TX2MIX_INPUT_1_VOLUME             0x809
+#define MADERA_EQ1MIX_INPUT_1_SOURCE                   0x880
+#define MADERA_EQ1MIX_INPUT_1_VOLUME                   0x881
+#define MADERA_EQ1MIX_INPUT_2_SOURCE                   0x882
+#define MADERA_EQ1MIX_INPUT_2_VOLUME                   0x883
+#define MADERA_EQ1MIX_INPUT_3_SOURCE                   0x884
+#define MADERA_EQ1MIX_INPUT_3_VOLUME                   0x885
+#define MADERA_EQ1MIX_INPUT_4_SOURCE                   0x886
+#define MADERA_EQ1MIX_INPUT_4_VOLUME                   0x887
+#define MADERA_EQ2MIX_INPUT_1_SOURCE                   0x888
+#define MADERA_EQ2MIX_INPUT_1_VOLUME                   0x889
+#define MADERA_EQ2MIX_INPUT_2_SOURCE                   0x88A
+#define MADERA_EQ2MIX_INPUT_2_VOLUME                   0x88B
+#define MADERA_EQ2MIX_INPUT_3_SOURCE                   0x88C
+#define MADERA_EQ2MIX_INPUT_3_VOLUME                   0x88D
+#define MADERA_EQ2MIX_INPUT_4_SOURCE                   0x88E
+#define MADERA_EQ2MIX_INPUT_4_VOLUME                   0x88F
+#define MADERA_EQ3MIX_INPUT_1_SOURCE                   0x890
+#define MADERA_EQ3MIX_INPUT_1_VOLUME                   0x891
+#define MADERA_EQ3MIX_INPUT_2_SOURCE                   0x892
+#define MADERA_EQ3MIX_INPUT_2_VOLUME                   0x893
+#define MADERA_EQ3MIX_INPUT_3_SOURCE                   0x894
+#define MADERA_EQ3MIX_INPUT_3_VOLUME                   0x895
+#define MADERA_EQ3MIX_INPUT_4_SOURCE                   0x896
+#define MADERA_EQ3MIX_INPUT_4_VOLUME                   0x897
+#define MADERA_EQ4MIX_INPUT_1_SOURCE                   0x898
+#define MADERA_EQ4MIX_INPUT_1_VOLUME                   0x899
+#define MADERA_EQ4MIX_INPUT_2_SOURCE                   0x89A
+#define MADERA_EQ4MIX_INPUT_2_VOLUME                   0x89B
+#define MADERA_EQ4MIX_INPUT_3_SOURCE                   0x89C
+#define MADERA_EQ4MIX_INPUT_3_VOLUME                   0x89D
+#define MADERA_EQ4MIX_INPUT_4_SOURCE                   0x89E
+#define MADERA_EQ4MIX_INPUT_4_VOLUME                   0x89F
+#define MADERA_DRC1LMIX_INPUT_1_SOURCE                 0x8C0
+#define MADERA_DRC1LMIX_INPUT_1_VOLUME                 0x8C1
+#define MADERA_DRC1LMIX_INPUT_2_SOURCE                 0x8C2
+#define MADERA_DRC1LMIX_INPUT_2_VOLUME                 0x8C3
+#define MADERA_DRC1LMIX_INPUT_3_SOURCE                 0x8C4
+#define MADERA_DRC1LMIX_INPUT_3_VOLUME                 0x8C5
+#define MADERA_DRC1LMIX_INPUT_4_SOURCE                 0x8C6
+#define MADERA_DRC1LMIX_INPUT_4_VOLUME                 0x8C7
+#define MADERA_DRC1RMIX_INPUT_1_SOURCE                 0x8C8
+#define MADERA_DRC1RMIX_INPUT_1_VOLUME                 0x8C9
+#define MADERA_DRC1RMIX_INPUT_2_SOURCE                 0x8CA
+#define MADERA_DRC1RMIX_INPUT_2_VOLUME                 0x8CB
+#define MADERA_DRC1RMIX_INPUT_3_SOURCE                 0x8CC
+#define MADERA_DRC1RMIX_INPUT_3_VOLUME                 0x8CD
+#define MADERA_DRC1RMIX_INPUT_4_SOURCE                 0x8CE
+#define MADERA_DRC1RMIX_INPUT_4_VOLUME                 0x8CF
+#define MADERA_DRC2LMIX_INPUT_1_SOURCE                 0x8D0
+#define MADERA_DRC2LMIX_INPUT_1_VOLUME                 0x8D1
+#define MADERA_DRC2LMIX_INPUT_2_SOURCE                 0x8D2
+#define MADERA_DRC2LMIX_INPUT_2_VOLUME                 0x8D3
+#define MADERA_DRC2LMIX_INPUT_3_SOURCE                 0x8D4
+#define MADERA_DRC2LMIX_INPUT_3_VOLUME                 0x8D5
+#define MADERA_DRC2LMIX_INPUT_4_SOURCE                 0x8D6
+#define MADERA_DRC2LMIX_INPUT_4_VOLUME                 0x8D7
+#define MADERA_DRC2RMIX_INPUT_1_SOURCE                 0x8D8
+#define MADERA_DRC2RMIX_INPUT_1_VOLUME                 0x8D9
+#define MADERA_DRC2RMIX_INPUT_2_SOURCE                 0x8DA
+#define MADERA_DRC2RMIX_INPUT_2_VOLUME                 0x8DB
+#define MADERA_DRC2RMIX_INPUT_3_SOURCE                 0x8DC
+#define MADERA_DRC2RMIX_INPUT_3_VOLUME                 0x8DD
+#define MADERA_DRC2RMIX_INPUT_4_SOURCE                 0x8DE
+#define MADERA_DRC2RMIX_INPUT_4_VOLUME                 0x8DF
+#define MADERA_HPLP1MIX_INPUT_1_SOURCE                 0x900
+#define MADERA_HPLP1MIX_INPUT_1_VOLUME                 0x901
+#define MADERA_HPLP1MIX_INPUT_2_SOURCE                 0x902
+#define MADERA_HPLP1MIX_INPUT_2_VOLUME                 0x903
+#define MADERA_HPLP1MIX_INPUT_3_SOURCE                 0x904
+#define MADERA_HPLP1MIX_INPUT_3_VOLUME                 0x905
+#define MADERA_HPLP1MIX_INPUT_4_SOURCE                 0x906
+#define MADERA_HPLP1MIX_INPUT_4_VOLUME                 0x907
+#define MADERA_HPLP2MIX_INPUT_1_SOURCE                 0x908
+#define MADERA_HPLP2MIX_INPUT_1_VOLUME                 0x909
+#define MADERA_HPLP2MIX_INPUT_2_SOURCE                 0x90A
+#define MADERA_HPLP2MIX_INPUT_2_VOLUME                 0x90B
+#define MADERA_HPLP2MIX_INPUT_3_SOURCE                 0x90C
+#define MADERA_HPLP2MIX_INPUT_3_VOLUME                 0x90D
+#define MADERA_HPLP2MIX_INPUT_4_SOURCE                 0x90E
+#define MADERA_HPLP2MIX_INPUT_4_VOLUME                 0x90F
+#define MADERA_HPLP3MIX_INPUT_1_SOURCE                 0x910
+#define MADERA_HPLP3MIX_INPUT_1_VOLUME                 0x911
+#define MADERA_HPLP3MIX_INPUT_2_SOURCE                 0x912
+#define MADERA_HPLP3MIX_INPUT_2_VOLUME                 0x913
+#define MADERA_HPLP3MIX_INPUT_3_SOURCE                 0x914
+#define MADERA_HPLP3MIX_INPUT_3_VOLUME                 0x915
+#define MADERA_HPLP3MIX_INPUT_4_SOURCE                 0x916
+#define MADERA_HPLP3MIX_INPUT_4_VOLUME                 0x917
+#define MADERA_HPLP4MIX_INPUT_1_SOURCE                 0x918
+#define MADERA_HPLP4MIX_INPUT_1_VOLUME                 0x919
+#define MADERA_HPLP4MIX_INPUT_2_SOURCE                 0x91A
+#define MADERA_HPLP4MIX_INPUT_2_VOLUME                 0x91B
+#define MADERA_HPLP4MIX_INPUT_3_SOURCE                 0x91C
+#define MADERA_HPLP4MIX_INPUT_3_VOLUME                 0x91D
+#define MADERA_HPLP4MIX_INPUT_4_SOURCE                 0x91E
+#define MADERA_HPLP4MIX_INPUT_4_VOLUME                 0x91F
+#define MADERA_DSP1LMIX_INPUT_1_SOURCE                 0x940
+#define MADERA_DSP1LMIX_INPUT_1_VOLUME                 0x941
+#define MADERA_DSP1LMIX_INPUT_2_SOURCE                 0x942
+#define MADERA_DSP1LMIX_INPUT_2_VOLUME                 0x943
+#define MADERA_DSP1LMIX_INPUT_3_SOURCE                 0x944
+#define MADERA_DSP1LMIX_INPUT_3_VOLUME                 0x945
+#define MADERA_DSP1LMIX_INPUT_4_SOURCE                 0x946
+#define MADERA_DSP1LMIX_INPUT_4_VOLUME                 0x947
+#define MADERA_DSP1RMIX_INPUT_1_SOURCE                 0x948
+#define MADERA_DSP1RMIX_INPUT_1_VOLUME                 0x949
+#define MADERA_DSP1RMIX_INPUT_2_SOURCE                 0x94A
+#define MADERA_DSP1RMIX_INPUT_2_VOLUME                 0x94B
+#define MADERA_DSP1RMIX_INPUT_3_SOURCE                 0x94C
+#define MADERA_DSP1RMIX_INPUT_3_VOLUME                 0x94D
+#define MADERA_DSP1RMIX_INPUT_4_SOURCE                 0x94E
+#define MADERA_DSP1RMIX_INPUT_4_VOLUME                 0x94F
+#define MADERA_DSP1AUX1MIX_INPUT_1_SOURCE              0x950
+#define MADERA_DSP1AUX2MIX_INPUT_1_SOURCE              0x958
+#define MADERA_DSP1AUX3MIX_INPUT_1_SOURCE              0x960
+#define MADERA_DSP1AUX4MIX_INPUT_1_SOURCE              0x968
+#define MADERA_DSP1AUX5MIX_INPUT_1_SOURCE              0x970
+#define MADERA_DSP1AUX6MIX_INPUT_1_SOURCE              0x978
+#define MADERA_DSP2LMIX_INPUT_1_SOURCE                 0x980
+#define MADERA_DSP2LMIX_INPUT_1_VOLUME                 0x981
+#define MADERA_DSP2LMIX_INPUT_2_SOURCE                 0x982
+#define MADERA_DSP2LMIX_INPUT_2_VOLUME                 0x983
+#define MADERA_DSP2LMIX_INPUT_3_SOURCE                 0x984
+#define MADERA_DSP2LMIX_INPUT_3_VOLUME                 0x985
+#define MADERA_DSP2LMIX_INPUT_4_SOURCE                 0x986
+#define MADERA_DSP2LMIX_INPUT_4_VOLUME                 0x987
+#define MADERA_DSP2RMIX_INPUT_1_SOURCE                 0x988
+#define MADERA_DSP2RMIX_INPUT_1_VOLUME                 0x989
+#define MADERA_DSP2RMIX_INPUT_2_SOURCE                 0x98A
+#define MADERA_DSP2RMIX_INPUT_2_VOLUME                 0x98B
+#define MADERA_DSP2RMIX_INPUT_3_SOURCE                 0x98C
+#define MADERA_DSP2RMIX_INPUT_3_VOLUME                 0x98D
+#define MADERA_DSP2RMIX_INPUT_4_SOURCE                 0x98E
+#define MADERA_DSP2RMIX_INPUT_4_VOLUME                 0x98F
+#define MADERA_DSP2AUX1MIX_INPUT_1_SOURCE              0x990
+#define MADERA_DSP2AUX2MIX_INPUT_1_SOURCE              0x998
+#define MADERA_DSP2AUX3MIX_INPUT_1_SOURCE              0x9A0
+#define MADERA_DSP2AUX4MIX_INPUT_1_SOURCE              0x9A8
+#define MADERA_DSP2AUX5MIX_INPUT_1_SOURCE              0x9B0
+#define MADERA_DSP2AUX6MIX_INPUT_1_SOURCE              0x9B8
+#define MADERA_DSP3LMIX_INPUT_1_SOURCE                 0x9C0
+#define MADERA_DSP3LMIX_INPUT_1_VOLUME                 0x9C1
+#define MADERA_DSP3LMIX_INPUT_2_SOURCE                 0x9C2
+#define MADERA_DSP3LMIX_INPUT_2_VOLUME                 0x9C3
+#define MADERA_DSP3LMIX_INPUT_3_SOURCE                 0x9C4
+#define MADERA_DSP3LMIX_INPUT_3_VOLUME                 0x9C5
+#define MADERA_DSP3LMIX_INPUT_4_SOURCE                 0x9C6
+#define MADERA_DSP3LMIX_INPUT_4_VOLUME                 0x9C7
+#define MADERA_DSP3RMIX_INPUT_1_SOURCE                 0x9C8
+#define MADERA_DSP3RMIX_INPUT_1_VOLUME                 0x9C9
+#define MADERA_DSP3RMIX_INPUT_2_SOURCE                 0x9CA
+#define MADERA_DSP3RMIX_INPUT_2_VOLUME                 0x9CB
+#define MADERA_DSP3RMIX_INPUT_3_SOURCE                 0x9CC
+#define MADERA_DSP3RMIX_INPUT_3_VOLUME                 0x9CD
+#define MADERA_DSP3RMIX_INPUT_4_SOURCE                 0x9CE
+#define MADERA_DSP3RMIX_INPUT_4_VOLUME                 0x9CF
+#define MADERA_DSP3AUX1MIX_INPUT_1_SOURCE              0x9D0
+#define MADERA_DSP3AUX2MIX_INPUT_1_SOURCE              0x9D8
+#define MADERA_DSP3AUX3MIX_INPUT_1_SOURCE              0x9E0
+#define MADERA_DSP3AUX4MIX_INPUT_1_SOURCE              0x9E8
+#define MADERA_DSP3AUX5MIX_INPUT_1_SOURCE              0x9F0
+#define MADERA_DSP3AUX6MIX_INPUT_1_SOURCE              0x9F8
+#define MADERA_DSP4LMIX_INPUT_1_SOURCE                 0xA00
+#define MADERA_DSP4LMIX_INPUT_1_VOLUME                 0xA01
+#define MADERA_DSP4LMIX_INPUT_2_SOURCE                 0xA02
+#define MADERA_DSP4LMIX_INPUT_2_VOLUME                 0xA03
+#define MADERA_DSP4LMIX_INPUT_3_SOURCE                 0xA04
+#define MADERA_DSP4LMIX_INPUT_3_VOLUME                 0xA05
+#define MADERA_DSP4LMIX_INPUT_4_SOURCE                 0xA06
+#define MADERA_DSP4LMIX_INPUT_4_VOLUME                 0xA07
+#define MADERA_DSP4RMIX_INPUT_1_SOURCE                 0xA08
+#define MADERA_DSP4RMIX_INPUT_1_VOLUME                 0xA09
+#define MADERA_DSP4RMIX_INPUT_2_SOURCE                 0xA0A
+#define MADERA_DSP4RMIX_INPUT_2_VOLUME                 0xA0B
+#define MADERA_DSP4RMIX_INPUT_3_SOURCE                 0xA0C
+#define MADERA_DSP4RMIX_INPUT_3_VOLUME                 0xA0D
+#define MADERA_DSP4RMIX_INPUT_4_SOURCE                 0xA0E
+#define MADERA_DSP4RMIX_INPUT_4_VOLUME                 0xA0F
+#define MADERA_DSP4AUX1MIX_INPUT_1_SOURCE              0xA10
+#define MADERA_DSP4AUX2MIX_INPUT_1_SOURCE              0xA18
+#define MADERA_DSP4AUX3MIX_INPUT_1_SOURCE              0xA20
+#define MADERA_DSP4AUX4MIX_INPUT_1_SOURCE              0xA28
+#define MADERA_DSP4AUX5MIX_INPUT_1_SOURCE              0xA30
+#define MADERA_DSP4AUX6MIX_INPUT_1_SOURCE              0xA38
+#define MADERA_DSP5LMIX_INPUT_1_SOURCE                 0xA40
+#define MADERA_DSP5LMIX_INPUT_1_VOLUME                 0xA41
+#define MADERA_DSP5LMIX_INPUT_2_SOURCE                 0xA42
+#define MADERA_DSP5LMIX_INPUT_2_VOLUME                 0xA43
+#define MADERA_DSP5LMIX_INPUT_3_SOURCE                 0xA44
+#define MADERA_DSP5LMIX_INPUT_3_VOLUME                 0xA45
+#define MADERA_DSP5LMIX_INPUT_4_SOURCE                 0xA46
+#define MADERA_DSP5LMIX_INPUT_4_VOLUME                 0xA47
+#define MADERA_DSP5RMIX_INPUT_1_SOURCE                 0xA48
+#define MADERA_DSP5RMIX_INPUT_1_VOLUME                 0xA49
+#define MADERA_DSP5RMIX_INPUT_2_SOURCE                 0xA4A
+#define MADERA_DSP5RMIX_INPUT_2_VOLUME                 0xA4B
+#define MADERA_DSP5RMIX_INPUT_3_SOURCE                 0xA4C
+#define MADERA_DSP5RMIX_INPUT_3_VOLUME                 0xA4D
+#define MADERA_DSP5RMIX_INPUT_4_SOURCE                 0xA4E
+#define MADERA_DSP5RMIX_INPUT_4_VOLUME                 0xA4F
+#define MADERA_DSP5AUX1MIX_INPUT_1_SOURCE              0xA50
+#define MADERA_DSP5AUX2MIX_INPUT_1_SOURCE              0xA58
+#define MADERA_DSP5AUX3MIX_INPUT_1_SOURCE              0xA60
+#define MADERA_DSP5AUX4MIX_INPUT_1_SOURCE              0xA68
+#define MADERA_DSP5AUX5MIX_INPUT_1_SOURCE              0xA70
+#define MADERA_DSP5AUX6MIX_INPUT_1_SOURCE              0xA78
+#define MADERA_ASRC1_1LMIX_INPUT_1_SOURCE              0xA80
+#define MADERA_ASRC1_1RMIX_INPUT_1_SOURCE              0xA88
+#define MADERA_ASRC1_2LMIX_INPUT_1_SOURCE              0xA90
+#define MADERA_ASRC1_2RMIX_INPUT_1_SOURCE              0xA98
+#define MADERA_ASRC2_1LMIX_INPUT_1_SOURCE              0xAA0
+#define MADERA_ASRC2_1RMIX_INPUT_1_SOURCE              0xAA8
+#define MADERA_ASRC2_2LMIX_INPUT_1_SOURCE              0xAB0
+#define MADERA_ASRC2_2RMIX_INPUT_1_SOURCE              0xAB8
+#define MADERA_ISRC1DEC1MIX_INPUT_1_SOURCE             0xB00
+#define MADERA_ISRC1DEC2MIX_INPUT_1_SOURCE             0xB08
+#define MADERA_ISRC1DEC3MIX_INPUT_1_SOURCE             0xB10
+#define MADERA_ISRC1DEC4MIX_INPUT_1_SOURCE             0xB18
+#define MADERA_ISRC1INT1MIX_INPUT_1_SOURCE             0xB20
+#define MADERA_ISRC1INT2MIX_INPUT_1_SOURCE             0xB28
+#define MADERA_ISRC1INT3MIX_INPUT_1_SOURCE             0xB30
+#define MADERA_ISRC1INT4MIX_INPUT_1_SOURCE             0xB38
+#define MADERA_ISRC2DEC1MIX_INPUT_1_SOURCE             0xB40
+#define MADERA_ISRC2DEC2MIX_INPUT_1_SOURCE             0xB48
+#define MADERA_ISRC2DEC3MIX_INPUT_1_SOURCE             0xB50
+#define MADERA_ISRC2DEC4MIX_INPUT_1_SOURCE             0xB58
+#define MADERA_ISRC2INT1MIX_INPUT_1_SOURCE             0xB60
+#define MADERA_ISRC2INT2MIX_INPUT_1_SOURCE             0xB68
+#define MADERA_ISRC2INT3MIX_INPUT_1_SOURCE             0xB70
+#define MADERA_ISRC2INT4MIX_INPUT_1_SOURCE             0xB78
+#define MADERA_ISRC3DEC1MIX_INPUT_1_SOURCE             0xB80
+#define MADERA_ISRC3DEC2MIX_INPUT_1_SOURCE             0xB88
+#define MADERA_ISRC3DEC3MIX_INPUT_1_SOURCE             0xB90
+#define MADERA_ISRC3DEC4MIX_INPUT_1_SOURCE             0xB98
+#define MADERA_ISRC3INT1MIX_INPUT_1_SOURCE             0xBA0
+#define MADERA_ISRC3INT2MIX_INPUT_1_SOURCE             0xBA8
+#define MADERA_ISRC3INT3MIX_INPUT_1_SOURCE             0xBB0
+#define MADERA_ISRC3INT4MIX_INPUT_1_SOURCE             0xBB8
+#define MADERA_ISRC4DEC1MIX_INPUT_1_SOURCE             0xBC0
+#define MADERA_ISRC4DEC2MIX_INPUT_1_SOURCE             0xBC8
+#define MADERA_ISRC4INT1MIX_INPUT_1_SOURCE             0xBE0
+#define MADERA_ISRC4INT2MIX_INPUT_1_SOURCE             0xBE8
+#define MADERA_DSP6LMIX_INPUT_1_SOURCE                 0xC00
+#define MADERA_DSP6LMIX_INPUT_1_VOLUME                 0xC01
+#define MADERA_DSP6LMIX_INPUT_2_SOURCE                 0xC02
+#define MADERA_DSP6LMIX_INPUT_2_VOLUME                 0xC03
+#define MADERA_DSP6LMIX_INPUT_3_SOURCE                 0xC04
+#define MADERA_DSP6LMIX_INPUT_3_VOLUME                 0xC05
+#define MADERA_DSP6LMIX_INPUT_4_SOURCE                 0xC06
+#define MADERA_DSP6LMIX_INPUT_4_VOLUME                 0xC07
+#define MADERA_DSP6RMIX_INPUT_1_SOURCE                 0xC08
+#define MADERA_DSP6RMIX_INPUT_1_VOLUME                 0xC09
+#define MADERA_DSP6RMIX_INPUT_2_SOURCE                 0xC0A
+#define MADERA_DSP6RMIX_INPUT_2_VOLUME                 0xC0B
+#define MADERA_DSP6RMIX_INPUT_3_SOURCE                 0xC0C
+#define MADERA_DSP6RMIX_INPUT_3_VOLUME                 0xC0D
+#define MADERA_DSP6RMIX_INPUT_4_SOURCE                 0xC0E
+#define MADERA_DSP6RMIX_INPUT_4_VOLUME                 0xC0F
+#define MADERA_DSP6AUX1MIX_INPUT_1_SOURCE              0xC10
+#define MADERA_DSP6AUX2MIX_INPUT_1_SOURCE              0xC18
+#define MADERA_DSP6AUX3MIX_INPUT_1_SOURCE              0xC20
+#define MADERA_DSP6AUX4MIX_INPUT_1_SOURCE              0xC28
+#define MADERA_DSP6AUX5MIX_INPUT_1_SOURCE              0xC30
+#define MADERA_DSP6AUX6MIX_INPUT_1_SOURCE              0xC38
+#define MADERA_DSP7LMIX_INPUT_1_SOURCE                 0xC40
+#define MADERA_DSP7LMIX_INPUT_1_VOLUME                 0xC41
+#define MADERA_DSP7LMIX_INPUT_2_SOURCE                 0xC42
+#define MADERA_DSP7LMIX_INPUT_2_VOLUME                 0xC43
+#define MADERA_DSP7LMIX_INPUT_3_SOURCE                 0xC44
+#define MADERA_DSP7LMIX_INPUT_3_VOLUME                 0xC45
+#define MADERA_DSP7LMIX_INPUT_4_SOURCE                 0xC46
+#define MADERA_DSP7LMIX_INPUT_4_VOLUME                 0xC47
+#define MADERA_DSP7RMIX_INPUT_1_SOURCE                 0xC48
+#define MADERA_DSP7RMIX_INPUT_1_VOLUME                 0xC49
+#define MADERA_DSP7RMIX_INPUT_2_SOURCE                 0xC4A
+#define MADERA_DSP7RMIX_INPUT_2_VOLUME                 0xC4B
+#define MADERA_DSP7RMIX_INPUT_3_SOURCE                 0xC4C
+#define MADERA_DSP7RMIX_INPUT_3_VOLUME                 0xC4D
+#define MADERA_DSP7RMIX_INPUT_4_SOURCE                 0xC4E
+#define MADERA_DSP7RMIX_INPUT_4_VOLUME                 0xC4F
+#define MADERA_DSP7AUX1MIX_INPUT_1_SOURCE              0xC50
+#define MADERA_DSP7AUX2MIX_INPUT_1_SOURCE              0xC58
+#define MADERA_DSP7AUX3MIX_INPUT_1_SOURCE              0xC60
+#define MADERA_DSP7AUX4MIX_INPUT_1_SOURCE              0xC68
+#define MADERA_DSP7AUX5MIX_INPUT_1_SOURCE              0xC70
+#define MADERA_DSP7AUX6MIX_INPUT_1_SOURCE              0xC78
+#define MADERA_DFC1MIX_INPUT_1_SOURCE                  0xDC0
+#define MADERA_DFC2MIX_INPUT_1_SOURCE                  0xDC8
+#define MADERA_DFC3MIX_INPUT_1_SOURCE                  0xDD0
+#define MADERA_DFC4MIX_INPUT_1_SOURCE                  0xDD8
+#define MADERA_DFC5MIX_INPUT_1_SOURCE                  0xDE0
+#define MADERA_DFC6MIX_INPUT_1_SOURCE                  0xDE8
+#define MADERA_DFC7MIX_INPUT_1_SOURCE                  0xDF0
+#define MADERA_DFC8MIX_INPUT_1_SOURCE                  0xDF8
+#define MADERA_FX_CTRL1                                        0xE00
+#define MADERA_FX_CTRL2                                        0xE01
+#define MADERA_EQ1_1                                   0xE10
+#define MADERA_EQ1_2                                   0xE11
+#define MADERA_EQ1_21                                  0xE24
+#define MADERA_EQ2_1                                   0xE26
+#define MADERA_EQ2_2                                   0xE27
+#define MADERA_EQ2_21                                  0xE3A
+#define MADERA_EQ3_1                                   0xE3C
+#define MADERA_EQ3_2                                   0xE3D
+#define MADERA_EQ3_21                                  0xE50
+#define MADERA_EQ4_1                                   0xE52
+#define MADERA_EQ4_2                                   0xE53
+#define MADERA_EQ4_21                                  0xE66
+#define MADERA_DRC1_CTRL1                              0xE80
+#define MADERA_DRC1_CTRL2                              0xE81
+#define MADERA_DRC1_CTRL3                              0xE82
+#define MADERA_DRC1_CTRL4                              0xE83
+#define MADERA_DRC1_CTRL5                              0xE84
+#define MADERA_DRC2_CTRL1                              0xE88
+#define MADERA_DRC2_CTRL2                              0xE89
+#define MADERA_DRC2_CTRL3                              0xE8A
+#define MADERA_DRC2_CTRL4                              0xE8B
+#define MADERA_DRC2_CTRL5                              0xE8C
+#define MADERA_HPLPF1_1                                        0xEC0
+#define MADERA_HPLPF1_2                                        0xEC1
+#define MADERA_HPLPF2_1                                        0xEC4
+#define MADERA_HPLPF2_2                                        0xEC5
+#define MADERA_HPLPF3_1                                        0xEC8
+#define MADERA_HPLPF3_2                                        0xEC9
+#define MADERA_HPLPF4_1                                        0xECC
+#define MADERA_HPLPF4_2                                        0xECD
+#define MADERA_ASRC2_ENABLE                            0xED0
+#define MADERA_ASRC2_STATUS                            0xED1
+#define MADERA_ASRC2_RATE1                             0xED2
+#define MADERA_ASRC2_RATE2                             0xED3
+#define MADERA_ASRC1_ENABLE                            0xEE0
+#define MADERA_ASRC1_STATUS                            0xEE1
+#define MADERA_ASRC1_RATE1                             0xEE2
+#define MADERA_ASRC1_RATE2                             0xEE3
+#define MADERA_ISRC_1_CTRL_1                           0xEF0
+#define MADERA_ISRC_1_CTRL_2                           0xEF1
+#define MADERA_ISRC_1_CTRL_3                           0xEF2
+#define MADERA_ISRC_2_CTRL_1                           0xEF3
+#define MADERA_ISRC_2_CTRL_2                           0xEF4
+#define MADERA_ISRC_2_CTRL_3                           0xEF5
+#define MADERA_ISRC_3_CTRL_1                           0xEF6
+#define MADERA_ISRC_3_CTRL_2                           0xEF7
+#define MADERA_ISRC_3_CTRL_3                           0xEF8
+#define MADERA_ISRC_4_CTRL_1                           0xEF9
+#define MADERA_ISRC_4_CTRL_2                           0xEFA
+#define MADERA_ISRC_4_CTRL_3                           0xEFB
+#define MADERA_CLOCK_CONTROL                           0xF00
+#define MADERA_ANC_SRC                                 0xF01
+#define MADERA_DSP_STATUS                              0xF02
+#define MADERA_ANC_COEFF_START                         0xF08
+#define MADERA_ANC_COEFF_END                           0xF12
+#define MADERA_FCL_FILTER_CONTROL                      0xF15
+#define MADERA_FCL_ADC_REFORMATTER_CONTROL             0xF17
+#define MADERA_FCL_COEFF_START                         0xF18
+#define MADERA_FCL_COEFF_END                           0xF69
+#define MADERA_FCR_FILTER_CONTROL                      0xF71
+#define MADERA_FCR_ADC_REFORMATTER_CONTROL             0xF73
+#define MADERA_FCR_COEFF_START                         0xF74
+#define MADERA_FCR_COEFF_END                           0xFC5
+#define MADERA_DAC_COMP_1                              0x1300
+#define MADERA_DAC_COMP_2                              0x1302
+#define MADERA_FRF_COEFFICIENT_1L_1                    0x1380
+#define MADERA_FRF_COEFFICIENT_1L_2                    0x1381
+#define MADERA_FRF_COEFFICIENT_1L_3                    0x1382
+#define MADERA_FRF_COEFFICIENT_1L_4                    0x1383
+#define MADERA_FRF_COEFFICIENT_1R_1                    0x1390
+#define MADERA_FRF_COEFFICIENT_1R_2                    0x1391
+#define MADERA_FRF_COEFFICIENT_1R_3                    0x1392
+#define MADERA_FRF_COEFFICIENT_1R_4                    0x1393
+#define MADERA_FRF_COEFFICIENT_2L_1                    0x13A0
+#define MADERA_FRF_COEFFICIENT_2L_2                    0x13A1
+#define MADERA_FRF_COEFFICIENT_2L_3                    0x13A2
+#define MADERA_FRF_COEFFICIENT_2L_4                    0x13A3
+#define MADERA_FRF_COEFFICIENT_2R_1                    0x13B0
+#define MADERA_FRF_COEFFICIENT_2R_2                    0x13B1
+#define MADERA_FRF_COEFFICIENT_2R_3                    0x13B2
+#define MADERA_FRF_COEFFICIENT_2R_4                    0x13B3
+#define MADERA_FRF_COEFFICIENT_3L_1                    0x13C0
+#define MADERA_FRF_COEFFICIENT_3L_2                    0x13C1
+#define MADERA_FRF_COEFFICIENT_3L_3                    0x13C2
+#define MADERA_FRF_COEFFICIENT_3L_4                    0x13C3
+#define MADERA_FRF_COEFFICIENT_3R_1                    0x13D0
+#define MADERA_FRF_COEFFICIENT_3R_2                    0x13D1
+#define MADERA_FRF_COEFFICIENT_3R_3                    0x13D2
+#define MADERA_FRF_COEFFICIENT_3R_4                    0x13D3
+#define MADERA_FRF_COEFFICIENT_4L_1                    0x13E0
+#define MADERA_FRF_COEFFICIENT_4L_2                    0x13E1
+#define MADERA_FRF_COEFFICIENT_4L_3                    0x13E2
+#define MADERA_FRF_COEFFICIENT_4L_4                    0x13E3
+#define MADERA_FRF_COEFFICIENT_4R_1                    0x13F0
+#define MADERA_FRF_COEFFICIENT_4R_2                    0x13F1
+#define MADERA_FRF_COEFFICIENT_4R_3                    0x13F2
+#define MADERA_FRF_COEFFICIENT_4R_4                    0x13F3
+#define CS47L35_FRF_COEFFICIENT_4L_1                   0x13A0
+#define CS47L35_FRF_COEFFICIENT_4L_2                   0x13A1
+#define CS47L35_FRF_COEFFICIENT_4L_3                   0x13A2
+#define CS47L35_FRF_COEFFICIENT_4L_4                   0x13A3
+#define CS47L35_FRF_COEFFICIENT_5L_1                   0x13B0
+#define CS47L35_FRF_COEFFICIENT_5L_2                   0x13B1
+#define CS47L35_FRF_COEFFICIENT_5L_3                   0x13B2
+#define CS47L35_FRF_COEFFICIENT_5L_4                   0x13B3
+#define CS47L35_FRF_COEFFICIENT_5R_1                   0x13C0
+#define CS47L35_FRF_COEFFICIENT_5R_2                   0x13C1
+#define CS47L35_FRF_COEFFICIENT_5R_3                   0x13C2
+#define CS47L35_FRF_COEFFICIENT_5R_4                   0x13C3
+#define MADERA_FRF_COEFFICIENT_5L_1                    0x1400
+#define MADERA_FRF_COEFFICIENT_5L_2                    0x1401
+#define MADERA_FRF_COEFFICIENT_5L_3                    0x1402
+#define MADERA_FRF_COEFFICIENT_5L_4                    0x1403
+#define MADERA_FRF_COEFFICIENT_5R_1                    0x1410
+#define MADERA_FRF_COEFFICIENT_5R_2                    0x1411
+#define MADERA_FRF_COEFFICIENT_5R_3                    0x1412
+#define MADERA_FRF_COEFFICIENT_5R_4                    0x1413
+#define MADERA_FRF_COEFFICIENT_6L_1                    0x1420
+#define MADERA_FRF_COEFFICIENT_6L_2                    0x1421
+#define MADERA_FRF_COEFFICIENT_6L_3                    0x1422
+#define MADERA_FRF_COEFFICIENT_6L_4                    0x1423
+#define MADERA_FRF_COEFFICIENT_6R_1                    0x1430
+#define MADERA_FRF_COEFFICIENT_6R_2                    0x1431
+#define MADERA_FRF_COEFFICIENT_6R_3                    0x1432
+#define MADERA_FRF_COEFFICIENT_6R_4                    0x1433
+#define MADERA_DFC1_CTRL                               0x1480
+#define MADERA_DFC1_RX                                 0x1482
+#define MADERA_DFC1_TX                                 0x1484
+#define MADERA_DFC2_CTRL                               0x1486
+#define MADERA_DFC2_RX                                 0x1488
+#define MADERA_DFC2_TX                                 0x148A
+#define MADERA_DFC3_CTRL                               0x148C
+#define MADERA_DFC3_RX                                 0x148E
+#define MADERA_DFC3_TX                                 0x1490
+#define MADERA_DFC4_CTRL                               0x1492
+#define MADERA_DFC4_RX                                 0x1494
+#define MADERA_DFC4_TX                                 0x1496
+#define MADERA_DFC5_CTRL                               0x1498
+#define MADERA_DFC5_RX                                 0x149A
+#define MADERA_DFC5_TX                                 0x149C
+#define MADERA_DFC6_CTRL                               0x149E
+#define MADERA_DFC6_RX                                 0x14A0
+#define MADERA_DFC6_TX                                 0x14A2
+#define MADERA_DFC7_CTRL                               0x14A4
+#define MADERA_DFC7_RX                                 0x14A6
+#define MADERA_DFC7_TX                                 0x14A8
+#define MADERA_DFC8_CTRL                               0x14AA
+#define MADERA_DFC8_RX                                 0x14AC
+#define MADERA_DFC8_TX                                 0x14AE
+#define MADERA_DFC_STATUS                              0x14B6
+#define MADERA_ADSP2_IRQ0                              0x1600
+#define MADERA_ADSP2_IRQ1                              0x1601
+#define MADERA_ADSP2_IRQ2                              0x1602
+#define MADERA_ADSP2_IRQ3                              0x1603
+#define MADERA_ADSP2_IRQ4                              0x1604
+#define MADERA_ADSP2_IRQ5                              0x1605
+#define MADERA_ADSP2_IRQ6                              0x1606
+#define MADERA_ADSP2_IRQ7                              0x1607
+#define MADERA_GPIO1_CTRL_1                            0x1700
+#define MADERA_GPIO1_CTRL_2                            0x1701
+#define MADERA_GPIO2_CTRL_1                            0x1702
+#define MADERA_GPIO2_CTRL_2                            0x1703
+#define MADERA_GPIO16_CTRL_1                           0x171E
+#define MADERA_GPIO16_CTRL_2                           0x171F
+#define MADERA_GPIO38_CTRL_1                           0x174A
+#define MADERA_GPIO38_CTRL_2                           0x174B
+#define MADERA_GPIO40_CTRL_1                           0x174E
+#define MADERA_GPIO40_CTRL_2                           0x174F
+#define MADERA_IRQ1_STATUS_1                           0x1800
+#define MADERA_IRQ1_STATUS_2                           0x1801
+#define MADERA_IRQ1_STATUS_6                           0x1805
+#define MADERA_IRQ1_STATUS_7                           0x1806
+#define MADERA_IRQ1_STATUS_9                           0x1808
+#define MADERA_IRQ1_STATUS_11                          0x180A
+#define MADERA_IRQ1_STATUS_12                          0x180B
+#define MADERA_IRQ1_STATUS_15                          0x180E
+#define MADERA_IRQ1_STATUS_33                          0x1820
+#define MADERA_IRQ1_MASK_1                             0x1840
+#define MADERA_IRQ1_MASK_2                             0x1841
+#define MADERA_IRQ1_MASK_6                             0x1845
+#define MADERA_IRQ1_MASK_33                            0x1860
+#define MADERA_IRQ1_RAW_STATUS_1                       0x1880
+#define MADERA_IRQ1_RAW_STATUS_2                       0x1881
+#define MADERA_IRQ1_RAW_STATUS_7                       0x1886
+#define MADERA_IRQ1_RAW_STATUS_15                      0x188E
+#define MADERA_IRQ1_RAW_STATUS_33                      0x18A0
+#define MADERA_INTERRUPT_DEBOUNCE_7                    0x1A06
+#define MADERA_INTERRUPT_DEBOUNCE_15                   0x1A0E
+#define MADERA_IRQ1_CTRL                               0x1A80
+#define MADERA_IRQ2_CTRL                               0x1A82
+#define MADERA_INTERRUPT_RAW_STATUS_1                  0x1AA0
+#define MADERA_WSEQ_SEQUENCE_1                         0x3000
+#define MADERA_WSEQ_SEQUENCE_252                       0x31F6
+#define CS47L35_OTP_HPDET_CAL_1                                0x31F8
+#define CS47L35_OTP_HPDET_CAL_2                                0x31FA
+#define MADERA_WSEQ_SEQUENCE_508                       0x33F6
+#define CS47L85_OTP_HPDET_CAL_1                                0x33F8
+#define CS47L85_OTP_HPDET_CAL_2                                0x33FA
+#define MADERA_OTP_HPDET_CAL_1                         0x20004
+#define MADERA_OTP_HPDET_CAL_2                         0x20006
+#define MADERA_DSP1_CONFIG_1                           0x0FFE00
+#define MADERA_DSP1_CONFIG_2                           0x0FFE02
+#define MADERA_DSP1_SCRATCH_1                          0x0FFE40
+#define MADERA_DSP1_SCRATCH_2                          0x0FFE42
+#define MADERA_DSP1_PMEM_ERR_ADDR___XMEM_ERR_ADDR      0xFFE7C
+#define MADERA_DSP2_CONFIG_1                           0x17FE00
+#define MADERA_DSP2_CONFIG_2                           0x17FE02
+#define MADERA_DSP2_SCRATCH_1                          0x17FE40
+#define MADERA_DSP2_SCRATCH_2                          0x17FE42
+#define MADERA_DSP2_PMEM_ERR_ADDR___XMEM_ERR_ADDR      0x17FE7C
+#define MADERA_DSP3_CONFIG_1                           0x1FFE00
+#define MADERA_DSP3_CONFIG_2                           0x1FFE02
+#define MADERA_DSP3_SCRATCH_1                          0x1FFE40
+#define MADERA_DSP3_SCRATCH_2                          0x1FFE42
+#define MADERA_DSP3_PMEM_ERR_ADDR___XMEM_ERR_ADDR      0x1FFE7C
+#define MADERA_DSP4_CONFIG_1                           0x27FE00
+#define MADERA_DSP4_CONFIG_2                           0x27FE02
+#define MADERA_DSP4_SCRATCH_1                          0x27FE40
+#define MADERA_DSP4_SCRATCH_2                          0x27FE42
+#define MADERA_DSP4_PMEM_ERR_ADDR___XMEM_ERR_ADDR      0x27FE7C
+#define MADERA_DSP5_CONFIG_1                           0x2FFE00
+#define MADERA_DSP5_CONFIG_2                           0x2FFE02
+#define MADERA_DSP5_SCRATCH_1                          0x2FFE40
+#define MADERA_DSP5_SCRATCH_2                          0x2FFE42
+#define MADERA_DSP5_PMEM_ERR_ADDR___XMEM_ERR_ADDR      0x2FFE7C
+#define MADERA_DSP6_CONFIG_1                           0x37FE00
+#define MADERA_DSP6_CONFIG_2                           0x37FE02
+#define MADERA_DSP6_SCRATCH_1                          0x37FE40
+#define MADERA_DSP6_SCRATCH_2                          0x37FE42
+#define MADERA_DSP6_PMEM_ERR_ADDR___XMEM_ERR_ADDR      0x37FE7C
+#define MADERA_DSP7_CONFIG_1                           0x3FFE00
+#define MADERA_DSP7_CONFIG_2                           0x3FFE02
+#define MADERA_DSP7_SCRATCH_1                          0x3FFE40
+#define MADERA_DSP7_SCRATCH_2                          0x3FFE42
+#define MADERA_DSP7_PMEM_ERR_ADDR___XMEM_ERR_ADDR      0x3FFE7C
+
+/* (0x0000)  Software_Reset */
+#define MADERA_SW_RST_DEV_ID1_MASK                     0xFFFF
+#define MADERA_SW_RST_DEV_ID1_SHIFT                         0
+#define MADERA_SW_RST_DEV_ID1_WIDTH                        16
+
+/* (0x0001)  Hardware_Revision */
+#define MADERA_HW_REVISION_MASK                                0x00FF
+#define MADERA_HW_REVISION_SHIFT                            0
+#define MADERA_HW_REVISION_WIDTH                            8
+
+/* (0x0020)  Tone_Generator_1 */
+#define MADERA_TONE2_ENA                               0x0002
+#define MADERA_TONE2_ENA_MASK                          0x0002
+#define MADERA_TONE2_ENA_SHIFT                              1
+#define MADERA_TONE2_ENA_WIDTH                              1
+#define MADERA_TONE1_ENA                               0x0001
+#define MADERA_TONE1_ENA_MASK                          0x0001
+#define MADERA_TONE1_ENA_SHIFT                              0
+#define MADERA_TONE1_ENA_WIDTH                              1
+
+/* (0x0021)  Tone_Generator_2 */
+#define MADERA_TONE1_LVL_0_MASK                                0xFFFF
+#define MADERA_TONE1_LVL_0_SHIFT                            0
+#define MADERA_TONE1_LVL_0_WIDTH                           16
+
+/* (0x0022)  Tone_Generator_3 */
+#define MADERA_TONE1_LVL_MASK                          0x00FF
+#define MADERA_TONE1_LVL_SHIFT                              0
+#define MADERA_TONE1_LVL_WIDTH                              8
+
+/* (0x0023)  Tone_Generator_4 */
+#define MADERA_TONE2_LVL_0_MASK                                0xFFFF
+#define MADERA_TONE2_LVL_0_SHIFT                            0
+#define MADERA_TONE2_LVL_0_WIDTH                           16
+
+/* (0x0024)  Tone_Generator_5 */
+#define MADERA_TONE2_LVL_MASK                          0x00FF
+#define MADERA_TONE2_LVL_SHIFT                              0
+#define MADERA_TONE2_LVL_WIDTH                              8
+
+/* (0x0030)  PWM_Drive_1 */
+#define MADERA_PWM2_ENA                                        0x0002
+#define MADERA_PWM2_ENA_MASK                           0x0002
+#define MADERA_PWM2_ENA_SHIFT                               1
+#define MADERA_PWM2_ENA_WIDTH                               1
+#define MADERA_PWM1_ENA                                        0x0001
+#define MADERA_PWM1_ENA_MASK                           0x0001
+#define MADERA_PWM1_ENA_SHIFT                               0
+#define MADERA_PWM1_ENA_WIDTH                               1
+
+/* (0x00A0)  Comfort_Noise_Generator */
+#define MADERA_NOISE_GEN_ENA                           0x0020
+#define MADERA_NOISE_GEN_ENA_MASK                      0x0020
+#define MADERA_NOISE_GEN_ENA_SHIFT                          5
+#define MADERA_NOISE_GEN_ENA_WIDTH                          1
+#define MADERA_NOISE_GEN_GAIN_MASK                     0x001F
+#define MADERA_NOISE_GEN_GAIN_SHIFT                         0
+#define MADERA_NOISE_GEN_GAIN_WIDTH                         5
+
+/* (0x0100)  Clock_32k_1 */
+#define MADERA_CLK_32K_ENA                             0x0040
+#define MADERA_CLK_32K_ENA_MASK                                0x0040
+#define MADERA_CLK_32K_ENA_SHIFT                            6
+#define MADERA_CLK_32K_ENA_WIDTH                            1
+#define MADERA_CLK_32K_SRC_MASK                                0x0003
+#define MADERA_CLK_32K_SRC_SHIFT                            0
+#define MADERA_CLK_32K_SRC_WIDTH                            2
+
+/* (0x0101)  System_Clock_1 */
+#define MADERA_SYSCLK_FRAC                             0x8000
+#define MADERA_SYSCLK_FRAC_MASK                                0x8000
+#define MADERA_SYSCLK_FRAC_SHIFT                           15
+#define MADERA_SYSCLK_FRAC_WIDTH                            1
+#define MADERA_SYSCLK_FREQ_MASK                                0x0700
+#define MADERA_SYSCLK_FREQ_SHIFT                            8
+#define MADERA_SYSCLK_FREQ_WIDTH                            3
+#define MADERA_SYSCLK_ENA                              0x0040
+#define MADERA_SYSCLK_ENA_MASK                         0x0040
+#define MADERA_SYSCLK_ENA_SHIFT                                     6
+#define MADERA_SYSCLK_ENA_WIDTH                                     1
+#define MADERA_SYSCLK_SRC_MASK                         0x000F
+#define MADERA_SYSCLK_SRC_SHIFT                                     0
+#define MADERA_SYSCLK_SRC_WIDTH                                     4
+
+/* (0x0102)  Sample_rate_1 */
+#define MADERA_SAMPLE_RATE_1_MASK                      0x001F
+#define MADERA_SAMPLE_RATE_1_SHIFT                          0
+#define MADERA_SAMPLE_RATE_1_WIDTH                          5
+
+/* (0x0103)  Sample_rate_2 */
+#define MADERA_SAMPLE_RATE_2_MASK                      0x001F
+#define MADERA_SAMPLE_RATE_2_SHIFT                          0
+#define MADERA_SAMPLE_RATE_2_WIDTH                          5
+
+/* (0x0104)  Sample_rate_3 */
+#define MADERA_SAMPLE_RATE_3_MASK                      0x001F
+#define MADERA_SAMPLE_RATE_3_SHIFT                          0
+#define MADERA_SAMPLE_RATE_3_WIDTH                          5
+
+/* (0x0112)  Async_clock_1 */
+#define MADERA_ASYNC_CLK_FREQ_MASK                     0x0700
+#define MADERA_ASYNC_CLK_FREQ_SHIFT                         8
+#define MADERA_ASYNC_CLK_FREQ_WIDTH                         3
+#define MADERA_ASYNC_CLK_ENA                           0x0040
+#define MADERA_ASYNC_CLK_ENA_MASK                      0x0040
+#define MADERA_ASYNC_CLK_ENA_SHIFT                          6
+#define MADERA_ASYNC_CLK_ENA_WIDTH                          1
+#define MADERA_ASYNC_CLK_SRC_MASK                      0x000F
+#define MADERA_ASYNC_CLK_SRC_SHIFT                          0
+#define MADERA_ASYNC_CLK_SRC_WIDTH                          4
+
+/* (0x0113)  Async_sample_rate_1 */
+#define MADERA_ASYNC_SAMPLE_RATE_1_MASK                        0x001F
+#define MADERA_ASYNC_SAMPLE_RATE_1_SHIFT                    0
+#define MADERA_ASYNC_SAMPLE_RATE_1_WIDTH                    5
+
+/* (0x0114)  Async_sample_rate_2 */
+#define MADERA_ASYNC_SAMPLE_RATE_2_MASK                        0x001F
+#define MADERA_ASYNC_SAMPLE_RATE_2_SHIFT                    0
+#define MADERA_ASYNC_SAMPLE_RATE_2_WIDTH                    5
+
+/* (0x0120)  DSP_Clock_1 */
+#define MADERA_DSP_CLK_FREQ_LEGACY                     0x0700
+#define MADERA_DSP_CLK_FREQ_LEGACY_MASK                        0x0700
+#define MADERA_DSP_CLK_FREQ_LEGACY_SHIFT                    8
+#define MADERA_DSP_CLK_FREQ_LEGACY_WIDTH                    3
+#define MADERA_DSP_CLK_ENA                             0x0040
+#define MADERA_DSP_CLK_ENA_MASK                                0x0040
+#define MADERA_DSP_CLK_ENA_SHIFT                            6
+#define MADERA_DSP_CLK_ENA_WIDTH                            1
+#define MADERA_DSP_CLK_SRC                             0x000F
+#define MADERA_DSP_CLK_SRC_MASK                                0x000F
+#define MADERA_DSP_CLK_SRC_SHIFT                            0
+#define MADERA_DSP_CLK_SRC_WIDTH                            4
+
+/* (0x0122)  DSP_Clock_2 */
+#define MADERA_DSP_CLK_FREQ_MASK                       0x03FF
+#define MADERA_DSP_CLK_FREQ_SHIFT                           0
+#define MADERA_DSP_CLK_FREQ_WIDTH                          10
+
+/* (0x0149)  Output_system_clock */
+#define MADERA_OPCLK_ENA                               0x8000
+#define MADERA_OPCLK_ENA_MASK                          0x8000
+#define MADERA_OPCLK_ENA_SHIFT                             15
+#define MADERA_OPCLK_ENA_WIDTH                              1
+#define MADERA_OPCLK_DIV_MASK                          0x00F8
+#define MADERA_OPCLK_DIV_SHIFT                              3
+#define MADERA_OPCLK_DIV_WIDTH                              5
+#define MADERA_OPCLK_SEL_MASK                          0x0007
+#define MADERA_OPCLK_SEL_SHIFT                              0
+#define MADERA_OPCLK_SEL_WIDTH                              3
+
+/* (0x014A)  Output_async_clock */
+#define MADERA_OPCLK_ASYNC_ENA                         0x8000
+#define MADERA_OPCLK_ASYNC_ENA_MASK                    0x8000
+#define MADERA_OPCLK_ASYNC_ENA_SHIFT                       15
+#define MADERA_OPCLK_ASYNC_ENA_WIDTH                        1
+#define MADERA_OPCLK_ASYNC_DIV_MASK                    0x00F8
+#define MADERA_OPCLK_ASYNC_DIV_SHIFT                        3
+#define MADERA_OPCLK_ASYNC_DIV_WIDTH                        5
+#define MADERA_OPCLK_ASYNC_SEL_MASK                    0x0007
+#define MADERA_OPCLK_ASYNC_SEL_SHIFT                        0
+#define MADERA_OPCLK_ASYNC_SEL_WIDTH                        3
+
+/* (0x0171)  FLL1_Control_1 */
+#define MADERA_FLL1_FREERUN                            0x0002
+#define MADERA_FLL1_FREERUN_MASK                       0x0002
+#define MADERA_FLL1_FREERUN_SHIFT                           1
+#define MADERA_FLL1_FREERUN_WIDTH                           1
+#define MADERA_FLL1_ENA                                        0x0001
+#define MADERA_FLL1_ENA_MASK                           0x0001
+#define MADERA_FLL1_ENA_SHIFT                               0
+#define MADERA_FLL1_ENA_WIDTH                               1
+
+/* (0x0172)  FLL1_Control_2 */
+#define MADERA_FLL1_CTRL_UPD                           0x8000
+#define MADERA_FLL1_CTRL_UPD_MASK                      0x8000
+#define MADERA_FLL1_CTRL_UPD_SHIFT                         15
+#define MADERA_FLL1_CTRL_UPD_WIDTH                          1
+#define MADERA_FLL1_N_MASK                             0x03FF
+#define MADERA_FLL1_N_SHIFT                                 0
+#define MADERA_FLL1_N_WIDTH                                10
+
+/* (0x0173)  FLL1_Control_3 */
+#define MADERA_FLL1_THETA_MASK                         0xFFFF
+#define MADERA_FLL1_THETA_SHIFT                                     0
+#define MADERA_FLL1_THETA_WIDTH                                    16
+
+/* (0x0174)  FLL1_Control_4 */
+#define MADERA_FLL1_LAMBDA_MASK                                0xFFFF
+#define MADERA_FLL1_LAMBDA_SHIFT                            0
+#define MADERA_FLL1_LAMBDA_WIDTH                           16
+
+/* (0x0175)  FLL1_Control_5 */
+#define MADERA_FLL1_FRATIO_MASK                                0x0F00
+#define MADERA_FLL1_FRATIO_SHIFT                            8
+#define MADERA_FLL1_FRATIO_WIDTH                            4
+
+/* (0x0176)  FLL1_Control_6 */
+#define MADERA_FLL1_REFCLK_DIV_MASK                    0x00C0
+#define MADERA_FLL1_REFCLK_DIV_SHIFT                        6
+#define MADERA_FLL1_REFCLK_DIV_WIDTH                        2
+#define MADERA_FLL1_REFCLK_SRC_MASK                    0x000F
+#define MADERA_FLL1_REFCLK_SRC_SHIFT                        0
+#define MADERA_FLL1_REFCLK_SRC_WIDTH                        4
+
+/* (0x0177)  FLL1_Loop_Filter_Test_1 */
+#define MADERA_FLL1_FRC_INTEG_UPD                      0x8000
+#define MADERA_FLL1_FRC_INTEG_UPD_MASK                 0x8000
+#define MADERA_FLL1_FRC_INTEG_UPD_SHIFT                            15
+#define MADERA_FLL1_FRC_INTEG_UPD_WIDTH                             1
+#define MADERA_FLL1_FRC_INTEG_VAL_MASK                 0x0FFF
+#define MADERA_FLL1_FRC_INTEG_VAL_SHIFT                             0
+#define MADERA_FLL1_FRC_INTEG_VAL_WIDTH                            12
+
+/* (0x0179)  FLL1_Control_7 */
+#define MADERA_FLL1_GAIN_MASK                          0x003c
+#define MADERA_FLL1_GAIN_SHIFT                              2
+#define MADERA_FLL1_GAIN_WIDTH                              4
+
+/* (0x017A)  FLL1_EFS_2 */
+#define MADERA_FLL1_PHASE_GAIN_MASK                    0xF000
+#define MADERA_FLL1_PHASE_GAIN_SHIFT                       12
+#define MADERA_FLL1_PHASE_GAIN_WIDTH                        4
+#define MADERA_FLL1_PHASE_ENA_MASK                     0x0800
+#define MADERA_FLL1_PHASE_ENA_SHIFT                        11
+#define MADERA_FLL1_PHASE_ENA_WIDTH                         1
+
+/* (0x0181)  FLL1_Synchroniser_1 */
+#define MADERA_FLL1_SYNC_ENA                           0x0001
+#define MADERA_FLL1_SYNC_ENA_MASK                      0x0001
+#define MADERA_FLL1_SYNC_ENA_SHIFT                          0
+#define MADERA_FLL1_SYNC_ENA_WIDTH                          1
+
+/* (0x0182)  FLL1_Synchroniser_2 */
+#define MADERA_FLL1_SYNC_N_MASK                                0x03FF
+#define MADERA_FLL1_SYNC_N_SHIFT                            0
+#define MADERA_FLL1_SYNC_N_WIDTH                           10
+
+/* (0x0183)  FLL1_Synchroniser_3 */
+#define MADERA_FLL1_SYNC_THETA_MASK                    0xFFFF
+#define MADERA_FLL1_SYNC_THETA_SHIFT                        0
+#define MADERA_FLL1_SYNC_THETA_WIDTH                       16
+
+/* (0x0184)  FLL1_Synchroniser_4 */
+#define MADERA_FLL1_SYNC_LAMBDA_MASK                   0xFFFF
+#define MADERA_FLL1_SYNC_LAMBDA_SHIFT                       0
+#define MADERA_FLL1_SYNC_LAMBDA_WIDTH                      16
+
+/* (0x0185)  FLL1_Synchroniser_5 */
+#define MADERA_FLL1_SYNC_FRATIO_MASK                   0x0700
+#define MADERA_FLL1_SYNC_FRATIO_SHIFT                       8
+#define MADERA_FLL1_SYNC_FRATIO_WIDTH                       3
+
+/* (0x0186)  FLL1_Synchroniser_6 */
+#define MADERA_FLL1_SYNCCLK_DIV_MASK                   0x00C0
+#define MADERA_FLL1_SYNCCLK_DIV_SHIFT                       6
+#define MADERA_FLL1_SYNCCLK_DIV_WIDTH                       2
+#define MADERA_FLL1_SYNCCLK_SRC_MASK                   0x000F
+#define MADERA_FLL1_SYNCCLK_SRC_SHIFT                       0
+#define MADERA_FLL1_SYNCCLK_SRC_WIDTH                       4
+
+/* (0x0187)  FLL1_Synchroniser_7 */
+#define MADERA_FLL1_SYNC_GAIN_MASK                     0x003c
+#define MADERA_FLL1_SYNC_GAIN_SHIFT                         2
+#define MADERA_FLL1_SYNC_GAIN_WIDTH                         4
+#define MADERA_FLL1_SYNC_DFSAT                         0x0001
+#define MADERA_FLL1_SYNC_DFSAT_MASK                    0x0001
+#define MADERA_FLL1_SYNC_DFSAT_SHIFT                        0
+#define MADERA_FLL1_SYNC_DFSAT_WIDTH                        1
+
+/* (0x01D1)  FLL_AO_Control_1 */
+#define MADERA_FLL_AO_HOLD                             0x0004
+#define MADERA_FLL_AO_HOLD_MASK                                0x0004
+#define MADERA_FLL_AO_HOLD_SHIFT                            2
+#define MADERA_FLL_AO_HOLD_WIDTH                            1
+#define MADERA_FLL_AO_FREERUN                          0x0002
+#define MADERA_FLL_AO_FREERUN_MASK                     0x0002
+#define MADERA_FLL_AO_FREERUN_SHIFT                         1
+#define MADERA_FLL_AO_FREERUN_WIDTH                         1
+#define MADERA_FLL_AO_ENA                              0x0001
+#define MADERA_FLL_AO_ENA_MASK                         0x0001
+#define MADERA_FLL_AO_ENA_SHIFT                                     0
+#define MADERA_FLL_AO_ENA_WIDTH                                     1
+
+/* (0x01D2)  FLL_AO_Control_2 */
+#define MADERA_FLL_AO_CTRL_UPD                         0x8000
+#define MADERA_FLL_AO_CTRL_UPD_MASK                    0x8000
+#define MADERA_FLL_AO_CTRL_UPD_SHIFT                       15
+#define MADERA_FLL_AO_CTRL_UPD_WIDTH                        1
+
+/* (0x01D6)  FLL_AO_Control_6 */
+#define MADERA_FLL_AO_REFCLK_SRC_MASK                  0x000F
+#define MADERA_FLL_AO_REFCLK_SRC_SHIFT                      0
+#define MADERA_FLL_AO_REFCLK_SRC_WIDTH                      4
+
+/* (0x0200)  Mic_Charge_Pump_1 */
+#define MADERA_CPMIC_BYPASS                            0x0002
+#define MADERA_CPMIC_BYPASS_MASK                       0x0002
+#define MADERA_CPMIC_BYPASS_SHIFT                           1
+#define MADERA_CPMIC_BYPASS_WIDTH                           1
+#define MADERA_CPMIC_ENA                               0x0001
+#define MADERA_CPMIC_ENA_MASK                          0x0001
+#define MADERA_CPMIC_ENA_SHIFT                              0
+#define MADERA_CPMIC_ENA_WIDTH                              1
+
+/* (0x0210)  LDO1_Control_1 */
+#define MADERA_LDO1_VSEL_MASK                          0x07E0
+#define MADERA_LDO1_VSEL_SHIFT                              5
+#define MADERA_LDO1_VSEL_WIDTH                              6
+#define MADERA_LDO1_FAST                               0x0010
+#define MADERA_LDO1_FAST_MASK                          0x0010
+#define MADERA_LDO1_FAST_SHIFT                              4
+#define MADERA_LDO1_FAST_WIDTH                              1
+#define MADERA_LDO1_DISCH                              0x0004
+#define MADERA_LDO1_DISCH_MASK                         0x0004
+#define MADERA_LDO1_DISCH_SHIFT                                     2
+#define MADERA_LDO1_DISCH_WIDTH                                     1
+#define MADERA_LDO1_BYPASS                             0x0002
+#define MADERA_LDO1_BYPASS_MASK                                0x0002
+#define MADERA_LDO1_BYPASS_SHIFT                            1
+#define MADERA_LDO1_BYPASS_WIDTH                            1
+#define MADERA_LDO1_ENA                                        0x0001
+#define MADERA_LDO1_ENA_MASK                           0x0001
+#define MADERA_LDO1_ENA_SHIFT                               0
+#define MADERA_LDO1_ENA_WIDTH                               1
+
+/* (0x0213)  LDO2_Control_1 */
+#define MADERA_LDO2_VSEL_MASK                          0x07E0
+#define MADERA_LDO2_VSEL_SHIFT                              5
+#define MADERA_LDO2_VSEL_WIDTH                              6
+#define MADERA_LDO2_FAST                               0x0010
+#define MADERA_LDO2_FAST_MASK                          0x0010
+#define MADERA_LDO2_FAST_SHIFT                              4
+#define MADERA_LDO2_FAST_WIDTH                              1
+#define MADERA_LDO2_DISCH                              0x0004
+#define MADERA_LDO2_DISCH_MASK                         0x0004
+#define MADERA_LDO2_DISCH_SHIFT                                     2
+#define MADERA_LDO2_DISCH_WIDTH                                     1
+#define MADERA_LDO2_BYPASS                             0x0002
+#define MADERA_LDO2_BYPASS_MASK                                0x0002
+#define MADERA_LDO2_BYPASS_SHIFT                            1
+#define MADERA_LDO2_BYPASS_WIDTH                            1
+#define MADERA_LDO2_ENA                                        0x0001
+#define MADERA_LDO2_ENA_MASK                           0x0001
+#define MADERA_LDO2_ENA_SHIFT                               0
+#define MADERA_LDO2_ENA_WIDTH                               1
+
+/* (0x0218)  Mic_Bias_Ctrl_1 */
+#define MADERA_MICB1_ENA                               0x0001
+#define MADERA_MICB1_ENA_MASK                          0x0001
+#define MADERA_MICB1_ENA_SHIFT                              0
+#define MADERA_MICB1_ENA_WIDTH                              1
+
+/* (0x021C)  Mic_Bias_Ctrl_5 */
+#define MADERA_MICB1D_ENA                              0x1000
+#define MADERA_MICB1D_ENA_MASK                         0x1000
+#define MADERA_MICB1D_ENA_SHIFT                                    12
+#define MADERA_MICB1D_ENA_WIDTH                                     1
+#define MADERA_MICB1C_ENA                              0x0100
+#define MADERA_MICB1C_ENA_MASK                         0x0100
+#define MADERA_MICB1C_ENA_SHIFT                                     8
+#define MADERA_MICB1C_ENA_WIDTH                                     1
+#define MADERA_MICB1B_ENA                              0x0010
+#define MADERA_MICB1B_ENA_MASK                         0x0010
+#define MADERA_MICB1B_ENA_SHIFT                                     4
+#define MADERA_MICB1B_ENA_WIDTH                                     1
+#define MADERA_MICB1A_ENA                              0x0001
+#define MADERA_MICB1A_ENA_MASK                         0x0001
+#define MADERA_MICB1A_ENA_SHIFT                                     0
+#define MADERA_MICB1A_ENA_WIDTH                                     1
+
+/* (0x021E)  Mic_Bias_Ctrl_6 */
+#define MADERA_MICB2D_ENA                              0x1000
+#define MADERA_MICB2D_ENA_MASK                         0x1000
+#define MADERA_MICB2D_ENA_SHIFT                                    12
+#define MADERA_MICB2D_ENA_WIDTH                                     1
+#define MADERA_MICB2C_ENA                              0x0100
+#define MADERA_MICB2C_ENA_MASK                         0x0100
+#define MADERA_MICB2C_ENA_SHIFT                                     8
+#define MADERA_MICB2C_ENA_WIDTH                                     1
+#define MADERA_MICB2B_ENA                              0x0010
+#define MADERA_MICB2B_ENA_MASK                         0x0010
+#define MADERA_MICB2B_ENA_SHIFT                                     4
+#define MADERA_MICB2B_ENA_WIDTH                                     1
+#define MADERA_MICB2A_ENA                              0x0001
+#define MADERA_MICB2A_ENA_MASK                         0x0001
+#define MADERA_MICB2A_ENA_SHIFT                                     0
+#define MADERA_MICB2A_ENA_WIDTH                                     1
+
+/* (0x0225) - HP Ctrl 1L */
+#define MADERA_RMV_SHRT_HP1L                           0x4000
+#define MADERA_RMV_SHRT_HP1L_MASK                      0x4000
+#define MADERA_RMV_SHRT_HP1L_SHIFT                         14
+#define MADERA_RMV_SHRT_HP1L_WIDTH                          1
+#define MADERA_HP1L_FLWR                               0x0004
+#define MADERA_HP1L_FLWR_MASK                          0x0004
+#define MADERA_HP1L_FLWR_SHIFT                              2
+#define MADERA_HP1L_FLWR_WIDTH                              1
+#define MADERA_HP1L_SHRTI                              0x0002
+#define MADERA_HP1L_SHRTI_MASK                         0x0002
+#define MADERA_HP1L_SHRTI_SHIFT                                     1
+#define MADERA_HP1L_SHRTI_WIDTH                                     1
+#define MADERA_HP1L_SHRTO                              0x0001
+#define MADERA_HP1L_SHRTO_MASK                         0x0001
+#define MADERA_HP1L_SHRTO_SHIFT                                     0
+#define MADERA_HP1L_SHRTO_WIDTH                                     1
+
+/* (0x0226) - HP Ctrl 1R */
+#define MADERA_RMV_SHRT_HP1R                           0x4000
+#define MADERA_RMV_SHRT_HP1R_MASK                      0x4000
+#define MADERA_RMV_SHRT_HP1R_SHIFT                         14
+#define MADERA_RMV_SHRT_HP1R_WIDTH                          1
+#define MADERA_HP1R_FLWR                               0x0004
+#define MADERA_HP1R_FLWR_MASK                          0x0004
+#define MADERA_HP1R_FLWR_SHIFT                              2
+#define MADERA_HP1R_FLWR_WIDTH                              1
+#define MADERA_HP1R_SHRTI                              0x0002
+#define MADERA_HP1R_SHRTI_MASK                         0x0002
+#define MADERA_HP1R_SHRTI_SHIFT                                     1
+#define MADERA_HP1R_SHRTI_WIDTH                                     1
+#define MADERA_HP1R_SHRTO                              0x0001
+#define MADERA_HP1R_SHRTO_MASK                         0x0001
+#define MADERA_HP1R_SHRTO_SHIFT                                     0
+#define MADERA_HP1R_SHRTO_WIDTH                                     1
+
+/* (0x0293)  Accessory_Detect_Mode_1 */
+#define MADERA_ACCDET_SRC                              0x2000
+#define MADERA_ACCDET_SRC_MASK                         0x2000
+#define MADERA_ACCDET_SRC_SHIFT                                    13
+#define MADERA_ACCDET_SRC_WIDTH                                     1
+#define MADERA_ACCDET_POLARITY_INV_ENA                 0x0080
+#define MADERA_ACCDET_POLARITY_INV_ENA_MASK            0x0080
+#define MADERA_ACCDET_POLARITY_INV_ENA_SHIFT                7
+#define MADERA_ACCDET_POLARITY_INV_ENA_WIDTH                1
+#define MADERA_ACCDET_MODE_MASK                                0x0007
+#define MADERA_ACCDET_MODE_SHIFT                            0
+#define MADERA_ACCDET_MODE_WIDTH                            3
+
+/* (0x0299)  Headphone_Detect_0 */
+#define MADERA_HPD_GND_SEL                             0x0007
+#define MADERA_HPD_GND_SEL_MASK                                0x0007
+#define MADERA_HPD_GND_SEL_SHIFT                            0
+#define MADERA_HPD_GND_SEL_WIDTH                            3
+#define MADERA_HPD_SENSE_SEL                           0x00F0
+#define MADERA_HPD_SENSE_SEL_MASK                      0x00F0
+#define MADERA_HPD_SENSE_SEL_SHIFT                          4
+#define MADERA_HPD_SENSE_SEL_WIDTH                          4
+#define MADERA_HPD_FRC_SEL                             0x0F00
+#define MADERA_HPD_FRC_SEL_MASK                                0x0F00
+#define MADERA_HPD_FRC_SEL_SHIFT                            8
+#define MADERA_HPD_FRC_SEL_WIDTH                            4
+#define MADERA_HPD_OUT_SEL                             0x7000
+#define MADERA_HPD_OUT_SEL_MASK                                0x7000
+#define MADERA_HPD_OUT_SEL_SHIFT                           12
+#define MADERA_HPD_OUT_SEL_WIDTH                            3
+#define MADERA_HPD_OVD_ENA_SEL                         0x8000
+#define MADERA_HPD_OVD_ENA_SEL_MASK                    0x8000
+#define MADERA_HPD_OVD_ENA_SEL_SHIFT                       15
+#define MADERA_HPD_OVD_ENA_SEL_WIDTH                        1
+
+/* (0x029B)  Headphone_Detect_1 */
+#define MADERA_HP_IMPEDANCE_RANGE_MASK                 0x0600
+#define MADERA_HP_IMPEDANCE_RANGE_SHIFT                             9
+#define MADERA_HP_IMPEDANCE_RANGE_WIDTH                             2
+#define MADERA_HP_STEP_SIZE                            0x0100
+#define MADERA_HP_STEP_SIZE_MASK                       0x0100
+#define MADERA_HP_STEP_SIZE_SHIFT                           8
+#define MADERA_HP_STEP_SIZE_WIDTH                           1
+#define MADERA_HP_CLK_DIV_MASK                         0x0018
+#define MADERA_HP_CLK_DIV_SHIFT                                     3
+#define MADERA_HP_CLK_DIV_WIDTH                                     2
+#define MADERA_HP_RATE_MASK                            0x0006
+#define MADERA_HP_RATE_SHIFT                                1
+#define MADERA_HP_RATE_WIDTH                                2
+#define MADERA_HP_POLL                                 0x0001
+#define MADERA_HP_POLL_MASK                            0x0001
+#define MADERA_HP_POLL_SHIFT                                0
+#define MADERA_HP_POLL_WIDTH                                1
+
+/* (0x029C)  Headphone_Detect_2 */
+#define MADERA_HP_DONE_MASK                            0x8000
+#define MADERA_HP_DONE_SHIFT                               15
+#define MADERA_HP_DONE_WIDTH                                1
+#define MADERA_HP_LVL_MASK                             0x7FFF
+#define MADERA_HP_LVL_SHIFT                                 0
+#define MADERA_HP_LVL_WIDTH                                15
+
+/* (0x029D)  Headphone_Detect_3 */
+#define MADERA_HP_DACVAL_MASK                          0x03FF
+#define MADERA_HP_DACVAL_SHIFT                              0
+#define MADERA_HP_DACVAL_WIDTH                             10
+
+/* (0x029F) - Headphone Detect 5 */
+#define MADERA_HP_DACVAL_DOWN_MASK                     0x03FF
+#define MADERA_HP_DACVAL_DOWN_SHIFT                         0
+#define MADERA_HP_DACVAL_DOWN_WIDTH                        10
+
+/* (0x02A2)  Mic_Detect_1_Control_0 */
+#define MADERA_MICD1_GND_MASK                          0x0007
+#define MADERA_MICD1_GND_SHIFT                              0
+#define MADERA_MICD1_GND_WIDTH                              3
+#define MADERA_MICD1_SENSE_MASK                                0x00F0
+#define MADERA_MICD1_SENSE_SHIFT                            4
+#define MADERA_MICD1_SENSE_WIDTH                            4
+#define MADERA_MICD1_ADC_MODE_MASK                     0x8000
+#define MADERA_MICD1_ADC_MODE_SHIFT                        15
+#define MADERA_MICD1_ADC_MODE_WIDTH                         1
+
+/* (0x02A3)  Mic_Detect_1_Control_1 */
+#define MADERA_MICD_BIAS_STARTTIME_MASK                        0xF000
+#define MADERA_MICD_BIAS_STARTTIME_SHIFT                   12
+#define MADERA_MICD_BIAS_STARTTIME_WIDTH                    4
+#define MADERA_MICD_RATE_MASK                          0x0F00
+#define MADERA_MICD_RATE_SHIFT                              8
+#define MADERA_MICD_RATE_WIDTH                              4
+#define MADERA_MICD_BIAS_SRC_MASK                      0x00F0
+#define MADERA_MICD_BIAS_SRC_SHIFT                          4
+#define MADERA_MICD_BIAS_SRC_WIDTH                          4
+#define MADERA_MICD_DBTIME                             0x0002
+#define MADERA_MICD_DBTIME_MASK                                0x0002
+#define MADERA_MICD_DBTIME_SHIFT                            1
+#define MADERA_MICD_DBTIME_WIDTH                            1
+#define MADERA_MICD_ENA                                        0x0001
+#define MADERA_MICD_ENA_MASK                           0x0001
+#define MADERA_MICD_ENA_SHIFT                               0
+#define MADERA_MICD_ENA_WIDTH                               1
+
+/* (0x02A4)  Mic_Detect_1_Control_2 */
+#define MADERA_MICD_LVL_SEL_MASK                       0x00FF
+#define MADERA_MICD_LVL_SEL_SHIFT                           0
+#define MADERA_MICD_LVL_SEL_WIDTH                           8
+
+/* (0x02A5)  Mic_Detect_1_Control_3 */
+#define MADERA_MICD_LVL_0                              0x0004
+#define MADERA_MICD_LVL_1                              0x0008
+#define MADERA_MICD_LVL_2                              0x0010
+#define MADERA_MICD_LVL_3                              0x0020
+#define MADERA_MICD_LVL_4                              0x0040
+#define MADERA_MICD_LVL_5                              0x0080
+#define MADERA_MICD_LVL_6                              0x0100
+#define MADERA_MICD_LVL_7                              0x0200
+#define MADERA_MICD_LVL_8                              0x0400
+#define MADERA_MICD_LVL_MASK                           0x07FC
+#define MADERA_MICD_LVL_SHIFT                               2
+#define MADERA_MICD_LVL_WIDTH                               9
+#define MADERA_MICD_VALID                              0x0002
+#define MADERA_MICD_VALID_MASK                         0x0002
+#define MADERA_MICD_VALID_SHIFT                                     1
+#define MADERA_MICD_VALID_WIDTH                                     1
+#define MADERA_MICD_STS                                        0x0001
+#define MADERA_MICD_STS_MASK                           0x0001
+#define MADERA_MICD_STS_SHIFT                               0
+#define MADERA_MICD_STS_WIDTH                               1
+
+/* (0x02AB)  Mic_Detect_1_Control_4 */
+#define MADERA_MICDET_ADCVAL_DIFF_MASK                 0xFF00
+#define MADERA_MICDET_ADCVAL_DIFF_SHIFT                             8
+#define MADERA_MICDET_ADCVAL_DIFF_WIDTH                             8
+#define MADERA_MICDET_ADCVAL_MASK                      0x007F
+#define MADERA_MICDET_ADCVAL_SHIFT                          0
+#define MADERA_MICDET_ADCVAL_WIDTH                          7
+
+/* (0x02C6)  Micd_Clamp_control */
+#define MADERA_MICD_CLAMP_OVD                          0x0010
+#define MADERA_MICD_CLAMP_OVD_MASK                     0x0010
+#define MADERA_MICD_CLAMP_OVD_SHIFT                         4
+#define MADERA_MICD_CLAMP_OVD_WIDTH                         1
+#define MADERA_MICD_CLAMP_MODE_MASK                    0x000F
+#define MADERA_MICD_CLAMP_MODE_SHIFT                        0
+#define MADERA_MICD_CLAMP_MODE_WIDTH                        4
+
+/* (0x02C8)  GP_Switch_1 */
+#define MADERA_SW2_MODE_MASK                           0x000C
+#define MADERA_SW2_MODE_SHIFT                               2
+#define MADERA_SW2_MODE_WIDTH                               2
+#define MADERA_SW1_MODE_MASK                           0x0003
+#define MADERA_SW1_MODE_SHIFT                               0
+#define MADERA_SW1_MODE_WIDTH                               2
+
+/* (0x02D3)  Jack_detect_analogue */
+#define MADERA_JD2_ENA                                 0x0002
+#define MADERA_JD2_ENA_MASK                            0x0002
+#define MADERA_JD2_ENA_SHIFT                                1
+#define MADERA_JD2_ENA_WIDTH                                1
+#define MADERA_JD1_ENA                                 0x0001
+#define MADERA_JD1_ENA_MASK                            0x0001
+#define MADERA_JD1_ENA_SHIFT                                0
+#define MADERA_JD1_ENA_WIDTH                                1
+
+/* (0x0300)  Input_Enables */
+#define MADERA_IN6L_ENA                                        0x0800
+#define MADERA_IN6L_ENA_MASK                           0x0800
+#define MADERA_IN6L_ENA_SHIFT                              11
+#define MADERA_IN6L_ENA_WIDTH                               1
+#define MADERA_IN6R_ENA                                        0x0400
+#define MADERA_IN6R_ENA_MASK                           0x0400
+#define MADERA_IN6R_ENA_SHIFT                              10
+#define MADERA_IN6R_ENA_WIDTH                               1
+#define MADERA_IN5L_ENA                                        0x0200
+#define MADERA_IN5L_ENA_MASK                           0x0200
+#define MADERA_IN5L_ENA_SHIFT                               9
+#define MADERA_IN5L_ENA_WIDTH                               1
+#define MADERA_IN5R_ENA                                        0x0100
+#define MADERA_IN5R_ENA_MASK                           0x0100
+#define MADERA_IN5R_ENA_SHIFT                               8
+#define MADERA_IN5R_ENA_WIDTH                               1
+#define MADERA_IN4L_ENA                                        0x0080
+#define MADERA_IN4L_ENA_MASK                           0x0080
+#define MADERA_IN4L_ENA_SHIFT                               7
+#define MADERA_IN4L_ENA_WIDTH                               1
+#define MADERA_IN4R_ENA                                        0x0040
+#define MADERA_IN4R_ENA_MASK                           0x0040
+#define MADERA_IN4R_ENA_SHIFT                               6
+#define MADERA_IN4R_ENA_WIDTH                               1
+#define MADERA_IN3L_ENA                                        0x0020
+#define MADERA_IN3L_ENA_MASK                           0x0020
+#define MADERA_IN3L_ENA_SHIFT                               5
+#define MADERA_IN3L_ENA_WIDTH                               1
+#define MADERA_IN3R_ENA                                        0x0010
+#define MADERA_IN3R_ENA_MASK                           0x0010
+#define MADERA_IN3R_ENA_SHIFT                               4
+#define MADERA_IN3R_ENA_WIDTH                               1
+#define MADERA_IN2L_ENA                                        0x0008
+#define MADERA_IN2L_ENA_MASK                           0x0008
+#define MADERA_IN2L_ENA_SHIFT                               3
+#define MADERA_IN2L_ENA_WIDTH                               1
+#define MADERA_IN2R_ENA                                        0x0004
+#define MADERA_IN2R_ENA_MASK                           0x0004
+#define MADERA_IN2R_ENA_SHIFT                               2
+#define MADERA_IN2R_ENA_WIDTH                               1
+#define MADERA_IN1L_ENA                                        0x0002
+#define MADERA_IN1L_ENA_MASK                           0x0002
+#define MADERA_IN1L_ENA_SHIFT                               1
+#define MADERA_IN1L_ENA_WIDTH                               1
+#define MADERA_IN1R_ENA                                        0x0001
+#define MADERA_IN1R_ENA_MASK                           0x0001
+#define MADERA_IN1R_ENA_SHIFT                               0
+#define MADERA_IN1R_ENA_WIDTH                               1
+
+/* (0x0308)  Input_Rate */
+#define MADERA_IN_RATE_MASK                            0xF800
+#define MADERA_IN_RATE_SHIFT                               11
+#define MADERA_IN_RATE_WIDTH                                5
+#define MADERA_IN_MODE_MASK                            0x0400
+#define MADERA_IN_MODE_SHIFT                               10
+#define MADERA_IN_MODE_WIDTH                                1
+
+/* (0x0309)  Input_Volume_Ramp */
+#define MADERA_IN_VD_RAMP_MASK                         0x0070
+#define MADERA_IN_VD_RAMP_SHIFT                                     4
+#define MADERA_IN_VD_RAMP_WIDTH                                     3
+#define MADERA_IN_VI_RAMP_MASK                         0x0007
+#define MADERA_IN_VI_RAMP_SHIFT                                     0
+#define MADERA_IN_VI_RAMP_WIDTH                                     3
+
+/* (0x030C)  HPF_Control */
+#define MADERA_IN_HPF_CUT_MASK                         0x0007
+#define MADERA_IN_HPF_CUT_SHIFT                                     0
+#define MADERA_IN_HPF_CUT_WIDTH                                     3
+
+/* (0x0310)  IN1L_Control */
+#define MADERA_IN1L_HPF_MASK                           0x8000
+#define MADERA_IN1L_HPF_SHIFT                              15
+#define MADERA_IN1L_HPF_WIDTH                               1
+#define MADERA_IN1_DMIC_SUP_MASK                       0x1800
+#define MADERA_IN1_DMIC_SUP_SHIFT                          11
+#define MADERA_IN1_DMIC_SUP_WIDTH                           2
+#define MADERA_IN1_MODE_MASK                           0x0400
+#define MADERA_IN1_MODE_SHIFT                              10
+#define MADERA_IN1_MODE_WIDTH                               1
+#define MADERA_IN1L_PGA_VOL_MASK                       0x00FE
+#define MADERA_IN1L_PGA_VOL_SHIFT                           1
+#define MADERA_IN1L_PGA_VOL_WIDTH                           7
+
+/* (0x0311)  ADC_Digital_Volume_1L */
+#define MADERA_IN1L_SRC_MASK                           0x4000
+#define MADERA_IN1L_SRC_SHIFT                              14
+#define MADERA_IN1L_SRC_WIDTH                               1
+#define MADERA_IN1L_SRC_SE_MASK                                0x2000
+#define MADERA_IN1L_SRC_SE_SHIFT                           13
+#define MADERA_IN1L_SRC_SE_WIDTH                            1
+#define MADERA_IN1L_LP_MODE                            0x0800
+#define MADERA_IN1L_LP_MODE_MASK                       0x0800
+#define MADERA_IN1L_LP_MODE_SHIFT                          11
+#define MADERA_IN1L_LP_MODE_WIDTH                           1
+#define MADERA_IN_VU                                   0x0200
+#define MADERA_IN_VU_MASK                              0x0200
+#define MADERA_IN_VU_SHIFT                                  9
+#define MADERA_IN_VU_WIDTH                                  1
+#define MADERA_IN1L_MUTE                               0x0100
+#define MADERA_IN1L_MUTE_MASK                          0x0100
+#define MADERA_IN1L_MUTE_SHIFT                              8
+#define MADERA_IN1L_MUTE_WIDTH                              1
+#define MADERA_IN1L_DIG_VOL_MASK                       0x00FF
+#define MADERA_IN1L_DIG_VOL_SHIFT                           0
+#define MADERA_IN1L_DIG_VOL_WIDTH                           8
+
+/* (0x0312)  DMIC1L_Control */
+#define MADERA_IN1_OSR_MASK                            0x0700
+#define MADERA_IN1_OSR_SHIFT                                8
+#define MADERA_IN1_OSR_WIDTH                                3
+
+/* (0x0313)  IN1L_Rate_Control */
+#define MADERA_IN1L_RATE_MASK                          0xF800
+#define MADERA_IN1L_RATE_SHIFT                             11
+#define MADERA_IN1L_RATE_WIDTH                              5
+
+/* (0x0314)  IN1R_Control */
+#define MADERA_IN1R_HPF_MASK                           0x8000
+#define MADERA_IN1R_HPF_SHIFT                              15
+#define MADERA_IN1R_HPF_WIDTH                               1
+#define MADERA_IN1R_PGA_VOL_MASK                       0x00FE
+#define MADERA_IN1R_PGA_VOL_SHIFT                           1
+#define MADERA_IN1R_PGA_VOL_WIDTH                           7
+#define MADERA_IN1_DMICCLK_SRC_MASK                    0x1800
+#define MADERA_IN1_DMICCLK_SRC_SHIFT                       11
+#define MADERA_IN1_DMICCLK_SRC_WIDTH                        2
+
+/* (0x0315)  ADC_Digital_Volume_1R */
+#define MADERA_IN1R_SRC_MASK                           0x4000
+#define MADERA_IN1R_SRC_SHIFT                              14
+#define MADERA_IN1R_SRC_WIDTH                               1
+#define MADERA_IN1R_SRC_SE_MASK                                0x2000
+#define MADERA_IN1R_SRC_SE_SHIFT                           13
+#define MADERA_IN1R_SRC_SE_WIDTH                            1
+#define MADERA_IN1R_LP_MODE                            0x0800
+#define MADERA_IN1R_LP_MODE_MASK                       0x0800
+#define MADERA_IN1R_LP_MODE_SHIFT                          11
+#define MADERA_IN1R_LP_MODE_WIDTH                           1
+#define MADERA_IN1R_MUTE                               0x0100
+#define MADERA_IN1R_MUTE_MASK                          0x0100
+#define MADERA_IN1R_MUTE_SHIFT                              8
+#define MADERA_IN1R_MUTE_WIDTH                              1
+#define MADERA_IN1R_DIG_VOL_MASK                       0x00FF
+#define MADERA_IN1R_DIG_VOL_SHIFT                           0
+#define MADERA_IN1R_DIG_VOL_WIDTH                           8
+
+/* (0x0317)  IN1R_Rate_Control */
+#define MADERA_IN1R_RATE_MASK                          0xF800
+#define MADERA_IN1R_RATE_SHIFT                             11
+#define MADERA_IN1R_RATE_WIDTH                              5
+
+/* (0x0318)  IN2L_Control */
+#define MADERA_IN2L_HPF_MASK                           0x8000
+#define MADERA_IN2L_HPF_SHIFT                              15
+#define MADERA_IN2L_HPF_WIDTH                               1
+#define MADERA_IN2_DMIC_SUP_MASK                       0x1800
+#define MADERA_IN2_DMIC_SUP_SHIFT                          11
+#define MADERA_IN2_DMIC_SUP_WIDTH                           2
+#define MADERA_IN2_MODE_MASK                           0x0400
+#define MADERA_IN2_MODE_SHIFT                              10
+#define MADERA_IN2_MODE_WIDTH                               1
+#define MADERA_IN2L_PGA_VOL_MASK                       0x00FE
+#define MADERA_IN2L_PGA_VOL_SHIFT                           1
+#define MADERA_IN2L_PGA_VOL_WIDTH                           7
+
+/* (0x0319)  ADC_Digital_Volume_2L */
+#define MADERA_IN2L_SRC_MASK                           0x4000
+#define MADERA_IN2L_SRC_SHIFT                              14
+#define MADERA_IN2L_SRC_WIDTH                               1
+#define MADERA_IN2L_SRC_SE_MASK                                0x2000
+#define MADERA_IN2L_SRC_SE_SHIFT                           13
+#define MADERA_IN2L_SRC_SE_WIDTH                            1
+#define MADERA_IN2L_LP_MODE                            0x0800
+#define MADERA_IN2L_LP_MODE_MASK                       0x0800
+#define MADERA_IN2L_LP_MODE_SHIFT                          11
+#define MADERA_IN2L_LP_MODE_WIDTH                           1
+#define MADERA_IN2L_MUTE                               0x0100
+#define MADERA_IN2L_MUTE_MASK                          0x0100
+#define MADERA_IN2L_MUTE_SHIFT                              8
+#define MADERA_IN2L_MUTE_WIDTH                              1
+#define MADERA_IN2L_DIG_VOL_MASK                       0x00FF
+#define MADERA_IN2L_DIG_VOL_SHIFT                           0
+#define MADERA_IN2L_DIG_VOL_WIDTH                           8
+
+/* (0x031A)  DMIC2L_Control */
+#define MADERA_IN2_OSR_MASK                            0x0700
+#define MADERA_IN2_OSR_SHIFT                                8
+#define MADERA_IN2_OSR_WIDTH                                3
+
+/* (0x031C)  IN2R_Control */
+#define MADERA_IN2R_HPF_MASK                           0x8000
+#define MADERA_IN2R_HPF_SHIFT                              15
+#define MADERA_IN2R_HPF_WIDTH                               1
+#define MADERA_IN2R_PGA_VOL_MASK                       0x00FE
+#define MADERA_IN2R_PGA_VOL_SHIFT                           1
+#define MADERA_IN2R_PGA_VOL_WIDTH                           7
+#define MADERA_IN2_DMICCLK_SRC_MASK                    0x1800
+#define MADERA_IN2_DMICCLK_SRC_SHIFT                       11
+#define MADERA_IN2_DMICCLK_SRC_WIDTH                        2
+
+/* (0x031D)  ADC_Digital_Volume_2R */
+#define MADERA_IN2R_SRC_MASK                           0x4000
+#define MADERA_IN2R_SRC_SHIFT                              14
+#define MADERA_IN2R_SRC_WIDTH                               1
+#define MADERA_IN2R_SRC_SE_MASK                                0x2000
+#define MADERA_IN2R_SRC_SE_SHIFT                           13
+#define MADERA_IN2R_SRC_SE_WIDTH                            1
+#define MADERA_IN2R_LP_MODE                            0x0800
+#define MADERA_IN2R_LP_MODE_MASK                       0x0800
+#define MADERA_IN2R_LP_MODE_SHIFT                          11
+#define MADERA_IN2R_LP_MODE_WIDTH                           1
+#define MADERA_IN2R_MUTE                               0x0100
+#define MADERA_IN2R_MUTE_MASK                          0x0100
+#define MADERA_IN2R_MUTE_SHIFT                              8
+#define MADERA_IN2R_MUTE_WIDTH                              1
+#define MADERA_IN2R_DIG_VOL_MASK                       0x00FF
+#define MADERA_IN2R_DIG_VOL_SHIFT                           0
+#define MADERA_IN2R_DIG_VOL_WIDTH                           8
+
+/* (0x0320)  IN3L_Control */
+#define MADERA_IN3L_HPF_MASK                           0x8000
+#define MADERA_IN3L_HPF_SHIFT                              15
+#define MADERA_IN3L_HPF_WIDTH                               1
+#define MADERA_IN3_DMIC_SUP_MASK                       0x1800
+#define MADERA_IN3_DMIC_SUP_SHIFT                          11
+#define MADERA_IN3_DMIC_SUP_WIDTH                           2
+#define MADERA_IN3_MODE_MASK                           0x0400
+#define MADERA_IN3_MODE_SHIFT                              10
+#define MADERA_IN3_MODE_WIDTH                               1
+#define MADERA_IN3L_PGA_VOL_MASK                       0x00FE
+#define MADERA_IN3L_PGA_VOL_SHIFT                           1
+#define MADERA_IN3L_PGA_VOL_WIDTH                           7
+
+/* (0x0321)  ADC_Digital_Volume_3L */
+#define MADERA_IN3L_MUTE                               0x0100
+#define MADERA_IN3L_MUTE_MASK                          0x0100
+#define MADERA_IN3L_MUTE_SHIFT                              8
+#define MADERA_IN3L_MUTE_WIDTH                              1
+#define MADERA_IN3L_DIG_VOL_MASK                       0x00FF
+#define MADERA_IN3L_DIG_VOL_SHIFT                           0
+#define MADERA_IN3L_DIG_VOL_WIDTH                           8
+
+/* (0x0322)  DMIC3L_Control */
+#define MADERA_IN3_OSR_MASK                            0x0700
+#define MADERA_IN3_OSR_SHIFT                                8
+#define MADERA_IN3_OSR_WIDTH                                3
+
+/* (0x0324)  IN3R_Control */
+#define MADERA_IN3R_HPF_MASK                           0x8000
+#define MADERA_IN3R_HPF_SHIFT                              15
+#define MADERA_IN3R_HPF_WIDTH                               1
+#define MADERA_IN3R_PGA_VOL_MASK                       0x00FE
+#define MADERA_IN3R_PGA_VOL_SHIFT                           1
+#define MADERA_IN3R_PGA_VOL_WIDTH                           7
+#define MADERA_IN3_DMICCLK_SRC_MASK                    0x1800
+#define MADERA_IN3_DMICCLK_SRC_SHIFT                       11
+#define MADERA_IN3_DMICCLK_SRC_WIDTH                        2
+
+/* (0x0325)  ADC_Digital_Volume_3R */
+#define MADERA_IN3R_MUTE                               0x0100
+#define MADERA_IN3R_MUTE_MASK                          0x0100
+#define MADERA_IN3R_MUTE_SHIFT                              8
+#define MADERA_IN3R_MUTE_WIDTH                              1
+#define MADERA_IN3R_DIG_VOL_MASK                       0x00FF
+#define MADERA_IN3R_DIG_VOL_SHIFT                           0
+#define MADERA_IN3R_DIG_VOL_WIDTH                           8
+
+/* (0x0328)  IN4L_Control */
+#define MADERA_IN4L_HPF_MASK                           0x8000
+#define MADERA_IN4L_HPF_SHIFT                              15
+#define MADERA_IN4L_HPF_WIDTH                               1
+#define MADERA_IN4_DMIC_SUP_MASK                       0x1800
+#define MADERA_IN4_DMIC_SUP_SHIFT                          11
+#define MADERA_IN4_DMIC_SUP_WIDTH                           2
+
+/* (0x0329)  ADC_Digital_Volume_4L */
+#define MADERA_IN4L_MUTE                               0x0100
+#define MADERA_IN4L_MUTE_MASK                          0x0100
+#define MADERA_IN4L_MUTE_SHIFT                              8
+#define MADERA_IN4L_MUTE_WIDTH                              1
+#define MADERA_IN4L_DIG_VOL_MASK                       0x00FF
+#define MADERA_IN4L_DIG_VOL_SHIFT                           0
+#define MADERA_IN4L_DIG_VOL_WIDTH                           8
+
+/* (0x032A)  DMIC4L_Control */
+#define MADERA_IN4_OSR_MASK                            0x0700
+#define MADERA_IN4_OSR_SHIFT                                8
+#define MADERA_IN4_OSR_WIDTH                                3
+
+/* (0x032C)  IN4R_Control */
+#define MADERA_IN4R_HPF_MASK                           0x8000
+#define MADERA_IN4R_HPF_SHIFT                              15
+#define MADERA_IN4R_HPF_WIDTH                               1
+#define MADERA_IN4_DMICCLK_SRC_MASK                    0x1800
+#define MADERA_IN4_DMICCLK_SRC_SHIFT                       11
+#define MADERA_IN4_DMICCLK_SRC_WIDTH                        2
+
+/* (0x032D)  ADC_Digital_Volume_4R */
+#define MADERA_IN4R_MUTE                               0x0100
+#define MADERA_IN4R_MUTE_MASK                          0x0100
+#define MADERA_IN4R_MUTE_SHIFT                              8
+#define MADERA_IN4R_MUTE_WIDTH                              1
+#define MADERA_IN4R_DIG_VOL_MASK                       0x00FF
+#define MADERA_IN4R_DIG_VOL_SHIFT                           0
+#define MADERA_IN4R_DIG_VOL_WIDTH                           8
+
+/* (0x0330)  IN5L_Control */
+#define MADERA_IN5L_HPF_MASK                           0x8000
+#define MADERA_IN5L_HPF_SHIFT                              15
+#define MADERA_IN5L_HPF_WIDTH                               1
+#define MADERA_IN5_DMIC_SUP_MASK                       0x1800
+#define MADERA_IN5_DMIC_SUP_SHIFT                          11
+#define MADERA_IN5_DMIC_SUP_WIDTH                           2
+
+/* (0x0331)  ADC_Digital_Volume_5L */
+#define MADERA_IN5L_MUTE                               0x0100
+#define MADERA_IN5L_MUTE_MASK                          0x0100
+#define MADERA_IN5L_MUTE_SHIFT                              8
+#define MADERA_IN5L_MUTE_WIDTH                              1
+#define MADERA_IN5L_DIG_VOL_MASK                       0x00FF
+#define MADERA_IN5L_DIG_VOL_SHIFT                           0
+#define MADERA_IN5L_DIG_VOL_WIDTH                           8
+
+/* (0x0332)  DMIC5L_Control */
+#define MADERA_IN5_OSR_MASK                            0x0700
+#define MADERA_IN5_OSR_SHIFT                                8
+#define MADERA_IN5_OSR_WIDTH                                3
+
+/* (0x0334)  IN5R_Control */
+#define MADERA_IN5R_HPF_MASK                           0x8000
+#define MADERA_IN5R_HPF_SHIFT                              15
+#define MADERA_IN5R_HPF_WIDTH                               1
+#define MADERA_IN5_DMICCLK_SRC_MASK                    0x1800
+#define MADERA_IN5_DMICCLK_SRC_SHIFT                       11
+#define MADERA_IN5_DMICCLK_SRC_WIDTH                        2
+
+/* (0x0335)  ADC_Digital_Volume_5R */
+#define MADERA_IN5R_MUTE                               0x0100
+#define MADERA_IN5R_MUTE_MASK                          0x0100
+#define MADERA_IN5R_MUTE_SHIFT                              8
+#define MADERA_IN5R_MUTE_WIDTH                              1
+#define MADERA_IN5R_DIG_VOL_MASK                       0x00FF
+#define MADERA_IN5R_DIG_VOL_SHIFT                           0
+#define MADERA_IN5R_DIG_VOL_WIDTH                           8
+
+/* (0x0338)  IN6L_Control */
+#define MADERA_IN6L_HPF_MASK                           0x8000
+#define MADERA_IN6L_HPF_SHIFT                              15
+#define MADERA_IN6L_HPF_WIDTH                               1
+#define MADERA_IN6_DMIC_SUP_MASK                       0x1800
+#define MADERA_IN6_DMIC_SUP_SHIFT                          11
+#define MADERA_IN6_DMIC_SUP_WIDTH                           2
+
+/* (0x0339)  ADC_Digital_Volume_6L */
+#define MADERA_IN6L_MUTE                               0x0100
+#define MADERA_IN6L_MUTE_MASK                          0x0100
+#define MADERA_IN6L_MUTE_SHIFT                              8
+#define MADERA_IN6L_MUTE_WIDTH                              1
+#define MADERA_IN6L_DIG_VOL_MASK                       0x00FF
+#define MADERA_IN6L_DIG_VOL_SHIFT                           0
+#define MADERA_IN6L_DIG_VOL_WIDTH                           8
+
+/* (0x033A)  DMIC6L_Control */
+#define MADERA_IN6_OSR_MASK                            0x0700
+#define MADERA_IN6_OSR_SHIFT                                8
+#define MADERA_IN6_OSR_WIDTH                                3
+
+/* (0x033C)  IN6R_Control */
+#define MADERA_IN6R_HPF_MASK                           0x8000
+#define MADERA_IN6R_HPF_SHIFT                              15
+#define MADERA_IN6R_HPF_WIDTH                               1
+
+/* (0x033D)  ADC_Digital_Volume_6R */
+#define MADERA_IN6R_MUTE                               0x0100
+#define MADERA_IN6R_MUTE_MASK                          0x0100
+#define MADERA_IN6R_MUTE_SHIFT                              8
+#define MADERA_IN6R_MUTE_WIDTH                              1
+#define MADERA_IN6R_DIG_VOL_MASK                       0x00FF
+#define MADERA_IN6R_DIG_VOL_SHIFT                           0
+#define MADERA_IN6R_DIG_VOL_WIDTH                           8
+
+/* (0x033E)  DMIC6R_Control */
+#define MADERA_IN6_DMICCLK_SRC_MASK                    0x1800
+#define MADERA_IN6_DMICCLK_SRC_SHIFT                       11
+#define MADERA_IN6_DMICCLK_SRC_WIDTH                        2
+
+/* (0x0400)  Output_Enables_1 */
+#define MADERA_EP_SEL                                  0x8000
+#define MADERA_EP_SEL_MASK                             0x8000
+#define MADERA_EP_SEL_SHIFT                                15
+#define MADERA_EP_SEL_WIDTH                                 1
+#define MADERA_OUT6L_ENA                               0x0800
+#define MADERA_OUT6L_ENA_MASK                          0x0800
+#define MADERA_OUT6L_ENA_SHIFT                             11
+#define MADERA_OUT6L_ENA_WIDTH                              1
+#define MADERA_OUT6R_ENA                               0x0400
+#define MADERA_OUT6R_ENA_MASK                          0x0400
+#define MADERA_OUT6R_ENA_SHIFT                             10
+#define MADERA_OUT6R_ENA_WIDTH                              1
+#define MADERA_OUT5L_ENA                               0x0200
+#define MADERA_OUT5L_ENA_MASK                          0x0200
+#define MADERA_OUT5L_ENA_SHIFT                              9
+#define MADERA_OUT5L_ENA_WIDTH                              1
+#define MADERA_OUT5R_ENA                               0x0100
+#define MADERA_OUT5R_ENA_MASK                          0x0100
+#define MADERA_OUT5R_ENA_SHIFT                              8
+#define MADERA_OUT5R_ENA_WIDTH                              1
+#define MADERA_OUT4L_ENA                               0x0080
+#define MADERA_OUT4L_ENA_MASK                          0x0080
+#define MADERA_OUT4L_ENA_SHIFT                              7
+#define MADERA_OUT4L_ENA_WIDTH                              1
+#define MADERA_OUT4R_ENA                               0x0040
+#define MADERA_OUT4R_ENA_MASK                          0x0040
+#define MADERA_OUT4R_ENA_SHIFT                              6
+#define MADERA_OUT4R_ENA_WIDTH                              1
+#define MADERA_OUT3L_ENA                               0x0020
+#define MADERA_OUT3L_ENA_MASK                          0x0020
+#define MADERA_OUT3L_ENA_SHIFT                              5
+#define MADERA_OUT3L_ENA_WIDTH                              1
+#define MADERA_OUT3R_ENA                               0x0010
+#define MADERA_OUT3R_ENA_MASK                          0x0010
+#define MADERA_OUT3R_ENA_SHIFT                              4
+#define MADERA_OUT3R_ENA_WIDTH                              1
+#define MADERA_OUT2L_ENA                               0x0008
+#define MADERA_OUT2L_ENA_MASK                          0x0008
+#define MADERA_OUT2L_ENA_SHIFT                              3
+#define MADERA_OUT2L_ENA_WIDTH                              1
+#define MADERA_OUT2R_ENA                               0x0004
+#define MADERA_OUT2R_ENA_MASK                          0x0004
+#define MADERA_OUT2R_ENA_SHIFT                              2
+#define MADERA_OUT2R_ENA_WIDTH                              1
+#define MADERA_OUT1L_ENA                               0x0002
+#define MADERA_OUT1L_ENA_MASK                          0x0002
+#define MADERA_OUT1L_ENA_SHIFT                              1
+#define MADERA_OUT1L_ENA_WIDTH                              1
+#define MADERA_OUT1R_ENA                               0x0001
+#define MADERA_OUT1R_ENA_MASK                          0x0001
+#define MADERA_OUT1R_ENA_SHIFT                              0
+#define MADERA_OUT1R_ENA_WIDTH                              1
+
+/* (0x0409)  Output_Volume_Ramp */
+#define MADERA_OUT_VD_RAMP_MASK                                0x0070
+#define MADERA_OUT_VD_RAMP_SHIFT                            4
+#define MADERA_OUT_VD_RAMP_WIDTH                            3
+#define MADERA_OUT_VI_RAMP_MASK                                0x0007
+#define MADERA_OUT_VI_RAMP_SHIFT                            0
+#define MADERA_OUT_VI_RAMP_WIDTH                            3
+
+/* (0x0410)  Output_Path_Config_1L */
+#define MADERA_OUT1_MONO                               0x1000
+#define MADERA_OUT1_MONO_MASK                          0x1000
+#define MADERA_OUT1_MONO_SHIFT                             12
+#define MADERA_OUT1_MONO_WIDTH                              1
+#define MADERA_OUT1L_ANC_SRC_MASK                      0x0C00
+#define MADERA_OUT1L_ANC_SRC_SHIFT                         10
+#define MADERA_OUT1L_ANC_SRC_WIDTH                          2
+
+/* (0x0411)  DAC_Digital_Volume_1L */
+#define MADERA_OUT1L_VU                                        0x0200
+#define MADERA_OUT1L_VU_MASK                           0x0200
+#define MADERA_OUT1L_VU_SHIFT                               9
+#define MADERA_OUT1L_VU_WIDTH                               1
+#define MADERA_OUT1L_MUTE                              0x0100
+#define MADERA_OUT1L_MUTE_MASK                         0x0100
+#define MADERA_OUT1L_MUTE_SHIFT                                     8
+#define MADERA_OUT1L_MUTE_WIDTH                                     1
+#define MADERA_OUT1L_VOL_MASK                          0x00FF
+#define MADERA_OUT1L_VOL_SHIFT                              0
+#define MADERA_OUT1L_VOL_WIDTH                              8
+
+/* (0x0412)  Output_Path_Config_1 */
+#define MADERA_HP1_GND_SEL_MASK                                0x0007
+#define MADERA_HP1_GND_SEL_SHIFT                            0
+#define MADERA_HP1_GND_SEL_WIDTH                            3
+
+/* (0x0414)  Output_Path_Config_1R */
+#define MADERA_OUT1R_ANC_SRC_MASK                      0x0C00
+#define MADERA_OUT1R_ANC_SRC_SHIFT                         10
+#define MADERA_OUT1R_ANC_SRC_WIDTH                          2
+
+/* (0x0415)  DAC_Digital_Volume_1R */
+#define MADERA_OUT1R_MUTE                              0x0100
+#define MADERA_OUT1R_MUTE_MASK                         0x0100
+#define MADERA_OUT1R_MUTE_SHIFT                                     8
+#define MADERA_OUT1R_MUTE_WIDTH                                     1
+#define MADERA_OUT1R_VOL_MASK                          0x00FF
+#define MADERA_OUT1R_VOL_SHIFT                              0
+#define MADERA_OUT1R_VOL_WIDTH                              8
+
+/* (0x0418)  Output_Path_Config_2L */
+#define MADERA_OUT2L_ANC_SRC_MASK                      0x0C00
+#define MADERA_OUT2L_ANC_SRC_SHIFT                         10
+#define MADERA_OUT2L_ANC_SRC_WIDTH                          2
+
+/* (0x0419)  DAC_Digital_Volume_2L */
+#define MADERA_OUT2L_MUTE                              0x0100
+#define MADERA_OUT2L_MUTE_MASK                         0x0100
+#define MADERA_OUT2L_MUTE_SHIFT                                     8
+#define MADERA_OUT2L_MUTE_WIDTH                                     1
+#define MADERA_OUT2L_VOL_MASK                          0x00FF
+#define MADERA_OUT2L_VOL_SHIFT                              0
+#define MADERA_OUT2L_VOL_WIDTH                              8
+
+/* (0x041A)  Output_Path_Config_2 */
+#define MADERA_HP2_GND_SEL_MASK                                0x0007
+#define MADERA_HP2_GND_SEL_SHIFT                            0
+#define MADERA_HP2_GND_SEL_WIDTH                            3
+
+/* (0x041C)  Output_Path_Config_2R */
+#define MADERA_OUT2R_ANC_SRC_MASK                      0x0C00
+#define MADERA_OUT2R_ANC_SRC_SHIFT                         10
+#define MADERA_OUT2R_ANC_SRC_WIDTH                          2
+
+/* (0x041D)  DAC_Digital_Volume_2R */
+#define MADERA_OUT2R_MUTE                              0x0100
+#define MADERA_OUT2R_MUTE_MASK                         0x0100
+#define MADERA_OUT2R_MUTE_SHIFT                                     8
+#define MADERA_OUT2R_MUTE_WIDTH                                     1
+#define MADERA_OUT2R_VOL_MASK                          0x00FF
+#define MADERA_OUT2R_VOL_SHIFT                              0
+#define MADERA_OUT2R_VOL_WIDTH                              8
+
+/* (0x0420)  Output_Path_Config_3L */
+#define MADERA_OUT3L_ANC_SRC_MASK                      0x0C00
+#define MADERA_OUT3L_ANC_SRC_SHIFT                         10
+#define MADERA_OUT3L_ANC_SRC_WIDTH                          2
+
+/* (0x0421)  DAC_Digital_Volume_3L */
+#define MADERA_OUT3L_MUTE                              0x0100
+#define MADERA_OUT3L_MUTE_MASK                         0x0100
+#define MADERA_OUT3L_MUTE_SHIFT                                     8
+#define MADERA_OUT3L_MUTE_WIDTH                                     1
+#define MADERA_OUT3L_VOL_MASK                          0x00FF
+#define MADERA_OUT3L_VOL_SHIFT                              0
+#define MADERA_OUT3L_VOL_WIDTH                              8
+
+/* (0x0424)  Output_Path_Config_3R */
+#define MADERA_OUT3R_ANC_SRC_MASK                      0x0C00
+#define MADERA_OUT3R_ANC_SRC_SHIFT                         10
+#define MADERA_OUT3R_ANC_SRC_WIDTH                          2
+
+/* (0x0425)  DAC_Digital_Volume_3R */
+#define MADERA_OUT3R_MUTE                              0x0100
+#define MADERA_OUT3R_MUTE_MASK                         0x0100
+#define MADERA_OUT3R_MUTE_SHIFT                                     8
+#define MADERA_OUT3R_MUTE_WIDTH                                     1
+#define MADERA_OUT3R_VOL_MASK                          0x00FF
+#define MADERA_OUT3R_VOL_SHIFT                              0
+#define MADERA_OUT3R_VOL_WIDTH                              8
+
+/* (0x0428)  Output_Path_Config_4L */
+#define MADERA_OUT4L_ANC_SRC_MASK                      0x0C00
+#define MADERA_OUT4L_ANC_SRC_SHIFT                         10
+#define MADERA_OUT4L_ANC_SRC_WIDTH                          2
+
+/* (0x0429)  DAC_Digital_Volume_4L */
+#define MADERA_OUT4L_MUTE                              0x0100
+#define MADERA_OUT4L_MUTE_MASK                         0x0100
+#define MADERA_OUT4L_MUTE_SHIFT                                     8
+#define MADERA_OUT4L_MUTE_WIDTH                                     1
+#define MADERA_OUT4L_VOL_MASK                          0x00FF
+#define MADERA_OUT4L_VOL_SHIFT                              0
+#define MADERA_OUT4L_VOL_WIDTH                              8
+
+/* (0x042C)  Output_Path_Config_4R */
+#define MADERA_OUT4R_ANC_SRC_MASK                      0x0C00
+#define MADERA_OUT4R_ANC_SRC_SHIFT                         10
+#define MADERA_OUT4R_ANC_SRC_WIDTH                          2
+
+/* (0x042D)  DAC_Digital_Volume_4R */
+#define MADERA_OUT4R_MUTE                              0x0100
+#define MADERA_OUT4R_MUTE_MASK                         0x0100
+#define MADERA_OUT4R_MUTE_SHIFT                                     8
+#define MADERA_OUT4R_MUTE_WIDTH                                     1
+#define MADERA_OUT4R_VOL_MASK                          0x00FF
+#define MADERA_OUT4R_VOL_SHIFT                              0
+#define MADERA_OUT4R_VOL_WIDTH                              8
+
+/* (0x0430)  Output_Path_Config_5L */
+#define MADERA_OUT5_OSR                                        0x2000
+#define MADERA_OUT5_OSR_MASK                           0x2000
+#define MADERA_OUT5_OSR_SHIFT                              13
+#define MADERA_OUT5_OSR_WIDTH                               1
+#define MADERA_OUT5L_ANC_SRC_MASK                      0x0C00
+#define MADERA_OUT5L_ANC_SRC_SHIFT                         10
+#define MADERA_OUT5L_ANC_SRC_WIDTH                          2
+
+/* (0x0431)  DAC_Digital_Volume_5L */
+#define MADERA_OUT5L_MUTE                              0x0100
+#define MADERA_OUT5L_MUTE_MASK                         0x0100
+#define MADERA_OUT5L_MUTE_SHIFT                                     8
+#define MADERA_OUT5L_MUTE_WIDTH                                     1
+#define MADERA_OUT5L_VOL_MASK                          0x00FF
+#define MADERA_OUT5L_VOL_SHIFT                              0
+#define MADERA_OUT5L_VOL_WIDTH                              8
+
+/* (0x0434)  Output_Path_Config_5R */
+#define MADERA_OUT5R_ANC_SRC_MASK                      0x0C00
+#define MADERA_OUT5R_ANC_SRC_SHIFT                         10
+#define MADERA_OUT5R_ANC_SRC_WIDTH                          2
+
+/* (0x0435)  DAC_Digital_Volume_5R */
+#define MADERA_OUT5R_MUTE                              0x0100
+#define MADERA_OUT5R_MUTE_MASK                         0x0100
+#define MADERA_OUT5R_MUTE_SHIFT                                     8
+#define MADERA_OUT5R_MUTE_WIDTH                                     1
+#define MADERA_OUT5R_VOL_MASK                          0x00FF
+#define MADERA_OUT5R_VOL_SHIFT                              0
+#define MADERA_OUT5R_VOL_WIDTH                              8
+
+/* (0x0438)  Output_Path_Config_6L */
+#define MADERA_OUT6_OSR                                        0x2000
+#define MADERA_OUT6_OSR_MASK                           0x2000
+#define MADERA_OUT6_OSR_SHIFT                              13
+#define MADERA_OUT6_OSR_WIDTH                               1
+#define MADERA_OUT6L_ANC_SRC_MASK                      0x0C00
+#define MADERA_OUT6L_ANC_SRC_SHIFT                         10
+#define MADERA_OUT6L_ANC_SRC_WIDTH                          2
+
+/* (0x0439)  DAC_Digital_Volume_6L */
+#define MADERA_OUT6L_MUTE                              0x0100
+#define MADERA_OUT6L_MUTE_MASK                         0x0100
+#define MADERA_OUT6L_MUTE_SHIFT                                     8
+#define MADERA_OUT6L_MUTE_WIDTH                                     1
+#define MADERA_OUT6L_VOL_MASK                          0x00FF
+#define MADERA_OUT6L_VOL_SHIFT                              0
+#define MADERA_OUT6L_VOL_WIDTH                              8
+
+/* (0x043C)  Output_Path_Config_6R */
+#define MADERA_OUT6R_ANC_SRC_MASK                      0x0C00
+#define MADERA_OUT6R_ANC_SRC_SHIFT                         10
+#define MADERA_OUT6R_ANC_SRC_WIDTH                          2
+
+/* (0x043D)  DAC_Digital_Volume_6R */
+#define MADERA_OUT6R_MUTE                              0x0100
+#define MADERA_OUT6R_MUTE_MASK                         0x0100
+#define MADERA_OUT6R_MUTE_SHIFT                                     8
+#define MADERA_OUT6R_MUTE_WIDTH                                     1
+#define MADERA_OUT6R_VOL_MASK                          0x00FF
+#define MADERA_OUT6R_VOL_SHIFT                              0
+#define MADERA_OUT6R_VOL_WIDTH                              8
+
+/* (0x0450) - DAC AEC Control 1 */
+#define MADERA_AEC1_LOOPBACK_SRC_MASK                  0x003C
+#define MADERA_AEC1_LOOPBACK_SRC_SHIFT                      2
+#define MADERA_AEC1_LOOPBACK_SRC_WIDTH                      4
+#define MADERA_AEC1_ENA_STS                            0x0002
+#define MADERA_AEC1_ENA_STS_MASK                       0x0002
+#define MADERA_AEC1_ENA_STS_SHIFT                           1
+#define MADERA_AEC1_ENA_STS_WIDTH                           1
+#define MADERA_AEC1_LOOPBACK_ENA                       0x0001
+#define MADERA_AEC1_LOOPBACK_ENA_MASK                  0x0001
+#define MADERA_AEC1_LOOPBACK_ENA_SHIFT                      0
+#define MADERA_AEC1_LOOPBACK_ENA_WIDTH                      1
+
+/* (0x0451)  DAC_AEC_Control_2 */
+#define MADERA_AEC2_LOOPBACK_SRC_MASK                  0x003C
+#define MADERA_AEC2_LOOPBACK_SRC_SHIFT                      2
+#define MADERA_AEC2_LOOPBACK_SRC_WIDTH                      4
+#define MADERA_AEC2_ENA_STS                            0x0002
+#define MADERA_AEC2_ENA_STS_MASK                       0x0002
+#define MADERA_AEC2_ENA_STS_SHIFT                           1
+#define MADERA_AEC2_ENA_STS_WIDTH                           1
+#define MADERA_AEC2_LOOPBACK_ENA                       0x0001
+#define MADERA_AEC2_LOOPBACK_ENA_MASK                  0x0001
+#define MADERA_AEC2_LOOPBACK_ENA_SHIFT                      0
+#define MADERA_AEC2_LOOPBACK_ENA_WIDTH                      1
+
+/* (0x0458)  Noise_Gate_Control */
+#define MADERA_NGATE_HOLD_MASK                         0x0030
+#define MADERA_NGATE_HOLD_SHIFT                                     4
+#define MADERA_NGATE_HOLD_WIDTH                                     2
+#define MADERA_NGATE_THR_MASK                          0x000E
+#define MADERA_NGATE_THR_SHIFT                              1
+#define MADERA_NGATE_THR_WIDTH                              3
+#define MADERA_NGATE_ENA                               0x0001
+#define MADERA_NGATE_ENA_MASK                          0x0001
+#define MADERA_NGATE_ENA_SHIFT                              0
+#define MADERA_NGATE_ENA_WIDTH                              1
+
+/* (0x0490)  PDM_SPK1_CTRL_1 */
+#define MADERA_SPK1R_MUTE                              0x2000
+#define MADERA_SPK1R_MUTE_MASK                         0x2000
+#define MADERA_SPK1R_MUTE_SHIFT                                    13
+#define MADERA_SPK1R_MUTE_WIDTH                                     1
+#define MADERA_SPK1L_MUTE                              0x1000
+#define MADERA_SPK1L_MUTE_MASK                         0x1000
+#define MADERA_SPK1L_MUTE_SHIFT                                    12
+#define MADERA_SPK1L_MUTE_WIDTH                                     1
+#define MADERA_SPK1_MUTE_ENDIAN                                0x0100
+#define MADERA_SPK1_MUTE_ENDIAN_MASK                   0x0100
+#define MADERA_SPK1_MUTE_ENDIAN_SHIFT                       8
+#define MADERA_SPK1_MUTE_ENDIAN_WIDTH                       1
+#define MADERA_SPK1_MUTE_SEQ1_MASK                     0x00FF
+#define MADERA_SPK1_MUTE_SEQ1_SHIFT                         0
+#define MADERA_SPK1_MUTE_SEQ1_WIDTH                         8
+
+/* (0x0491)  PDM_SPK1_CTRL_2 */
+#define MADERA_SPK1_FMT                                        0x0001
+#define MADERA_SPK1_FMT_MASK                           0x0001
+#define MADERA_SPK1_FMT_SHIFT                               0
+#define MADERA_SPK1_FMT_WIDTH                               1
+
+/* (0x0492)  PDM_SPK2_CTRL_1 */
+#define MADERA_SPK2R_MUTE                              0x2000
+#define MADERA_SPK2R_MUTE_MASK                         0x2000
+#define MADERA_SPK2R_MUTE_SHIFT                                    13
+#define MADERA_SPK2R_MUTE_WIDTH                                     1
+#define MADERA_SPK2L_MUTE                              0x1000
+#define MADERA_SPK2L_MUTE_MASK                         0x1000
+#define MADERA_SPK2L_MUTE_SHIFT                                    12
+#define MADERA_SPK2L_MUTE_WIDTH                                     1
+
+/* (0x04A0) - HP1 Short Circuit Ctrl */
+#define MADERA_HP1_SC_ENA                              0x1000
+#define MADERA_HP1_SC_ENA_MASK                         0x1000
+#define MADERA_HP1_SC_ENA_SHIFT                                    12
+#define MADERA_HP1_SC_ENA_WIDTH                                     1
+
+/* (0x04A1) - HP2 Short Circuit Ctrl */
+#define MADERA_HP2_SC_ENA                              0x1000
+#define MADERA_HP2_SC_ENA_MASK                         0x1000
+#define MADERA_HP2_SC_ENA_SHIFT                                    12
+#define MADERA_HP2_SC_ENA_WIDTH                                     1
+
+/* (0x04A2) - HP3 Short Circuit Ctrl */
+#define MADERA_HP3_SC_ENA                              0x1000
+#define MADERA_HP3_SC_ENA_MASK                         0x1000
+#define MADERA_HP3_SC_ENA_SHIFT                                    12
+#define MADERA_HP3_SC_ENA_WIDTH                                     1
+
+/* (0x04A8) - HP_Test_Ctrl_5 */
+#define MADERA_HP1L_ONEFLT                             0x0100
+#define MADERA_HP1L_ONEFLT_MASK                                0x0100
+#define MADERA_HP1L_ONEFLT_SHIFT                            8
+#define MADERA_HP1L_ONEFLT_WIDTH                            1
+
+/* (0x04A9) - HP_Test_Ctrl_6 */
+#define MADERA_HP1R_ONEFLT                             0x0100
+#define MADERA_HP1R_ONEFLT_MASK                                0x0100
+#define MADERA_HP1R_ONEFLT_SHIFT                            8
+#define MADERA_HP1R_ONEFLT_WIDTH                            1
+
+/* (0x0500)  AIF1_BCLK_Ctrl */
+#define MADERA_AIF1_BCLK_INV                           0x0080
+#define MADERA_AIF1_BCLK_INV_MASK                      0x0080
+#define MADERA_AIF1_BCLK_INV_SHIFT                          7
+#define MADERA_AIF1_BCLK_INV_WIDTH                          1
+#define MADERA_AIF1_BCLK_MSTR                          0x0020
+#define MADERA_AIF1_BCLK_MSTR_MASK                     0x0020
+#define MADERA_AIF1_BCLK_MSTR_SHIFT                         5
+#define MADERA_AIF1_BCLK_MSTR_WIDTH                         1
+#define MADERA_AIF1_BCLK_FREQ_MASK                     0x001F
+#define MADERA_AIF1_BCLK_FREQ_SHIFT                         0
+#define MADERA_AIF1_BCLK_FREQ_WIDTH                         5
+
+/* (0x0501)  AIF1_Tx_Pin_Ctrl */
+#define MADERA_AIF1TX_LRCLK_SRC                                0x0008
+#define MADERA_AIF1TX_LRCLK_SRC_MASK                   0x0008
+#define MADERA_AIF1TX_LRCLK_SRC_SHIFT                       3
+#define MADERA_AIF1TX_LRCLK_SRC_WIDTH                       1
+#define MADERA_AIF1TX_LRCLK_INV                                0x0004
+#define MADERA_AIF1TX_LRCLK_INV_MASK                   0x0004
+#define MADERA_AIF1TX_LRCLK_INV_SHIFT                       2
+#define MADERA_AIF1TX_LRCLK_INV_WIDTH                       1
+#define MADERA_AIF1TX_LRCLK_MSTR                       0x0001
+#define MADERA_AIF1TX_LRCLK_MSTR_MASK                  0x0001
+#define MADERA_AIF1TX_LRCLK_MSTR_SHIFT                      0
+#define MADERA_AIF1TX_LRCLK_MSTR_WIDTH                      1
+
+/* (0x0502)  AIF1_Rx_Pin_Ctrl */
+#define MADERA_AIF1RX_LRCLK_INV                                0x0004
+#define MADERA_AIF1RX_LRCLK_INV_MASK                   0x0004
+#define MADERA_AIF1RX_LRCLK_INV_SHIFT                       2
+#define MADERA_AIF1RX_LRCLK_INV_WIDTH                       1
+#define MADERA_AIF1RX_LRCLK_FRC                                0x0002
+#define MADERA_AIF1RX_LRCLK_FRC_MASK                   0x0002
+#define MADERA_AIF1RX_LRCLK_FRC_SHIFT                       1
+#define MADERA_AIF1RX_LRCLK_FRC_WIDTH                       1
+#define MADERA_AIF1RX_LRCLK_MSTR                       0x0001
+#define MADERA_AIF1RX_LRCLK_MSTR_MASK                  0x0001
+#define MADERA_AIF1RX_LRCLK_MSTR_SHIFT                      0
+#define MADERA_AIF1RX_LRCLK_MSTR_WIDTH                      1
+
+/* (0x0503)  AIF1_Rate_Ctrl */
+#define MADERA_AIF1_RATE_MASK                          0xF800
+#define MADERA_AIF1_RATE_SHIFT                             11
+#define MADERA_AIF1_RATE_WIDTH                              5
+#define MADERA_AIF1_TRI                                        0x0040
+#define MADERA_AIF1_TRI_MASK                           0x0040
+#define MADERA_AIF1_TRI_SHIFT                               6
+#define MADERA_AIF1_TRI_WIDTH                               1
+
+/* (0x0504)  AIF1_Format */
+#define MADERA_AIF1_FMT_MASK                           0x0007
+#define MADERA_AIF1_FMT_SHIFT                               0
+#define MADERA_AIF1_FMT_WIDTH                               3
+
+/* (0x0506)  AIF1_Rx_BCLK_Rate */
+#define MADERA_AIF1RX_BCPF_MASK                                0x1FFF
+#define MADERA_AIF1RX_BCPF_SHIFT                            0
+#define MADERA_AIF1RX_BCPF_WIDTH                           13
+
+/* (0x0507)  AIF1_Frame_Ctrl_1 */
+#define MADERA_AIF1TX_WL_MASK                          0x3F00
+#define MADERA_AIF1TX_WL_SHIFT                              8
+#define MADERA_AIF1TX_WL_WIDTH                              6
+#define MADERA_AIF1TX_SLOT_LEN_MASK                    0x00FF
+#define MADERA_AIF1TX_SLOT_LEN_SHIFT                        0
+#define MADERA_AIF1TX_SLOT_LEN_WIDTH                        8
+
+/* (0x0508)  AIF1_Frame_Ctrl_2 */
+#define MADERA_AIF1RX_WL_MASK                          0x3F00
+#define MADERA_AIF1RX_WL_SHIFT                              8
+#define MADERA_AIF1RX_WL_WIDTH                              6
+#define MADERA_AIF1RX_SLOT_LEN_MASK                    0x00FF
+#define MADERA_AIF1RX_SLOT_LEN_SHIFT                        0
+#define MADERA_AIF1RX_SLOT_LEN_WIDTH                        8
+
+/* (0x0509)  AIF1_Frame_Ctrl_3 */
+#define MADERA_AIF1TX1_SLOT_MASK                       0x003F
+#define MADERA_AIF1TX1_SLOT_SHIFT                           0
+#define MADERA_AIF1TX1_SLOT_WIDTH                           6
+
+/* (0x0519)  AIF1_Tx_Enables */
+#define MADERA_AIF1TX8_ENA                             0x0080
+#define MADERA_AIF1TX8_ENA_MASK                                0x0080
+#define MADERA_AIF1TX8_ENA_SHIFT                            7
+#define MADERA_AIF1TX8_ENA_WIDTH                            1
+#define MADERA_AIF1TX7_ENA                             0x0040
+#define MADERA_AIF1TX7_ENA_MASK                                0x0040
+#define MADERA_AIF1TX7_ENA_SHIFT                            6
+#define MADERA_AIF1TX7_ENA_WIDTH                            1
+#define MADERA_AIF1TX6_ENA                             0x0020
+#define MADERA_AIF1TX6_ENA_MASK                                0x0020
+#define MADERA_AIF1TX6_ENA_SHIFT                            5
+#define MADERA_AIF1TX6_ENA_WIDTH                            1
+#define MADERA_AIF1TX5_ENA                             0x0010
+#define MADERA_AIF1TX5_ENA_MASK                                0x0010
+#define MADERA_AIF1TX5_ENA_SHIFT                            4
+#define MADERA_AIF1TX5_ENA_WIDTH                            1
+#define MADERA_AIF1TX4_ENA                             0x0008
+#define MADERA_AIF1TX4_ENA_MASK                                0x0008
+#define MADERA_AIF1TX4_ENA_SHIFT                            3
+#define MADERA_AIF1TX4_ENA_WIDTH                            1
+#define MADERA_AIF1TX3_ENA                             0x0004
+#define MADERA_AIF1TX3_ENA_MASK                                0x0004
+#define MADERA_AIF1TX3_ENA_SHIFT                            2
+#define MADERA_AIF1TX3_ENA_WIDTH                            1
+#define MADERA_AIF1TX2_ENA                             0x0002
+#define MADERA_AIF1TX2_ENA_MASK                                0x0002
+#define MADERA_AIF1TX2_ENA_SHIFT                            1
+#define MADERA_AIF1TX2_ENA_WIDTH                            1
+#define MADERA_AIF1TX1_ENA                             0x0001
+#define MADERA_AIF1TX1_ENA_MASK                                0x0001
+#define MADERA_AIF1TX1_ENA_SHIFT                            0
+#define MADERA_AIF1TX1_ENA_WIDTH                            1
+
+/* (0x051A)  AIF1_Rx_Enables */
+#define MADERA_AIF1RX8_ENA                             0x0080
+#define MADERA_AIF1RX8_ENA_MASK                                0x0080
+#define MADERA_AIF1RX8_ENA_SHIFT                            7
+#define MADERA_AIF1RX8_ENA_WIDTH                            1
+#define MADERA_AIF1RX7_ENA                             0x0040
+#define MADERA_AIF1RX7_ENA_MASK                                0x0040
+#define MADERA_AIF1RX7_ENA_SHIFT                            6
+#define MADERA_AIF1RX7_ENA_WIDTH                            1
+#define MADERA_AIF1RX6_ENA                             0x0020
+#define MADERA_AIF1RX6_ENA_MASK                                0x0020
+#define MADERA_AIF1RX6_ENA_SHIFT                            5
+#define MADERA_AIF1RX6_ENA_WIDTH                            1
+#define MADERA_AIF1RX5_ENA                             0x0010
+#define MADERA_AIF1RX5_ENA_MASK                                0x0010
+#define MADERA_AIF1RX5_ENA_SHIFT                            4
+#define MADERA_AIF1RX5_ENA_WIDTH                            1
+#define MADERA_AIF1RX4_ENA                             0x0008
+#define MADERA_AIF1RX4_ENA_MASK                                0x0008
+#define MADERA_AIF1RX4_ENA_SHIFT                            3
+#define MADERA_AIF1RX4_ENA_WIDTH                            1
+#define MADERA_AIF1RX3_ENA                             0x0004
+#define MADERA_AIF1RX3_ENA_MASK                                0x0004
+#define MADERA_AIF1RX3_ENA_SHIFT                            2
+#define MADERA_AIF1RX3_ENA_WIDTH                            1
+#define MADERA_AIF1RX2_ENA                             0x0002
+#define MADERA_AIF1RX2_ENA_MASK                                0x0002
+#define MADERA_AIF1RX2_ENA_SHIFT                            1
+#define MADERA_AIF1RX2_ENA_WIDTH                            1
+#define MADERA_AIF1RX1_ENA                             0x0001
+#define MADERA_AIF1RX1_ENA_MASK                                0x0001
+#define MADERA_AIF1RX1_ENA_SHIFT                            0
+#define MADERA_AIF1RX1_ENA_WIDTH                            1
+
+/* (0x0559)  AIF2_Tx_Enables */
+#define MADERA_AIF2TX8_ENA                             0x0080
+#define MADERA_AIF2TX8_ENA_MASK                                0x0080
+#define MADERA_AIF2TX8_ENA_SHIFT                            7
+#define MADERA_AIF2TX8_ENA_WIDTH                            1
+#define MADERA_AIF2TX7_ENA                             0x0040
+#define MADERA_AIF2TX7_ENA_MASK                                0x0040
+#define MADERA_AIF2TX7_ENA_SHIFT                            6
+#define MADERA_AIF2TX7_ENA_WIDTH                            1
+#define MADERA_AIF2TX6_ENA                             0x0020
+#define MADERA_AIF2TX6_ENA_MASK                                0x0020
+#define MADERA_AIF2TX6_ENA_SHIFT                            5
+#define MADERA_AIF2TX6_ENA_WIDTH                            1
+#define MADERA_AIF2TX5_ENA                             0x0010
+#define MADERA_AIF2TX5_ENA_MASK                                0x0010
+#define MADERA_AIF2TX5_ENA_SHIFT                            4
+#define MADERA_AIF2TX5_ENA_WIDTH                            1
+#define MADERA_AIF2TX4_ENA                             0x0008
+#define MADERA_AIF2TX4_ENA_MASK                                0x0008
+#define MADERA_AIF2TX4_ENA_SHIFT                            3
+#define MADERA_AIF2TX4_ENA_WIDTH                            1
+#define MADERA_AIF2TX3_ENA                             0x0004
+#define MADERA_AIF2TX3_ENA_MASK                                0x0004
+#define MADERA_AIF2TX3_ENA_SHIFT                            2
+#define MADERA_AIF2TX3_ENA_WIDTH                            1
+#define MADERA_AIF2TX2_ENA                             0x0002
+#define MADERA_AIF2TX2_ENA_MASK                                0x0002
+#define MADERA_AIF2TX2_ENA_SHIFT                            1
+#define MADERA_AIF2TX2_ENA_WIDTH                            1
+#define MADERA_AIF2TX1_ENA                             0x0001
+#define MADERA_AIF2TX1_ENA_MASK                                0x0001
+#define MADERA_AIF2TX1_ENA_SHIFT                            0
+#define MADERA_AIF2TX1_ENA_WIDTH                            1
+
+/* (0x055A)  AIF2_Rx_Enables */
+#define MADERA_AIF2RX8_ENA                             0x0080
+#define MADERA_AIF2RX8_ENA_MASK                                0x0080
+#define MADERA_AIF2RX8_ENA_SHIFT                            7
+#define MADERA_AIF2RX8_ENA_WIDTH                            1
+#define MADERA_AIF2RX7_ENA                             0x0040
+#define MADERA_AIF2RX7_ENA_MASK                                0x0040
+#define MADERA_AIF2RX7_ENA_SHIFT                            6
+#define MADERA_AIF2RX7_ENA_WIDTH                            1
+#define MADERA_AIF2RX6_ENA                             0x0020
+#define MADERA_AIF2RX6_ENA_MASK                                0x0020
+#define MADERA_AIF2RX6_ENA_SHIFT                            5
+#define MADERA_AIF2RX6_ENA_WIDTH                            1
+#define MADERA_AIF2RX5_ENA                             0x0010
+#define MADERA_AIF2RX5_ENA_MASK                                0x0010
+#define MADERA_AIF2RX5_ENA_SHIFT                            4
+#define MADERA_AIF2RX5_ENA_WIDTH                            1
+#define MADERA_AIF2RX4_ENA                             0x0008
+#define MADERA_AIF2RX4_ENA_MASK                                0x0008
+#define MADERA_AIF2RX4_ENA_SHIFT                            3
+#define MADERA_AIF2RX4_ENA_WIDTH                            1
+#define MADERA_AIF2RX3_ENA                             0x0004
+#define MADERA_AIF2RX3_ENA_MASK                                0x0004
+#define MADERA_AIF2RX3_ENA_SHIFT                            2
+#define MADERA_AIF2RX3_ENA_WIDTH                            1
+#define MADERA_AIF2RX2_ENA                             0x0002
+#define MADERA_AIF2RX2_ENA_MASK                                0x0002
+#define MADERA_AIF2RX2_ENA_SHIFT                            1
+#define MADERA_AIF2RX2_ENA_WIDTH                            1
+#define MADERA_AIF2RX1_ENA                             0x0001
+#define MADERA_AIF2RX1_ENA_MASK                                0x0001
+#define MADERA_AIF2RX1_ENA_SHIFT                            0
+#define MADERA_AIF2RX1_ENA_WIDTH                            1
+
+/* (0x0599)  AIF3_Tx_Enables */
+#define MADERA_AIF3TX2_ENA                             0x0002
+#define MADERA_AIF3TX2_ENA_MASK                                0x0002
+#define MADERA_AIF3TX2_ENA_SHIFT                            1
+#define MADERA_AIF3TX2_ENA_WIDTH                            1
+#define MADERA_AIF3TX1_ENA                             0x0001
+#define MADERA_AIF3TX1_ENA_MASK                                0x0001
+#define MADERA_AIF3TX1_ENA_SHIFT                            0
+#define MADERA_AIF3TX1_ENA_WIDTH                            1
+
+/* (0x059A)  AIF3_Rx_Enables */
+#define MADERA_AIF3RX2_ENA                             0x0002
+#define MADERA_AIF3RX2_ENA_MASK                                0x0002
+#define MADERA_AIF3RX2_ENA_SHIFT                            1
+#define MADERA_AIF3RX2_ENA_WIDTH                            1
+#define MADERA_AIF3RX1_ENA                             0x0001
+#define MADERA_AIF3RX1_ENA_MASK                                0x0001
+#define MADERA_AIF3RX1_ENA_SHIFT                            0
+#define MADERA_AIF3RX1_ENA_WIDTH                            1
+
+/* (0x05B9)  AIF4_Tx_Enables */
+#define MADERA_AIF4TX2_ENA                             0x0002
+#define MADERA_AIF4TX2_ENA_MASK                                0x0002
+#define MADERA_AIF4TX2_ENA_SHIFT                            1
+#define MADERA_AIF4TX2_ENA_WIDTH                            1
+#define MADERA_AIF4TX1_ENA                             0x0001
+#define MADERA_AIF4TX1_ENA_MASK                                0x0001
+#define MADERA_AIF4TX1_ENA_SHIFT                            0
+#define MADERA_AIF4TX1_ENA_WIDTH                            1
+
+/* (0x05BA)  AIF4_Rx_Enables */
+#define MADERA_AIF4RX2_ENA                             0x0002
+#define MADERA_AIF4RX2_ENA_MASK                                0x0002
+#define MADERA_AIF4RX2_ENA_SHIFT                            1
+#define MADERA_AIF4RX2_ENA_WIDTH                            1
+#define MADERA_AIF4RX1_ENA                             0x0001
+#define MADERA_AIF4RX1_ENA_MASK                                0x0001
+#define MADERA_AIF4RX1_ENA_SHIFT                            0
+#define MADERA_AIF4RX1_ENA_WIDTH                            1
+
+/* (0x05C2)  SPD1_TX_Control */
+#define MADERA_SPD1_VAL2                               0x2000
+#define MADERA_SPD1_VAL2_MASK                          0x2000
+#define MADERA_SPD1_VAL2_SHIFT                             13
+#define MADERA_SPD1_VAL2_WIDTH                              1
+#define MADERA_SPD1_VAL1                               0x1000
+#define MADERA_SPD1_VAL1_MASK                          0x1000
+#define MADERA_SPD1_VAL1_SHIFT                             12
+#define MADERA_SPD1_VAL1_WIDTH                              1
+#define MADERA_SPD1_RATE_MASK                          0x00F0
+#define MADERA_SPD1_RATE_SHIFT                              4
+#define MADERA_SPD1_RATE_WIDTH                              4
+#define MADERA_SPD1_ENA                                        0x0001
+#define MADERA_SPD1_ENA_MASK                           0x0001
+#define MADERA_SPD1_ENA_SHIFT                               0
+#define MADERA_SPD1_ENA_WIDTH                               1
+
+/* (0x05F5)  SLIMbus_RX_Channel_Enable */
+#define MADERA_SLIMRX8_ENA                             0x0080
+#define MADERA_SLIMRX8_ENA_MASK                                0x0080
+#define MADERA_SLIMRX8_ENA_SHIFT                            7
+#define MADERA_SLIMRX8_ENA_WIDTH                            1
+#define MADERA_SLIMRX7_ENA                             0x0040
+#define MADERA_SLIMRX7_ENA_MASK                                0x0040
+#define MADERA_SLIMRX7_ENA_SHIFT                            6
+#define MADERA_SLIMRX7_ENA_WIDTH                            1
+#define MADERA_SLIMRX6_ENA                             0x0020
+#define MADERA_SLIMRX6_ENA_MASK                                0x0020
+#define MADERA_SLIMRX6_ENA_SHIFT                            5
+#define MADERA_SLIMRX6_ENA_WIDTH                            1
+#define MADERA_SLIMRX5_ENA                             0x0010
+#define MADERA_SLIMRX5_ENA_MASK                                0x0010
+#define MADERA_SLIMRX5_ENA_SHIFT                            4
+#define MADERA_SLIMRX5_ENA_WIDTH                            1
+#define MADERA_SLIMRX4_ENA                             0x0008
+#define MADERA_SLIMRX4_ENA_MASK                                0x0008
+#define MADERA_SLIMRX4_ENA_SHIFT                            3
+#define MADERA_SLIMRX4_ENA_WIDTH                            1
+#define MADERA_SLIMRX3_ENA                             0x0004
+#define MADERA_SLIMRX3_ENA_MASK                                0x0004
+#define MADERA_SLIMRX3_ENA_SHIFT                            2
+#define MADERA_SLIMRX3_ENA_WIDTH                            1
+#define MADERA_SLIMRX2_ENA                             0x0002
+#define MADERA_SLIMRX2_ENA_MASK                                0x0002
+#define MADERA_SLIMRX2_ENA_SHIFT                            1
+#define MADERA_SLIMRX2_ENA_WIDTH                            1
+#define MADERA_SLIMRX1_ENA                             0x0001
+#define MADERA_SLIMRX1_ENA_MASK                                0x0001
+#define MADERA_SLIMRX1_ENA_SHIFT                            0
+#define MADERA_SLIMRX1_ENA_WIDTH                            1
+
+/* (0x05F6)  SLIMbus_TX_Channel_Enable */
+#define MADERA_SLIMTX8_ENA                             0x0080
+#define MADERA_SLIMTX8_ENA_MASK                                0x0080
+#define MADERA_SLIMTX8_ENA_SHIFT                            7
+#define MADERA_SLIMTX8_ENA_WIDTH                            1
+#define MADERA_SLIMTX7_ENA                             0x0040
+#define MADERA_SLIMTX7_ENA_MASK                                0x0040
+#define MADERA_SLIMTX7_ENA_SHIFT                            6
+#define MADERA_SLIMTX7_ENA_WIDTH                            1
+#define MADERA_SLIMTX6_ENA                             0x0020
+#define MADERA_SLIMTX6_ENA_MASK                                0x0020
+#define MADERA_SLIMTX6_ENA_SHIFT                            5
+#define MADERA_SLIMTX6_ENA_WIDTH                            1
+#define MADERA_SLIMTX5_ENA                             0x0010
+#define MADERA_SLIMTX5_ENA_MASK                                0x0010
+#define MADERA_SLIMTX5_ENA_SHIFT                            4
+#define MADERA_SLIMTX5_ENA_WIDTH                            1
+#define MADERA_SLIMTX4_ENA                             0x0008
+#define MADERA_SLIMTX4_ENA_MASK                                0x0008
+#define MADERA_SLIMTX4_ENA_SHIFT                            3
+#define MADERA_SLIMTX4_ENA_WIDTH                            1
+#define MADERA_SLIMTX3_ENA                             0x0004
+#define MADERA_SLIMTX3_ENA_MASK                                0x0004
+#define MADERA_SLIMTX3_ENA_SHIFT                            2
+#define MADERA_SLIMTX3_ENA_WIDTH                            1
+#define MADERA_SLIMTX2_ENA                             0x0002
+#define MADERA_SLIMTX2_ENA_MASK                                0x0002
+#define MADERA_SLIMTX2_ENA_SHIFT                            1
+#define MADERA_SLIMTX2_ENA_WIDTH                            1
+#define MADERA_SLIMTX1_ENA                             0x0001
+#define MADERA_SLIMTX1_ENA_MASK                                0x0001
+#define MADERA_SLIMTX1_ENA_SHIFT                            0
+#define MADERA_SLIMTX1_ENA_WIDTH                            1
+
+/* (0x0E10)  EQ1_1 */
+#define MADERA_EQ1_B1_GAIN_MASK                                0xF800
+#define MADERA_EQ1_B1_GAIN_SHIFT                           11
+#define MADERA_EQ1_B1_GAIN_WIDTH                            5
+#define MADERA_EQ1_B2_GAIN_MASK                                0x07C0
+#define MADERA_EQ1_B2_GAIN_SHIFT                            6
+#define MADERA_EQ1_B2_GAIN_WIDTH                            5
+#define MADERA_EQ1_B3_GAIN_MASK                                0x003E
+#define MADERA_EQ1_B3_GAIN_SHIFT                            1
+#define MADERA_EQ1_B3_GAIN_WIDTH                            5
+#define MADERA_EQ1_ENA                                 0x0001
+#define MADERA_EQ1_ENA_MASK                            0x0001
+#define MADERA_EQ1_ENA_SHIFT                                0
+#define MADERA_EQ1_ENA_WIDTH                                1
+
+/* (0x0E11)  EQ1_2 */
+#define MADERA_EQ1_B4_GAIN_MASK                                0xF800
+#define MADERA_EQ1_B4_GAIN_SHIFT                           11
+#define MADERA_EQ1_B4_GAIN_WIDTH                            5
+#define MADERA_EQ1_B5_GAIN_MASK                                0x07C0
+#define MADERA_EQ1_B5_GAIN_SHIFT                            6
+#define MADERA_EQ1_B5_GAIN_WIDTH                            5
+#define MADERA_EQ1_B1_MODE                             0x0001
+#define MADERA_EQ1_B1_MODE_MASK                                0x0001
+#define MADERA_EQ1_B1_MODE_SHIFT                            0
+#define MADERA_EQ1_B1_MODE_WIDTH                            1
+
+/* (0x0E26)  EQ2_1 */
+#define MADERA_EQ2_B1_GAIN_MASK                                0xF800
+#define MADERA_EQ2_B1_GAIN_SHIFT                           11
+#define MADERA_EQ2_B1_GAIN_WIDTH                            5
+#define MADERA_EQ2_B2_GAIN_MASK                                0x07C0
+#define MADERA_EQ2_B2_GAIN_SHIFT                            6
+#define MADERA_EQ2_B2_GAIN_WIDTH                            5
+#define MADERA_EQ2_B3_GAIN_MASK                                0x003E
+#define MADERA_EQ2_B3_GAIN_SHIFT                            1
+#define MADERA_EQ2_B3_GAIN_WIDTH                            5
+#define MADERA_EQ2_ENA                                 0x0001
+#define MADERA_EQ2_ENA_MASK                            0x0001
+#define MADERA_EQ2_ENA_SHIFT                                0
+#define MADERA_EQ2_ENA_WIDTH                                1
+
+/* (0x0E27)  EQ2_2 */
+#define MADERA_EQ2_B4_GAIN_MASK                                0xF800
+#define MADERA_EQ2_B4_GAIN_SHIFT                           11
+#define MADERA_EQ2_B4_GAIN_WIDTH                            5
+#define MADERA_EQ2_B5_GAIN_MASK                                0x07C0
+#define MADERA_EQ2_B5_GAIN_SHIFT                            6
+#define MADERA_EQ2_B5_GAIN_WIDTH                            5
+#define MADERA_EQ2_B1_MODE                             0x0001
+#define MADERA_EQ2_B1_MODE_MASK                                0x0001
+#define MADERA_EQ2_B1_MODE_SHIFT                            0
+#define MADERA_EQ2_B1_MODE_WIDTH                            1
+
+/* (0x0E3C)  EQ3_1 */
+#define MADERA_EQ3_B1_GAIN_MASK                                0xF800
+#define MADERA_EQ3_B1_GAIN_SHIFT                           11
+#define MADERA_EQ3_B1_GAIN_WIDTH                            5
+#define MADERA_EQ3_B2_GAIN_MASK                                0x07C0
+#define MADERA_EQ3_B2_GAIN_SHIFT                            6
+#define MADERA_EQ3_B2_GAIN_WIDTH                            5
+#define MADERA_EQ3_B3_GAIN_MASK                                0x003E
+#define MADERA_EQ3_B3_GAIN_SHIFT                            1
+#define MADERA_EQ3_B3_GAIN_WIDTH                            5
+#define MADERA_EQ3_ENA                                 0x0001
+#define MADERA_EQ3_ENA_MASK                            0x0001
+#define MADERA_EQ3_ENA_SHIFT                                0
+#define MADERA_EQ3_ENA_WIDTH                                1
+
+/* (0x0E3D)  EQ3_2 */
+#define MADERA_EQ3_B4_GAIN_MASK                                0xF800
+#define MADERA_EQ3_B4_GAIN_SHIFT                           11
+#define MADERA_EQ3_B4_GAIN_WIDTH                            5
+#define MADERA_EQ3_B5_GAIN_MASK                                0x07C0
+#define MADERA_EQ3_B5_GAIN_SHIFT                            6
+#define MADERA_EQ3_B5_GAIN_WIDTH                            5
+#define MADERA_EQ3_B1_MODE                             0x0001
+#define MADERA_EQ3_B1_MODE_MASK                                0x0001
+#define MADERA_EQ3_B1_MODE_SHIFT                            0
+#define MADERA_EQ3_B1_MODE_WIDTH                            1
+
+/* (0x0E52)  EQ4_1 */
+#define MADERA_EQ4_B1_GAIN_MASK                                0xF800
+#define MADERA_EQ4_B1_GAIN_SHIFT                           11
+#define MADERA_EQ4_B1_GAIN_WIDTH                            5
+#define MADERA_EQ4_B2_GAIN_MASK                                0x07C0
+#define MADERA_EQ4_B2_GAIN_SHIFT                            6
+#define MADERA_EQ4_B2_GAIN_WIDTH                            5
+#define MADERA_EQ4_B3_GAIN_MASK                                0x003E
+#define MADERA_EQ4_B3_GAIN_SHIFT                            1
+#define MADERA_EQ4_B3_GAIN_WIDTH                            5
+#define MADERA_EQ4_ENA                                 0x0001
+#define MADERA_EQ4_ENA_MASK                            0x0001
+#define MADERA_EQ4_ENA_SHIFT                                0
+#define MADERA_EQ4_ENA_WIDTH                                1
+
+/* (0x0E53)  EQ4_2 */
+#define MADERA_EQ4_B4_GAIN_MASK                                0xF800
+#define MADERA_EQ4_B4_GAIN_SHIFT                           11
+#define MADERA_EQ4_B4_GAIN_WIDTH                            5
+#define MADERA_EQ4_B5_GAIN_MASK                                0x07C0
+#define MADERA_EQ4_B5_GAIN_SHIFT                            6
+#define MADERA_EQ4_B5_GAIN_WIDTH                            5
+#define MADERA_EQ4_B1_MODE                             0x0001
+#define MADERA_EQ4_B1_MODE_MASK                                0x0001
+#define MADERA_EQ4_B1_MODE_SHIFT                            0
+#define MADERA_EQ4_B1_MODE_WIDTH                            1
+
+/* (0x0E80)  DRC1_ctrl1 */
+#define MADERA_DRC1L_ENA                               0x0002
+#define MADERA_DRC1L_ENA_MASK                          0x0002
+#define MADERA_DRC1L_ENA_SHIFT                              1
+#define MADERA_DRC1L_ENA_WIDTH                              1
+#define MADERA_DRC1R_ENA                               0x0001
+#define MADERA_DRC1R_ENA_MASK                          0x0001
+#define MADERA_DRC1R_ENA_SHIFT                              0
+#define MADERA_DRC1R_ENA_WIDTH                              1
+
+/* (0x0E88)  DRC2_ctrl1 */
+#define MADERA_DRC2L_ENA                               0x0002
+#define MADERA_DRC2L_ENA_MASK                          0x0002
+#define MADERA_DRC2L_ENA_SHIFT                              1
+#define MADERA_DRC2L_ENA_WIDTH                              1
+#define MADERA_DRC2R_ENA                               0x0001
+#define MADERA_DRC2R_ENA_MASK                          0x0001
+#define MADERA_DRC2R_ENA_SHIFT                              0
+#define MADERA_DRC2R_ENA_WIDTH                              1
+
+/* (0x0EC0)  HPLPF1_1 */
+#define MADERA_LHPF1_MODE                              0x0002
+#define MADERA_LHPF1_MODE_MASK                         0x0002
+#define MADERA_LHPF1_MODE_SHIFT                                     1
+#define MADERA_LHPF1_MODE_WIDTH                                     1
+#define MADERA_LHPF1_ENA                               0x0001
+#define MADERA_LHPF1_ENA_MASK                          0x0001
+#define MADERA_LHPF1_ENA_SHIFT                              0
+#define MADERA_LHPF1_ENA_WIDTH                              1
+
+/* (0x0EC1)  HPLPF1_2 */
+#define MADERA_LHPF1_COEFF_MASK                                0xFFFF
+#define MADERA_LHPF1_COEFF_SHIFT                            0
+#define MADERA_LHPF1_COEFF_WIDTH                           16
+
+/* (0x0EC4)  HPLPF2_1 */
+#define MADERA_LHPF2_MODE                              0x0002
+#define MADERA_LHPF2_MODE_MASK                         0x0002
+#define MADERA_LHPF2_MODE_SHIFT                                     1
+#define MADERA_LHPF2_MODE_WIDTH                                     1
+#define MADERA_LHPF2_ENA                               0x0001
+#define MADERA_LHPF2_ENA_MASK                          0x0001
+#define MADERA_LHPF2_ENA_SHIFT                              0
+#define MADERA_LHPF2_ENA_WIDTH                              1
+
+/* (0x0EC5)  HPLPF2_2 */
+#define MADERA_LHPF2_COEFF_MASK                                0xFFFF
+#define MADERA_LHPF2_COEFF_SHIFT                            0
+#define MADERA_LHPF2_COEFF_WIDTH                           16
+
+/* (0x0EC8)  HPLPF3_1 */
+#define MADERA_LHPF3_MODE                              0x0002
+#define MADERA_LHPF3_MODE_MASK                         0x0002
+#define MADERA_LHPF3_MODE_SHIFT                                     1
+#define MADERA_LHPF3_MODE_WIDTH                                     1
+#define MADERA_LHPF3_ENA                               0x0001
+#define MADERA_LHPF3_ENA_MASK                          0x0001
+#define MADERA_LHPF3_ENA_SHIFT                              0
+#define MADERA_LHPF3_ENA_WIDTH                              1
+
+/* (0x0EC9)  HPLPF3_2 */
+#define MADERA_LHPF3_COEFF_MASK                                0xFFFF
+#define MADERA_LHPF3_COEFF_SHIFT                            0
+#define MADERA_LHPF3_COEFF_WIDTH                           16
+
+/* (0x0ECC)  HPLPF4_1 */
+#define MADERA_LHPF4_MODE                              0x0002
+#define MADERA_LHPF4_MODE_MASK                         0x0002
+#define MADERA_LHPF4_MODE_SHIFT                                     1
+#define MADERA_LHPF4_MODE_WIDTH                                     1
+#define MADERA_LHPF4_ENA                               0x0001
+#define MADERA_LHPF4_ENA_MASK                          0x0001
+#define MADERA_LHPF4_ENA_SHIFT                              0
+#define MADERA_LHPF4_ENA_WIDTH                              1
+
+/* (0x0ECD)  HPLPF4_2 */
+#define MADERA_LHPF4_COEFF_MASK                                0xFFFF
+#define MADERA_LHPF4_COEFF_SHIFT                            0
+#define MADERA_LHPF4_COEFF_WIDTH                           16
+
+/* (0x0ED0)  ASRC2_ENABLE */
+#define MADERA_ASRC2_IN2L_ENA                          0x0008
+#define MADERA_ASRC2_IN2L_ENA_MASK                     0x0008
+#define MADERA_ASRC2_IN2L_ENA_SHIFT                         3
+#define MADERA_ASRC2_IN2L_ENA_WIDTH                         1
+#define MADERA_ASRC2_IN2R_ENA                          0x0004
+#define MADERA_ASRC2_IN2R_ENA_MASK                     0x0004
+#define MADERA_ASRC2_IN2R_ENA_SHIFT                         2
+#define MADERA_ASRC2_IN2R_ENA_WIDTH                         1
+#define MADERA_ASRC2_IN1L_ENA                          0x0002
+#define MADERA_ASRC2_IN1L_ENA_MASK                     0x0002
+#define MADERA_ASRC2_IN1L_ENA_SHIFT                         1
+#define MADERA_ASRC2_IN1L_ENA_WIDTH                         1
+#define MADERA_ASRC2_IN1R_ENA                          0x0001
+#define MADERA_ASRC2_IN1R_ENA_MASK                     0x0001
+#define MADERA_ASRC2_IN1R_ENA_SHIFT                         0
+#define MADERA_ASRC2_IN1R_ENA_WIDTH                         1
+
+/* (0x0ED2)  ASRC2_RATE1 */
+#define MADERA_ASRC2_RATE1_MASK                                0xF800
+#define MADERA_ASRC2_RATE1_SHIFT                           11
+#define MADERA_ASRC2_RATE1_WIDTH                            5
+
+/* (0x0ED3)  ASRC2_RATE2 */
+#define MADERA_ASRC2_RATE2_MASK                                0xF800
+#define MADERA_ASRC2_RATE2_SHIFT                           11
+#define MADERA_ASRC2_RATE2_WIDTH                            5
+
+/* (0x0EE0)  ASRC1_ENABLE */
+#define MADERA_ASRC1_IN2L_ENA                          0x0008
+#define MADERA_ASRC1_IN2L_ENA_MASK                     0x0008
+#define MADERA_ASRC1_IN2L_ENA_SHIFT                         3
+#define MADERA_ASRC1_IN2L_ENA_WIDTH                         1
+#define MADERA_ASRC1_IN2R_ENA                          0x0004
+#define MADERA_ASRC1_IN2R_ENA_MASK                     0x0004
+#define MADERA_ASRC1_IN2R_ENA_SHIFT                         2
+#define MADERA_ASRC1_IN2R_ENA_WIDTH                         1
+#define MADERA_ASRC1_IN1L_ENA                          0x0002
+#define MADERA_ASRC1_IN1L_ENA_MASK                     0x0002
+#define MADERA_ASRC1_IN1L_ENA_SHIFT                         1
+#define MADERA_ASRC1_IN1L_ENA_WIDTH                         1
+#define MADERA_ASRC1_IN1R_ENA                          0x0001
+#define MADERA_ASRC1_IN1R_ENA_MASK                     0x0001
+#define MADERA_ASRC1_IN1R_ENA_SHIFT                         0
+#define MADERA_ASRC1_IN1R_ENA_WIDTH                         1
+
+/* (0x0EE2)  ASRC1_RATE1 */
+#define MADERA_ASRC1_RATE1_MASK                                0xF800
+#define MADERA_ASRC1_RATE1_SHIFT                           11
+#define MADERA_ASRC1_RATE1_WIDTH                            5
+
+/* (0x0EE3)  ASRC1_RATE2 */
+#define MADERA_ASRC1_RATE2_MASK                                0xF800
+#define MADERA_ASRC1_RATE2_SHIFT                           11
+#define MADERA_ASRC1_RATE2_WIDTH                            5
+
+/* (0x0EF0) - ISRC1 CTRL 1 */
+#define MADERA_ISRC1_FSH_MASK                          0xF800
+#define MADERA_ISRC1_FSH_SHIFT                             11
+#define MADERA_ISRC1_FSH_WIDTH                              5
+#define MADERA_ISRC1_CLK_SEL_MASK                      0x0700
+#define MADERA_ISRC1_CLK_SEL_SHIFT                          8
+#define MADERA_ISRC1_CLK_SEL_WIDTH                          3
+
+/* (0x0EF1)  ISRC1_CTRL_2 */
+#define MADERA_ISRC1_FSL_MASK                          0xF800
+#define MADERA_ISRC1_FSL_SHIFT                             11
+#define MADERA_ISRC1_FSL_WIDTH                              5
+
+/* (0x0EF2)  ISRC1_CTRL_3 */
+#define MADERA_ISRC1_INT1_ENA                          0x8000
+#define MADERA_ISRC1_INT1_ENA_MASK                     0x8000
+#define MADERA_ISRC1_INT1_ENA_SHIFT                        15
+#define MADERA_ISRC1_INT1_ENA_WIDTH                         1
+#define MADERA_ISRC1_INT2_ENA                          0x4000
+#define MADERA_ISRC1_INT2_ENA_MASK                     0x4000
+#define MADERA_ISRC1_INT2_ENA_SHIFT                        14
+#define MADERA_ISRC1_INT2_ENA_WIDTH                         1
+#define MADERA_ISRC1_INT3_ENA                          0x2000
+#define MADERA_ISRC1_INT3_ENA_MASK                     0x2000
+#define MADERA_ISRC1_INT3_ENA_SHIFT                        13
+#define MADERA_ISRC1_INT3_ENA_WIDTH                         1
+#define MADERA_ISRC1_INT4_ENA                          0x1000
+#define MADERA_ISRC1_INT4_ENA_MASK                     0x1000
+#define MADERA_ISRC1_INT4_ENA_SHIFT                        12
+#define MADERA_ISRC1_INT4_ENA_WIDTH                         1
+#define MADERA_ISRC1_DEC1_ENA                          0x0200
+#define MADERA_ISRC1_DEC1_ENA_MASK                     0x0200
+#define MADERA_ISRC1_DEC1_ENA_SHIFT                         9
+#define MADERA_ISRC1_DEC1_ENA_WIDTH                         1
+#define MADERA_ISRC1_DEC2_ENA                          0x0100
+#define MADERA_ISRC1_DEC2_ENA_MASK                     0x0100
+#define MADERA_ISRC1_DEC2_ENA_SHIFT                         8
+#define MADERA_ISRC1_DEC2_ENA_WIDTH                         1
+#define MADERA_ISRC1_DEC3_ENA                          0x0080
+#define MADERA_ISRC1_DEC3_ENA_MASK                     0x0080
+#define MADERA_ISRC1_DEC3_ENA_SHIFT                         7
+#define MADERA_ISRC1_DEC3_ENA_WIDTH                         1
+#define MADERA_ISRC1_DEC4_ENA                          0x0040
+#define MADERA_ISRC1_DEC4_ENA_MASK                     0x0040
+#define MADERA_ISRC1_DEC4_ENA_SHIFT                         6
+#define MADERA_ISRC1_DEC4_ENA_WIDTH                         1
+#define MADERA_ISRC1_NOTCH_ENA                         0x0001
+#define MADERA_ISRC1_NOTCH_ENA_MASK                    0x0001
+#define MADERA_ISRC1_NOTCH_ENA_SHIFT                        0
+#define MADERA_ISRC1_NOTCH_ENA_WIDTH                        1
+
+/* (0x0EF3)  ISRC2_CTRL_1 */
+#define MADERA_ISRC2_FSH_MASK                          0xF800
+#define MADERA_ISRC2_FSH_SHIFT                             11
+#define MADERA_ISRC2_FSH_WIDTH                              5
+#define MADERA_ISRC2_CLK_SEL_MASK                      0x0700
+#define MADERA_ISRC2_CLK_SEL_SHIFT                          8
+#define MADERA_ISRC2_CLK_SEL_WIDTH                          3
+
+/* (0x0EF4)  ISRC2_CTRL_2 */
+#define MADERA_ISRC2_FSL_MASK                          0xF800
+#define MADERA_ISRC2_FSL_SHIFT                             11
+#define MADERA_ISRC2_FSL_WIDTH                              5
+
+/* (0x0EF5)  ISRC2_CTRL_3 */
+#define MADERA_ISRC2_INT1_ENA                          0x8000
+#define MADERA_ISRC2_INT1_ENA_MASK                     0x8000
+#define MADERA_ISRC2_INT1_ENA_SHIFT                        15
+#define MADERA_ISRC2_INT1_ENA_WIDTH                         1
+#define MADERA_ISRC2_INT2_ENA                          0x4000
+#define MADERA_ISRC2_INT2_ENA_MASK                     0x4000
+#define MADERA_ISRC2_INT2_ENA_SHIFT                        14
+#define MADERA_ISRC2_INT2_ENA_WIDTH                         1
+#define MADERA_ISRC2_INT3_ENA                          0x2000
+#define MADERA_ISRC2_INT3_ENA_MASK                     0x2000
+#define MADERA_ISRC2_INT3_ENA_SHIFT                        13
+#define MADERA_ISRC2_INT3_ENA_WIDTH                         1
+#define MADERA_ISRC2_INT4_ENA                          0x1000
+#define MADERA_ISRC2_INT4_ENA_MASK                     0x1000
+#define MADERA_ISRC2_INT4_ENA_SHIFT                        12
+#define MADERA_ISRC2_INT4_ENA_WIDTH                         1
+#define MADERA_ISRC2_DEC1_ENA                          0x0200
+#define MADERA_ISRC2_DEC1_ENA_MASK                     0x0200
+#define MADERA_ISRC2_DEC1_ENA_SHIFT                         9
+#define MADERA_ISRC2_DEC1_ENA_WIDTH                         1
+#define MADERA_ISRC2_DEC2_ENA                          0x0100
+#define MADERA_ISRC2_DEC2_ENA_MASK                     0x0100
+#define MADERA_ISRC2_DEC2_ENA_SHIFT                         8
+#define MADERA_ISRC2_DEC2_ENA_WIDTH                         1
+#define MADERA_ISRC2_DEC3_ENA                          0x0080
+#define MADERA_ISRC2_DEC3_ENA_MASK                     0x0080
+#define MADERA_ISRC2_DEC3_ENA_SHIFT                         7
+#define MADERA_ISRC2_DEC3_ENA_WIDTH                         1
+#define MADERA_ISRC2_DEC4_ENA                          0x0040
+#define MADERA_ISRC2_DEC4_ENA_MASK                     0x0040
+#define MADERA_ISRC2_DEC4_ENA_SHIFT                         6
+#define MADERA_ISRC2_DEC4_ENA_WIDTH                         1
+#define MADERA_ISRC2_NOTCH_ENA                         0x0001
+#define MADERA_ISRC2_NOTCH_ENA_MASK                    0x0001
+#define MADERA_ISRC2_NOTCH_ENA_SHIFT                        0
+#define MADERA_ISRC2_NOTCH_ENA_WIDTH                        1
+
+/* (0x0EF6)  ISRC3_CTRL_1 */
+#define MADERA_ISRC3_FSH_MASK                          0xF800
+#define MADERA_ISRC3_FSH_SHIFT                             11
+#define MADERA_ISRC3_FSH_WIDTH                              5
+#define MADERA_ISRC3_CLK_SEL_MASK                      0x0700
+#define MADERA_ISRC3_CLK_SEL_SHIFT                          8
+#define MADERA_ISRC3_CLK_SEL_WIDTH                          3
+
+/* (0x0EF7)  ISRC3_CTRL_2 */
+#define MADERA_ISRC3_FSL_MASK                          0xF800
+#define MADERA_ISRC3_FSL_SHIFT                             11
+#define MADERA_ISRC3_FSL_WIDTH                              5
+
+/* (0x0EF8)  ISRC3_CTRL_3 */
+#define MADERA_ISRC3_INT1_ENA                          0x8000
+#define MADERA_ISRC3_INT1_ENA_MASK                     0x8000
+#define MADERA_ISRC3_INT1_ENA_SHIFT                        15
+#define MADERA_ISRC3_INT1_ENA_WIDTH                         1
+#define MADERA_ISRC3_INT2_ENA                          0x4000
+#define MADERA_ISRC3_INT2_ENA_MASK                     0x4000
+#define MADERA_ISRC3_INT2_ENA_SHIFT                        14
+#define MADERA_ISRC3_INT2_ENA_WIDTH                         1
+#define MADERA_ISRC3_INT3_ENA                          0x2000
+#define MADERA_ISRC3_INT3_ENA_MASK                     0x2000
+#define MADERA_ISRC3_INT3_ENA_SHIFT                        13
+#define MADERA_ISRC3_INT3_ENA_WIDTH                         1
+#define MADERA_ISRC3_INT4_ENA                          0x1000
+#define MADERA_ISRC3_INT4_ENA_MASK                     0x1000
+#define MADERA_ISRC3_INT4_ENA_SHIFT                        12
+#define MADERA_ISRC3_INT4_ENA_WIDTH                         1
+#define MADERA_ISRC3_DEC1_ENA                          0x0200
+#define MADERA_ISRC3_DEC1_ENA_MASK                     0x0200
+#define MADERA_ISRC3_DEC1_ENA_SHIFT                         9
+#define MADERA_ISRC3_DEC1_ENA_WIDTH                         1
+#define MADERA_ISRC3_DEC2_ENA                          0x0100
+#define MADERA_ISRC3_DEC2_ENA_MASK                     0x0100
+#define MADERA_ISRC3_DEC2_ENA_SHIFT                         8
+#define MADERA_ISRC3_DEC2_ENA_WIDTH                         1
+#define MADERA_ISRC3_DEC3_ENA                          0x0080
+#define MADERA_ISRC3_DEC3_ENA_MASK                     0x0080
+#define MADERA_ISRC3_DEC3_ENA_SHIFT                         7
+#define MADERA_ISRC3_DEC3_ENA_WIDTH                         1
+#define MADERA_ISRC3_DEC4_ENA                          0x0040
+#define MADERA_ISRC3_DEC4_ENA_MASK                     0x0040
+#define MADERA_ISRC3_DEC4_ENA_SHIFT                         6
+#define MADERA_ISRC3_DEC4_ENA_WIDTH                         1
+#define MADERA_ISRC3_NOTCH_ENA                         0x0001
+#define MADERA_ISRC3_NOTCH_ENA_MASK                    0x0001
+#define MADERA_ISRC3_NOTCH_ENA_SHIFT                        0
+#define MADERA_ISRC3_NOTCH_ENA_WIDTH                        1
+
+/* (0x0EF9)  ISRC4_CTRL_1 */
+#define MADERA_ISRC4_FSH_MASK                          0xF800
+#define MADERA_ISRC4_FSH_SHIFT                             11
+#define MADERA_ISRC4_FSH_WIDTH                              5
+#define MADERA_ISRC4_CLK_SEL_MASK                      0x0700
+#define MADERA_ISRC4_CLK_SEL_SHIFT                          8
+#define MADERA_ISRC4_CLK_SEL_WIDTH                          3
+
+/* (0x0EFA)  ISRC4_CTRL_2 */
+#define MADERA_ISRC4_FSL_MASK                          0xF800
+#define MADERA_ISRC4_FSL_SHIFT                             11
+#define MADERA_ISRC4_FSL_WIDTH                              5
+
+/* (0x0EFB)  ISRC4_CTRL_3 */
+#define MADERA_ISRC4_INT1_ENA                          0x8000
+#define MADERA_ISRC4_INT1_ENA_MASK                     0x8000
+#define MADERA_ISRC4_INT1_ENA_SHIFT                        15
+#define MADERA_ISRC4_INT1_ENA_WIDTH                         1
+#define MADERA_ISRC4_INT2_ENA                          0x4000
+#define MADERA_ISRC4_INT2_ENA_MASK                     0x4000
+#define MADERA_ISRC4_INT2_ENA_SHIFT                        14
+#define MADERA_ISRC4_INT2_ENA_WIDTH                         1
+#define MADERA_ISRC4_INT3_ENA                          0x2000
+#define MADERA_ISRC4_INT3_ENA_MASK                     0x2000
+#define MADERA_ISRC4_INT3_ENA_SHIFT                        13
+#define MADERA_ISRC4_INT3_ENA_WIDTH                         1
+#define MADERA_ISRC4_INT4_ENA                          0x1000
+#define MADERA_ISRC4_INT4_ENA_MASK                     0x1000
+#define MADERA_ISRC4_INT4_ENA_SHIFT                        12
+#define MADERA_ISRC4_INT4_ENA_WIDTH                         1
+#define MADERA_ISRC4_DEC1_ENA                          0x0200
+#define MADERA_ISRC4_DEC1_ENA_MASK                     0x0200
+#define MADERA_ISRC4_DEC1_ENA_SHIFT                         9
+#define MADERA_ISRC4_DEC1_ENA_WIDTH                         1
+#define MADERA_ISRC4_DEC2_ENA                          0x0100
+#define MADERA_ISRC4_DEC2_ENA_MASK                     0x0100
+#define MADERA_ISRC4_DEC2_ENA_SHIFT                         8
+#define MADERA_ISRC4_DEC2_ENA_WIDTH                         1
+#define MADERA_ISRC4_DEC3_ENA                          0x0080
+#define MADERA_ISRC4_DEC3_ENA_MASK                     0x0080
+#define MADERA_ISRC4_DEC3_ENA_SHIFT                         7
+#define MADERA_ISRC4_DEC3_ENA_WIDTH                         1
+#define MADERA_ISRC4_DEC4_ENA                          0x0040
+#define MADERA_ISRC4_DEC4_ENA_MASK                     0x0040
+#define MADERA_ISRC4_DEC4_ENA_SHIFT                         6
+#define MADERA_ISRC4_DEC4_ENA_WIDTH                         1
+#define MADERA_ISRC4_NOTCH_ENA                         0x0001
+#define MADERA_ISRC4_NOTCH_ENA_MASK                    0x0001
+#define MADERA_ISRC4_NOTCH_ENA_SHIFT                        0
+#define MADERA_ISRC4_NOTCH_ENA_WIDTH                        1
+
+/* (0x0F00)  Clock_Control */
+#define MADERA_EXT_NG_SEL_CLR                          0x0080
+#define MADERA_EXT_NG_SEL_CLR_MASK                     0x0080
+#define MADERA_EXT_NG_SEL_CLR_SHIFT                         7
+#define MADERA_EXT_NG_SEL_CLR_WIDTH                         1
+#define MADERA_EXT_NG_SEL_SET                          0x0040
+#define MADERA_EXT_NG_SEL_SET_MASK                     0x0040
+#define MADERA_EXT_NG_SEL_SET_SHIFT                         6
+#define MADERA_EXT_NG_SEL_SET_WIDTH                         1
+#define MADERA_CLK_R_ENA_CLR                           0x0020
+#define MADERA_CLK_R_ENA_CLR_MASK                      0x0020
+#define MADERA_CLK_R_ENA_CLR_SHIFT                          5
+#define MADERA_CLK_R_ENA_CLR_WIDTH                          1
+#define MADERA_CLK_R_ENA_SET                           0x0010
+#define MADERA_CLK_R_ENA_SET_MASK                      0x0010
+#define MADERA_CLK_R_ENA_SET_SHIFT                          4
+#define MADERA_CLK_R_ENA_SET_WIDTH                          1
+#define MADERA_CLK_NG_ENA_CLR                          0x0008
+#define MADERA_CLK_NG_ENA_CLR_MASK                     0x0008
+#define MADERA_CLK_NG_ENA_CLR_SHIFT                         3
+#define MADERA_CLK_NG_ENA_CLR_WIDTH                         1
+#define MADERA_CLK_NG_ENA_SET                          0x0004
+#define MADERA_CLK_NG_ENA_SET_MASK                     0x0004
+#define MADERA_CLK_NG_ENA_SET_SHIFT                         2
+#define MADERA_CLK_NG_ENA_SET_WIDTH                         1
+#define MADERA_CLK_L_ENA_CLR                           0x0002
+#define MADERA_CLK_L_ENA_CLR_MASK                      0x0002
+#define MADERA_CLK_L_ENA_CLR_SHIFT                          1
+#define MADERA_CLK_L_ENA_CLR_WIDTH                          1
+#define MADERA_CLK_L_ENA_SET                           0x0001
+#define MADERA_CLK_L_ENA_SET_MASK                      0x0001
+#define MADERA_CLK_L_ENA_SET_SHIFT                          0
+#define MADERA_CLK_L_ENA_SET_WIDTH                          1
+
+/* (0x0F01)  ANC_SRC */
+#define MADERA_IN_RXANCR_SEL_MASK                      0x0070
+#define MADERA_IN_RXANCR_SEL_SHIFT                          4
+#define MADERA_IN_RXANCR_SEL_WIDTH                          3
+#define MADERA_IN_RXANCL_SEL_MASK                      0x0007
+#define MADERA_IN_RXANCL_SEL_SHIFT                          0
+#define MADERA_IN_RXANCL_SEL_WIDTH                          3
+
+/* (0x0F17)  FCL_ADC_reformatter_control */
+#define MADERA_FCL_MIC_MODE_SEL                                0x000C
+#define MADERA_FCL_MIC_MODE_SEL_SHIFT                       2
+#define MADERA_FCL_MIC_MODE_SEL_WIDTH                       2
+
+/* (0x0F73)  FCR_ADC_reformatter_control */
+#define MADERA_FCR_MIC_MODE_SEL                                0x000C
+#define MADERA_FCR_MIC_MODE_SEL_SHIFT                       2
+#define MADERA_FCR_MIC_MODE_SEL_WIDTH                       2
+
+/* (0x1480)  DFC1_CTRL_W0 */
+#define MADERA_DFC1_RATE_MASK                          0x007C
+#define MADERA_DFC1_RATE_SHIFT                              2
+#define MADERA_DFC1_RATE_WIDTH                              5
+#define MADERA_DFC1_DITH_ENA                           0x0002
+#define MADERA_DFC1_DITH_ENA_MASK                      0x0002
+#define MADERA_DFC1_DITH_ENA_SHIFT                          1
+#define MADERA_DFC1_DITH_ENA_WIDTH                          1
+#define MADERA_DFC1_ENA                                        0x0001
+#define MADERA_DFC1_ENA_MASK                           0x0001
+#define MADERA_DFC1_ENA_SHIFT                               0
+#define MADERA_DFC1_ENA_WIDTH                               1
+
+/* (0x1482)  DFC1_RX_W0 */
+#define MADERA_DFC1_RX_DATA_WIDTH_MASK                 0x1F00
+#define MADERA_DFC1_RX_DATA_WIDTH_SHIFT                             8
+#define MADERA_DFC1_RX_DATA_WIDTH_WIDTH                             5
+
+#define MADERA_DFC1_RX_DATA_TYPE_MASK                  0x0007
+#define MADERA_DFC1_RX_DATA_TYPE_SHIFT                      0
+#define MADERA_DFC1_RX_DATA_TYPE_WIDTH                      3
+
+/* (0x1484)  DFC1_TX_W0 */
+#define MADERA_DFC1_TX_DATA_WIDTH_MASK                 0x1F00
+#define MADERA_DFC1_TX_DATA_WIDTH_SHIFT                             8
+#define MADERA_DFC1_TX_DATA_WIDTH_WIDTH                             5
+
+#define MADERA_DFC1_TX_DATA_TYPE_MASK                  0x0007
+#define MADERA_DFC1_TX_DATA_TYPE_SHIFT                      0
+#define MADERA_DFC1_TX_DATA_TYPE_WIDTH                      3
+
+/* (0x1600)  ADSP2_IRQ0 */
+#define MADERA_DSP_IRQ2                                        0x0002
+#define MADERA_DSP_IRQ1                                        0x0001
+
+/* (0x1601)  ADSP2_IRQ1 */
+#define MADERA_DSP_IRQ4                                        0x0002
+#define MADERA_DSP_IRQ3                                        0x0001
+
+/* (0x1602)  ADSP2_IRQ2 */
+#define MADERA_DSP_IRQ6                                        0x0002
+#define MADERA_DSP_IRQ5                                        0x0001
+
+/* (0x1603)  ADSP2_IRQ3 */
+#define MADERA_DSP_IRQ8                                        0x0002
+#define MADERA_DSP_IRQ7                                        0x0001
+
+/* (0x1604)  ADSP2_IRQ4 */
+#define MADERA_DSP_IRQ10                               0x0002
+#define MADERA_DSP_IRQ9                                        0x0001
+
+/* (0x1605)  ADSP2_IRQ5 */
+#define MADERA_DSP_IRQ12                               0x0002
+#define MADERA_DSP_IRQ11                               0x0001
+
+/* (0x1606)  ADSP2_IRQ6 */
+#define MADERA_DSP_IRQ14                               0x0002
+#define MADERA_DSP_IRQ13                               0x0001
+
+/* (0x1607)  ADSP2_IRQ7 */
+#define MADERA_DSP_IRQ16                               0x0002
+#define MADERA_DSP_IRQ15                               0x0001
+
+/* (0x1700)  GPIO1_CTRL_1 */
+#define MADERA_GP1_LVL                                 0x8000
+#define MADERA_GP1_LVL_MASK                            0x8000
+#define MADERA_GP1_LVL_SHIFT                               15
+#define MADERA_GP1_LVL_WIDTH                                1
+#define MADERA_GP1_OP_CFG                              0x4000
+#define MADERA_GP1_OP_CFG_MASK                         0x4000
+#define MADERA_GP1_OP_CFG_SHIFT                                    14
+#define MADERA_GP1_OP_CFG_WIDTH                                     1
+#define MADERA_GP1_DB                                  0x2000
+#define MADERA_GP1_DB_MASK                             0x2000
+#define MADERA_GP1_DB_SHIFT                                13
+#define MADERA_GP1_DB_WIDTH                                 1
+#define MADERA_GP1_POL                                 0x1000
+#define MADERA_GP1_POL_MASK                            0x1000
+#define MADERA_GP1_POL_SHIFT                               12
+#define MADERA_GP1_POL_WIDTH                                1
+#define MADERA_GP1_IP_CFG                              0x0800
+#define MADERA_GP1_IP_CFG_MASK                         0x0800
+#define MADERA_GP1_IP_CFG_SHIFT                                    11
+#define MADERA_GP1_IP_CFG_WIDTH                                     1
+#define MADERA_GP1_FN_MASK                             0x03FF
+#define MADERA_GP1_FN_SHIFT                                 0
+#define MADERA_GP1_FN_WIDTH                                10
+
+/* (0x1701)  GPIO1_CTRL_2 */
+#define MADERA_GP1_DIR                                 0x8000
+#define MADERA_GP1_DIR_MASK                            0x8000
+#define MADERA_GP1_DIR_SHIFT                               15
+#define MADERA_GP1_DIR_WIDTH                                1
+#define MADERA_GP1_PU                                  0x4000
+#define MADERA_GP1_PU_MASK                             0x4000
+#define MADERA_GP1_PU_SHIFT                                14
+#define MADERA_GP1_PU_WIDTH                                 1
+#define MADERA_GP1_PD                                  0x2000
+#define MADERA_GP1_PD_MASK                             0x2000
+#define MADERA_GP1_PD_SHIFT                                13
+#define MADERA_GP1_PD_WIDTH                                 1
+#define MADERA_GP1_DRV_STR_MASK                                0x1800
+#define MADERA_GP1_DRV_STR_SHIFT                           11
+#define MADERA_GP1_DRV_STR_WIDTH                            2
+
+/* (0x1800)  IRQ1_Status_1 */
+#define MADERA_CTRLIF_ERR_EINT1                                0x1000
+#define MADERA_CTRLIF_ERR_EINT1_MASK                   0x1000
+#define MADERA_CTRLIF_ERR_EINT1_SHIFT                      12
+#define MADERA_CTRLIF_ERR_EINT1_WIDTH                       1
+#define MADERA_SYSCLK_FAIL_EINT1                       0x0200
+#define MADERA_SYSCLK_FAIL_EINT1_MASK                  0x0200
+#define MADERA_SYSCLK_FAIL_EINT1_SHIFT                      9
+#define MADERA_SYSCLK_FAIL_EINT1_WIDTH                      1
+#define MADERA_CLOCK_DETECT_EINT1                      0x0100
+#define MADERA_CLOCK_DETECT_EINT1_MASK                 0x0100
+#define MADERA_CLOCK_DETECT_EINT1_SHIFT                             8
+#define MADERA_CLOCK_DETECT_EINT1_WIDTH                             1
+#define MADERA_BOOT_DONE_EINT1                         0x0080
+#define MADERA_BOOT_DONE_EINT1_MASK                    0x0080
+#define MADERA_BOOT_DONE_EINT1_SHIFT                        7
+#define MADERA_BOOT_DONE_EINT1_WIDTH                        1
+
+/* (0x1801)  IRQ1_Status_2 */
+#define MADERA_FLLAO_LOCK_EINT1                                0x0800
+#define MADERA_FLLAO_LOCK_EINT1_MASK                   0x0800
+#define MADERA_FLLAO_LOCK_EINT1_SHIFT                      11
+#define MADERA_FLLAO_LOCK_EINT1_WIDTH                       1
+#define MADERA_FLL3_LOCK_EINT1                         0x0400
+#define MADERA_FLL3_LOCK_EINT1_MASK                    0x0400
+#define MADERA_FLL3_LOCK_EINT1_SHIFT                       10
+#define MADERA_FLL3_LOCK_EINT1_WIDTH                        1
+#define MADERA_FLL2_LOCK_EINT1                         0x0200
+#define MADERA_FLL2_LOCK_EINT1_MASK                    0x0200
+#define MADERA_FLL2_LOCK_EINT1_SHIFT                        9
+#define MADERA_FLL2_LOCK_EINT1_WIDTH                        1
+#define MADERA_FLL1_LOCK_EINT1                         0x0100
+#define MADERA_FLL1_LOCK_EINT1_MASK                    0x0100
+#define MADERA_FLL1_LOCK_EINT1_SHIFT                        8
+#define MADERA_FLL1_LOCK_EINT1_WIDTH                        1
+
+/* (0x1805)  IRQ1_Status_6 */
+#define MADERA_MICDET2_EINT1                           0x0200
+#define MADERA_MICDET2_EINT1_MASK                      0x0200
+#define MADERA_MICDET2_EINT1_SHIFT                          9
+#define MADERA_MICDET2_EINT1_WIDTH                          1
+#define MADERA_MICDET1_EINT1                           0x0100
+#define MADERA_MICDET1_EINT1_MASK                      0x0100
+#define MADERA_MICDET1_EINT1_SHIFT                          8
+#define MADERA_MICDET1_EINT1_WIDTH                          1
+#define MADERA_HPDET_EINT1                             0x0001
+#define MADERA_HPDET_EINT1_MASK                                0x0001
+#define MADERA_HPDET_EINT1_SHIFT                            0
+#define MADERA_HPDET_EINT1_WIDTH                            1
+
+/* (0x1806)  IRQ1_Status_7 */
+#define MADERA_MICD_CLAMP_FALL_EINT1                   0x0020
+#define MADERA_MICD_CLAMP_FALL_EINT1_MASK              0x0020
+#define MADERA_MICD_CLAMP_FALL_EINT1_SHIFT                  5
+#define MADERA_MICD_CLAMP_FALL_EINT1_WIDTH                  1
+#define MADERA_MICD_CLAMP_RISE_EINT1                   0x0010
+#define MADERA_MICD_CLAMP_RISE_EINT1_MASK              0x0010
+#define MADERA_MICD_CLAMP_RISE_EINT1_SHIFT                  4
+#define MADERA_MICD_CLAMP_RISE_EINT1_WIDTH                  1
+#define MADERA_JD2_FALL_EINT1                          0x0008
+#define MADERA_JD2_FALL_EINT1_MASK                     0x0008
+#define MADERA_JD2_FALL_EINT1_SHIFT                         3
+#define MADERA_JD2_FALL_EINT1_WIDTH                         1
+#define MADERA_JD2_RISE_EINT1                          0x0004
+#define MADERA_JD2_RISE_EINT1_MASK                     0x0004
+#define MADERA_JD2_RISE_EINT1_SHIFT                         2
+#define MADERA_JD2_RISE_EINT1_WIDTH                         1
+#define MADERA_JD1_FALL_EINT1                          0x0002
+#define MADERA_JD1_FALL_EINT1_MASK                     0x0002
+#define MADERA_JD1_FALL_EINT1_SHIFT                         1
+#define MADERA_JD1_FALL_EINT1_WIDTH                         1
+#define MADERA_JD1_RISE_EINT1                          0x0001
+#define MADERA_JD1_RISE_EINT1_MASK                     0x0001
+#define MADERA_JD1_RISE_EINT1_SHIFT                         0
+#define MADERA_JD1_RISE_EINT1_WIDTH                         1
+
+/* (0x1808)  IRQ1_Status_9 */
+#define MADERA_ASRC2_IN2_LOCK_EINT1                    0x0800
+#define MADERA_ASRC2_IN2_LOCK_EINT1_MASK               0x0800
+#define MADERA_ASRC2_IN2_LOCK_EINT1_SHIFT                  11
+#define MADERA_ASRC2_IN2_LOCK_EINT1_WIDTH                   1
+#define MADERA_ASRC2_IN1_LOCK_EINT1                    0x0400
+#define MADERA_ASRC2_IN1_LOCK_EINT1_MASK               0x0400
+#define MADERA_ASRC2_IN1_LOCK_EINT1_SHIFT                  10
+#define MADERA_ASRC2_IN1_LOCK_EINT1_WIDTH                   1
+#define MADERA_ASRC1_IN2_LOCK_EINT1                    0x0200
+#define MADERA_ASRC1_IN2_LOCK_EINT1_MASK               0x0200
+#define MADERA_ASRC1_IN2_LOCK_EINT1_SHIFT                   9
+#define MADERA_ASRC1_IN2_LOCK_EINT1_WIDTH                   1
+#define MADERA_ASRC1_IN1_LOCK_EINT1                    0x0100
+#define MADERA_ASRC1_IN1_LOCK_EINT1_MASK               0x0100
+#define MADERA_ASRC1_IN1_LOCK_EINT1_SHIFT                   8
+#define MADERA_ASRC1_IN1_LOCK_EINT1_WIDTH                   1
+#define MADERA_DRC2_SIG_DET_EINT1                      0x0002
+#define MADERA_DRC2_SIG_DET_EINT1_MASK                 0x0002
+#define MADERA_DRC2_SIG_DET_EINT1_SHIFT                             1
+#define MADERA_DRC2_SIG_DET_EINT1_WIDTH                             1
+#define MADERA_DRC1_SIG_DET_EINT1                      0x0001
+#define MADERA_DRC1_SIG_DET_EINT1_MASK                 0x0001
+#define MADERA_DRC1_SIG_DET_EINT1_SHIFT                             0
+#define MADERA_DRC1_SIG_DET_EINT1_WIDTH                             1
+
+/* (0x180A)  IRQ1_Status_11 */
+#define MADERA_DSP_IRQ16_EINT1                         0x8000
+#define MADERA_DSP_IRQ16_EINT1_MASK                    0x8000
+#define MADERA_DSP_IRQ16_EINT1_SHIFT                       15
+#define MADERA_DSP_IRQ16_EINT1_WIDTH                        1
+#define MADERA_DSP_IRQ15_EINT1                         0x4000
+#define MADERA_DSP_IRQ15_EINT1_MASK                    0x4000
+#define MADERA_DSP_IRQ15_EINT1_SHIFT                       14
+#define MADERA_DSP_IRQ15_EINT1_WIDTH                        1
+#define MADERA_DSP_IRQ14_EINT1                         0x2000
+#define MADERA_DSP_IRQ14_EINT1_MASK                    0x2000
+#define MADERA_DSP_IRQ14_EINT1_SHIFT                       13
+#define MADERA_DSP_IRQ14_EINT1_WIDTH                        1
+#define MADERA_DSP_IRQ13_EINT1                         0x1000
+#define MADERA_DSP_IRQ13_EINT1_MASK                    0x1000
+#define MADERA_DSP_IRQ13_EINT1_SHIFT                       12
+#define MADERA_DSP_IRQ13_EINT1_WIDTH                        1
+#define MADERA_DSP_IRQ12_EINT1                         0x0800
+#define MADERA_DSP_IRQ12_EINT1_MASK                    0x0800
+#define MADERA_DSP_IRQ12_EINT1_SHIFT                       11
+#define MADERA_DSP_IRQ12_EINT1_WIDTH                        1
+#define MADERA_DSP_IRQ11_EINT1                         0x0400
+#define MADERA_DSP_IRQ11_EINT1_MASK                    0x0400
+#define MADERA_DSP_IRQ11_EINT1_SHIFT                       10
+#define MADERA_DSP_IRQ11_EINT1_WIDTH                        1
+#define MADERA_DSP_IRQ10_EINT1                         0x0200
+#define MADERA_DSP_IRQ10_EINT1_MASK                    0x0200
+#define MADERA_DSP_IRQ10_EINT1_SHIFT                        9
+#define MADERA_DSP_IRQ10_EINT1_WIDTH                        1
+#define MADERA_DSP_IRQ9_EINT1                          0x0100
+#define MADERA_DSP_IRQ9_EINT1_MASK                     0x0100
+#define MADERA_DSP_IRQ9_EINT1_SHIFT                         8
+#define MADERA_DSP_IRQ9_EINT1_WIDTH                         1
+#define MADERA_DSP_IRQ8_EINT1                          0x0080
+#define MADERA_DSP_IRQ8_EINT1_MASK                     0x0080
+#define MADERA_DSP_IRQ8_EINT1_SHIFT                         7
+#define MADERA_DSP_IRQ8_EINT1_WIDTH                         1
+#define MADERA_DSP_IRQ7_EINT1                          0x0040
+#define MADERA_DSP_IRQ7_EINT1_MASK                     0x0040
+#define MADERA_DSP_IRQ7_EINT1_SHIFT                         6
+#define MADERA_DSP_IRQ7_EINT1_WIDTH                         1
+#define MADERA_DSP_IRQ6_EINT1                          0x0020
+#define MADERA_DSP_IRQ6_EINT1_MASK                     0x0020
+#define MADERA_DSP_IRQ6_EINT1_SHIFT                         5
+#define MADERA_DSP_IRQ6_EINT1_WIDTH                         1
+#define MADERA_DSP_IRQ5_EINT1                          0x0010
+#define MADERA_DSP_IRQ5_EINT1_MASK                     0x0010
+#define MADERA_DSP_IRQ5_EINT1_SHIFT                         4
+#define MADERA_DSP_IRQ5_EINT1_WIDTH                         1
+#define MADERA_DSP_IRQ4_EINT1                          0x0008
+#define MADERA_DSP_IRQ4_EINT1_MASK                     0x0008
+#define MADERA_DSP_IRQ4_EINT1_SHIFT                         3
+#define MADERA_DSP_IRQ4_EINT1_WIDTH                         1
+#define MADERA_DSP_IRQ3_EINT1                          0x0004
+#define MADERA_DSP_IRQ3_EINT1_MASK                     0x0004
+#define MADERA_DSP_IRQ3_EINT1_SHIFT                         2
+#define MADERA_DSP_IRQ3_EINT1_WIDTH                         1
+#define MADERA_DSP_IRQ2_EINT1                          0x0002
+#define MADERA_DSP_IRQ2_EINT1_MASK                     0x0002
+#define MADERA_DSP_IRQ2_EINT1_SHIFT                         1
+#define MADERA_DSP_IRQ2_EINT1_WIDTH                         1
+#define MADERA_DSP_IRQ1_EINT1                          0x0001
+#define MADERA_DSP_IRQ1_EINT1_MASK                     0x0001
+#define MADERA_DSP_IRQ1_EINT1_SHIFT                         0
+#define MADERA_DSP_IRQ1_EINT1_WIDTH                         1
+
+/* (0x180B)  IRQ1_Status_12 */
+#define MADERA_SPKOUTR_SC_EINT1                                0x0080
+#define MADERA_SPKOUTR_SC_EINT1_MASK                   0x0080
+#define MADERA_SPKOUTR_SC_EINT1_SHIFT                       7
+#define MADERA_SPKOUTR_SC_EINT1_WIDTH                       1
+#define MADERA_SPKOUTL_SC_EINT1                                0x0040
+#define MADERA_SPKOUTL_SC_EINT1_MASK                   0x0040
+#define MADERA_SPKOUTL_SC_EINT1_SHIFT                       6
+#define MADERA_SPKOUTL_SC_EINT1_WIDTH                       1
+#define MADERA_HP3R_SC_EINT1                           0x0020
+#define MADERA_HP3R_SC_EINT1_MASK                      0x0020
+#define MADERA_HP3R_SC_EINT1_SHIFT                          5
+#define MADERA_HP3R_SC_EINT1_WIDTH                          1
+#define MADERA_HP3L_SC_EINT1                           0x0010
+#define MADERA_HP3L_SC_EINT1_MASK                      0x0010
+#define MADERA_HP3L_SC_EINT1_SHIFT                          4
+#define MADERA_HP3L_SC_EINT1_WIDTH                          1
+#define MADERA_HP2R_SC_EINT1                           0x0008
+#define MADERA_HP2R_SC_EINT1_MASK                      0x0008
+#define MADERA_HP2R_SC_EINT1_SHIFT                          3
+#define MADERA_HP2R_SC_EINT1_WIDTH                          1
+#define MADERA_HP2L_SC_EINT1                           0x0004
+#define MADERA_HP2L_SC_EINT1_MASK                      0x0004
+#define MADERA_HP2L_SC_EINT1_SHIFT                          2
+#define MADERA_HP2L_SC_EINT1_WIDTH                          1
+#define MADERA_HP1R_SC_EINT1                           0x0002
+#define MADERA_HP1R_SC_EINT1_MASK                      0x0002
+#define MADERA_HP1R_SC_EINT1_SHIFT                          1
+#define MADERA_HP1R_SC_EINT1_WIDTH                          1
+#define MADERA_HP1L_SC_EINT1                           0x0001
+#define MADERA_HP1L_SC_EINT1_MASK                      0x0001
+#define MADERA_HP1L_SC_EINT1_SHIFT                          0
+#define MADERA_HP1L_SC_EINT1_WIDTH                          1
+
+/* (0x180E)  IRQ1_Status_15 */
+#define MADERA_SPK_OVERHEAT_WARN_EINT1                 0x0004
+#define MADERA_SPK_OVERHEAT_WARN_EINT1_MASK            0x0004
+#define MADERA_SPK_OVERHEAT_WARN_EINT1_SHIFT                2
+#define MADERA_SPK_OVERHEAT_WARN_EINT1_WIDTH                1
+#define MADERA_SPK_OVERHEAT_EINT1                      0x0002
+#define MADERA_SPK_OVERHEAT_EINT1_MASK                 0x0002
+#define MADERA_SPK_OVERHEAT_EINT1_SHIFT                             1
+#define MADERA_SPK_OVERHEAT_EINT1_WIDTH                             1
+#define MADERA_SPK_SHUTDOWN_EINT1                      0x0001
+#define MADERA_SPK_SHUTDOWN_EINT1_MASK                 0x0001
+#define MADERA_SPK_SHUTDOWN_EINT1_SHIFT                             0
+#define MADERA_SPK_SHUTDOWN_EINT1_WIDTH                             1
+
+/* (0x1820) - IRQ1 Status 33 */
+#define MADERA_DSP7_BUS_ERR_EINT1                      0x0040
+#define MADERA_DSP7_BUS_ERR_EINT1_MASK                 0x0040
+#define MADERA_DSP7_BUS_ERR_EINT1_SHIFT                             6
+#define MADERA_DSP7_BUS_ERR_EINT1_WIDTH                             1
+#define MADERA_DSP6_BUS_ERR_EINT1                      0x0020
+#define MADERA_DSP6_BUS_ERR_EINT1_MASK                 0x0020
+#define MADERA_DSP6_BUS_ERR_EINT1_SHIFT                             5
+#define MADERA_DSP6_BUS_ERR_EINT1_WIDTH                             1
+#define MADERA_DSP5_BUS_ERR_EINT1                      0x0010
+#define MADERA_DSP5_BUS_ERR_EINT1_MASK                 0x0010
+#define MADERA_DSP5_BUS_ERR_EINT1_SHIFT                             4
+#define MADERA_DSP5_BUS_ERR_EINT1_WIDTH                             1
+#define MADERA_DSP4_BUS_ERR_EINT1                      0x0008
+#define MADERA_DSP4_BUS_ERR_EINT1_MASK                 0x0008
+#define MADERA_DSP4_BUS_ERR_EINT1_SHIFT                             3
+#define MADERA_DSP4_BUS_ERR_EINT1_WIDTH                             1
+#define MADERA_DSP3_BUS_ERR_EINT1                      0x0004
+#define MADERA_DSP3_BUS_ERR_EINT1_MASK                 0x0004
+#define MADERA_DSP3_BUS_ERR_EINT1_SHIFT                             2
+#define MADERA_DSP3_BUS_ERR_EINT1_WIDTH                             1
+#define MADERA_DSP2_BUS_ERR_EINT1                      0x0002
+#define MADERA_DSP2_BUS_ERR_EINT1_MASK                 0x0002
+#define MADERA_DSP2_BUS_ERR_EINT1_SHIFT                             1
+#define MADERA_DSP2_BUS_ERR_EINT1_WIDTH                             1
+#define MADERA_DSP1_BUS_ERR_EINT1                      0x0001
+#define MADERA_DSP1_BUS_ERR_EINT1_MASK                 0x0001
+#define MADERA_DSP1_BUS_ERR_EINT1_SHIFT                             0
+#define MADERA_DSP1_BUS_ERR_EINT1_WIDTH                             1
+
+/* (0x1845)  IRQ1_Mask_6 */
+#define MADERA_IM_MICDET2_EINT1                                0x0200
+#define MADERA_IM_MICDET2_EINT1_MASK                   0x0200
+#define MADERA_IM_MICDET2_EINT1_SHIFT                       9
+#define MADERA_IM_MICDET2_EINT1_WIDTH                       1
+#define MADERA_IM_MICDET1_EINT1                                0x0100
+#define MADERA_IM_MICDET1_EINT1_MASK                   0x0100
+#define MADERA_IM_MICDET1_EINT1_SHIFT                       8
+#define MADERA_IM_MICDET1_EINT1_WIDTH                       1
+#define MADERA_IM_HPDET_EINT1                          0x0001
+#define MADERA_IM_HPDET_EINT1_MASK                     0x0001
+#define MADERA_IM_HPDET_EINT1_SHIFT                         0
+#define MADERA_IM_HPDET_EINT1_WIDTH                         1
+/* (0x184E)  IRQ1_Mask_15 */
+#define MADERA_IM_SPK_OVERHEAT_WARN_EINT1              0x0004
+#define MADERA_IM_SPK_OVERHEAT_WARN_EINT1_MASK         0x0004
+#define MADERA_IM_SPK_OVERHEAT_WARN_EINT1_SHIFT                     2
+#define MADERA_IM_SPK_OVERHEAT_WARN_EINT1_WIDTH                     1
+#define MADERA_IM_SPK_OVERHEAT_EINT1                   0x0002
+#define MADERA_IM_SPK_OVERHEAT_EINT1_MASK              0x0002
+#define MADERA_IM_SPK_OVERHEAT_EINT1_SHIFT                  1
+#define MADERA_IM_SPK_OVERHEAT_EINT1_WIDTH                  1
+#define MADERA_IM_SPK_SHUTDOWN_EINT1                   0x0001
+#define MADERA_IM_SPK_SHUTDOWN_EINT1_MASK              0x0001
+#define MADERA_IM_SPK_SHUTDOWN_EINT1_SHIFT                  0
+#define MADERA_IM_SPK_SHUTDOWN_EINT1_WIDTH                  1
+
+/* (0x1880) - IRQ1 Raw Status 1 */
+#define MADERA_CTRLIF_ERR_STS1                         0x1000
+#define MADERA_CTRLIF_ERR_STS1_MASK                    0x1000
+#define MADERA_CTRLIF_ERR_STS1_SHIFT                       12
+#define MADERA_CTRLIF_ERR_STS1_WIDTH                        1
+#define MADERA_SYSCLK_FAIL_STS1                                0x0200
+#define MADERA_SYSCLK_FAIL_STS1_MASK                   0x0200
+#define MADERA_SYSCLK_FAIL_STS1_SHIFT                       9
+#define MADERA_SYSCLK_FAIL_STS1_WIDTH                       1
+#define MADERA_CLOCK_DETECT_STS1                       0x0100
+#define MADERA_CLOCK_DETECT_STS1_MASK                  0x0100
+#define MADERA_CLOCK_DETECT_STS1_SHIFT                      8
+#define MADERA_CLOCK_DETECT_STS1_WIDTH                      1
+#define MADERA_BOOT_DONE_STS1                          0x0080
+#define MADERA_BOOT_DONE_STS1_MASK                     0x0080
+#define MADERA_BOOT_DONE_STS1_SHIFT                         7
+#define MADERA_BOOT_DONE_STS1_WIDTH                         1
+
+/* (0x1881) - IRQ1 Raw Status 2 */
+#define MADERA_FLL3_LOCK_STS1                          0x0400
+#define MADERA_FLL3_LOCK_STS1_MASK                     0x0400
+#define MADERA_FLL3_LOCK_STS1_SHIFT                        10
+#define MADERA_FLL3_LOCK_STS1_WIDTH                         1
+#define MADERA_FLL2_LOCK_STS1                          0x0200
+#define MADERA_FLL2_LOCK_STS1_MASK                     0x0200
+#define MADERA_FLL2_LOCK_STS1_SHIFT                         9
+#define MADERA_FLL2_LOCK_STS1_WIDTH                         1
+#define MADERA_FLL1_LOCK_STS1                          0x0100
+#define MADERA_FLL1_LOCK_STS1_MASK                     0x0100
+#define MADERA_FLL1_LOCK_STS1_SHIFT                         8
+#define MADERA_FLL1_LOCK_STS1_WIDTH                         1
+
+/* (0x1886) - IRQ1 Raw Status 7 */
+#define MADERA_MICD_CLAMP_FALL_STS1                    0x0020
+#define MADERA_MICD_CLAMP_FALL_STS1_MASK               0x0020
+#define MADERA_MICD_CLAMP_FALL_STS1_SHIFT                   5
+#define MADERA_MICD_CLAMP_FALL_STS1_WIDTH                   1
+#define MADERA_MICD_CLAMP_RISE_STS1                    0x0010
+#define MADERA_MICD_CLAMP_RISE_STS1_MASK               0x0010
+#define MADERA_MICD_CLAMP_RISE_STS1_SHIFT                   4
+#define MADERA_MICD_CLAMP_RISE_STS1_WIDTH                   1
+#define MADERA_JD2_FALL_STS1                           0x0008
+#define MADERA_JD2_FALL_STS1_MASK                      0x0008
+#define MADERA_JD2_FALL_STS1_SHIFT                          3
+#define MADERA_JD2_FALL_STS1_WIDTH                          1
+#define MADERA_JD2_RISE_STS1                           0x0004
+#define MADERA_JD2_RISE_STS1_MASK                      0x0004
+#define MADERA_JD2_RISE_STS1_SHIFT                          2
+#define MADERA_JD2_RISE_STS1_WIDTH                          1
+#define MADERA_JD1_FALL_STS1                           0x0002
+#define MADERA_JD1_FALL_STS1_MASK                      0x0002
+#define MADERA_JD1_FALL_STS1_SHIFT                          1
+#define MADERA_JD1_FALL_STS1_WIDTH                          1
+#define MADERA_JD1_RISE_STS1                           0x0001
+#define MADERA_JD1_RISE_STS1_MASK                      0x0001
+#define MADERA_JD1_RISE_STS1_SHIFT                          0
+#define MADERA_JD1_RISE_STS1_WIDTH                          1
+
+/* (0x188E) - IRQ1 Raw Status 15 */
+#define MADERA_SPK_OVERHEAT_WARN_STS1                  0x0004
+#define MADERA_SPK_OVERHEAT_WARN_STS1_MASK             0x0004
+#define MADERA_SPK_OVERHEAT_WARN_STS1_SHIFT                 2
+#define MADERA_SPK_OVERHEAT_WARN_STS1_WIDTH                 1
+#define MADERA_SPK_OVERHEAT_STS1                       0x0002
+#define MADERA_SPK_OVERHEAT_STS1_MASK                  0x0002
+#define MADERA_SPK_OVERHEAT_STS1_SHIFT                      1
+#define MADERA_SPK_OVERHEAT_STS1_WIDTH                      1
+#define MADERA_SPK_SHUTDOWN_STS1                       0x0001
+#define MADERA_SPK_SHUTDOWN_STS1_MASK                  0x0001
+#define MADERA_SPK_SHUTDOWN_STS1_SHIFT                      0
+#define MADERA_SPK_SHUTDOWN_STS1_WIDTH                      1
+
+/* (0x1A06)  Interrupt_Debounce_7 */
+#define MADERA_MICD_CLAMP_DB                           0x0010
+#define MADERA_MICD_CLAMP_DB_MASK                      0x0010
+#define MADERA_MICD_CLAMP_DB_SHIFT                          4
+#define MADERA_MICD_CLAMP_DB_WIDTH                          1
+#define MADERA_JD2_DB                                  0x0004
+#define MADERA_JD2_DB_MASK                             0x0004
+#define MADERA_JD2_DB_SHIFT                                 2
+#define MADERA_JD2_DB_WIDTH                                 1
+#define MADERA_JD1_DB                                  0x0001
+#define MADERA_JD1_DB_MASK                             0x0001
+#define MADERA_JD1_DB_SHIFT                                 0
+#define MADERA_JD1_DB_WIDTH                                 1
+
+/* (0x1A0E)  Interrupt_Debounce_15 */
+#define MADERA_SPK_OVERHEAT_WARN_DB                    0x0004
+#define MADERA_SPK_OVERHEAT_WARN_DB_MASK               0x0004
+#define MADERA_SPK_OVERHEAT_WARN_DB_SHIFT                   2
+#define MADERA_SPK_OVERHEAT_WARN_DB_WIDTH                   1
+#define MADERA_SPK_OVERHEAT_DB                         0x0002
+#define MADERA_SPK_OVERHEAT_DB_MASK                    0x0002
+#define MADERA_SPK_OVERHEAT_DB_SHIFT                        1
+#define MADERA_SPK_OVERHEAT_DB_WIDTH                        1
+
+/* (0x1A80)  IRQ1_CTRL */
+#define MADERA_IM_IRQ1                                 0x0800
+#define MADERA_IM_IRQ1_MASK                            0x0800
+#define MADERA_IM_IRQ1_SHIFT                               11
+#define MADERA_IM_IRQ1_WIDTH                                1
+#define MADERA_IRQ_POL                                 0x0400
+#define MADERA_IRQ_POL_MASK                            0x0400
+#define MADERA_IRQ_POL_SHIFT                               10
+#define MADERA_IRQ_POL_WIDTH                                1
+
+/* (0x20004)  OTP_HPDET_Cal_1 */
+#define MADERA_OTP_HPDET_CALIB_OFFSET_11           0xFF000000
+#define MADERA_OTP_HPDET_CALIB_OFFSET_11_MASK      0xFF000000
+#define MADERA_OTP_HPDET_CALIB_OFFSET_11_SHIFT             24
+#define MADERA_OTP_HPDET_CALIB_OFFSET_11_WIDTH              8
+#define MADERA_OTP_HPDET_CALIB_OFFSET_10           0x00FF0000
+#define MADERA_OTP_HPDET_CALIB_OFFSET_10_MASK      0x00FF0000
+#define MADERA_OTP_HPDET_CALIB_OFFSET_10_SHIFT             16
+#define MADERA_OTP_HPDET_CALIB_OFFSET_10_WIDTH              8
+#define MADERA_OTP_HPDET_CALIB_OFFSET_01           0x0000FF00
+#define MADERA_OTP_HPDET_CALIB_OFFSET_01_MASK      0x0000FF00
+#define MADERA_OTP_HPDET_CALIB_OFFSET_01_SHIFT              8
+#define MADERA_OTP_HPDET_CALIB_OFFSET_01_WIDTH              8
+#define MADERA_OTP_HPDET_CALIB_OFFSET_00           0x000000FF
+#define MADERA_OTP_HPDET_CALIB_OFFSET_00_MASK      0x000000FF
+#define MADERA_OTP_HPDET_CALIB_OFFSET_00_SHIFT              0
+#define MADERA_OTP_HPDET_CALIB_OFFSET_00_WIDTH              8
+
+/* (0x20006)  OTP_HPDET_Cal_2 */
+#define MADERA_OTP_HPDET_GRADIENT_1X               0x0000FF00
+#define MADERA_OTP_HPDET_GRADIENT_1X_MASK          0x0000FF00
+#define MADERA_OTP_HPDET_GRADIENT_1X_SHIFT                  8
+#define MADERA_OTP_HPDET_GRADIENT_1X_WIDTH                  8
+#define MADERA_OTP_HPDET_GRADIENT_0X               0x000000FF
+#define MADERA_OTP_HPDET_GRADIENT_0X_MASK          0x000000FF
+#define MADERA_OTP_HPDET_GRADIENT_0X_SHIFT                  0
+#define MADERA_OTP_HPDET_GRADIENT_0X_WIDTH                  8
+
+#endif
index fe0ce7b..11eef77 100644 (file)
@@ -21,6 +21,7 @@ enum rave_sp_command {
        RAVE_SP_CMD_STATUS                      = 0xA0,
        RAVE_SP_CMD_SW_WDT                      = 0xA1,
        RAVE_SP_CMD_PET_WDT                     = 0xA2,
+       RAVE_SP_CMD_RMB_EEPROM                  = 0xA4,
        RAVE_SP_CMD_SET_BACKLIGHT               = 0xA6,
        RAVE_SP_CMD_RESET                       = 0xA7,
        RAVE_SP_CMD_RESET_REASON                = 0xA8,
diff --git a/include/linux/mfd/rohm-bd718x7.h b/include/linux/mfd/rohm-bd718x7.h
new file mode 100644 (file)
index 0000000..a528747
--- /dev/null
@@ -0,0 +1,332 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/* Copyright (C) 2018 ROHM Semiconductors */
+
+#ifndef __LINUX_MFD_BD71837_H__
+#define __LINUX_MFD_BD71837_H__
+
+#include <linux/regmap.h>
+
+enum {
+       BD71837_BUCK1   =       0,
+       BD71837_BUCK2,
+       BD71837_BUCK3,
+       BD71837_BUCK4,
+       BD71837_BUCK5,
+       BD71837_BUCK6,
+       BD71837_BUCK7,
+       BD71837_BUCK8,
+       BD71837_LDO1,
+       BD71837_LDO2,
+       BD71837_LDO3,
+       BD71837_LDO4,
+       BD71837_LDO5,
+       BD71837_LDO6,
+       BD71837_LDO7,
+       BD71837_REGULATOR_CNT,
+};
+
+#define BD71837_BUCK1_VOLTAGE_NUM      0x40
+#define BD71837_BUCK2_VOLTAGE_NUM      0x40
+#define BD71837_BUCK3_VOLTAGE_NUM      0x40
+#define BD71837_BUCK4_VOLTAGE_NUM      0x40
+
+#define BD71837_BUCK5_VOLTAGE_NUM      0x08
+#define BD71837_BUCK6_VOLTAGE_NUM      0x04
+#define BD71837_BUCK7_VOLTAGE_NUM      0x08
+#define BD71837_BUCK8_VOLTAGE_NUM      0x40
+
+#define BD71837_LDO1_VOLTAGE_NUM       0x04
+#define BD71837_LDO2_VOLTAGE_NUM       0x02
+#define BD71837_LDO3_VOLTAGE_NUM       0x10
+#define BD71837_LDO4_VOLTAGE_NUM       0x10
+#define BD71837_LDO5_VOLTAGE_NUM       0x10
+#define BD71837_LDO6_VOLTAGE_NUM       0x10
+#define BD71837_LDO7_VOLTAGE_NUM       0x10
+
+enum {
+       BD71837_REG_REV                = 0x00,
+       BD71837_REG_SWRESET            = 0x01,
+       BD71837_REG_I2C_DEV            = 0x02,
+       BD71837_REG_PWRCTRL0           = 0x03,
+       BD71837_REG_PWRCTRL1           = 0x04,
+       BD71837_REG_BUCK1_CTRL         = 0x05,
+       BD71837_REG_BUCK2_CTRL         = 0x06,
+       BD71837_REG_BUCK3_CTRL         = 0x07,
+       BD71837_REG_BUCK4_CTRL         = 0x08,
+       BD71837_REG_BUCK5_CTRL         = 0x09,
+       BD71837_REG_BUCK6_CTRL         = 0x0A,
+       BD71837_REG_BUCK7_CTRL         = 0x0B,
+       BD71837_REG_BUCK8_CTRL         = 0x0C,
+       BD71837_REG_BUCK1_VOLT_RUN     = 0x0D,
+       BD71837_REG_BUCK1_VOLT_IDLE    = 0x0E,
+       BD71837_REG_BUCK1_VOLT_SUSP    = 0x0F,
+       BD71837_REG_BUCK2_VOLT_RUN     = 0x10,
+       BD71837_REG_BUCK2_VOLT_IDLE    = 0x11,
+       BD71837_REG_BUCK3_VOLT_RUN     = 0x12,
+       BD71837_REG_BUCK4_VOLT_RUN     = 0x13,
+       BD71837_REG_BUCK5_VOLT         = 0x14,
+       BD71837_REG_BUCK6_VOLT         = 0x15,
+       BD71837_REG_BUCK7_VOLT         = 0x16,
+       BD71837_REG_BUCK8_VOLT         = 0x17,
+       BD71837_REG_LDO1_VOLT          = 0x18,
+       BD71837_REG_LDO2_VOLT          = 0x19,
+       BD71837_REG_LDO3_VOLT          = 0x1A,
+       BD71837_REG_LDO4_VOLT          = 0x1B,
+       BD71837_REG_LDO5_VOLT          = 0x1C,
+       BD71837_REG_LDO6_VOLT          = 0x1D,
+       BD71837_REG_LDO7_VOLT          = 0x1E,
+       BD71837_REG_TRANS_COND0        = 0x1F,
+       BD71837_REG_TRANS_COND1        = 0x20,
+       BD71837_REG_VRFAULTEN          = 0x21,
+       BD71837_REG_MVRFLTMASK0        = 0x22,
+       BD71837_REG_MVRFLTMASK1        = 0x23,
+       BD71837_REG_MVRFLTMASK2        = 0x24,
+       BD71837_REG_RCVCFG             = 0x25,
+       BD71837_REG_RCVNUM             = 0x26,
+       BD71837_REG_PWRONCONFIG0       = 0x27,
+       BD71837_REG_PWRONCONFIG1       = 0x28,
+       BD71837_REG_RESETSRC           = 0x29,
+       BD71837_REG_MIRQ               = 0x2A,
+       BD71837_REG_IRQ                = 0x2B,
+       BD71837_REG_IN_MON             = 0x2C,
+       BD71837_REG_POW_STATE          = 0x2D,
+       BD71837_REG_OUT32K             = 0x2E,
+       BD71837_REG_REGLOCK            = 0x2F,
+       BD71837_REG_OTPVER             = 0xFF,
+       BD71837_MAX_REGISTER           = 0x100,
+};
+
+#define REGLOCK_PWRSEQ 0x1
+#define REGLOCK_VREG   0x10
+
+/* Generic BUCK control masks */
+#define BD71837_BUCK_SEL       0x02
+#define BD71837_BUCK_EN                0x01
+#define BD71837_BUCK_RUN_ON    0x04
+
+/* Generic LDO masks */
+#define BD71837_LDO_SEL                0x80
+#define BD71837_LDO_EN         0x40
+
+/* BD71837 BUCK ramp rate CTRL reg bits */
+#define BUCK_RAMPRATE_MASK     0xC0
+#define BUCK_RAMPRATE_10P00MV  0x0
+#define BUCK_RAMPRATE_5P00MV   0x1
+#define BUCK_RAMPRATE_2P50MV   0x2
+#define BUCK_RAMPRATE_1P25MV   0x3
+
+/* BD71837_REG_BUCK1_VOLT_RUN bits */
+#define BUCK1_RUN_MASK         0x3F
+#define BUCK1_RUN_DEFAULT      0x14
+
+/* BD71837_REG_BUCK1_VOLT_SUSP bits */
+#define BUCK1_SUSP_MASK                0x3F
+#define BUCK1_SUSP_DEFAULT     0x14
+
+/* BD71837_REG_BUCK1_VOLT_IDLE bits */
+#define BUCK1_IDLE_MASK                0x3F
+#define BUCK1_IDLE_DEFAULT     0x14
+
+/* BD71837_REG_BUCK2_VOLT_RUN bits */
+#define BUCK2_RUN_MASK         0x3F
+#define BUCK2_RUN_DEFAULT      0x1E
+
+/* BD71837_REG_BUCK2_VOLT_IDLE bits */
+#define BUCK2_IDLE_MASK                0x3F
+#define BUCK2_IDLE_DEFAULT     0x14
+
+/* BD71837_REG_BUCK3_VOLT_RUN bits */
+#define BUCK3_RUN_MASK         0x3F
+#define BUCK3_RUN_DEFAULT      0x1E
+
+/* BD71837_REG_BUCK4_VOLT_RUN bits */
+#define BUCK4_RUN_MASK         0x3F
+#define BUCK4_RUN_DEFAULT      0x1E
+
+/* BD71837_REG_BUCK5_VOLT bits */
+#define BUCK5_MASK             0x07
+#define BUCK5_DEFAULT          0x02
+
+/* BD71837_REG_BUCK6_VOLT bits */
+#define BUCK6_MASK             0x03
+#define BUCK6_DEFAULT          0x03
+
+/* BD71837_REG_BUCK7_VOLT bits */
+#define BUCK7_MASK             0x07
+#define BUCK7_DEFAULT          0x03
+
+/* BD71837_REG_BUCK8_VOLT bits */
+#define BUCK8_MASK             0x3F
+#define BUCK8_DEFAULT          0x1E
+
+/* BD71837_REG_IRQ bits */
+#define IRQ_SWRST              0x40
+#define IRQ_PWRON_S            0x20
+#define IRQ_PWRON_L            0x10
+#define IRQ_PWRON              0x08
+#define IRQ_WDOG               0x04
+#define IRQ_ON_REQ             0x02
+#define IRQ_STBY_REQ           0x01
+
+/* BD71837_REG_OUT32K bits */
+#define BD71837_OUT32K_EN      0x01
+
+/* BD71837 gated clock rate */
+#define BD71837_CLK_RATE 32768
+
+/* ROHM BD71837 irqs */
+enum {
+       BD71837_INT_STBY_REQ,
+       BD71837_INT_ON_REQ,
+       BD71837_INT_WDOG,
+       BD71837_INT_PWRBTN,
+       BD71837_INT_PWRBTN_L,
+       BD71837_INT_PWRBTN_S,
+       BD71837_INT_SWRST
+};
+
+/* ROHM BD71837 interrupt masks */
+#define BD71837_INT_SWRST_MASK         0x40
+#define BD71837_INT_PWRBTN_S_MASK      0x20
+#define BD71837_INT_PWRBTN_L_MASK      0x10
+#define BD71837_INT_PWRBTN_MASK                0x8
+#define BD71837_INT_WDOG_MASK          0x4
+#define BD71837_INT_ON_REQ_MASK                0x2
+#define BD71837_INT_STBY_REQ_MASK      0x1
+
+/* BD71837_REG_LDO1_VOLT bits */
+#define LDO1_MASK              0x03
+
+/* BD71837_REG_LDO1_VOLT bits */
+#define LDO2_MASK              0x20
+
+/* BD71837_REG_LDO3_VOLT bits */
+#define LDO3_MASK              0x0F
+
+/* BD71837_REG_LDO4_VOLT bits */
+#define LDO4_MASK              0x0F
+
+/* BD71837_REG_LDO5_VOLT bits */
+#define LDO5_MASK              0x0F
+
+/* BD71837_REG_LDO6_VOLT bits */
+#define LDO6_MASK              0x0F
+
+/* BD71837_REG_LDO7_VOLT bits */
+#define LDO7_MASK              0x0F
+
+/* Register write induced reset settings */
+
+/*
+ * Even though the bit zero is not SWRESET type we still want to write zero
+ * to it when changing type. Bit zero is 'SWRESET' trigger bit and if we
+ * write 1 to it we will trigger the action. So always write 0 to it when
+ * changning SWRESET action - no matter what we read from it.
+ */
+#define BD71837_SWRESET_TYPE_MASK      7
+#define BD71837_SWRESET_TYPE_DISABLED  0
+#define BD71837_SWRESET_TYPE_COLD      4
+#define BD71837_SWRESET_TYPE_WARM      6
+
+#define BD71837_SWRESET_RESET_MASK     1
+#define BD71837_SWRESET_RESET          1
+
+/* Poweroff state transition conditions */
+
+#define BD718XX_ON_REQ_POWEROFF_MASK   1
+#define BD718XX_SWRESET_POWEROFF_MASK  2
+#define BD718XX_WDOG_POWEROFF_MASK     4
+#define BD718XX_KEY_L_POWEROFF_MASK    8
+
+#define BD718XX_POWOFF_TO_SNVS 0
+#define BD718XX_POWOFF_TO_RDY  0xF
+
+#define BD718XX_POWOFF_TIME_MASK 0xF0
+enum {
+       BD718XX_POWOFF_TIME_5MS = 0,
+       BD718XX_POWOFF_TIME_10MS,
+       BD718XX_POWOFF_TIME_15MS,
+       BD718XX_POWOFF_TIME_20MS,
+       BD718XX_POWOFF_TIME_25MS,
+       BD718XX_POWOFF_TIME_30MS,
+       BD718XX_POWOFF_TIME_35MS,
+       BD718XX_POWOFF_TIME_40MS,
+       BD718XX_POWOFF_TIME_45MS,
+       BD718XX_POWOFF_TIME_50MS,
+       BD718XX_POWOFF_TIME_75MS,
+       BD718XX_POWOFF_TIME_100MS,
+       BD718XX_POWOFF_TIME_250MS,
+       BD718XX_POWOFF_TIME_500MS,
+       BD718XX_POWOFF_TIME_750MS,
+       BD718XX_POWOFF_TIME_1500MS
+};
+
+/* Poweron sequence state transition conditions */
+#define BD718XX_RDY_TO_SNVS_MASK 0xF
+#define BD718XX_SNVS_TO_RUN_MASK 0xF0
+
+#define BD718XX_PWR_TRIG_KEY_L         1
+#define BD718XX_PWR_TRIG_KEY_S         2
+#define BD718XX_PWR_TRIG_PMIC_ON       4
+#define BD718XX_PWR_TRIG_VSYS_UVLO     8
+#define BD718XX_RDY_TO_SNVS_SIFT       0
+#define BD718XX_SNVS_TO_RUN_SIFT       4
+
+#define BD718XX_PWRBTN_PRESS_DURATION_MASK 0xF
+
+/* Timeout value for detecting short press */
+enum {
+       BD718XX_PWRBTN_SHORT_PRESS_10MS = 0,
+       BD718XX_PWRBTN_SHORT_PRESS_500MS,
+       BD718XX_PWRBTN_SHORT_PRESS_1000MS,
+       BD718XX_PWRBTN_SHORT_PRESS_1500MS,
+       BD718XX_PWRBTN_SHORT_PRESS_2000MS,
+       BD718XX_PWRBTN_SHORT_PRESS_2500MS,
+       BD718XX_PWRBTN_SHORT_PRESS_3000MS,
+       BD718XX_PWRBTN_SHORT_PRESS_3500MS,
+       BD718XX_PWRBTN_SHORT_PRESS_4000MS,
+       BD718XX_PWRBTN_SHORT_PRESS_4500MS,
+       BD718XX_PWRBTN_SHORT_PRESS_5000MS,
+       BD718XX_PWRBTN_SHORT_PRESS_5500MS,
+       BD718XX_PWRBTN_SHORT_PRESS_6000MS,
+       BD718XX_PWRBTN_SHORT_PRESS_6500MS,
+       BD718XX_PWRBTN_SHORT_PRESS_7000MS,
+       BD718XX_PWRBTN_SHORT_PRESS_7500MS
+};
+
+/* Timeout value for detecting LONG press */
+enum {
+       BD718XX_PWRBTN_LONG_PRESS_10MS = 0,
+       BD718XX_PWRBTN_LONG_PRESS_1S,
+       BD718XX_PWRBTN_LONG_PRESS_2S,
+       BD718XX_PWRBTN_LONG_PRESS_3S,
+       BD718XX_PWRBTN_LONG_PRESS_4S,
+       BD718XX_PWRBTN_LONG_PRESS_5S,
+       BD718XX_PWRBTN_LONG_PRESS_6S,
+       BD718XX_PWRBTN_LONG_PRESS_7S,
+       BD718XX_PWRBTN_LONG_PRESS_8S,
+       BD718XX_PWRBTN_LONG_PRESS_9S,
+       BD718XX_PWRBTN_LONG_PRESS_10S,
+       BD718XX_PWRBTN_LONG_PRESS_11S,
+       BD718XX_PWRBTN_LONG_PRESS_12S,
+       BD718XX_PWRBTN_LONG_PRESS_13S,
+       BD718XX_PWRBTN_LONG_PRESS_14S,
+       BD718XX_PWRBTN_LONG_PRESS_15S
+};
+
+struct bd71837_pmic;
+struct bd71837_clk;
+
+struct bd71837 {
+       struct device *dev;
+       struct regmap *regmap;
+       unsigned long int id;
+
+       int chip_irq;
+       struct regmap_irq_chip_data *irq_data;
+
+       struct bd71837_pmic *pmic;
+       struct bd71837_clk *clk;
+};
+
+#endif /* __LINUX_MFD_BD71837_H__ */
index e06f5f7..6c1ad16 100644 (file)
 #define MCLK_DIR(x) (x == 1 ? IMX6UL_GPR1_SAI1_MCLK_DIR : x == 2 ? \
                     IMX6UL_GPR1_SAI2_MCLK_DIR : IMX6UL_GPR1_SAI3_MCLK_DIR)
 
+/* For imx6sll iomux gpr register field define */
+#define IMX6SLL_GPR5_AFCG_X_BYPASS_MASK                (0x1f << 11)
+
 #endif /* __LINUX_IMX6Q_IOMUXC_GPR_H */
index 90c6052..b19c370 100644 (file)
@@ -222,6 +222,12 @@ struct wm8994_pdata {
         */
        bool spkmode_pu;
 
+       /*
+        * CS/ADDR must be pulled internally by the device on this
+        * system.
+        */
+       bool csnaddr_pd;
+
        /**
         * Maximum number of channels clocks will be generated for,
         * useful for systems where and I2S bus with multiple data
index a3cae49..a61ebe8 100644 (file)
@@ -456,6 +456,7 @@ static inline void vma_init(struct vm_area_struct *vma, struct mm_struct *mm)
 {
        static const struct vm_operations_struct dummy_vm_ops = {};
 
+       memset(vma, 0, sizeof(*vma));
        vma->vm_mm = mm;
        vma->vm_ops = &dummy_vm_ops;
        INIT_LIST_HEAD(&vma->anon_vma_chain);
@@ -727,10 +728,10 @@ static inline pte_t maybe_mkwrite(pte_t pte, struct vm_area_struct *vma)
        return pte;
 }
 
-int alloc_set_pte(struct vm_fault *vmf, struct mem_cgroup *memcg,
+vm_fault_t alloc_set_pte(struct vm_fault *vmf, struct mem_cgroup *memcg,
                struct page *page);
-int finish_fault(struct vm_fault *vmf);
-int finish_mkwrite_fault(struct vm_fault *vmf);
+vm_fault_t finish_fault(struct vm_fault *vmf);
+vm_fault_t finish_mkwrite_fault(struct vm_fault *vmf);
 #endif
 
 /*
@@ -959,15 +960,6 @@ static inline int page_zone_id(struct page *page)
        return (page->flags >> ZONEID_PGSHIFT) & ZONEID_MASK;
 }
 
-static inline int zone_to_nid(struct zone *zone)
-{
-#ifdef CONFIG_NUMA
-       return zone->node;
-#else
-       return 0;
-#endif
-}
-
 #ifdef NODE_NOT_IN_PAGE_FLAGS
 extern int page_to_nid(const struct page *page);
 #else
@@ -1411,8 +1403,8 @@ int generic_error_remove_page(struct address_space *mapping, struct page *page);
 int invalidate_inode_page(struct page *page);
 
 #ifdef CONFIG_MMU
-extern int handle_mm_fault(struct vm_area_struct *vma, unsigned long address,
-               unsigned int flags);
+extern vm_fault_t handle_mm_fault(struct vm_area_struct *vma,
+                       unsigned long address, unsigned int flags);
 extern int fixup_user_fault(struct task_struct *tsk, struct mm_struct *mm,
                            unsigned long address, unsigned int fault_flags,
                            bool *unlocked);
@@ -1421,7 +1413,7 @@ void unmap_mapping_pages(struct address_space *mapping,
 void unmap_mapping_range(struct address_space *mapping,
                loff_t const holebegin, loff_t const holelen, int even_cows);
 #else
-static inline int handle_mm_fault(struct vm_area_struct *vma,
+static inline vm_fault_t handle_mm_fault(struct vm_area_struct *vma,
                unsigned long address, unsigned int flags)
 {
        /* should never happen if there's no MMU */
@@ -2023,7 +2015,7 @@ static inline spinlock_t *pud_lock(struct mm_struct *mm, pud_t *pud)
 
 extern void __init pagecache_init(void);
 extern void free_area_init(unsigned long * zones_size);
-extern void free_area_init_node(int nid, unsigned long * zones_size,
+extern void __init free_area_init_node(int nid, unsigned long * zones_size,
                unsigned long zone_start_pfn, unsigned long *zholes_size);
 extern void free_initmem(void);
 
@@ -2571,7 +2563,7 @@ static inline struct page *follow_page(struct vm_area_struct *vma,
 #define FOLL_COW       0x4000  /* internal GUP flag */
 #define FOLL_ANON      0x8000  /* don't do file mappings */
 
-static inline int vm_fault_to_errno(int vm_fault, int foll_flags)
+static inline int vm_fault_to_errno(vm_fault_t vm_fault, int foll_flags)
 {
        if (vm_fault & VM_FAULT_OOM)
                return -ENOMEM;
@@ -2739,6 +2731,7 @@ enum mf_action_page_type {
        MF_MSG_TRUNCATED_LRU,
        MF_MSG_BUDDY,
        MF_MSG_BUDDY_2ND,
+       MF_MSG_DAX,
        MF_MSG_UNKNOWN,
 };
 
index 392e6af..133ba78 100644 (file)
@@ -151,13 +151,15 @@ struct mmu_notifier_ops {
         * address space but may still be referenced by sptes until
         * the last refcount is dropped.
         *
-        * If both of these callbacks cannot block, and invalidate_range
-        * cannot block, mmu_notifier_ops.flags should have
-        * MMU_INVALIDATE_DOES_NOT_BLOCK set.
+        * If blockable argument is set to false then the callback cannot
+        * sleep and has to return with -EAGAIN. 0 should be returned
+        * otherwise.
+        *
         */
-       void (*invalidate_range_start)(struct mmu_notifier *mn,
+       int (*invalidate_range_start)(struct mmu_notifier *mn,
                                       struct mm_struct *mm,
-                                      unsigned long start, unsigned long end);
+                                      unsigned long start, unsigned long end,
+                                      bool blockable);
        void (*invalidate_range_end)(struct mmu_notifier *mn,
                                     struct mm_struct *mm,
                                     unsigned long start, unsigned long end);
@@ -229,8 +231,9 @@ extern int __mmu_notifier_test_young(struct mm_struct *mm,
                                     unsigned long address);
 extern void __mmu_notifier_change_pte(struct mm_struct *mm,
                                      unsigned long address, pte_t pte);
-extern void __mmu_notifier_invalidate_range_start(struct mm_struct *mm,
-                                 unsigned long start, unsigned long end);
+extern int __mmu_notifier_invalidate_range_start(struct mm_struct *mm,
+                                 unsigned long start, unsigned long end,
+                                 bool blockable);
 extern void __mmu_notifier_invalidate_range_end(struct mm_struct *mm,
                                  unsigned long start, unsigned long end,
                                  bool only_end);
@@ -281,7 +284,15 @@ static inline void mmu_notifier_invalidate_range_start(struct mm_struct *mm,
                                  unsigned long start, unsigned long end)
 {
        if (mm_has_notifiers(mm))
-               __mmu_notifier_invalidate_range_start(mm, start, end);
+               __mmu_notifier_invalidate_range_start(mm, start, end, true);
+}
+
+static inline int mmu_notifier_invalidate_range_start_nonblock(struct mm_struct *mm,
+                                 unsigned long start, unsigned long end)
+{
+       if (mm_has_notifiers(mm))
+               return __mmu_notifier_invalidate_range_start(mm, start, end, false);
+       return 0;
 }
 
 static inline void mmu_notifier_invalidate_range_end(struct mm_struct *mm,
@@ -461,6 +472,12 @@ static inline void mmu_notifier_invalidate_range_start(struct mm_struct *mm,
 {
 }
 
+static inline int mmu_notifier_invalidate_range_start_nonblock(struct mm_struct *mm,
+                                 unsigned long start, unsigned long end)
+{
+       return 0;
+}
+
 static inline void mmu_notifier_invalidate_range_end(struct mm_struct *mm,
                                  unsigned long start, unsigned long end)
 {
index 32699b2..1e22d96 100644 (file)
@@ -755,25 +755,6 @@ static inline bool pgdat_is_empty(pg_data_t *pgdat)
        return !pgdat->node_start_pfn && !pgdat->node_spanned_pages;
 }
 
-static inline int zone_id(const struct zone *zone)
-{
-       struct pglist_data *pgdat = zone->zone_pgdat;
-
-       return zone - pgdat->node_zones;
-}
-
-#ifdef CONFIG_ZONE_DEVICE
-static inline bool is_dev_zone(const struct zone *zone)
-{
-       return zone_id(zone) == ZONE_DEVICE;
-}
-#else
-static inline bool is_dev_zone(const struct zone *zone)
-{
-       return false;
-}
-#endif
-
 #include <linux/memory_hotplug.h>
 
 void build_all_zonelists(pg_data_t *pgdat);
@@ -824,6 +805,18 @@ static inline int local_memory_node(int node_id) { return node_id; };
  */
 #define zone_idx(zone)         ((zone) - (zone)->zone_pgdat->node_zones)
 
+#ifdef CONFIG_ZONE_DEVICE
+static inline bool is_dev_zone(const struct zone *zone)
+{
+       return zone_idx(zone) == ZONE_DEVICE;
+}
+#else
+static inline bool is_dev_zone(const struct zone *zone)
+{
+       return false;
+}
+#endif
+
 /*
  * Returns true if a zone has pages managed by the buddy allocator.
  * All the reclaim decisions have to use this function rather than
@@ -841,6 +834,25 @@ static inline bool populated_zone(struct zone *zone)
        return zone->present_pages;
 }
 
+#ifdef CONFIG_NUMA
+static inline int zone_to_nid(struct zone *zone)
+{
+       return zone->node;
+}
+
+static inline void zone_set_nid(struct zone *zone, int nid)
+{
+       zone->node = nid;
+}
+#else
+static inline int zone_to_nid(struct zone *zone)
+{
+       return 0;
+}
+
+static inline void zone_set_nid(struct zone *zone, int nid) {}
+#endif
+
 extern int movable_zone;
 
 #ifdef CONFIG_HIGHMEM
@@ -956,12 +968,7 @@ static inline int zonelist_zone_idx(struct zoneref *zoneref)
 
 static inline int zonelist_node_idx(struct zoneref *zoneref)
 {
-#ifdef CONFIG_NUMA
-       /* zone_to_nid not available in this context */
-       return zoneref->zone->node;
-#else
-       return 0;
-#endif /* CONFIG_NUMA */
+       return zone_to_nid(zoneref->zone);
 }
 
 struct zoneref *__next_zones_zonelist(struct zoneref *z,
index db99240..c79e859 100644 (file)
@@ -363,7 +363,6 @@ static inline void net_dim_sample(u16 event_ctr,
 }
 
 #define NET_DIM_NEVENTS 64
-#define BITS_PER_TYPE(type) (sizeof(type) * BITS_PER_BYTE)
 #define BIT_GAP(bits, end, start) ((((end) - (start)) + BIT_ULL(bits)) & (BIT_ULL(bits) - 1))
 
 static inline void net_dim_calc_stats(struct net_dim_sample *start,
index 57ffaa2..1b06f0b 100644 (file)
@@ -374,6 +374,13 @@ enum lock_type4 {
        NFS4_WRITEW_LT = 4
 };
 
+enum change_attr_type4 {
+       NFS4_CHANGE_TYPE_IS_MONOTONIC_INCR = 0,
+       NFS4_CHANGE_TYPE_IS_VERSION_COUNTER = 1,
+       NFS4_CHANGE_TYPE_IS_VERSION_COUNTER_NOPNFS = 2,
+       NFS4_CHANGE_TYPE_IS_TIME_METADATA = 3,
+       NFS4_CHANGE_TYPE_IS_UNDEFINED = 4
+};
 
 /* Mandatory Attributes */
 #define FATTR4_WORD0_SUPPORTED_ATTRS    (1UL << 0)
@@ -441,6 +448,7 @@ enum lock_type4 {
 #define FATTR4_WORD2_LAYOUT_BLKSIZE     (1UL << 1)
 #define FATTR4_WORD2_MDSTHRESHOLD       (1UL << 4)
 #define FATTR4_WORD2_CLONE_BLKSIZE     (1UL << 13)
+#define FATTR4_WORD2_CHANGE_ATTR_TYPE  (1UL << 15)
 #define FATTR4_WORD2_SECURITY_LABEL     (1UL << 16)
 #define FATTR4_WORD2_MODE_UMASK                (1UL << 17)
 
@@ -527,6 +535,7 @@ enum {
        NFSPROC4_CLNT_LAYOUTSTATS,
        NFSPROC4_CLNT_CLONE,
        NFSPROC4_CLNT_COPY,
+       NFSPROC4_CLNT_OFFLOAD_CANCEL,
 
        NFSPROC4_CLNT_LOOKUPP,
 };
index 2f129bb..a0831e9 100644 (file)
@@ -185,6 +185,17 @@ struct nfs_inode {
        struct inode            vfs_inode;
 };
 
+struct nfs4_copy_state {
+       struct list_head        copies;
+       nfs4_stateid            stateid;
+       struct completion       completion;
+       uint64_t                count;
+       struct nfs_writeverf    verf;
+       int                     error;
+       int                     flags;
+       struct nfs4_state       *parent_state;
+};
+
 /*
  * Access bit flags
  */
index 74ae3e1..bf39d9c 100644 (file)
@@ -28,7 +28,6 @@ struct nfs41_impl_id;
 struct nfs_client {
        refcount_t              cl_count;
        atomic_t                cl_mds_count;
-       seqcount_t              cl_callback_count;
        int                     cl_cons_state;  /* current construction state (-ve: init error) */
 #define NFS_CS_READY           0               /* ready to be used */
 #define NFS_CS_INITING         1               /* busy initialising */
@@ -122,6 +121,7 @@ struct nfs_client {
 #endif
 
        struct net              *cl_net;
+       struct list_head        pending_cb_stateids;
 };
 
 /*
@@ -209,6 +209,7 @@ struct nfs_server {
        struct list_head        state_owners_lru;
        struct list_head        layouts;
        struct list_head        delegations;
+       struct list_head        ss_copies;
 
        unsigned long           mig_gen;
        unsigned long           mig_status;
@@ -256,5 +257,6 @@ struct nfs_server {
 #define NFS_CAP_LAYOUTSTATS    (1U << 22)
 #define NFS_CAP_CLONE          (1U << 23)
 #define NFS_CAP_COPY           (1U << 24)
+#define NFS_CAP_OFFLOAD_CANCEL (1U << 25)
 
 #endif
index 712eed1..bd1c889 100644 (file)
@@ -271,7 +271,6 @@ struct nfs4_layoutget {
        struct nfs4_layoutget_args args;
        struct nfs4_layoutget_res res;
        struct rpc_cred *cred;
-       unsigned callback_count;
        gfp_t gfp_flags;
 };
 
@@ -1389,9 +1388,11 @@ struct nfs42_copy_args {
        u64                             dst_pos;
 
        u64                             count;
+       bool                            sync;
 };
 
 struct nfs42_write_res {
+       nfs4_stateid            stateid;
        u64                     count;
        struct nfs_writeverf    verifier;
 };
@@ -1404,6 +1405,18 @@ struct nfs42_copy_res {
        struct nfs_commitres            commit_res;
 };
 
+struct nfs42_offload_status_args {
+       struct nfs4_sequence_args       osa_seq_args;
+       struct nfs_fh                   *osa_src_fh;
+       nfs4_stateid                    osa_stateid;
+};
+
+struct nfs42_offload_status_res {
+       struct nfs4_sequence_res        osr_seq_res;
+       uint64_t                        osr_count;
+       int                             osr_status;
+};
+
 struct nfs42_seek_args {
        struct nfs4_sequence_args       seq_args;
 
index 1fbde8a..5a30ad5 100644 (file)
@@ -518,7 +518,7 @@ static inline int node_random(const nodemask_t *mask)
  * NODEMASK_ALLOC(type, name) allocates an object with a specified type and
  * name.
  */
-#if NODES_SHIFT > 8 /* nodemask_t > 256 bytes */
+#if NODES_SHIFT > 8 /* nodemask_t > 32 bytes */
 #define NODEMASK_ALLOC(type, name, gfp_flags)  \
                        type *name = kmalloc(sizeof(*name), gfp_flags)
 #define NODEMASK_FREE(m)                       kfree(m)
index 6adac11..69864a5 100644 (file)
@@ -88,14 +88,14 @@ static inline bool mm_is_oom_victim(struct mm_struct *mm)
  *
  * Return 0 when the PF is safe VM_FAULT_SIGBUS otherwise.
  */
-static inline int check_stable_address_space(struct mm_struct *mm)
+static inline vm_fault_t check_stable_address_space(struct mm_struct *mm)
 {
        if (unlikely(test_bit(MMF_UNSTABLE, &mm->flags)))
                return VM_FAULT_SIGBUS;
        return 0;
 }
 
-void __oom_reap_task_mm(struct mm_struct *mm);
+bool __oom_reap_task_mm(struct mm_struct *mm);
 
 extern unsigned long oom_badness(struct task_struct *p,
                struct mem_cgroup *memcg, const nodemask_t *nodemask,
index 901943e..74bee8c 100644 (file)
@@ -369,8 +369,13 @@ PAGEFLAG_FALSE(Uncached)
 PAGEFLAG(HWPoison, hwpoison, PF_ANY)
 TESTSCFLAG(HWPoison, hwpoison, PF_ANY)
 #define __PG_HWPOISON (1UL << PG_hwpoison)
+extern bool set_hwpoison_free_buddy_page(struct page *page);
 #else
 PAGEFLAG_FALSE(HWPoison)
+static inline bool set_hwpoison_free_buddy_page(struct page *page)
+{
+       return 0;
+}
 #define __PG_HWPOISON 0
 #endif
 
index 9b87f19..e72ca8d 100644 (file)
@@ -1809,7 +1809,11 @@ struct pci_fixup {
        u16 device;                     /* Or PCI_ANY_ID */
        u32 class;                      /* Or PCI_ANY_ID */
        unsigned int class_shift;       /* should be 0, 8, 16 */
+#ifdef CONFIG_HAVE_ARCH_PREL32_RELOCATIONS
+       int hook_offset;
+#else
        void (*hook)(struct pci_dev *dev);
+#endif
 };
 
 enum pci_fixup_pass {
@@ -1823,12 +1827,28 @@ enum pci_fixup_pass {
        pci_fixup_suspend_late, /* pci_device_suspend_late() */
 };
 
+#ifdef CONFIG_HAVE_ARCH_PREL32_RELOCATIONS
+#define __DECLARE_PCI_FIXUP_SECTION(sec, name, vendor, device, class,  \
+                                   class_shift, hook)                  \
+       __ADDRESSABLE(hook)                                             \
+       asm(".section " #sec ", \"a\"                           \n"     \
+           ".balign    16                                      \n"     \
+           ".short "   #vendor ", " #device "                  \n"     \
+           ".long "    #class ", " #class_shift "              \n"     \
+           ".long "    #hook " - .                             \n"     \
+           ".previous                                          \n");
+#define DECLARE_PCI_FIXUP_SECTION(sec, name, vendor, device, class,    \
+                                 class_shift, hook)                    \
+       __DECLARE_PCI_FIXUP_SECTION(sec, name, vendor, device, class,   \
+                                 class_shift, hook)
+#else
 /* Anonymous variables would be nice... */
 #define DECLARE_PCI_FIXUP_SECTION(section, name, vendor, device, class,        \
                                  class_shift, hook)                    \
        static const struct pci_fixup __PASTE(__pci_fixup_##name,__LINE__) __used       \
        __attribute__((__section__(#section), aligned((sizeof(void *)))))    \
                = { vendor, device, class, class_shift, hook };
+#endif
 
 #define DECLARE_PCI_FIXUP_CLASS_EARLY(vendor, device, class,           \
                                         class_shift, hook)             \
index 296bbe4..70b7123 100644 (file)
@@ -149,4 +149,6 @@ extern phys_addr_t per_cpu_ptr_to_phys(void *addr);
        (typeof(type) __percpu *)__alloc_percpu(sizeof(type),           \
                                                __alignof__(type))
 
+extern unsigned long pcpu_nr_pages(void);
+
 #endif /* __LINUX_PERCPU_H */
index 7633d55..14a9a39 100644 (file)
@@ -7,11 +7,10 @@
 enum pid_type
 {
        PIDTYPE_PID,
+       PIDTYPE_TGID,
        PIDTYPE_PGID,
        PIDTYPE_SID,
        PIDTYPE_MAX,
-       /* only valid to __task_pid_nr_ns() */
-       __PIDTYPE_TGID
 };
 
 /*
@@ -67,12 +66,6 @@ struct pid
 
 extern struct pid init_struct_pid;
 
-struct pid_link
-{
-       struct hlist_node node;
-       struct pid *pid;
-};
-
 static inline struct pid *get_pid(struct pid *pid)
 {
        if (pid)
@@ -177,7 +170,7 @@ pid_t pid_vnr(struct pid *pid);
        do {                                                            \
                if ((pid) != NULL)                                      \
                        hlist_for_each_entry_rcu((task),                \
-                               &(pid)->tasks[type], pids[type].node) {
+                               &(pid)->tasks[type], pid_links[type]) {
 
                        /*
                         * Both old and new leaders may be attached to
@@ -1,5 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
 /*
- * arch/arm/mach-omap1/include/ams-delta-fiq.h
+ * include/linux/platform_data/ams-delta-fiq.h
  *
  * Taken from the original Amstrad modifications to fiq.h
  *
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-#ifndef __AMS_DELTA_FIQ_H
-#define __AMS_DELTA_FIQ_H
-
-#include <mach/irqs.h>
-
-/*
- * Interrupt number used for passing control from FIQ to IRQ.
- * IRQ12, described as reserved, has been selected.
- */
-#define INT_DEFERRED_FIQ       INT_1510_RES12
-/*
- * Base address of an interrupt handler that the INT_DEFERRED_FIQ belongs to.
- */
-#if (INT_DEFERRED_FIQ < IH2_BASE)
-#define DEFERRED_FIQ_IH_BASE   OMAP_IH1_BASE
-#else
-#define DEFERRED_FIQ_IH_BASE   OMAP_IH2_BASE
-#endif
+#ifndef __LINUX_PLATFORM_DATA_AMS_DELTA_FIQ_H
+#define __LINUX_PLATFORM_DATA_AMS_DELTA_FIQ_H
 
 /*
  * These are the offsets from the beginning of the fiq_buffer. They are put here
 
 #define FIQ_CIRC_BUFF          30      /*Start of circular buffer */
 
-#ifndef __ASSEMBLER__
-extern unsigned int fiq_buffer[];
-extern unsigned char qwerty_fiqin_start, qwerty_fiqin_end;
-
-extern void __init ams_delta_init_fiq(void);
-#endif
-
 #endif
index 1fb0882..c628bb5 100644 (file)
 #ifndef __LINUX_I2C_HID_H
 #define __LINUX_I2C_HID_H
 
+#include <linux/regulator/consumer.h>
 #include <linux/types.h>
 
-struct regulator;
-
 /**
  * struct i2chid_platform_data - used by hid over i2c implementation.
  * @hid_descriptor_address: i2c register where the HID descriptor is stored.
- * @supply: regulator for powering on the device.
+ * @supplies: regulators for powering on the device.
  * @post_power_delay_ms: delay after powering on before device is usable.
  *
  * Note that it is the responsibility of the platform driver (or the acpi 5.0
@@ -35,7 +34,7 @@ struct regulator;
  */
 struct i2c_hid_platform_data {
        u16 hid_descriptor_address;
-       struct regulator *supply;
+       struct regulator_bulk_data supplies[2];
        int post_power_delay_ms;
 };
 
index 01edd96..113d6b1 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * i2c-ocores.h - definitions for the i2c-ocores interface
  *
- * Peter Korsgaard <jacmet@sunsite.dk>
+ * Peter Korsgaard <peter@korsgaard.com>
  *
  * This file is licensed under the terms of the GNU General Public License
  * version 2.  This program is licensed "as is" without any warranty of any
index 97948ac..a403dd5 100644 (file)
@@ -33,5 +33,4 @@ struct davinci_aemif_timing {
        u8      ta;
 };
 
-int davinci_aemif_setup(struct platform_device *pdev);
 #endif
index f9bed2a..fbf5ed7 100644 (file)
 #include <linux/kbuild.h>
 #include <linux/types.h>
 
+/*
+ * WFI Flags for sleep code control
+ *
+ * These flags allow PM code to exclude certain operations from happening
+ * in the low level ASM code found in sleep33xx.S and sleep43xx.S
+ *
+ * WFI_FLAG_FLUSH_CACHE: Flush the ARM caches and disable caching. Only
+ *                      needed when MPU will lose context.
+ * WFI_FLAG_SELF_REFRESH: Let EMIF place DDR memory into self-refresh and
+ *                       disable EMIF.
+ * WFI_FLAG_SAVE_EMIF: Save context of all EMIF registers and restore in
+ *                    resume path. Only needed if PER domain loses context
+ *                    and must also have WFI_FLAG_SELF_REFRESH set.
+ * WFI_FLAG_WAKE_M3: Disable MPU clock or clockdomain to cause wkup_m3 to
+ *                  execute when WFI instruction executes.
+ * WFI_FLAG_RTC_ONLY: Configure the RTC to enter RTC+DDR mode.
+ */
+#define WFI_FLAG_FLUSH_CACHE           BIT(0)
+#define WFI_FLAG_SELF_REFRESH          BIT(1)
+#define WFI_FLAG_SAVE_EMIF             BIT(2)
+#define WFI_FLAG_WAKE_M3               BIT(3)
+#define WFI_FLAG_RTC_ONLY              BIT(4)
+
 #ifndef __ASSEMBLER__
 struct am33xx_pm_sram_addr {
        void (*do_wfi)(void);
@@ -19,12 +42,15 @@ struct am33xx_pm_sram_addr {
        unsigned long *resume_offset;
        unsigned long *emif_sram_table;
        unsigned long *ro_sram_data;
+       unsigned long resume_address;
 };
 
 struct am33xx_pm_platform_data {
        int     (*init)(void);
-       int     (*soc_suspend)(unsigned int state, int (*fn)(unsigned long));
+       int     (*soc_suspend)(unsigned int state, int (*fn)(unsigned long),
+                              unsigned long args);
        struct  am33xx_pm_sram_addr *(*get_sram_addrs)(void);
+       void __iomem *(*get_rtc_base_addr)(void);
 };
 
 struct am33xx_pm_sram_data {
@@ -36,6 +62,7 @@ struct am33xx_pm_sram_data {
 struct am33xx_pm_ro_sram_data {
        u32 amx3_pm_sram_data_virt;
        u32 amx3_pm_sram_data_phys;
+       void __iomem *rtc_base_virt;
 } __packed __aligned(8);
 
 #endif /* __ASSEMBLER__ */
diff --git a/include/linux/platform_data/sh_ipmmu.h b/include/linux/platform_data/sh_ipmmu.h
deleted file mode 100644 (file)
index 39f7405..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-/* sh_ipmmu.h
- *
- * Copyright (C) 2012  Hideki EIRAKU
- *
- * 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.
- */
-
-#ifndef __SH_IPMMU_H__
-#define __SH_IPMMU_H__
-
-struct shmobile_ipmmu_platform_data {
-       const char * const *dev_names;
-       unsigned int num_dev_names;
-};
-
-#endif /* __SH_IPMMU_H__ */
index 990aad4..2efa347 100644 (file)
@@ -14,6 +14,7 @@ enum ti_sysc_module_type {
        TI_SYSC_OMAP4_SR,
        TI_SYSC_OMAP4_MCASP,
        TI_SYSC_OMAP4_USB_HOST_FS,
+       TI_SYSC_DRA7_MCAN,
 };
 
 struct ti_sysc_cookie {
index b21c4bd..f807691 100644 (file)
@@ -269,6 +269,7 @@ struct power_supply {
        spinlock_t changed_lock;
        bool changed;
        bool initialized;
+       bool removing;
        atomic_t use_cnt;
 #ifdef CONFIG_THERMAL
        struct thermal_zone_device *tzd;
index 5bd3f15..c01813c 100644 (file)
  */
 #define in_atomic_preempt_off() (preempt_count() != PREEMPT_DISABLE_OFFSET)
 
-#if defined(CONFIG_DEBUG_PREEMPT) || defined(CONFIG_PREEMPT_TRACER)
+#if defined(CONFIG_DEBUG_PREEMPT) || defined(CONFIG_TRACE_PREEMPT_TOGGLE)
 extern void preempt_count_add(int val);
 extern void preempt_count_sub(int val);
 #define preempt_count_dec_and_test() \
index 626fc65..d0e1f15 100644 (file)
@@ -129,7 +129,7 @@ int open_related_ns(struct ns_common *ns,
                   struct ns_common *(*get_ns)(struct ns_common *ns));
 
 /* get the associated pid namespace for a file in procfs */
-static inline struct pid_namespace *proc_pid_ns(struct inode *inode)
+static inline struct pid_namespace *proc_pid_ns(const struct inode *inode)
 {
        return inode->i_sb->s_fs_info;
 }
index 037bf0e..4f36431 100644 (file)
@@ -214,8 +214,6 @@ static inline void ptrace_init_task(struct task_struct *child, bool ptrace)
                        task_set_jobctl_pending(child, JOBCTL_TRAP_STOP);
                else
                        sigaddset(&child->pending.signal, SIGSTOP);
-
-               set_tsk_thread_flag(child, TIF_SIGPENDING);
        }
        else
                child->ptracer_cred = NULL;
index 003d09a..0940fda 100644 (file)
@@ -164,8 +164,8 @@ void ring_buffer_record_disable(struct ring_buffer *buffer);
 void ring_buffer_record_enable(struct ring_buffer *buffer);
 void ring_buffer_record_off(struct ring_buffer *buffer);
 void ring_buffer_record_on(struct ring_buffer *buffer);
-int ring_buffer_record_is_on(struct ring_buffer *buffer);
-int ring_buffer_record_is_set_on(struct ring_buffer *buffer);
+bool ring_buffer_record_is_on(struct ring_buffer *buffer);
+bool ring_buffer_record_is_set_on(struct ring_buffer *buffer);
 void ring_buffer_record_disable_cpu(struct ring_buffer *buffer, int cpu);
 void ring_buffer_record_enable_cpu(struct ring_buffer *buffer, int cpu);
 
index 6268208..6aedc30 100644 (file)
@@ -87,16 +87,11 @@ struct rtc_class_ops {
        int (*set_offset)(struct device *, long offset);
 };
 
-typedef struct rtc_task {
-       void (*func)(void *private_data);
-       void *private_data;
-} rtc_task_t;
-
-
 struct rtc_timer {
-       struct rtc_task task;
        struct timerqueue_node node;
        ktime_t period;
+       void (*func)(void *private_data);
+       void *private_data;
        int enabled;
 };
 
@@ -121,8 +116,6 @@ struct rtc_device {
        wait_queue_head_t irq_queue;
        struct fasync_struct *async_queue;
 
-       struct rtc_task *irq_task;
-       spinlock_t irq_task_lock;
        int irq_freq;
        int max_user_freq;
 
@@ -204,14 +197,8 @@ extern void rtc_update_irq(struct rtc_device *rtc,
 extern struct rtc_device *rtc_class_open(const char *name);
 extern void rtc_class_close(struct rtc_device *rtc);
 
-extern int rtc_irq_register(struct rtc_device *rtc,
-                               struct rtc_task *task);
-extern void rtc_irq_unregister(struct rtc_device *rtc,
-                               struct rtc_task *task);
-extern int rtc_irq_set_state(struct rtc_device *rtc,
-                               struct rtc_task *task, int enabled);
-extern int rtc_irq_set_freq(struct rtc_device *rtc,
-                               struct rtc_task *task, int freq);
+extern int rtc_irq_set_state(struct rtc_device *rtc, int enabled);
+extern int rtc_irq_set_freq(struct rtc_device *rtc, int freq);
 extern int rtc_update_irq_enable(struct rtc_device *rtc, unsigned int enabled);
 extern int rtc_alarm_irq_enable(struct rtc_device *rtc, unsigned int enabled);
 extern int rtc_dev_update_irq_enable_emul(struct rtc_device *rtc,
index 789923f..977cb57 100644 (file)
@@ -779,7 +779,8 @@ struct task_struct {
        struct list_head                ptrace_entry;
 
        /* PID/PID hash table linkage. */
-       struct pid_link                 pids[PIDTYPE_MAX];
+       struct pid                      *thread_pid;
+       struct hlist_node               pid_links[PIDTYPE_MAX];
        struct list_head                thread_group;
        struct list_head                thread_node;
 
@@ -853,6 +854,7 @@ struct task_struct {
 #endif
 #ifdef CONFIG_DETECT_HUNG_TASK
        unsigned long                   last_switch_count;
+       unsigned long                   last_switch_time;
 #endif
        /* Filesystem information: */
        struct fs_struct                *fs;
@@ -1209,27 +1211,7 @@ struct task_struct {
 
 static inline struct pid *task_pid(struct task_struct *task)
 {
-       return task->pids[PIDTYPE_PID].pid;
-}
-
-static inline struct pid *task_tgid(struct task_struct *task)
-{
-       return task->group_leader->pids[PIDTYPE_PID].pid;
-}
-
-/*
- * Without tasklist or RCU lock it is not safe to dereference
- * the result of task_pgrp/task_session even if task == current,
- * we can race with another thread doing sys_setsid/sys_setpgid.
- */
-static inline struct pid *task_pgrp(struct task_struct *task)
-{
-       return task->group_leader->pids[PIDTYPE_PGID].pid;
-}
-
-static inline struct pid *task_session(struct task_struct *task)
-{
-       return task->group_leader->pids[PIDTYPE_SID].pid;
+       return task->thread_pid;
 }
 
 /*
@@ -1278,7 +1260,7 @@ static inline pid_t task_tgid_nr(struct task_struct *tsk)
  */
 static inline int pid_alive(const struct task_struct *p)
 {
-       return p->pids[PIDTYPE_PID].pid != NULL;
+       return p->thread_pid != NULL;
 }
 
 static inline pid_t task_pgrp_nr_ns(struct task_struct *tsk, struct pid_namespace *ns)
@@ -1304,12 +1286,12 @@ static inline pid_t task_session_vnr(struct task_struct *tsk)
 
 static inline pid_t task_tgid_nr_ns(struct task_struct *tsk, struct pid_namespace *ns)
 {
-       return __task_pid_nr_ns(tsk, __PIDTYPE_TGID, ns);
+       return __task_pid_nr_ns(tsk, PIDTYPE_TGID, ns);
 }
 
 static inline pid_t task_tgid_vnr(struct task_struct *tsk)
 {
-       return __task_pid_nr_ns(tsk, __PIDTYPE_TGID, NULL);
+       return __task_pid_nr_ns(tsk, PIDTYPE_TGID, NULL);
 }
 
 static inline pid_t task_ppid_nr_ns(const struct task_struct *tsk, struct pid_namespace *ns)
index 113d1ad..1be3572 100644 (file)
@@ -69,6 +69,11 @@ struct thread_group_cputimer {
        bool checking_timer;
 };
 
+struct multiprocess_signals {
+       sigset_t signal;
+       struct hlist_node node;
+};
+
 /*
  * NOTE! "signal_struct" does not have its own
  * locking, because a shared signal_struct always
@@ -90,6 +95,9 @@ struct signal_struct {
        /* shared signal handling: */
        struct sigpending       shared_pending;
 
+       /* For collecting multiprocess signals during fork */
+       struct hlist_head       multiprocess;
+
        /* thread group exit support */
        int                     group_exit_code;
        /* overloaded:
@@ -146,7 +154,8 @@ struct signal_struct {
 
 #endif
 
-       struct pid *leader_pid;
+       /* PID/PID hash table linkage. */
+       struct pid *pids[PIDTYPE_MAX];
 
 #ifdef CONFIG_NO_HZ_FULL
        atomic_t tick_dep_mask;
@@ -314,7 +323,7 @@ int force_sig_pkuerr(void __user *addr, u32 pkey);
 int force_sig_ptrace_errno_trap(int errno, void __user *addr);
 
 extern int send_sig_info(int, struct siginfo *, struct task_struct *);
-extern int force_sigsegv(int, struct task_struct *);
+extern void force_sigsegv(int sig, struct task_struct *p);
 extern int force_sig_info(int, struct siginfo *, struct task_struct *);
 extern int __kill_pgrp_info(int sig, struct siginfo *info, struct pid *pgrp);
 extern int kill_pid_info(int sig, struct siginfo *info, struct pid *pid);
@@ -329,7 +338,7 @@ extern int send_sig(int, struct task_struct *, int);
 extern int zap_other_threads(struct task_struct *p);
 extern struct sigqueue *sigqueue_alloc(void);
 extern void sigqueue_free(struct sigqueue *);
-extern int send_sigqueue(struct sigqueue *,  struct task_struct *, int group);
+extern int send_sigqueue(struct sigqueue *, struct pid *, enum pid_type);
 extern int do_sigaction(int, struct k_sigaction *, struct k_sigaction *);
 
 static inline int restart_syscall(void)
@@ -371,6 +380,7 @@ static inline int signal_pending_state(long state, struct task_struct *p)
  */
 extern void recalc_sigpending_and_wake(struct task_struct *t);
 extern void recalc_sigpending(void);
+extern void calculate_sigpending(void);
 
 extern void signal_wake_up_state(struct task_struct *t, unsigned int state);
 
@@ -383,6 +393,8 @@ static inline void ptrace_signal_wake_up(struct task_struct *t, bool resume)
        signal_wake_up_state(t, resume ? __TASK_TRACED : 0);
 }
 
+void task_join_group_stop(struct task_struct *task);
+
 #ifdef TIF_RESTORE_SIGMASK
 /*
  * Legacy restore_sigmask accessors.  These are inefficient on
@@ -556,6 +568,37 @@ extern bool current_is_single_threaded(void);
 typedef int (*proc_visitor)(struct task_struct *p, void *data);
 void walk_process_tree(struct task_struct *top, proc_visitor, void *);
 
+static inline
+struct pid *task_pid_type(struct task_struct *task, enum pid_type type)
+{
+       struct pid *pid;
+       if (type == PIDTYPE_PID)
+               pid = task_pid(task);
+       else
+               pid = task->signal->pids[type];
+       return pid;
+}
+
+static inline struct pid *task_tgid(struct task_struct *task)
+{
+       return task->signal->pids[PIDTYPE_TGID];
+}
+
+/*
+ * Without tasklist or RCU lock it is not safe to dereference
+ * the result of task_pgrp/task_session even if task == current,
+ * we can race with another thread doing sys_setsid/sys_setpgid.
+ */
+static inline struct pid *task_pgrp(struct task_struct *task)
+{
+       return task->signal->pids[PIDTYPE_PGID];
+}
+
+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)
 {
        return tsk->signal->nr_threads;
@@ -574,7 +617,7 @@ static inline bool thread_group_leader(struct task_struct *p)
  */
 static inline bool has_group_leader_pid(struct task_struct *p)
 {
-       return task_pid(p) == p->signal->leader_pid;
+       return task_pid(p) == task_tgid(p);
 }
 
 static inline
index 913488d..a9c32da 100644 (file)
@@ -10,6 +10,7 @@ struct ctl_table;
 extern int          sysctl_hung_task_check_count;
 extern unsigned int  sysctl_hung_task_panic;
 extern unsigned long sysctl_hung_task_timeout_secs;
+extern unsigned long sysctl_hung_task_check_interval_secs;
 extern int sysctl_hung_task_warnings;
 extern int proc_dohung_task_timeout_secs(struct ctl_table *table, int write,
                                         void __user *buffer,
index 96fe289..39ad98c 100644 (file)
@@ -4,6 +4,7 @@
 
 #include <linux/uidgid.h>
 #include <linux/atomic.h>
+#include <linux/refcount.h>
 #include <linux/ratelimit.h>
 
 struct key;
@@ -12,7 +13,7 @@ struct key;
  * Some day this will be a full-fledged user tracking system..
  */
 struct user_struct {
-       atomic_t __count;       /* reference count */
+       refcount_t __count;     /* reference count */
        atomic_t processes;     /* How many processes does this user have? */
        atomic_t sigpending;    /* How many pending signals does this user have? */
 #ifdef CONFIG_FANOTIFY
@@ -59,7 +60,7 @@ extern struct user_struct root_user;
 extern struct user_struct * alloc_uid(kuid_t);
 static inline struct user_struct *get_uid(struct user_struct *u)
 {
-       atomic_inc(&u->__count);
+       refcount_inc(&u->__count);
        return u;
 }
 extern void free_uid(struct user_struct *);
index da51782..2a986d2 100644 (file)
@@ -17,6 +17,20 @@ static inline int set_memory_x(unsigned long addr,  int numpages) { return 0; }
 static inline int set_memory_nx(unsigned long addr, int numpages) { return 0; }
 #endif
 
+#ifndef set_mce_nospec
+static inline int set_mce_nospec(unsigned long pfn)
+{
+       return 0;
+}
+#endif
+
+#ifndef clear_mce_nospec
+static inline int clear_mce_nospec(unsigned long pfn)
+{
+       return 0;
+}
+#endif
+
 #ifndef CONFIG_ARCH_HAS_MEM_ENCRYPT
 static inline int set_memory_encrypted(unsigned long addr, int numpages)
 {
index b154fd2..9443caf 100644 (file)
@@ -12,6 +12,9 @@
 struct shrink_control {
        gfp_t gfp_mask;
 
+       /* current node being shrunk (for NUMA aware shrinkers) */
+       int nid;
+
        /*
         * How many objects scan_objects should scan and try to reclaim.
         * This is reset before every call, so it is safe for callees
@@ -26,9 +29,6 @@ struct shrink_control {
         */
        unsigned long nr_scanned;
 
-       /* current node being shrunk (for NUMA aware shrinkers) */
-       int nid;
-
        /* current memcg being shrunk (for memcg aware shrinkers) */
        struct mem_cgroup *memcg;
 };
@@ -63,9 +63,9 @@ struct shrinker {
        unsigned long (*scan_objects)(struct shrinker *,
                                      struct shrink_control *sc);
 
-       int seeks;      /* seeks to recreate an obj */
        long batch;     /* reclaim batch size, 0 = default */
-       unsigned long flags;
+       int seeks;      /* seeks to recreate an obj */
+       unsigned flags;
 
        /* These are for internal use */
        struct list_head list;
index 3c52001..3d4cd5d 100644 (file)
@@ -254,18 +254,20 @@ static inline int valid_signal(unsigned long sig)
 
 struct timespec;
 struct pt_regs;
+enum pid_type;
 
 extern int next_signal(struct sigpending *pending, sigset_t *mask);
 extern int do_send_sig_info(int sig, struct siginfo *info,
-                               struct task_struct *p, bool group);
-extern int group_send_sig_info(int sig, struct siginfo *info, struct task_struct *p);
+                               struct task_struct *p, enum pid_type type);
+extern int group_send_sig_info(int sig, struct siginfo *info,
+                              struct task_struct *p, enum pid_type type);
 extern int __group_send_sig_info(int, struct siginfo *, struct task_struct *);
 extern int sigprocmask(int, sigset_t *, sigset_t *);
 extern void set_current_blocked(sigset_t *);
 extern void __set_current_blocked(const sigset_t *);
 extern int show_unhandled_signals;
 
-extern int get_signal(struct ksignal *ksig);
+extern bool get_signal(struct ksignal *ksig);
 extern void signal_setup_done(int failed, struct ksignal *ksig, int stepping);
 extern void exit_signals(struct task_struct *tsk);
 extern void kernel_sigaction(int, __sighandler_t);
@@ -287,7 +289,7 @@ static inline void disallow_signal(int sig)
 
 extern struct kmem_cache *sighand_cachep;
 
-int unhandled_signal(struct task_struct *tsk, int sig);
+extern bool unhandled_signal(struct task_struct *tsk, int sig);
 
 /*
  * In POSIX a signal is sent either to a specific thread (Linux task)
index 8a6086d..00fae6f 100644 (file)
@@ -2,16 +2,7 @@
 #ifndef __LINUX_SOC_RENESAS_RCAR_SYSC_H__
 #define __LINUX_SOC_RENESAS_RCAR_SYSC_H__
 
-#include <linux/types.h>
-
-struct rcar_sysc_ch {
-       u16 chan_offs;
-       u8 chan_bit;
-       u8 isr_bit;
-};
-
-int rcar_sysc_power_down(const struct rcar_sysc_ch *sysc_ch);
-int rcar_sysc_power_up(const struct rcar_sysc_ch *sysc_ch);
-void rcar_sysc_init(phys_addr_t base, u32 syscier);
+int rcar_sysc_power_down_cpu(unsigned int cpu);
+int rcar_sysc_power_up_cpu(unsigned int cpu);
 
 #endif /* __LINUX_SOC_RENESAS_RCAR_SYSC_H__ */
index 3e72a29..67135d4 100644 (file)
@@ -170,6 +170,11 @@ static inline int srcu_read_lock_held(const struct srcu_struct *sp)
 #define srcu_dereference(p, sp) srcu_dereference_check((p), (sp), 0)
 
 /**
+ * srcu_dereference_notrace - no tracing and no lockdep calls from here
+ */
+#define srcu_dereference_notrace(p, sp) srcu_dereference_check((p), (sp), 1)
+
+/**
  * srcu_read_lock - register a new reader for an SRCU-protected structure.
  * @sp: srcu_struct in which to register the new reader.
  *
index d9af474..58a6765 100644 (file)
@@ -125,7 +125,8 @@ struct rpc_authops {
        struct module           *owner;
        rpc_authflavor_t        au_flavor;      /* flavor (RPC_AUTH_*) */
        char *                  au_name;
-       struct rpc_auth *       (*create)(struct rpc_auth_create_args *, struct rpc_clnt *);
+       struct rpc_auth *       (*create)(const struct rpc_auth_create_args *,
+                                         struct rpc_clnt *);
        void                    (*destroy)(struct rpc_auth *);
 
        int                     (*hash_cred)(struct auth_cred *, unsigned int);
@@ -174,7 +175,7 @@ struct rpc_cred *   rpc_lookup_generic_cred(struct auth_cred *, int, gfp_t);
 struct rpc_cred *      rpc_lookup_machine_cred(const char *service_name);
 int                    rpcauth_register(const struct rpc_authops *);
 int                    rpcauth_unregister(const struct rpc_authops *);
-struct rpc_auth *      rpcauth_create(struct rpc_auth_create_args *,
+struct rpc_auth *      rpcauth_create(const struct rpc_auth_create_args *,
                                struct rpc_clnt *);
 void                   rpcauth_release(struct rpc_auth *);
 rpc_authflavor_t       rpcauth_get_pseudoflavor(rpc_authflavor_t,
index 9b11b6a..73d5c4a 100644 (file)
@@ -156,6 +156,7 @@ int         rpc_switch_client_transport(struct rpc_clnt *,
 
 void           rpc_shutdown_client(struct rpc_clnt *);
 void           rpc_release_client(struct rpc_clnt *);
+void           rpc_task_release_transport(struct rpc_task *);
 void           rpc_task_release_client(struct rpc_task *);
 
 int            rpcb_create_local(struct net *);
index 9baed7b..1b37513 100644 (file)
@@ -82,7 +82,7 @@ void                  rpc_count_iostats(const struct rpc_task *,
                                          struct rpc_iostats *);
 void                   rpc_count_iostats_metrics(const struct rpc_task *,
                                          struct rpc_iostats *);
-void                   rpc_print_iostats(struct seq_file *, struct rpc_clnt *);
+void                   rpc_clnt_show_stats(struct seq_file *, struct rpc_clnt *);
 void                   rpc_free_iostats(struct rpc_iostats *);
 
 #else  /*  CONFIG_PROC_FS  */
@@ -95,7 +95,7 @@ static inline void rpc_count_iostats_metrics(const struct rpc_task *task,
 {
 }
 
-static inline void rpc_print_iostats(struct seq_file *seq, struct rpc_clnt *clnt) {}
+static inline void rpc_clnt_show_stats(struct seq_file *seq, struct rpc_clnt *clnt) {}
 static inline void rpc_free_iostats(struct rpc_iostats *stats) {}
 
 #endif  /*  CONFIG_PROC_FS  */
index 574368e..73e130a 100644 (file)
@@ -496,9 +496,11 @@ void                  svc_reserve(struct svc_rqst *rqstp, int space);
 struct svc_pool *  svc_pool_for_cpu(struct svc_serv *serv, int cpu);
 char *            svc_print_addr(struct svc_rqst *, char *, size_t);
 unsigned int      svc_fill_write_vector(struct svc_rqst *rqstp,
+                                        struct page **pages,
                                         struct kvec *first, size_t total);
 char             *svc_fill_symlink_pathname(struct svc_rqst *rqstp,
-                                            struct kvec *first, size_t total);
+                                            struct kvec *first, void *p,
+                                            size_t total);
 
 #define        RPC_MAX_ADDRBUFLEN      (63U)
 
index 7c36565..04e404a 100644 (file)
@@ -31,6 +31,7 @@ struct svc_cred {
        /* name of form servicetype@hostname, passed down by
         * rpc.svcgssd, or computed from the above: */
        char                    *cr_principal;
+       char                    *cr_targ_princ;
        struct gss_api_mech     *cr_gss_mech;
 };
 
@@ -39,6 +40,7 @@ static inline void init_svc_cred(struct svc_cred *cred)
        cred->cr_group_info = NULL;
        cred->cr_raw_principal = NULL;
        cred->cr_principal = NULL;
+       cred->cr_targ_princ = NULL;
        cred->cr_gss_mech = NULL;
 }
 
@@ -48,6 +50,7 @@ static inline void free_svc_cred(struct svc_cred *cred)
                put_group_info(cred->cr_group_info);
        kfree(cred->cr_raw_principal);
        kfree(cred->cr_principal);
+       kfree(cred->cr_targ_princ);
        gss_mech_put(cred->cr_gss_mech);
        init_svc_cred(cred);
 }
index 1a8bd05..8e2c11e 100644 (file)
@@ -447,7 +447,7 @@ extern void si_swapinfo(struct sysinfo *);
 extern swp_entry_t get_swap_page(struct page *page);
 extern void put_swap_page(struct page *page, swp_entry_t entry);
 extern swp_entry_t get_swap_page_of_type(int);
-extern int get_swap_pages(int n, bool cluster, swp_entry_t swp_entries[]);
+extern int get_swap_pages(int n, swp_entry_t swp_entries[], int entry_size);
 extern int add_swap_count_continuation(swp_entry_t, gfp_t);
 extern void swap_shmem_alloc(swp_entry_t);
 extern int swap_duplicate(swp_entry_t);
index 1d3877c..22af9d8 100644 (file)
@@ -4,6 +4,7 @@
 
 #include <linux/radix-tree.h>
 #include <linux/bug.h>
+#include <linux/mm_types.h>
 
 /*
  * swapcache pages are stored in the swapper_space radix tree.  We want to
@@ -134,7 +135,7 @@ static inline struct page *device_private_entry_to_page(swp_entry_t entry)
        return pfn_to_page(swp_offset(entry));
 }
 
-int device_private_entry_fault(struct vm_area_struct *vma,
+vm_fault_t device_private_entry_fault(struct vm_area_struct *vma,
                       unsigned long addr,
                       swp_entry_t entry,
                       unsigned int flags,
@@ -169,7 +170,7 @@ static inline struct page *device_private_entry_to_page(swp_entry_t entry)
        return NULL;
 }
 
-static inline int device_private_entry_fault(struct vm_area_struct *vma,
+static inline vm_fault_t device_private_entry_fault(struct vm_area_struct *vma,
                                     unsigned long addr,
                                     swp_entry_t entry,
                                     unsigned int flags,
@@ -340,11 +341,6 @@ static inline int is_hwpoison_entry(swp_entry_t entry)
        return swp_type(entry) == SWP_HWPOISON;
 }
 
-static inline bool test_set_page_hwpoison(struct page *page)
-{
-       return TestSetPageHWPoison(page);
-}
-
 static inline void num_poisoned_pages_inc(void)
 {
        atomic_long_inc(&num_poisoned_pages);
@@ -367,11 +363,6 @@ static inline int is_hwpoison_entry(swp_entry_t swp)
        return 0;
 }
 
-static inline bool test_set_page_hwpoison(struct page *page)
-{
-       return false;
-}
-
 static inline void num_poisoned_pages_inc(void)
 {
 }
index 0b14f93..d1ae43c 100644 (file)
@@ -207,4 +207,19 @@ static inline s64 timeval_to_ns(const struct timeval *tv)
 extern struct timeval ns_to_timeval(const s64 nsec);
 extern struct __kernel_old_timeval ns_to_kernel_old_timeval(s64 nsec);
 
+/*
+ * New aliases for compat time functions. These will be used to replace
+ * the compat code so it can be shared between 32-bit and 64-bit builds
+ * both of which provide compatibility with old 32-bit tasks.
+ */
+#define old_time32_t           compat_time_t
+#define old_timeval32          compat_timeval
+#define old_timespec32         compat_timespec
+#define old_itimerspec32       compat_itimerspec
+#define ns_to_old_timeval32    ns_to_compat_timeval
+#define get_old_itimerspec32   get_compat_itimerspec64
+#define put_old_itimerspec32   put_compat_itimerspec64
+#define get_old_timespec32     compat_get_timespec64
+#define put_old_timespec32     compat_put_timespec64
+
 #endif
index 19a690b..7f2e16e 100644 (file)
@@ -15,6 +15,7 @@
  */
 
 #include <linux/smp.h>
+#include <linux/srcu.h>
 #include <linux/errno.h>
 #include <linux/types.h>
 #include <linux/cpumask.h>
@@ -33,6 +34,8 @@ struct trace_eval_map {
 
 #define TRACEPOINT_DEFAULT_PRIO        10
 
+extern struct srcu_struct tracepoint_srcu;
+
 extern int
 tracepoint_probe_register(struct tracepoint *tp, void *probe, void *data);
 extern int
@@ -75,10 +78,16 @@ int unregister_tracepoint_module_notifier(struct notifier_block *nb)
  * probe unregistration and the end of module exit to make sure there is no
  * caller executing a probe when it is freed.
  */
+#ifdef CONFIG_TRACEPOINTS
 static inline void tracepoint_synchronize_unregister(void)
 {
+       synchronize_srcu(&tracepoint_srcu);
        synchronize_sched();
 }
+#else
+static inline void tracepoint_synchronize_unregister(void)
+{ }
+#endif
 
 #ifdef CONFIG_HAVE_SYSCALL_TRACEPOINTS
 extern int syscall_regfunc(void);
@@ -129,18 +138,31 @@ extern void syscall_unregfunc(void);
  * as "(void *, void)". The DECLARE_TRACE_NOARGS() will pass in just
  * "void *data", where as the DECLARE_TRACE() will pass in "void *data, proto".
  */
-#define __DO_TRACE(tp, proto, args, cond, rcucheck)                    \
+#define __DO_TRACE(tp, proto, args, cond, rcuidle)                     \
        do {                                                            \
                struct tracepoint_func *it_func_ptr;                    \
                void *it_func;                                          \
                void *__data;                                           \
+               int __maybe_unused idx = 0;                             \
                                                                        \
                if (!(cond))                                            \
                        return;                                         \
-               if (rcucheck)                                           \
-                       rcu_irq_enter_irqson();                         \
-               rcu_read_lock_sched_notrace();                          \
-               it_func_ptr = rcu_dereference_sched((tp)->funcs);       \
+                                                                       \
+               /* srcu can't be used from NMI */                       \
+               WARN_ON_ONCE(rcuidle && in_nmi());                      \
+                                                                       \
+               /* keep srcu and sched-rcu usage consistent */          \
+               preempt_disable_notrace();                              \
+                                                                       \
+               /*                                                      \
+                * For rcuidle callers, use srcu since sched-rcu        \
+                * doesn't work from the idle path.                     \
+                */                                                     \
+               if (rcuidle)                                            \
+                       idx = srcu_read_lock_notrace(&tracepoint_srcu); \
+                                                                       \
+               it_func_ptr = rcu_dereference_raw((tp)->funcs);         \
+                                                                       \
                if (it_func_ptr) {                                      \
                        do {                                            \
                                it_func = (it_func_ptr)->func;          \
@@ -148,9 +170,11 @@ extern void syscall_unregfunc(void);
                                ((void(*)(proto))(it_func))(args);      \
                        } while ((++it_func_ptr)->func);                \
                }                                                       \
-               rcu_read_unlock_sched_notrace();                        \
-               if (rcucheck)                                           \
-                       rcu_irq_exit_irqson();                          \
+                                                                       \
+               if (rcuidle)                                            \
+                       srcu_read_unlock_notrace(&tracepoint_srcu, idx);\
+                                                                       \
+               preempt_enable_notrace();                               \
        } while (0)
 
 #ifndef MODULE
@@ -225,6 +249,19 @@ extern void syscall_unregfunc(void);
                return static_key_false(&__tracepoint_##name.key);      \
        }
 
+#ifdef CONFIG_HAVE_ARCH_PREL32_RELOCATIONS
+#define __TRACEPOINT_ENTRY(name)                                       \
+       asm("   .section \"__tracepoints_ptrs\", \"a\"          \n"     \
+           "   .balign 4                                       \n"     \
+           "   .long   __tracepoint_" #name " - .              \n"     \
+           "   .previous                                       \n")
+#else
+#define __TRACEPOINT_ENTRY(name)                                        \
+       static struct tracepoint * const __tracepoint_ptr_##name __used  \
+       __attribute__((section("__tracepoints_ptrs"))) =                 \
+               &__tracepoint_##name
+#endif
+
 /*
  * We have no guarantee that gcc and the linker won't up-align the tracepoint
  * structures, so we create an array of pointers that will be used for iteration
@@ -234,11 +271,9 @@ extern void syscall_unregfunc(void);
        static const char __tpstrtab_##name[]                            \
        __attribute__((section("__tracepoints_strings"))) = #name;       \
        struct tracepoint __tracepoint_##name                            \
-       __attribute__((section("__tracepoints"))) =                      \
+       __attribute__((section("__tracepoints"), used)) =                \
                { __tpstrtab_##name, STATIC_KEY_INIT_FALSE, reg, unreg, NULL };\
-       static struct tracepoint * const __tracepoint_ptr_##name __used  \
-       __attribute__((section("__tracepoints_ptrs"))) =                 \
-               &__tracepoint_##name;
+       __TRACEPOINT_ENTRY(name);
 
 #define DEFINE_TRACE(name)                                             \
        DEFINE_TRACE_FN(name, NULL, NULL);
index 0a294e9..bb9d208 100644 (file)
@@ -121,7 +121,7 @@ extern bool is_swbp_insn(uprobe_opcode_t *insn);
 extern bool is_trap_insn(uprobe_opcode_t *insn);
 extern unsigned long uprobe_get_swbp_addr(struct pt_regs *regs);
 extern unsigned long uprobe_get_trap_addr(struct pt_regs *regs);
-extern int uprobe_write_opcode(struct mm_struct *mm, unsigned long vaddr, uprobe_opcode_t);
+extern int uprobe_write_opcode(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long vaddr, uprobe_opcode_t);
 extern int uprobe_register(struct inode *inode, loff_t offset, struct uprobe_consumer *uc);
 extern int uprobe_apply(struct inode *inode, loff_t offset, struct uprobe_consumer *uc, bool);
 extern void uprobe_unregister(struct inode *inode, loff_t offset, struct uprobe_consumer *uc);
index e091f0a..37c9eba 100644 (file)
@@ -28,7 +28,7 @@
 #define UFFD_SHARED_FCNTL_FLAGS (O_CLOEXEC | O_NONBLOCK)
 #define UFFD_FLAGS_SET (EFD_SHARED_FCNTL_FLAGS)
 
-extern int handle_userfault(struct vm_fault *vmf, unsigned long reason);
+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,
                            unsigned long src_start, unsigned long len,
@@ -77,7 +77,8 @@ extern void userfaultfd_unmap_complete(struct mm_struct *mm,
 #else /* CONFIG_USERFAULTFD */
 
 /* mm helpers */
-static inline int handle_userfault(struct vm_fault *vmf, unsigned long reason)
+static inline vm_fault_t handle_userfault(struct vm_fault *vmf,
+                               unsigned long reason)
 {
        return VM_FAULT_SIGBUS;
 }
index 694101f..3111585 100644 (file)
@@ -274,6 +274,8 @@ struct w1_family {
 
        struct w1_family_ops    *fops;
 
+       const struct of_device_id *of_match_table;
+
        atomic_t                refcnt;
 };
 
index d6ba7d3..e497e62 100644 (file)
@@ -40,6 +40,12 @@ struct wkup_m3_ipc {
        struct mbox_chan *mbox;
 
        struct wkup_m3_ipc_ops *ops;
+       int is_rtc_only;
+};
+
+struct wkup_m3_wakeup_src {
+       int irq_nr;
+       char src[10];
 };
 
 struct wkup_m3_ipc_ops {
@@ -48,8 +54,11 @@ struct wkup_m3_ipc_ops {
        int (*prepare_low_power)(struct wkup_m3_ipc *m3_ipc, int state);
        int (*finish_low_power)(struct wkup_m3_ipc *m3_ipc);
        int (*request_pm_status)(struct wkup_m3_ipc *m3_ipc);
+       const char *(*request_wake_src)(struct wkup_m3_ipc *m3_ipc);
+       void (*set_rtc_only)(struct wkup_m3_ipc *m3_ipc);
 };
 
 struct wkup_m3_ipc *wkup_m3_ipc_get(void);
 void wkup_m3_ipc_put(struct wkup_m3_ipc *m3_ipc);
+void wkup_m3_set_rtc_only_mode(void);
 #endif /* _LINUX_WKUP_M3_IPC_H */
index cf0add7..814eeef 100644 (file)
@@ -20,8 +20,10 @@ struct cec_notifier;
 #if IS_REACHABLE(CONFIG_CEC_CORE) && IS_ENABLED(CONFIG_CEC_NOTIFIER)
 
 /**
- * cec_notifier_get - find or create a new cec_notifier for the given device.
+ * cec_notifier_get_conn - find or create a new cec_notifier for the given
+ * device and connector tuple.
  * @dev: device that sends the events.
+ * @conn: the connector name from which the event occurs
  *
  * If a notifier for device @dev already exists, then increase the refcount
  * and return that notifier.
@@ -31,7 +33,8 @@ struct cec_notifier;
  *
  * Return NULL if the memory could not be allocated.
  */
-struct cec_notifier *cec_notifier_get(struct device *dev);
+struct cec_notifier *cec_notifier_get_conn(struct device *dev,
+                                          const char *conn);
 
 /**
  * cec_notifier_put - decrease refcount and delete when the refcount reaches 0.
@@ -85,7 +88,8 @@ void cec_register_cec_notifier(struct cec_adapter *adap,
                               struct cec_notifier *notifier);
 
 #else
-static inline struct cec_notifier *cec_notifier_get(struct device *dev)
+static inline struct cec_notifier *cec_notifier_get_conn(struct device *dev,
+                                                        const char *conn)
 {
        /* A non-NULL pointer is expected on success */
        return (struct cec_notifier *)0xdeadfeed;
@@ -121,6 +125,23 @@ static inline void cec_register_cec_notifier(struct cec_adapter *adap,
 #endif
 
 /**
+ * cec_notifier_get - find or create a new cec_notifier for the given device.
+ * @dev: device that sends the events.
+ *
+ * If a notifier for device @dev already exists, then increase the refcount
+ * and return that notifier.
+ *
+ * If it doesn't exist, then allocate a new notifier struct and return a
+ * pointer to that new struct.
+ *
+ * Return NULL if the memory could not be allocated.
+ */
+static inline struct cec_notifier *cec_notifier_get(struct device *dev)
+{
+       return cec_notifier_get_conn(dev, NULL);
+}
+
+/**
  * cec_notifier_phys_addr_invalidate() - set the physical address to INVALID
  *
  * @n: the CEC notifier
index 903771c..1ce365f 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/security.h>
 #include <linux/pid.h>
 #include <linux/nsproxy.h>
+#include <linux/sched/signal.h>
 
 /* Well, we should have at least one descriptor open
  * to accept passed FDs 8)
index 3e11e7c..62e990b 100644 (file)
@@ -133,28 +133,4 @@ const struct ib_gid_attr *rdma_get_gid_attr(struct ib_device *device,
 void rdma_put_gid_attr(const struct ib_gid_attr *attr);
 void rdma_hold_gid_attr(const struct ib_gid_attr *attr);
 
-/*
- * This is to be removed. It only exists to make merging rdma and smc simpler.
- */
-static inline __deprecated int ib_query_gid(struct ib_device *device,
-                                           u8 port_num, int index,
-                                           union ib_gid *gid,
-                                           struct ib_gid_attr *attr_out)
-{
-       const struct ib_gid_attr *attr;
-
-       memset(attr_out, 0, sizeof(*attr_out));
-       attr = rdma_get_gid_attr(device, port_num, index);
-       if (IS_ERR(attr))
-               return PTR_ERR(attr);
-
-       if (attr->ndev)
-               dev_hold(attr->ndev);
-       *attr_out = *attr;
-
-       rdma_put_gid_attr(attr);
-
-       return 0;
-}
-
 #endif /* _IB_CACHE_H */
index 6a17f85..381cdf5 100644 (file)
@@ -119,7 +119,8 @@ typedef int (*umem_call_back)(struct ib_umem *item, u64 start, u64 end,
  */
 int rbt_ib_umem_for_each_in_range(struct rb_root_cached *root,
                                  u64 start, u64 end,
-                                 umem_call_back cb, void *cookie);
+                                 umem_call_back cb,
+                                 bool blockable, void *cookie);
 
 /*
  * Find first region intersecting with address range.
index 8ee8991..c4a5c9e 100644 (file)
@@ -75,6 +75,7 @@ enum rpi_firmware_property_tag {
        RPI_FIRMWARE_GET_EDID_BLOCK =                         0x00030020,
        RPI_FIRMWARE_GET_CUSTOMER_OTP =                       0x00030021,
        RPI_FIRMWARE_GET_DOMAIN_STATE =                       0x00030030,
+       RPI_FIRMWARE_GET_THROTTLED =                          0x00030046,
        RPI_FIRMWARE_SET_CLOCK_STATE =                        0x00038001,
        RPI_FIRMWARE_SET_CLOCK_RATE =                         0x00038002,
        RPI_FIRMWARE_SET_VOLTAGE =                            0x00038003,
similarity index 97%
rename from drivers/staging/fsl-mc/include/dpaa2-fd.h
rename to include/soc/fsl/dpaa2-fd.h
index b55b89b..2576aba 100644 (file)
@@ -67,6 +67,18 @@ struct dpaa2_fd {
 #define SG_FINAL_FLAG_MASK     0x1
 #define SG_FINAL_FLAG_SHIFT    15
 
+/* Error bits in FD CTRL */
+#define FD_CTRL_ERR_MASK       0x000000FF
+#define FD_CTRL_UFD            0x00000004
+#define FD_CTRL_SBE            0x00000008
+#define FD_CTRL_FLC            0x00000010
+#define FD_CTRL_FSE            0x00000020
+#define FD_CTRL_FAERR          0x00000040
+
+/* Annotation bits in FD CTRL */
+#define FD_CTRL_PTA            0x00800000
+#define FD_CTRL_PTV1           0x00400000
+
 enum dpaa2_fd_format {
        dpaa2_fd_single = 0,
        dpaa2_fd_list,
index d74722c..a401ff5 100644 (file)
@@ -53,24 +53,22 @@ DEFINE_EVENT(cgroup_root, cgroup_remount,
 
 DECLARE_EVENT_CLASS(cgroup,
 
-       TP_PROTO(struct cgroup *cgrp),
+       TP_PROTO(struct cgroup *cgrp, const char *path),
 
-       TP_ARGS(cgrp),
+       TP_ARGS(cgrp, path),
 
        TP_STRUCT__entry(
                __field(        int,            root                    )
                __field(        int,            id                      )
                __field(        int,            level                   )
-               __dynamic_array(char,           path,
-                               cgroup_path(cgrp, NULL, 0) + 1)
+               __string(       path,           path                    )
        ),
 
        TP_fast_assign(
                __entry->root = cgrp->root->hierarchy_id;
                __entry->id = cgrp->id;
                __entry->level = cgrp->level;
-               cgroup_path(cgrp, __get_dynamic_array(path),
-                                 __get_dynamic_array_len(path));
+               __assign_str(path, path);
        ),
 
        TP_printk("root=%d id=%d level=%d path=%s",
@@ -79,45 +77,45 @@ DECLARE_EVENT_CLASS(cgroup,
 
 DEFINE_EVENT(cgroup, cgroup_mkdir,
 
-       TP_PROTO(struct cgroup *cgroup),
+       TP_PROTO(struct cgroup *cgrp, const char *path),
 
-       TP_ARGS(cgroup)
+       TP_ARGS(cgrp, path)
 );
 
 DEFINE_EVENT(cgroup, cgroup_rmdir,
 
-       TP_PROTO(struct cgroup *cgroup),
+       TP_PROTO(struct cgroup *cgrp, const char *path),
 
-       TP_ARGS(cgroup)
+       TP_ARGS(cgrp, path)
 );
 
 DEFINE_EVENT(cgroup, cgroup_release,
 
-       TP_PROTO(struct cgroup *cgroup),
+       TP_PROTO(struct cgroup *cgrp, const char *path),
 
-       TP_ARGS(cgroup)
+       TP_ARGS(cgrp, path)
 );
 
 DEFINE_EVENT(cgroup, cgroup_rename,
 
-       TP_PROTO(struct cgroup *cgroup),
+       TP_PROTO(struct cgroup *cgrp, const char *path),
 
-       TP_ARGS(cgroup)
+       TP_ARGS(cgrp, path)
 );
 
 DECLARE_EVENT_CLASS(cgroup_migrate,
 
-       TP_PROTO(struct cgroup *dst_cgrp, struct task_struct *task, bool threadgroup),
+       TP_PROTO(struct cgroup *dst_cgrp, const char *path,
+                struct task_struct *task, bool threadgroup),
 
-       TP_ARGS(dst_cgrp, task, threadgroup),
+       TP_ARGS(dst_cgrp, path, task, threadgroup),
 
        TP_STRUCT__entry(
                __field(        int,            dst_root                )
                __field(        int,            dst_id                  )
                __field(        int,            dst_level               )
-               __dynamic_array(char,           dst_path,
-                               cgroup_path(dst_cgrp, NULL, 0) + 1)
                __field(        int,            pid                     )
+               __string(       dst_path,       path                    )
                __string(       comm,           task->comm              )
        ),
 
@@ -125,8 +123,7 @@ DECLARE_EVENT_CLASS(cgroup_migrate,
                __entry->dst_root = dst_cgrp->root->hierarchy_id;
                __entry->dst_id = dst_cgrp->id;
                __entry->dst_level = dst_cgrp->level;
-               cgroup_path(dst_cgrp, __get_dynamic_array(dst_path),
-                                     __get_dynamic_array_len(dst_path));
+               __assign_str(dst_path, path);
                __entry->pid = task->pid;
                __assign_str(comm, task->comm);
        ),
@@ -138,16 +135,18 @@ DECLARE_EVENT_CLASS(cgroup_migrate,
 
 DEFINE_EVENT(cgroup_migrate, cgroup_attach_task,
 
-       TP_PROTO(struct cgroup *dst_cgrp, struct task_struct *task, bool threadgroup),
+       TP_PROTO(struct cgroup *dst_cgrp, const char *path,
+                struct task_struct *task, bool threadgroup),
 
-       TP_ARGS(dst_cgrp, task, threadgroup)
+       TP_ARGS(dst_cgrp, path, task, threadgroup)
 );
 
 DEFINE_EVENT(cgroup_migrate, cgroup_transfer_tasks,
 
-       TP_PROTO(struct cgroup *dst_cgrp, struct task_struct *task, bool threadgroup),
+       TP_PROTO(struct cgroup *dst_cgrp, const char *path,
+                struct task_struct *task, bool threadgroup),
 
-       TP_ARGS(dst_cgrp, task, threadgroup)
+       TP_ARGS(dst_cgrp, path, task, threadgroup)
 );
 
 #endif /* _TRACE_CGROUP_H */
index 9c4eb33..9a0d4ce 100644 (file)
@@ -1,4 +1,4 @@
-#ifdef CONFIG_PREEMPTIRQ_EVENTS
+#ifdef CONFIG_PREEMPTIRQ_TRACEPOINTS
 
 #undef TRACE_SYSTEM
 #define TRACE_SYSTEM preemptirq
@@ -32,7 +32,7 @@ DECLARE_EVENT_CLASS(preemptirq_template,
                  (void *)((unsigned long)(_stext) + __entry->parent_offs))
 );
 
-#ifndef CONFIG_PROVE_LOCKING
+#ifdef CONFIG_TRACE_IRQFLAGS
 DEFINE_EVENT(preemptirq_template, irq_disable,
             TP_PROTO(unsigned long ip, unsigned long parent_ip),
             TP_ARGS(ip, parent_ip));
@@ -40,9 +40,14 @@ DEFINE_EVENT(preemptirq_template, irq_disable,
 DEFINE_EVENT(preemptirq_template, irq_enable,
             TP_PROTO(unsigned long ip, unsigned long parent_ip),
             TP_ARGS(ip, parent_ip));
+#else
+#define trace_irq_enable(...)
+#define trace_irq_disable(...)
+#define trace_irq_enable_rcuidle(...)
+#define trace_irq_disable_rcuidle(...)
 #endif
 
-#ifdef CONFIG_DEBUG_PREEMPT
+#ifdef CONFIG_TRACE_PREEMPT_TOGGLE
 DEFINE_EVENT(preemptirq_template, preempt_disable,
             TP_PROTO(unsigned long ip, unsigned long parent_ip),
             TP_ARGS(ip, parent_ip));
@@ -50,22 +55,22 @@ DEFINE_EVENT(preemptirq_template, preempt_disable,
 DEFINE_EVENT(preemptirq_template, preempt_enable,
             TP_PROTO(unsigned long ip, unsigned long parent_ip),
             TP_ARGS(ip, parent_ip));
+#else
+#define trace_preempt_enable(...)
+#define trace_preempt_disable(...)
+#define trace_preempt_enable_rcuidle(...)
+#define trace_preempt_disable_rcuidle(...)
 #endif
 
 #endif /* _TRACE_PREEMPTIRQ_H */
 
 #include <trace/define_trace.h>
 
-#endif /* !CONFIG_PREEMPTIRQ_EVENTS */
-
-#if !defined(CONFIG_PREEMPTIRQ_EVENTS) || defined(CONFIG_PROVE_LOCKING)
+#else /* !CONFIG_PREEMPTIRQ_TRACEPOINTS */
 #define trace_irq_enable(...)
 #define trace_irq_disable(...)
 #define trace_irq_enable_rcuidle(...)
 #define trace_irq_disable_rcuidle(...)
-#endif
-
-#if !defined(CONFIG_PREEMPTIRQ_EVENTS) || !defined(CONFIG_DEBUG_PREEMPT)
 #define trace_preempt_enable(...)
 #define trace_preempt_disable(...)
 #define trace_preempt_enable_rcuidle(...)
index e13eec3..df31aa9 100644 (file)
@@ -23,7 +23,7 @@
 #define AUTOFS_MIN_PROTO_VERSION       3
 #define AUTOFS_MAX_PROTO_VERSION       5
 
-#define AUTOFS_PROTO_SUBVERSION                2
+#define AUTOFS_PROTO_SUBVERSION                3
 
 /*
  * The wait_queue_token (autofs_wqt_t) is part of a structure which is passed
@@ -90,8 +90,10 @@ enum {
 /* autofs version 4 and later definitions */
 
 /* Mask for expire behaviour */
-#define AUTOFS_EXP_IMMEDIATE           1
-#define AUTOFS_EXP_LEAVES              2
+#define AUTOFS_EXP_NORMAL              0x00
+#define AUTOFS_EXP_IMMEDIATE           0x01
+#define AUTOFS_EXP_LEAVES              0x02
+#define AUTOFS_EXP_FORCED              0x04
 
 #define AUTOFS_TYPE_ANY                        0U
 #define AUTOFS_TYPE_INDIRECT           1U
index 8d19e02..5d4f58e 100644 (file)
@@ -30,10 +30,10 @@ struct bkey {
        BITMASK(name, struct bkey, field, offset, size)
 
 #define PTR_FIELD(name, offset, size)                                  \
-static inline __u64 name(const struct bkey *k, unsigned i)             \
+static inline __u64 name(const struct bkey *k, unsigned int i)         \
 { return (k->ptr[i] >> offset) & ~(~0ULL << size); }                   \
                                                                        \
-static inline void SET_##name(struct bkey *k, unsigned i, __u64 v)     \
+static inline void SET_##name(struct bkey *k, unsigned int i, __u64 v) \
 {                                                                      \
        k->ptr[i] &= ~(~(~0ULL << size) << offset);                     \
        k->ptr[i] |= (v & ~(~0ULL << size)) << offset;                  \
@@ -117,12 +117,14 @@ static inline void bkey_copy_key(struct bkey *dest, const struct bkey *src)
 static inline struct bkey *bkey_next(const struct bkey *k)
 {
        __u64 *d = (void *) k;
+
        return (struct bkey *) (d + bkey_u64s(k));
 }
 
-static inline struct bkey *bkey_idx(const struct bkey *k, unsigned nr_keys)
+static inline struct bkey *bkey_idx(const struct bkey *k, unsigned int nr_keys)
 {
        __u64 *d = (void *) k;
+
        return (struct bkey *) (d + nr_keys);
 }
 /* Enough for a key with 6 pointers */
index 7288a7c..fb78f6f 100644 (file)
@@ -270,10 +270,11 @@ struct input_mask {
 /*
  * MT_TOOL types
  */
-#define MT_TOOL_FINGER         0
-#define MT_TOOL_PEN            1
-#define MT_TOOL_PALM           2
-#define MT_TOOL_MAX            2
+#define MT_TOOL_FINGER         0x00
+#define MT_TOOL_PEN            0x01
+#define MT_TOOL_PALM           0x02
+#define MT_TOOL_DIAL           0x0a
+#define MT_TOOL_MAX            0x0f
 
 /*
  * Values describing the status of a force-feedback effect
index 3cf6328..07548de 100644 (file)
@@ -951,6 +951,7 @@ struct kvm_ppc_resize_hpt {
 #define KVM_CAP_HYPERV_TLBFLUSH 155
 #define KVM_CAP_S390_HPAGE_1M 156
 #define KVM_CAP_NESTED_STATE 157
+#define KVM_CAP_ARM_INJECT_SERROR_ESR 158
 
 #ifdef KVM_CAP_IRQ_ROUTING
 
index 5b04a49..aad3b62 100644 (file)
@@ -285,6 +285,20 @@ struct ubi_attach_req {
        __s8 padding[10];
 };
 
+/*
+ * UBI volume flags.
+ *
+ * @UBI_VOL_SKIP_CRC_CHECK_FLG: skip the CRC check done on a static volume at
+ *                             open time. Only valid for static volumes and
+ *                             should only be used if the volume user has a
+ *                             way to verify data integrity
+ */
+enum {
+       UBI_VOL_SKIP_CRC_CHECK_FLG = 0x1,
+};
+
+#define UBI_VOL_VALID_FLGS     (UBI_VOL_SKIP_CRC_CHECK_FLG)
+
 /**
  * struct ubi_mkvol_req - volume description data structure used in
  *                        volume creation requests.
@@ -292,7 +306,7 @@ struct ubi_attach_req {
  * @alignment: volume alignment
  * @bytes: volume size in bytes
  * @vol_type: volume type (%UBI_DYNAMIC_VOLUME or %UBI_STATIC_VOLUME)
- * @padding1: reserved for future, not used, has to be zeroed
+ * @flags: volume flags (%UBI_VOL_SKIP_CRC_CHECK_FLG)
  * @name_len: volume name length
  * @padding2: reserved for future, not used, has to be zeroed
  * @name: volume name
@@ -321,7 +335,7 @@ struct ubi_mkvol_req {
        __s32 alignment;
        __s64 bytes;
        __s8 vol_type;
-       __s8 padding1;
+       __u8 flags;
        __s16 name_len;
        __s8 padding2[4];
        char name[UBI_MAX_VOLUME_NAME + 1];
index 0cabe6b..3abd327 100644 (file)
@@ -20,7 +20,6 @@ struct dloarea {
 struct urb_node {
        struct list_head entry;
        struct dlfb_data *dlfb;
-       struct delayed_work release_urb_work;
        struct urb *urb;
 };
 
@@ -52,11 +51,14 @@ struct dlfb_data {
        int base8;
        u32 pseudo_palette[256];
        int blank_mode; /*one of FB_BLANK_ */
+       struct fb_ops ops;
        /* blit-only rendering path metrics, exposed through sysfs */
        atomic_t bytes_rendered; /* raw pixel-bytes driver asked to render */
        atomic_t bytes_identical; /* saved effort with backbuffer comparison */
        atomic_t bytes_sent; /* to usb, after compression including overhead */
        atomic_t cpu_kcycles_used; /* transpired during pixel processing */
+       struct fb_var_screeninfo current_mode;
+       struct list_head deferred_free;
 };
 
 #define NR_USB_REQUEST_I2C_SUB_IO 0x02
@@ -87,7 +89,7 @@ struct dlfb_data {
 #define MIN_RAW_PIX_BYTES      2
 #define MIN_RAW_CMD_BYTES      (RAW_HEADER_BYTES + MIN_RAW_PIX_BYTES)
 
-#define DL_DEFIO_WRITE_DELAY    5 /* fb_deferred_io.delay in jiffies */
+#define DL_DEFIO_WRITE_DELAY    msecs_to_jiffies(HZ <= 300 ? 4 : 10) /* optimal value for 720p video */
 #define DL_DEFIO_WRITE_DISABLE  (HZ*60) /* "disable" with long delay */
 
 /* remove these once align.h patch is taken into kernel */
index 9bd50ba..1e234e2 100644 (file)
@@ -436,7 +436,7 @@ config BSD_PROCESS_ACCT_V3
        help
          If you say Y here, the process accounting information is written
          in a new file format that also logs the process IDs of each
-         process and it's parent. Note that this file format is incompatible
+         process and its parent. Note that this file format is incompatible
          with previous v0/v1/v2 file formats, so you will need updated tools
          for processing it. A preliminary version of these tools is available
          at <http://www.gnu.org/software/acct/>.
@@ -967,6 +967,18 @@ config NET_NS
 
 endif # NAMESPACES
 
+config CHECKPOINT_RESTORE
+       bool "Checkpoint/restore support"
+       select PROC_CHILDREN
+       default n
+       help
+         Enables additional kernel features in a sake of checkpoint/restore.
+         In particular it adds auxiliary prctl codes to setup process text,
+         data and heap segment sizes, and a few additional /proc filesystem
+         entries.
+
+         If unsure, say N here.
+
 config SCHED_AUTOGROUP
        bool "Automatic process group scheduling"
        select CGROUPS
@@ -1085,6 +1097,8 @@ config LD_DEAD_CODE_DATA_ELIMINATION
        bool "Dead code and data elimination (EXPERIMENTAL)"
        depends on HAVE_LD_DEAD_CODE_DATA_ELIMINATION
        depends on EXPERT
+       depends on $(cc-option,-ffunction-sections -fdata-sections)
+       depends on $(ld-option,--gc-sections)
        help
          Enable this if you want to do dead code and data elimination with
          the linker by compiling with -ffunction-sections -fdata-sections,
@@ -1383,18 +1397,6 @@ config MEMBARRIER
 
          If unsure, say Y.
 
-config CHECKPOINT_RESTORE
-       bool "Checkpoint/restore support" if EXPERT
-       select PROC_CHILDREN
-       default n
-       help
-         Enables additional kernel features in a sake of checkpoint/restore.
-         In particular it adds auxiliary prctl codes to setup process text,
-         data and heap segment sizes, and a few additional /proc filesystem
-         entries.
-
-         If unsure, say N here.
-
 config KALLSYMS
         bool "Load all symbols for debugging/ksymoops" if EXPERT
         default y
@@ -1702,7 +1704,7 @@ config MMAP_ALLOW_UNINITIALIZED
        default n
        help
          Normally, and according to the Linux spec, anonymous memory obtained
-         from mmap() has it's contents cleared before it is passed to
+         from mmap() has its contents cleared before it is passed to
          userspace.  Enabling this config option allows you to request that
          mmap() skip that if it is given an MAP_UNINITIALIZED flag, thus
          providing a huge performance boost.  If this option is not enabled,
index 2c71dab..e1c9afa 100644 (file)
@@ -1,13 +1,3 @@
-/*
- * Many of the syscalls used in this file expect some of the arguments
- * to be __user pointers not __kernel pointers.  To limit the sparse
- * noise, turn off sparse checking for this file.
- */
-#ifdef __CHECKER__
-#undef __CHECKER__
-#warning "Sparse checking disabled for this file"
-#endif
-
 #include <linux/module.h>
 #include <linux/sched.h>
 #include <linux/ctype.h>
index 5a91aef..d1a5d88 100644 (file)
@@ -1,14 +1,4 @@
 // SPDX-License-Identifier: GPL-2.0
-/*
- * Many of the syscalls used in this file expect some of the arguments
- * to be __user pointers not __kernel pointers.  To limit the sparse
- * noise, turn off sparse checking for this file.
- */
-#ifdef __CHECKER__
-#undef __CHECKER__
-#warning "Sparse checking disabled for this file"
-#endif
-
 #include <linux/unistd.h>
 #include <linux/kernel.h>
 #include <linux/fs.h>
index 7d85d17..b840315 100644 (file)
@@ -1,14 +1,4 @@
 // SPDX-License-Identifier: GPL-2.0
-/*
- * Many of the syscalls used in this file expect some of the arguments
- * to be __user pointers not __kernel pointers.  To limit the sparse
- * noise, turn off sparse checking for this file.
- */
-#ifdef __CHECKER__
-#undef __CHECKER__
-#warning "Sparse checking disabled for this file"
-#endif
-
 #include <linux/delay.h>
 #include <linux/raid/md_u.h>
 #include <linux/raid/md_p.h>
index 035a5f0..32fb049 100644 (file)
@@ -1,14 +1,4 @@
 // SPDX-License-Identifier: GPL-2.0
-/*
- * Many of the syscalls used in this file expect some of the arguments
- * to be __user pointers not __kernel pointers.  To limit the sparse
- * noise, turn off sparse checking for this file.
- */
-#ifdef __CHECKER__
-#undef __CHECKER__
-#warning "Sparse checking disabled for this file"
-#endif
-
 #include <linux/kernel.h>
 #include <linux/fs.h>
 #include <linux/minix_fs.h>
index 74f60ba..5aebe3b 100644 (file)
@@ -22,6 +22,7 @@ static struct signal_struct init_signals = {
                .list = LIST_HEAD_INIT(init_signals.shared_pending.list),
                .signal =  {{0}}
        },
+       .multiprocess   = HLIST_HEAD_INIT,
        .rlim           = INIT_RLIMITS,
        .cred_guard_mutex = __MUTEX_INITIALIZER(init_signals.cred_guard_mutex),
 #ifdef CONFIG_POSIX_TIMERS
@@ -33,6 +34,12 @@ static struct signal_struct init_signals = {
        },
 #endif
        INIT_CPU_TIMERS(init_signals)
+       .pids = {
+               [PIDTYPE_PID]   = &init_struct_pid,
+               [PIDTYPE_TGID]  = &init_struct_pid,
+               [PIDTYPE_PGID]  = &init_struct_pid,
+               [PIDTYPE_SID]   = &init_struct_pid,
+       },
        INIT_PREV_CPUTIME(init_signals)
 };
 
@@ -111,11 +118,7 @@ struct task_struct init_task
        INIT_CPU_TIMERS(init_task)
        .pi_lock        = __RAW_SPIN_LOCK_UNLOCKED(init_task.pi_lock),
        .timer_slack_ns = 50000, /* 50 usec default slack */
-       .pids = {
-               [PIDTYPE_PID]  = INIT_PID_LINK(PIDTYPE_PID),
-               [PIDTYPE_PGID] = INIT_PID_LINK(PIDTYPE_PGID),
-               [PIDTYPE_SID]  = INIT_PID_LINK(PIDTYPE_SID),
-       },
+       .thread_pid     = &init_struct_pid,
        .thread_group   = LIST_HEAD_INIT(init_task.thread_group),
        .thread_node    = LIST_HEAD_INIT(init_signals.thread_head),
 #ifdef CONFIG_AUDITSYSCALL
index 13643c4..6405577 100644 (file)
@@ -1,14 +1,4 @@
 // SPDX-License-Identifier: GPL-2.0
-/*
- * Many of the syscalls used in this file expect some of the arguments
- * to be __user pointers not __kernel pointers.  To limit the sparse
- * noise, turn off sparse checking for this file.
- */
-#ifdef __CHECKER__
-#undef __CHECKER__
-#warning "Sparse checking disabled for this file"
-#endif
-
 #include <linux/init.h>
 #include <linux/fs.h>
 #include <linux/slab.h>
index 38c68b5..18f8f01 100644 (file)
@@ -647,6 +647,7 @@ asmlinkage __visible void __init start_kernel(void)
        profile_init();
        call_function_init();
        WARN(!irqs_disabled(), "Interrupts were enabled early\n");
+
        early_boot_irqs_disabled = false;
        local_irq_enable();
 
@@ -662,7 +663,7 @@ asmlinkage __visible void __init start_kernel(void)
                panic("Too many boot %s vars at `%s'", panic_later,
                      panic_param);
 
-       lockdep_info();
+       lockdep_init();
 
        /*
         * Need to run this when irqs are enabled, because it wants
@@ -901,18 +902,18 @@ int __init_or_module do_one_initcall(initcall_t fn)
 }
 
 
-extern initcall_t __initcall_start[];
-extern initcall_t __initcall0_start[];
-extern initcall_t __initcall1_start[];
-extern initcall_t __initcall2_start[];
-extern initcall_t __initcall3_start[];
-extern initcall_t __initcall4_start[];
-extern initcall_t __initcall5_start[];
-extern initcall_t __initcall6_start[];
-extern initcall_t __initcall7_start[];
-extern initcall_t __initcall_end[];
+extern initcall_entry_t __initcall_start[];
+extern initcall_entry_t __initcall0_start[];
+extern initcall_entry_t __initcall1_start[];
+extern initcall_entry_t __initcall2_start[];
+extern initcall_entry_t __initcall3_start[];
+extern initcall_entry_t __initcall4_start[];
+extern initcall_entry_t __initcall5_start[];
+extern initcall_entry_t __initcall6_start[];
+extern initcall_entry_t __initcall7_start[];
+extern initcall_entry_t __initcall_end[];
 
-static initcall_t *initcall_levels[] __initdata = {
+static initcall_entry_t *initcall_levels[] __initdata = {
        __initcall0_start,
        __initcall1_start,
        __initcall2_start,
@@ -938,7 +939,7 @@ static char *initcall_level_names[] __initdata = {
 
 static void __init do_initcall_level(int level)
 {
-       initcall_t *fn;
+       initcall_entry_t *fn;
 
        strcpy(initcall_command_line, saved_command_line);
        parse_args(initcall_level_names[level],
@@ -949,7 +950,7 @@ static void __init do_initcall_level(int level)
 
        trace_initcall_level(initcall_level_names[level]);
        for (fn = initcall_levels[level]; fn < initcall_levels[level+1]; fn++)
-               do_one_initcall(*fn);
+               do_one_initcall(initcall_from_entry(fn));
 }
 
 static void __init do_initcalls(void)
@@ -980,11 +981,11 @@ static void __init do_basic_setup(void)
 
 static void __init do_pre_smp_initcalls(void)
 {
-       initcall_t *fn;
+       initcall_entry_t *fn;
 
        trace_initcall_level("early");
        for (fn = __initcall_start; fn < __initcall0_start; fn++)
-               do_one_initcall(*fn);
+               do_one_initcall(initcall_from_entry(fn));
 }
 
 /*
@@ -1001,6 +1002,7 @@ void __init load_default_modules(void)
 static int run_init_process(const char *init_filename)
 {
        argv_init[0] = init_filename;
+       pr_info("Run %s as init process\n", init_filename);
        return do_execve(getname_kernel(init_filename),
                (const char __user *const __user *)argv_init,
                (const char __user *const __user *)envp_init);
index 2032811..883642c 100644 (file)
--- a/ipc/msg.c
+++ b/ipc/msg.c
@@ -163,7 +163,7 @@ static int newque(struct ipc_namespace *ns, struct ipc_params *params)
        /* ipc_addid() locks msq upon success. */
        retval = ipc_addid(&msg_ids(ns), &msq->q_perm, ns->msg_ctlmni);
        if (retval < 0) {
-               call_rcu(&msq->q_perm.rcu, msg_rcu_free);
+               ipc_rcu_putref(&msq->q_perm, msg_rcu_free);
                return retval;
        }
 
@@ -386,7 +386,7 @@ static int msgctl_down(struct ipc_namespace *ns, int msqid, int cmd,
        down_write(&msg_ids(ns).rwsem);
        rcu_read_lock();
 
-       ipcp = ipcctl_pre_down_nolock(ns, &msg_ids(ns), msqid, cmd,
+       ipcp = ipcctl_obtain_check(ns, &msg_ids(ns), msqid, cmd,
                                      &msqid64->msg_perm, msqid64->msg_qbytes);
        if (IS_ERR(ipcp)) {
                err = PTR_ERR(ipcp);
@@ -456,7 +456,7 @@ static int msgctl_info(struct ipc_namespace *ns, int msqid,
                         int cmd, struct msginfo *msginfo)
 {
        int err;
-       int max_id;
+       int max_idx;
 
        /*
         * We must not return kernel stack data.
@@ -483,16 +483,15 @@ static int msgctl_info(struct ipc_namespace *ns, int msqid,
                msginfo->msgpool = MSGPOOL;
                msginfo->msgtql = MSGTQL;
        }
-       max_id = ipc_get_maxid(&msg_ids(ns));
+       max_idx = ipc_get_maxidx(&msg_ids(ns));
        up_read(&msg_ids(ns).rwsem);
-       return (max_id < 0) ? 0 : max_id;
+       return (max_idx < 0) ? 0 : max_idx;
 }
 
 static int msgctl_stat(struct ipc_namespace *ns, int msqid,
                         int cmd, struct msqid64_ds *p)
 {
        struct msg_queue *msq;
-       int id = 0;
        int err;
 
        memset(p, 0, sizeof(*p));
@@ -504,7 +503,6 @@ static int msgctl_stat(struct ipc_namespace *ns, int msqid,
                        err = PTR_ERR(msq);
                        goto out_unlock;
                }
-               id = msq->q_perm.id;
        } else { /* IPC_STAT */
                msq = msq_obtain_object_check(ns, msqid);
                if (IS_ERR(msq)) {
@@ -549,10 +547,21 @@ static int msgctl_stat(struct ipc_namespace *ns, int msqid,
        p->msg_lspid  = pid_vnr(msq->q_lspid);
        p->msg_lrpid  = pid_vnr(msq->q_lrpid);
 
-       ipc_unlock_object(&msq->q_perm);
-       rcu_read_unlock();
-       return id;
+       if (cmd == IPC_STAT) {
+               /*
+                * As defined in SUS:
+                * Return 0 on success
+                */
+               err = 0;
+       } else {
+               /*
+                * MSG_STAT and MSG_STAT_ANY (both Linux specific)
+                * Return the full id, including the sequence number
+                */
+               err = msq->q_perm.id;
+       }
 
+       ipc_unlock_object(&msq->q_perm);
 out_unlock:
        rcu_read_unlock();
        return err;
@@ -1229,7 +1238,7 @@ COMPAT_SYSCALL_DEFINE5(msgrcv, int, msqid, compat_uptr_t, msgp,
 }
 #endif
 
-int msg_init_ns(struct ipc_namespace *ns)
+void msg_init_ns(struct ipc_namespace *ns)
 {
        ns->msg_ctlmax = MSGMAX;
        ns->msg_ctlmnb = MSGMNB;
@@ -1237,7 +1246,7 @@ int msg_init_ns(struct ipc_namespace *ns)
 
        atomic_set(&ns->msg_bytes, 0);
        atomic_set(&ns->msg_hdrs, 0);
-       return ipc_init_ids(&ns->ids[IPC_MSG_IDS]);
+       ipc_init_ids(&ns->ids[IPC_MSG_IDS]);
 }
 
 #ifdef CONFIG_IPC_NS
@@ -1278,12 +1287,11 @@ static int sysvipc_msg_proc_show(struct seq_file *s, void *it)
 }
 #endif
 
-int __init msg_init(void)
+void __init msg_init(void)
 {
-       const int err = msg_init_ns(&init_ipc_ns);
+       msg_init_ns(&init_ipc_ns);
 
        ipc_init_proc_interface("sysvipc/msg",
                                "       key      msqid perms      cbytes       qnum lspid lrpid   uid   gid  cuid  cgid      stime      rtime      ctime\n",
                                IPC_MSG_IDS, sysvipc_msg_proc_show);
-       return err;
 }
index f59a899..2160779 100644 (file)
@@ -55,28 +55,16 @@ static struct ipc_namespace *create_ipc_ns(struct user_namespace *user_ns,
        ns->user_ns = get_user_ns(user_ns);
        ns->ucounts = ucounts;
 
-       err = sem_init_ns(ns);
+       err = mq_init_ns(ns);
        if (err)
                goto fail_put;
-       err = msg_init_ns(ns);
-       if (err)
-               goto fail_destroy_sem;
-       err = shm_init_ns(ns);
-       if (err)
-               goto fail_destroy_msg;
 
-       err = mq_init_ns(ns);
-       if (err)
-               goto fail_destroy_shm;
+       sem_init_ns(ns);
+       msg_init_ns(ns);
+       shm_init_ns(ns);
 
        return ns;
 
-fail_destroy_shm:
-       shm_exit_ns(ns);
-fail_destroy_msg:
-       msg_exit_ns(ns);
-fail_destroy_sem:
-       sem_exit_ns(ns);
 fail_put:
        put_user_ns(ns->user_ns);
        ns_free_inum(&ns->ns);
index 00ef2f7..26f8e37 100644 (file)
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -221,14 +221,14 @@ static int sysvipc_sem_proc_show(struct seq_file *s, void *it);
 #define sc_semopm      sem_ctls[2]
 #define sc_semmni      sem_ctls[3]
 
-int sem_init_ns(struct ipc_namespace *ns)
+void sem_init_ns(struct ipc_namespace *ns)
 {
        ns->sc_semmsl = SEMMSL;
        ns->sc_semmns = SEMMNS;
        ns->sc_semopm = SEMOPM;
        ns->sc_semmni = SEMMNI;
        ns->used_sems = 0;
-       return ipc_init_ids(&ns->ids[IPC_SEM_IDS]);
+       ipc_init_ids(&ns->ids[IPC_SEM_IDS]);
 }
 
 #ifdef CONFIG_IPC_NS
@@ -240,14 +240,12 @@ void sem_exit_ns(struct ipc_namespace *ns)
 }
 #endif
 
-int __init sem_init(void)
+void __init sem_init(void)
 {
-       const int err = sem_init_ns(&init_ipc_ns);
-
+       sem_init_ns(&init_ipc_ns);
        ipc_init_proc_interface("sysvipc/sem",
                                "       key      semid perms      nsems   uid   gid  cuid  cgid      otime      ctime\n",
                                IPC_SEM_IDS, sysvipc_sem_proc_show);
-       return err;
 }
 
 /**
@@ -557,7 +555,7 @@ static int newary(struct ipc_namespace *ns, struct ipc_params *params)
        /* ipc_addid() locks sma upon success. */
        retval = ipc_addid(&sem_ids(ns), &sma->sem_perm, ns->sc_semmni);
        if (retval < 0) {
-               call_rcu(&sma->sem_perm.rcu, sem_rcu_free);
+               ipc_rcu_putref(&sma->sem_perm, sem_rcu_free);
                return retval;
        }
        ns->used_sems += nsems;
@@ -1223,7 +1221,6 @@ static int semctl_stat(struct ipc_namespace *ns, int semid,
 {
        struct sem_array *sma;
        time64_t semotime;
-       int id = 0;
        int err;
 
        memset(semid64, 0, sizeof(*semid64));
@@ -1235,7 +1232,6 @@ static int semctl_stat(struct ipc_namespace *ns, int semid,
                        err = PTR_ERR(sma);
                        goto out_unlock;
                }
-               id = sma->sem_perm.id;
        } else { /* IPC_STAT */
                sma = sem_obtain_object_check(ns, semid);
                if (IS_ERR(sma)) {
@@ -1275,10 +1271,20 @@ static int semctl_stat(struct ipc_namespace *ns, int semid,
 #endif
        semid64->sem_nsems = sma->sem_nsems;
 
+       if (cmd == IPC_STAT) {
+               /*
+                * As defined in SUS:
+                * Return 0 on success
+                */
+               err = 0;
+       } else {
+               /*
+                * SEM_STAT and SEM_STAT_ANY (both Linux specific)
+                * Return the full id, including the sequence number
+                */
+               err = sma->sem_perm.id;
+       }
        ipc_unlock_object(&sma->sem_perm);
-       rcu_read_unlock();
-       return id;
-
 out_unlock:
        rcu_read_unlock();
        return err;
@@ -1288,7 +1294,7 @@ static int semctl_info(struct ipc_namespace *ns, int semid,
                         int cmd, void __user *p)
 {
        struct seminfo seminfo;
-       int max_id;
+       int max_idx;
        int err;
 
        err = security_sem_semctl(NULL, cmd);
@@ -1312,11 +1318,11 @@ static int semctl_info(struct ipc_namespace *ns, int semid,
                seminfo.semusz = SEMUSZ;
                seminfo.semaem = SEMAEM;
        }
-       max_id = ipc_get_maxid(&sem_ids(ns));
+       max_idx = ipc_get_maxidx(&sem_ids(ns));
        up_read(&sem_ids(ns).rwsem);
        if (copy_to_user(p, &seminfo, sizeof(struct seminfo)))
                return -EFAULT;
-       return (max_id < 0) ? 0 : max_id;
+       return (max_idx < 0) ? 0 : max_idx;
 }
 
 static int semctl_setval(struct ipc_namespace *ns, int semid, int semnum,
@@ -1588,7 +1594,7 @@ static int semctl_down(struct ipc_namespace *ns, int semid,
        down_write(&sem_ids(ns).rwsem);
        rcu_read_lock();
 
-       ipcp = ipcctl_pre_down_nolock(ns, &sem_ids(ns), semid, cmd,
+       ipcp = ipcctl_obtain_check(ns, &sem_ids(ns), semid, cmd,
                                      &semid64->sem_perm, 0);
        if (IS_ERR(ipcp)) {
                err = PTR_ERR(ipcp);
index b204feb..b0eb375 100644 (file)
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -96,14 +96,14 @@ static void shm_destroy(struct ipc_namespace *ns, struct shmid_kernel *shp);
 static int sysvipc_shm_proc_show(struct seq_file *s, void *it);
 #endif
 
-int shm_init_ns(struct ipc_namespace *ns)
+void shm_init_ns(struct ipc_namespace *ns)
 {
        ns->shm_ctlmax = SHMMAX;
        ns->shm_ctlall = SHMALL;
        ns->shm_ctlmni = SHMMNI;
        ns->shm_rmid_forced = 0;
        ns->shm_tot = 0;
-       return ipc_init_ids(&shm_ids(ns));
+       ipc_init_ids(&shm_ids(ns));
 }
 
 /*
@@ -136,9 +136,8 @@ void shm_exit_ns(struct ipc_namespace *ns)
 
 static int __init ipc_ns_init(void)
 {
-       const int err = shm_init_ns(&init_ipc_ns);
-       WARN(err, "ipc: sysv shm_init_ns failed: %d\n", err);
-       return err;
+       shm_init_ns(&init_ipc_ns);
+       return 0;
 }
 
 pure_initcall(ipc_ns_init);
@@ -180,16 +179,33 @@ static inline struct shmid_kernel *shm_obtain_object_check(struct ipc_namespace
  */
 static inline struct shmid_kernel *shm_lock(struct ipc_namespace *ns, int id)
 {
-       struct kern_ipc_perm *ipcp = ipc_lock(&shm_ids(ns), id);
+       struct kern_ipc_perm *ipcp;
+
+       rcu_read_lock();
+       ipcp = ipc_obtain_object_idr(&shm_ids(ns), id);
+       if (IS_ERR(ipcp))
+               goto err;
 
+       ipc_lock_object(ipcp);
+       /*
+        * ipc_rmid() may have already freed the ID while ipc_lock_object()
+        * was spinning: here verify that the structure is still valid.
+        * Upon races with RMID, return -EIDRM, thus indicating that
+        * the ID points to a removed identifier.
+        */
+       if (ipc_valid_object(ipcp)) {
+               /* return a locked ipc object upon success */
+               return container_of(ipcp, struct shmid_kernel, shm_perm);
+       }
+
+       ipc_unlock_object(ipcp);
+err:
+       rcu_read_unlock();
        /*
         * Callers of shm_lock() must validate the status of the returned ipc
-        * object pointer (as returned by ipc_lock()), and error out as
-        * appropriate.
+        * object pointer and error out as appropriate.
         */
-       if (IS_ERR(ipcp))
-               return (void *)ipcp;
-       return container_of(ipcp, struct shmid_kernel, shm_perm);
+       return (void *)ipcp;
 }
 
 static inline void shm_lock_by_ptr(struct shmid_kernel *ipcp)
@@ -684,6 +700,8 @@ no_id:
        if (is_file_hugepages(file) && shp->mlock_user)
                user_shm_unlock(size, shp->mlock_user);
        fput(file);
+       ipc_rcu_putref(&shp->shm_perm, shm_rcu_free);
+       return error;
 no_file:
        call_rcu(&shp->shm_perm.rcu, shm_rcu_free);
        return error;
@@ -879,7 +897,7 @@ static int shmctl_down(struct ipc_namespace *ns, int shmid, int cmd,
        down_write(&shm_ids(ns).rwsem);
        rcu_read_lock();
 
-       ipcp = ipcctl_pre_down_nolock(ns, &shm_ids(ns), shmid, cmd,
+       ipcp = ipcctl_obtain_check(ns, &shm_ids(ns), shmid, cmd,
                                      &shmid64->shm_perm, 0);
        if (IS_ERR(ipcp)) {
                err = PTR_ERR(ipcp);
@@ -930,7 +948,7 @@ static int shmctl_ipc_info(struct ipc_namespace *ns,
                shminfo->shmall = ns->shm_ctlall;
                shminfo->shmmin = SHMMIN;
                down_read(&shm_ids(ns).rwsem);
-               err = ipc_get_maxid(&shm_ids(ns));
+               err = ipc_get_maxidx(&shm_ids(ns));
                up_read(&shm_ids(ns).rwsem);
                if (err < 0)
                        err = 0;
@@ -950,7 +968,7 @@ static int shmctl_shm_info(struct ipc_namespace *ns,
                shm_info->shm_tot = ns->shm_tot;
                shm_info->swap_attempts = 0;
                shm_info->swap_successes = 0;
-               err = ipc_get_maxid(&shm_ids(ns));
+               err = ipc_get_maxidx(&shm_ids(ns));
                up_read(&shm_ids(ns).rwsem);
                if (err < 0)
                        err = 0;
@@ -962,7 +980,6 @@ static int shmctl_stat(struct ipc_namespace *ns, int shmid,
                        int cmd, struct shmid64_ds *tbuf)
 {
        struct shmid_kernel *shp;
-       int id = 0;
        int err;
 
        memset(tbuf, 0, sizeof(*tbuf));
@@ -974,7 +991,6 @@ static int shmctl_stat(struct ipc_namespace *ns, int shmid,
                        err = PTR_ERR(shp);
                        goto out_unlock;
                }
-               id = shp->shm_perm.id;
        } else { /* IPC_STAT */
                shp = shm_obtain_object_check(ns, shmid);
                if (IS_ERR(shp)) {
@@ -1024,10 +1040,21 @@ static int shmctl_stat(struct ipc_namespace *ns, int shmid,
        tbuf->shm_lpid  = pid_vnr(shp->shm_lprid);
        tbuf->shm_nattch = shp->shm_nattch;
 
-       ipc_unlock_object(&shp->shm_perm);
-       rcu_read_unlock();
-       return id;
+       if (cmd == IPC_STAT) {
+               /*
+                * As defined in SUS:
+                * Return 0 on success
+                */
+               err = 0;
+       } else {
+               /*
+                * SHM_STAT and SHM_STAT_ANY (both Linux specific)
+                * Return the full id, including the sequence number
+                */
+               err = shp->shm_perm.id;
+       }
 
+       ipc_unlock_object(&shp->shm_perm);
 out_unlock:
        rcu_read_unlock();
        return err;
index fdffff4..0af0575 100644 (file)
@@ -88,16 +88,12 @@ struct ipc_proc_iface {
  */
 static int __init ipc_init(void)
 {
-       int err_sem, err_msg;
-
        proc_mkdir("sysvipc", NULL);
-       err_sem = sem_init();
-       WARN(err_sem, "ipc: sysv sem_init failed: %d\n", err_sem);
-       err_msg = msg_init();
-       WARN(err_msg, "ipc: sysv msg_init failed: %d\n", err_msg);
+       sem_init();
+       msg_init();
        shm_init();
 
-       return err_msg ? err_msg : err_sem;
+       return 0;
 }
 device_initcall(ipc_init);
 
@@ -116,22 +112,17 @@ static const struct rhashtable_params ipc_kht_params = {
  * Set up the sequence range to use for the ipc identifier range (limited
  * below IPCMNI) then initialise the keys hashtable and ids idr.
  */
-int ipc_init_ids(struct ipc_ids *ids)
+void ipc_init_ids(struct ipc_ids *ids)
 {
-       int err;
        ids->in_use = 0;
        ids->seq = 0;
        init_rwsem(&ids->rwsem);
-       err = rhashtable_init(&ids->key_ht, &ipc_kht_params);
-       if (err)
-               return err;
+       rhashtable_init(&ids->key_ht, &ipc_kht_params);
        idr_init(&ids->ipcs_idr);
-       ids->tables_initialized = true;
-       ids->max_id = -1;
+       ids->max_idx = -1;
 #ifdef CONFIG_CHECKPOINT_RESTORE
        ids->next_id = -1;
 #endif
-       return 0;
 }
 
 #ifdef CONFIG_PROC_FS
@@ -179,61 +170,66 @@ void __init ipc_init_proc_interface(const char *path, const char *header,
  */
 static struct kern_ipc_perm *ipc_findkey(struct ipc_ids *ids, key_t key)
 {
-       struct kern_ipc_perm *ipcp = NULL;
+       struct kern_ipc_perm *ipcp;
 
-       if (likely(ids->tables_initialized))
-               ipcp = rhashtable_lookup_fast(&ids->key_ht, &key,
+       ipcp = rhashtable_lookup_fast(&ids->key_ht, &key,
                                              ipc_kht_params);
+       if (!ipcp)
+               return NULL;
 
-       if (ipcp) {
-               rcu_read_lock();
-               ipc_lock_object(ipcp);
-               return ipcp;
-       }
-
-       return NULL;
+       rcu_read_lock();
+       ipc_lock_object(ipcp);
+       return ipcp;
 }
 
-#ifdef CONFIG_CHECKPOINT_RESTORE
 /*
- * Specify desired id for next allocated IPC object.
+ * Insert new IPC object into idr tree, and set sequence number and id
+ * in the correct order.
+ * Especially:
+ * - the sequence number must be set before inserting the object into the idr,
+ *   because the sequence number is accessed without a lock.
+ * - the id can/must be set after inserting the object into the idr.
+ *   All accesses must be done after getting kern_ipc_perm.lock.
+ *
+ * The caller must own kern_ipc_perm.lock.of the new object.
+ * On error, the function returns a (negative) error code.
  */
-#define ipc_idr_alloc(ids, new)                                                \
-       idr_alloc(&(ids)->ipcs_idr, (new),                              \
-                 (ids)->next_id < 0 ? 0 : ipcid_to_idx((ids)->next_id),\
-                 0, GFP_NOWAIT)
-
-static inline int ipc_buildid(int id, struct ipc_ids *ids,
-                             struct kern_ipc_perm *new)
+static inline int ipc_idr_alloc(struct ipc_ids *ids, struct kern_ipc_perm *new)
 {
-       if (ids->next_id < 0) { /* default, behave as !CHECKPOINT_RESTORE */
+       int idx, next_id = -1;
+
+#ifdef CONFIG_CHECKPOINT_RESTORE
+       next_id = ids->next_id;
+       ids->next_id = -1;
+#endif
+
+       /*
+        * As soon as a new object is inserted into the idr,
+        * ipc_obtain_object_idr() or ipc_obtain_object_check() can find it,
+        * and the lockless preparations for ipc operations can start.
+        * This means especially: permission checks, audit calls, allocation
+        * of undo structures, ...
+        *
+        * Thus the object must be fully initialized, and if something fails,
+        * then the full tear-down sequence must be followed.
+        * (i.e.: set new->deleted, reduce refcount, call_rcu())
+        */
+
+       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);
        } else {
-               new->seq = ipcid_to_seqx(ids->next_id);
-               ids->next_id = -1;
+               new->seq = ipcid_to_seqx(next_id);
+               idx = idr_alloc(&ids->ipcs_idr, new, ipcid_to_idx(next_id),
+                               0, GFP_NOWAIT);
        }
-
-       return SEQ_MULTIPLIER * new->seq + id;
+       if (idx >= 0)
+               new->id = SEQ_MULTIPLIER * new->seq + idx;
+       return idx;
 }
 
-#else
-#define ipc_idr_alloc(ids, new)                                        \
-       idr_alloc(&(ids)->ipcs_idr, (new), 0, 0, GFP_NOWAIT)
-
-static inline int ipc_buildid(int id, struct ipc_ids *ids,
-                             struct kern_ipc_perm *new)
-{
-       new->seq = ids->seq++;
-       if (ids->seq > IPCID_SEQ_MAX)
-               ids->seq = 0;
-
-       return SEQ_MULTIPLIER * new->seq + id;
-}
-
-#endif /* CONFIG_CHECKPOINT_RESTORE */
-
 /**
  * ipc_addid - add an ipc identifier
  * @ids: ipc identifier set
@@ -241,9 +237,11 @@ static inline int ipc_buildid(int id, struct ipc_ids *ids,
  * @limit: limit for the number of used ids
  *
  * Add an entry 'new' to the ipc ids idr. The permissions object is
- * initialised and the first free entry is set up and the id assigned
+ * initialised and the first free entry is set up and the index assigned
  * is returned. The 'new' entry is returned in a locked state on success.
+ *
  * On failure the entry is not locked and a negative err-code is returned.
+ * The caller must use ipc_rcu_putref() to free the identifier.
  *
  * Called with writer ipc_ids.rwsem held.
  */
@@ -251,19 +249,20 @@ int ipc_addid(struct ipc_ids *ids, struct kern_ipc_perm *new, int limit)
 {
        kuid_t euid;
        kgid_t egid;
-       int id, err;
+       int idx, err;
+
+       /* 1) Initialize the refcount so that ipc_rcu_putref works */
+       refcount_set(&new->refcount, 1);
 
        if (limit > IPCMNI)
                limit = IPCMNI;
 
-       if (!ids->tables_initialized || ids->in_use >= limit)
+       if (ids->in_use >= limit)
                return -ENOSPC;
 
        idr_preload(GFP_KERNEL);
 
-       refcount_set(&new->refcount, 1);
        spin_lock_init(&new->lock);
-       new->deleted = false;
        rcu_read_lock();
        spin_lock(&new->lock);
 
@@ -271,30 +270,30 @@ int ipc_addid(struct ipc_ids *ids, struct kern_ipc_perm *new, int limit)
        new->cuid = new->uid = euid;
        new->gid = new->cgid = egid;
 
-       id = ipc_idr_alloc(ids, new);
+       new->deleted = false;
+
+       idx = ipc_idr_alloc(ids, new);
        idr_preload_end();
 
-       if (id >= 0 && new->key != IPC_PRIVATE) {
+       if (idx >= 0 && new->key != IPC_PRIVATE) {
                err = rhashtable_insert_fast(&ids->key_ht, &new->khtnode,
                                             ipc_kht_params);
                if (err < 0) {
-                       idr_remove(&ids->ipcs_idr, id);
-                       id = err;
+                       idr_remove(&ids->ipcs_idr, idx);
+                       idx = err;
                }
        }
-       if (id < 0) {
+       if (idx < 0) {
+               new->deleted = true;
                spin_unlock(&new->lock);
                rcu_read_unlock();
-               return id;
+               return idx;
        }
 
        ids->in_use++;
-       if (id > ids->max_id)
-               ids->max_id = id;
-
-       new->id = ipc_buildid(id, ids, new);
-
-       return id;
+       if (idx > ids->max_idx)
+               ids->max_idx = idx;
+       return idx;
 }
 
 /**
@@ -432,20 +431,20 @@ static void ipc_kht_remove(struct ipc_ids *ids, struct kern_ipc_perm *ipcp)
  */
 void ipc_rmid(struct ipc_ids *ids, struct kern_ipc_perm *ipcp)
 {
-       int lid = ipcid_to_idx(ipcp->id);
+       int idx = ipcid_to_idx(ipcp->id);
 
-       idr_remove(&ids->ipcs_idr, lid);
+       idr_remove(&ids->ipcs_idr, idx);
        ipc_kht_remove(ids, ipcp);
        ids->in_use--;
        ipcp->deleted = true;
 
-       if (unlikely(lid == ids->max_id)) {
+       if (unlikely(idx == ids->max_idx)) {
                do {
-                       lid--;
-                       if (lid == -1)
+                       idx--;
+                       if (idx == -1)
                                break;
-               } while (!idr_find(&ids->ipcs_idr, lid));
-               ids->max_id = lid;
+               } while (!idr_find(&ids->ipcs_idr, idx));
+               ids->max_idx = idx;
        }
 }
 
@@ -463,7 +462,7 @@ void ipc_set_key_private(struct ipc_ids *ids, struct kern_ipc_perm *ipcp)
        ipcp->key = IPC_PRIVATE;
 }
 
-int ipc_rcu_getref(struct kern_ipc_perm *ptr)
+bool ipc_rcu_getref(struct kern_ipc_perm *ptr)
 {
        return refcount_inc_not_zero(&ptr->refcount);
 }
@@ -565,12 +564,9 @@ void ipc64_perm_to_ipc_perm(struct ipc64_perm *in, struct ipc_perm *out)
 struct kern_ipc_perm *ipc_obtain_object_idr(struct ipc_ids *ids, int id)
 {
        struct kern_ipc_perm *out;
-       int lid = ipcid_to_idx(id);
-
-       if (unlikely(!ids->tables_initialized))
-               return ERR_PTR(-EINVAL);
+       int idx = ipcid_to_idx(id);
 
-       out = idr_find(&ids->ipcs_idr, lid);
+       out = idr_find(&ids->ipcs_idr, idx);
        if (!out)
                return ERR_PTR(-EINVAL);
 
@@ -578,48 +574,12 @@ struct kern_ipc_perm *ipc_obtain_object_idr(struct ipc_ids *ids, int id)
 }
 
 /**
- * ipc_lock - lock an ipc structure without rwsem held
- * @ids: ipc identifier set
- * @id: ipc id to look for
- *
- * Look for an id in the ipc ids idr and lock the associated ipc object.
- *
- * The ipc object is locked on successful exit.
- */
-struct kern_ipc_perm *ipc_lock(struct ipc_ids *ids, int id)
-{
-       struct kern_ipc_perm *out;
-
-       rcu_read_lock();
-       out = ipc_obtain_object_idr(ids, id);
-       if (IS_ERR(out))
-               goto err;
-
-       spin_lock(&out->lock);
-
-       /*
-        * ipc_rmid() may have already freed the ID while ipc_lock()
-        * was spinning: here verify that the structure is still valid.
-        * Upon races with RMID, return -EIDRM, thus indicating that
-        * the ID points to a removed identifier.
-        */
-       if (ipc_valid_object(out))
-               return out;
-
-       spin_unlock(&out->lock);
-       out = ERR_PTR(-EIDRM);
-err:
-       rcu_read_unlock();
-       return out;
-}
-
-/**
  * ipc_obtain_object_check
  * @ids: ipc identifier set
  * @id: ipc id to look for
  *
- * Similar to ipc_obtain_object_idr() but also checks
- * the ipc object reference counter.
+ * Similar to ipc_obtain_object_idr() but also checks the ipc object
+ * sequence number.
  *
  * Call inside the RCU critical section.
  * The ipc object is *not* locked on exit.
@@ -677,7 +637,7 @@ int ipc_update_perm(struct ipc64_perm *in, struct kern_ipc_perm *out)
 }
 
 /**
- * ipcctl_pre_down_nolock - retrieve an ipc and check permissions for some IPC_XXX cmd
+ * ipcctl_obtain_check - retrieve an ipc object and check permissions
  * @ns:  ipc namespace
  * @ids:  the table of ids where to look for the ipc
  * @id:   the id of the ipc to retrieve
@@ -687,16 +647,16 @@ int ipc_update_perm(struct ipc64_perm *in, struct kern_ipc_perm *out)
  *
  * This function does some common audit and permissions check for some IPC_XXX
  * cmd and is called from semctl_down, shmctl_down and msgctl_down.
- * It must be called without any lock held and:
  *
- *   - retrieves the ipc with the given id in the given table.
+ * It:
+ *   - retrieves the ipc object with the given id in the given table.
  *   - performs some audit and permission check, depending on the given cmd
  *   - returns a pointer to the ipc object or otherwise, the corresponding
  *     error.
  *
  * Call holding the both the rwsem and the rcu read lock.
  */
-struct kern_ipc_perm *ipcctl_pre_down_nolock(struct ipc_namespace *ns,
+struct kern_ipc_perm *ipcctl_obtain_check(struct ipc_namespace *ns,
                                        struct ipc_ids *ids, int id, int cmd,
                                        struct ipc64_perm *perm, int extra_perm)
 {
index 0aba323..0a159f6 100644 (file)
@@ -18,8 +18,8 @@
 #define IPCMNI 32768  /* <= MAX_INT limit for ipc arrays (including sysctl changes) */
 #define SEQ_MULTIPLIER (IPCMNI)
 
-int sem_init(void);
-int msg_init(void);
+void sem_init(void);
+void msg_init(void);
 void shm_init(void);
 
 struct ipc_namespace;
@@ -34,17 +34,17 @@ static inline void mq_put_mnt(struct ipc_namespace *ns) { }
 #endif
 
 #ifdef CONFIG_SYSVIPC
-int sem_init_ns(struct ipc_namespace *ns);
-int msg_init_ns(struct ipc_namespace *ns);
-int shm_init_ns(struct ipc_namespace *ns);
+void sem_init_ns(struct ipc_namespace *ns);
+void msg_init_ns(struct ipc_namespace *ns);
+void shm_init_ns(struct ipc_namespace *ns);
 
 void sem_exit_ns(struct ipc_namespace *ns);
 void msg_exit_ns(struct ipc_namespace *ns);
 void shm_exit_ns(struct ipc_namespace *ns);
 #else
-static inline int sem_init_ns(struct ipc_namespace *ns) { return 0; }
-static inline int msg_init_ns(struct ipc_namespace *ns) { return 0; }
-static inline int shm_init_ns(struct ipc_namespace *ns) { return 0; }
+static inline void sem_init_ns(struct ipc_namespace *ns) { }
+static inline void msg_init_ns(struct ipc_namespace *ns) { }
+static inline void shm_init_ns(struct ipc_namespace *ns) { }
 
 static inline void sem_exit_ns(struct ipc_namespace *ns) { }
 static inline void msg_exit_ns(struct ipc_namespace *ns) { }
@@ -83,7 +83,7 @@ struct ipc_ops {
 struct seq_file;
 struct ipc_ids;
 
-int ipc_init_ids(struct ipc_ids *);
+void ipc_init_ids(struct ipc_ids *ids);
 #ifdef CONFIG_PROC_FS
 void __init ipc_init_proc_interface(const char *path, const char *header,
                int ids, int (*show)(struct seq_file *, void *));
@@ -113,12 +113,12 @@ void ipc_set_key_private(struct ipc_ids *, struct kern_ipc_perm *);
 int ipcperms(struct ipc_namespace *ns, struct kern_ipc_perm *ipcp, short flg);
 
 /**
- * ipc_get_maxid - get the last assigned id
+ * ipc_get_maxidx - get the highest assigned index
  * @ids: ipc identifier set
  *
  * Called with ipc_ids.rwsem held for reading.
  */
-static inline int ipc_get_maxid(struct ipc_ids *ids)
+static inline int ipc_get_maxidx(struct ipc_ids *ids)
 {
        if (ids->in_use == 0)
                return -1;
@@ -126,7 +126,7 @@ static inline int ipc_get_maxid(struct ipc_ids *ids)
        if (ids->in_use == IPCMNI)
                return IPCMNI - 1;
 
-       return ids->max_id;
+       return ids->max_idx;
 }
 
 /*
@@ -138,17 +138,16 @@ static inline int ipc_get_maxid(struct ipc_ids *ids)
  * refcount is initialized by ipc_addid(), before that point call_rcu()
  * must be used.
  */
-int ipc_rcu_getref(struct kern_ipc_perm *ptr);
+bool ipc_rcu_getref(struct kern_ipc_perm *ptr);
 void ipc_rcu_putref(struct kern_ipc_perm *ptr,
                        void (*func)(struct rcu_head *head));
 
-struct kern_ipc_perm *ipc_lock(struct ipc_ids *, int);
 struct kern_ipc_perm *ipc_obtain_object_idr(struct ipc_ids *ids, int id);
 
 void kernel_to_ipc64_perm(struct kern_ipc_perm *in, struct ipc64_perm *out);
 void ipc64_perm_to_ipc_perm(struct ipc64_perm *in, struct ipc_perm *out);
 int ipc_update_perm(struct ipc64_perm *in, struct kern_ipc_perm *out);
-struct kern_ipc_perm *ipcctl_pre_down_nolock(struct ipc_namespace *ns,
+struct kern_ipc_perm *ipcctl_obtain_check(struct ipc_namespace *ns,
                                             struct ipc_ids *ids, int id, int cmd,
                                             struct ipc64_perm *perm, int extra_perm);
 
@@ -173,9 +172,9 @@ extern struct msg_msg *load_msg(const void __user *src, size_t len);
 extern struct msg_msg *copy_msg(struct msg_msg *src, struct msg_msg *dst);
 extern int store_msg(void __user *dest, struct msg_msg *msg, size_t len);
 
-static inline int ipc_checkid(struct kern_ipc_perm *ipcp, int uid)
+static inline int ipc_checkid(struct kern_ipc_perm *ipcp, int id)
 {
-       return uid / SEQ_MULTIPLIER != ipcp->seq;
+       return ipcid_to_seqx(id) != ipcp->seq;
 }
 
 static inline void ipc_lock_object(struct kern_ipc_perm *perm)
index 77ff1cd..75568fc 100644 (file)
@@ -8,6 +8,32 @@
 #include <linux/list.h>
 #include <linux/refcount.h>
 
+#define TRACE_CGROUP_PATH_LEN 1024
+extern spinlock_t trace_cgroup_path_lock;
+extern char trace_cgroup_path[TRACE_CGROUP_PATH_LEN];
+
+/*
+ * cgroup_path() takes a spin lock. It is good practice not to take
+ * spin locks within trace point handlers, as they are mostly hidden
+ * from normal view. As cgroup_path() can take the kernfs_rename_lock
+ * spin lock, it is best to not call that function from the trace event
+ * handler.
+ *
+ * Note: trace_cgroup_##type##_enabled() is a static branch that will only
+ *       be set when the trace event is enabled.
+ */
+#define TRACE_CGROUP_PATH(type, cgrp, ...)                             \
+       do {                                                            \
+               if (trace_cgroup_##type##_enabled()) {                  \
+                       spin_lock(&trace_cgroup_path_lock);             \
+                       cgroup_path(cgrp, trace_cgroup_path,            \
+                                   TRACE_CGROUP_PATH_LEN);             \
+                       trace_cgroup_##type(cgrp, trace_cgroup_path,    \
+                                           ##__VA_ARGS__);             \
+                       spin_unlock(&trace_cgroup_path_lock);           \
+               }                                                       \
+       } while (0)
+
 /*
  * A cgroup can be associated with multiple css_sets as different tasks may
  * belong to different cgroups on different hierarchies.  In the other
index 8b4f076..51063e7 100644 (file)
@@ -135,7 +135,7 @@ int cgroup_transfer_tasks(struct cgroup *to, struct cgroup *from)
                if (task) {
                        ret = cgroup_migrate(task, false, &mgctx);
                        if (!ret)
-                               trace_cgroup_transfer_tasks(to, task, false);
+                               TRACE_CGROUP_PATH(transfer_tasks, to, task, false);
                        put_task_struct(task);
                }
        } while (task && !ret);
@@ -865,7 +865,7 @@ static int cgroup1_rename(struct kernfs_node *kn, struct kernfs_node *new_parent
 
        ret = kernfs_rename(kn, new_parent, new_name_str);
        if (!ret)
-               trace_cgroup_rename(cgrp);
+               TRACE_CGROUP_PATH(rename, cgrp);
 
        mutex_unlock(&cgroup_mutex);
 
index 35cf3d7..aae10ba 100644 (file)
@@ -83,6 +83,9 @@ EXPORT_SYMBOL_GPL(cgroup_mutex);
 EXPORT_SYMBOL_GPL(css_set_lock);
 #endif
 
+DEFINE_SPINLOCK(trace_cgroup_path_lock);
+char trace_cgroup_path[TRACE_CGROUP_PATH_LEN];
+
 /*
  * Protects cgroup_idr and css_idr so that IDs can be released without
  * grabbing cgroup_mutex.
@@ -2638,7 +2641,7 @@ int cgroup_attach_task(struct cgroup *dst_cgrp, struct task_struct *leader,
        cgroup_migrate_finish(&mgctx);
 
        if (!ret)
-               trace_cgroup_attach_task(dst_cgrp, leader, threadgroup);
+               TRACE_CGROUP_PATH(attach_task, dst_cgrp, leader, threadgroup);
 
        return ret;
 }
@@ -4636,7 +4639,7 @@ static void css_release_work_fn(struct work_struct *work)
                struct cgroup *tcgrp;
 
                /* cgroup release path */
-               trace_cgroup_release(cgrp);
+               TRACE_CGROUP_PATH(release, cgrp);
 
                if (cgroup_on_dfl(cgrp))
                        cgroup_rstat_flush(cgrp);
@@ -4979,7 +4982,7 @@ int cgroup_mkdir(struct kernfs_node *parent_kn, const char *name, umode_t mode)
        if (ret)
                goto out_destroy;
 
-       trace_cgroup_mkdir(cgrp);
+       TRACE_CGROUP_PATH(mkdir, cgrp);
 
        /* let's create and online css's */
        kernfs_activate(kn);
@@ -5167,9 +5170,8 @@ int cgroup_rmdir(struct kernfs_node *kn)
                return 0;
 
        ret = cgroup_destroy_locked(cgrp);
-
        if (!ret)
-               trace_cgroup_rmdir(cgrp);
+               TRACE_CGROUP_PATH(rmdir, cgrp);
 
        cgroup_kn_unlock(kn);
        return ret;
index b66aced..933cb3e 100644 (file)
@@ -14,8 +14,8 @@
 #include <asm/sections.h>
 
 /* vmcoreinfo stuff */
-static unsigned char *vmcoreinfo_data;
-static size_t vmcoreinfo_size;
+unsigned char *vmcoreinfo_data;
+size_t vmcoreinfo_size;
 u32 *vmcoreinfo_note;
 
 /* trusted vmcoreinfo, e.g. we can make a copy in the crash memory */
@@ -344,7 +344,7 @@ void crash_save_vmcoreinfo(void)
        if (vmcoreinfo_data_safecopy)
                vmcoreinfo_data = vmcoreinfo_data_safecopy;
 
-       vmcoreinfo_append_str("CRASHTIME=%ld\n", get_seconds());
+       vmcoreinfo_append_str("CRASHTIME=%lld\n", ktime_get_real_seconds());
        update_vmcoreinfo_note();
 }
 
@@ -401,7 +401,7 @@ static int __init crash_save_vmcoreinfo_init(void)
        VMCOREINFO_SYMBOL(init_uts_ns);
        VMCOREINFO_SYMBOL(node_online_map);
 #ifdef CONFIG_MMU
-       VMCOREINFO_SYMBOL(swapper_pg_dir);
+       VMCOREINFO_SYMBOL_ARRAY(swapper_pg_dir);
 #endif
        VMCOREINFO_SYMBOL(_stext);
        VMCOREINFO_SYMBOL(vmap_area_list);
index c187aa3..24a77c3 100644 (file)
@@ -4,7 +4,7 @@
  *  Copyright (C) 2008 Thomas Gleixner <tglx@linutronix.de>
  *  Copyright (C) 2008-2011 Red Hat, Inc., Ingo Molnar
  *  Copyright (C) 2008-2011 Red Hat, Inc., Peter Zijlstra
- *  Copyright  ©  2009 Paul Mackerras, IBM Corp. <paulus@au1.ibm.com>
+ *  Copyright  Â©  2009 Paul Mackerras, IBM Corp. <paulus@au1.ibm.com>
  *
  * For licensing details see kernel-base/COPYING
  */
index 80f456e..2a62b96 100644 (file)
@@ -1334,7 +1334,7 @@ static u32 perf_event_pid_type(struct perf_event *event, struct task_struct *p,
 
 static u32 perf_event_pid(struct perf_event *event, struct task_struct *p)
 {
-       return perf_event_pid_type(event, p, __PIDTYPE_TGID);
+       return perf_event_pid_type(event, p, PIDTYPE_TGID);
 }
 
 static u32 perf_event_tid(struct perf_event *event, struct task_struct *p)
index aed1ba5..3207a4d 100644 (file)
@@ -299,8 +299,8 @@ static int verify_opcode(struct page *page, unsigned long vaddr, uprobe_opcode_t
  * Called with mm->mmap_sem held for write.
  * Return 0 (success) or a negative errno.
  */
-int uprobe_write_opcode(struct mm_struct *mm, unsigned long vaddr,
-                       uprobe_opcode_t opcode)
+int uprobe_write_opcode(struct arch_uprobe *auprobe, struct mm_struct *mm,
+                       unsigned long vaddr, uprobe_opcode_t opcode)
 {
        struct page *old_page, *new_page;
        struct vm_area_struct *vma;
@@ -351,7 +351,7 @@ put_old:
  */
 int __weak set_swbp(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long vaddr)
 {
-       return uprobe_write_opcode(mm, vaddr, UPROBE_SWBP_INSN);
+       return uprobe_write_opcode(auprobe, mm, vaddr, UPROBE_SWBP_INSN);
 }
 
 /**
@@ -366,7 +366,8 @@ int __weak set_swbp(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned
 int __weak
 set_orig_insn(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long vaddr)
 {
-       return uprobe_write_opcode(mm, vaddr, *(uprobe_opcode_t *)&auprobe->insn);
+       return uprobe_write_opcode(auprobe, mm, vaddr,
+                       *(uprobe_opcode_t *)&auprobe->insn);
 }
 
 static struct uprobe *get_uprobe(struct uprobe *uprobe)
@@ -840,13 +841,8 @@ register_for_each_vma(struct uprobe *uprobe, struct uprobe_consumer *new)
        return err;
 }
 
-static int __uprobe_register(struct uprobe *uprobe, struct uprobe_consumer *uc)
-{
-       consumer_add(uprobe, uc);
-       return register_for_each_vma(uprobe, uc);
-}
-
-static void __uprobe_unregister(struct uprobe *uprobe, struct uprobe_consumer *uc)
+static void
+__uprobe_unregister(struct uprobe *uprobe, struct uprobe_consumer *uc)
 {
        int err;
 
@@ -860,24 +856,46 @@ static void __uprobe_unregister(struct uprobe *uprobe, struct uprobe_consumer *u
 }
 
 /*
- * uprobe_register - register a probe
+ * uprobe_unregister - unregister an already registered probe.
+ * @inode: the file in which the probe has to be removed.
+ * @offset: offset from the start of the file.
+ * @uc: identify which probe if multiple probes are colocated.
+ */
+void uprobe_unregister(struct inode *inode, loff_t offset, struct uprobe_consumer *uc)
+{
+       struct uprobe *uprobe;
+
+       uprobe = find_uprobe(inode, offset);
+       if (WARN_ON(!uprobe))
+               return;
+
+       down_write(&uprobe->register_rwsem);
+       __uprobe_unregister(uprobe, uc);
+       up_write(&uprobe->register_rwsem);
+       put_uprobe(uprobe);
+}
+EXPORT_SYMBOL_GPL(uprobe_unregister);
+
+/*
+ * __uprobe_register - register a probe
  * @inode: the file in which the probe has to be placed.
  * @offset: offset from the start of the file.
  * @uc: information on howto handle the probe..
  *
- * Apart from the access refcount, uprobe_register() takes a creation
+ * Apart from the access refcount, __uprobe_register() takes a creation
  * refcount (thro alloc_uprobe) if and only if this @uprobe is getting
  * inserted into the rbtree (i.e first consumer for a @inode:@offset
  * tuple).  Creation refcount stops uprobe_unregister from freeing the
  * @uprobe even before the register operation is complete. Creation
  * refcount is released when the last @uc for the @uprobe
- * unregisters. Caller of uprobe_register() is required to keep @inode
+ * unregisters. Caller of __uprobe_register() is required to keep @inode
  * (and the containing mount) referenced.
  *
  * Return errno if it cannot successully install probes
  * else return 0 (success)
  */
-int uprobe_register(struct inode *inode, loff_t offset, struct uprobe_consumer *uc)
+static int __uprobe_register(struct inode *inode, loff_t offset,
+                            struct uprobe_consumer *uc)
 {
        struct uprobe *uprobe;
        int ret;
@@ -904,7 +922,8 @@ int uprobe_register(struct inode *inode, loff_t offset, struct uprobe_consumer *
        down_write(&uprobe->register_rwsem);
        ret = -EAGAIN;
        if (likely(uprobe_is_active(uprobe))) {
-               ret = __uprobe_register(uprobe, uc);
+               consumer_add(uprobe, uc);
+               ret = register_for_each_vma(uprobe, uc);
                if (ret)
                        __uprobe_unregister(uprobe, uc);
        }
@@ -915,6 +934,12 @@ int uprobe_register(struct inode *inode, loff_t offset, struct uprobe_consumer *
                goto retry;
        return ret;
 }
+
+int uprobe_register(struct inode *inode, loff_t offset,
+                   struct uprobe_consumer *uc)
+{
+       return __uprobe_register(inode, offset, uc);
+}
 EXPORT_SYMBOL_GPL(uprobe_register);
 
 /*
@@ -946,27 +971,6 @@ int uprobe_apply(struct inode *inode, loff_t offset,
        return ret;
 }
 
-/*
- * uprobe_unregister - unregister an already registered probe.
- * @inode: the file in which the probe has to be removed.
- * @offset: offset from the start of the file.
- * @uc: identify which probe if multiple probes are colocated.
- */
-void uprobe_unregister(struct inode *inode, loff_t offset, struct uprobe_consumer *uc)
-{
-       struct uprobe *uprobe;
-
-       uprobe = find_uprobe(inode, offset);
-       if (WARN_ON(!uprobe))
-               return;
-
-       down_write(&uprobe->register_rwsem);
-       __uprobe_unregister(uprobe, uc);
-       up_write(&uprobe->register_rwsem);
-       put_uprobe(uprobe);
-}
-EXPORT_SYMBOL_GPL(uprobe_unregister);
-
 static int unapply_uprobe(struct uprobe *uprobe, struct mm_struct *mm)
 {
        struct vm_area_struct *vma;
index c3c7ac5..0e21e6d 100644 (file)
@@ -73,6 +73,7 @@ static void __unhash_process(struct task_struct *p, bool group_dead)
        nr_threads--;
        detach_pid(p, PIDTYPE_PID);
        if (group_dead) {
+               detach_pid(p, PIDTYPE_TGID);
                detach_pid(p, PIDTYPE_PGID);
                detach_pid(p, PIDTYPE_SID);
 
@@ -680,7 +681,8 @@ static void forget_original_parent(struct task_struct *father,
                                t->parent = t->real_parent;
                        if (t->pdeath_signal)
                                group_send_sig_info(t->pdeath_signal,
-                                                   SEND_SIG_NOINFO, t);
+                                                   SEND_SIG_NOINFO, t,
+                                                   PIDTYPE_TGID);
                }
                /*
                 * If this is a threaded reparent there is no need to
@@ -1001,14 +1003,6 @@ struct wait_opts {
        int                     notask_error;
 };
 
-static inline
-struct pid *task_pid_type(struct task_struct *task, enum pid_type type)
-{
-       if (type != PIDTYPE_PID)
-               task = task->group_leader;
-       return task->pids[type].pid;
-}
-
 static int eligible_pid(struct wait_opts *wo, struct task_struct *p)
 {
        return  wo->wo_type == PIDTYPE_MAX ||
index 5ee74c1..d896e9c 100644 (file)
@@ -310,8 +310,9 @@ static struct kmem_cache *mm_cachep;
 
 struct vm_area_struct *vm_area_alloc(struct mm_struct *mm)
 {
-       struct vm_area_struct *vma = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL);
+       struct vm_area_struct *vma;
 
+       vma = kmem_cache_alloc(vm_area_cachep, GFP_KERNEL);
        if (vma)
                vma_init(vma, mm);
        return vma;
@@ -1301,6 +1302,7 @@ static int copy_mm(unsigned long clone_flags, struct task_struct *tsk)
        tsk->nvcsw = tsk->nivcsw = 0;
 #ifdef CONFIG_DETECT_HUNG_TASK
        tsk->last_switch_count = tsk->nvcsw + tsk->nivcsw;
+       tsk->last_switch_time = 0;
 #endif
 
        tsk->mm = NULL;
@@ -1425,7 +1427,9 @@ static int copy_sighand(unsigned long clone_flags, struct task_struct *tsk)
                return -ENOMEM;
 
        atomic_set(&sig->count, 1);
+       spin_lock_irq(&current->sighand->siglock);
        memcpy(sig->action, current->sighand->action, sizeof(sig->action));
+       spin_unlock_irq(&current->sighand->siglock);
        return 0;
 }
 
@@ -1487,6 +1491,7 @@ static int copy_signal(unsigned long clone_flags, struct task_struct *tsk)
        init_waitqueue_head(&sig->wait_chldexit);
        sig->curr_target = tsk;
        init_sigpending(&sig->shared_pending);
+       INIT_HLIST_HEAD(&sig->multiprocess);
        seqlock_init(&sig->stats_lock);
        prev_cputime_init(&sig->prev_cputime);
 
@@ -1580,10 +1585,22 @@ static void posix_cpu_timers_init(struct task_struct *tsk)
 static inline void posix_cpu_timers_init(struct task_struct *tsk) { }
 #endif
 
+static inline void init_task_pid_links(struct task_struct *task)
+{
+       enum pid_type type;
+
+       for (type = PIDTYPE_PID; type < PIDTYPE_MAX; ++type) {
+               INIT_HLIST_NODE(&task->pid_links[type]);
+       }
+}
+
 static inline void
 init_task_pid(struct task_struct *task, enum pid_type type, struct pid *pid)
 {
-        task->pids[type].pid = pid;
+       if (type == PIDTYPE_PID)
+               task->thread_pid = pid;
+       else
+               task->signal->pids[type] = pid;
 }
 
 static inline void rcu_copy_process(struct task_struct *p)
@@ -1621,6 +1638,7 @@ static __latent_entropy struct task_struct *copy_process(
 {
        int retval;
        struct task_struct *p;
+       struct multiprocess_signals delayed;
 
        /*
         * Don't allow sharing the root directory with processes in a different
@@ -1668,6 +1686,24 @@ static __latent_entropy struct task_struct *copy_process(
                        return ERR_PTR(-EINVAL);
        }
 
+       /*
+        * Force any signals received before this point to be delivered
+        * before the fork happens.  Collect up signals sent to multiple
+        * processes that happen during the fork and delay them so that
+        * they appear to happen after the fork.
+        */
+       sigemptyset(&delayed.signal);
+       INIT_HLIST_NODE(&delayed.node);
+
+       spin_lock_irq(&current->sighand->siglock);
+       if (!(clone_flags & CLONE_THREAD))
+               hlist_add_head(&delayed.node, &current->signal->multiprocess);
+       recalc_sigpending();
+       spin_unlock_irq(&current->sighand->siglock);
+       retval = -ERESTARTNOINTR;
+       if (signal_pending(current))
+               goto fork_out;
+
        retval = -ENOMEM;
        p = dup_task_struct(current, node);
        if (!p)
@@ -1941,29 +1977,26 @@ static __latent_entropy struct task_struct *copy_process(
 
        rseq_fork(p, clone_flags);
 
-       /*
-        * Process group and session signals need to be delivered to just the
-        * parent before the fork or both the parent and the child after the
-        * fork. Restart if a signal comes in before we add the new process to
-        * it's process group.
-        * A fatal signal pending means that current will exit, so the new
-        * thread can't slip out of an OOM kill (or normal SIGKILL).
-       */
-       recalc_sigpending();
-       if (signal_pending(current)) {
-               retval = -ERESTARTNOINTR;
-               goto bad_fork_cancel_cgroup;
-       }
+       /* Don't start children in a dying pid namespace */
        if (unlikely(!(ns_of_pid(pid)->pid_allocated & PIDNS_ADDING))) {
                retval = -ENOMEM;
                goto bad_fork_cancel_cgroup;
        }
 
+       /* Let kill terminate clone/fork in the middle */
+       if (fatal_signal_pending(current)) {
+               retval = -EINTR;
+               goto bad_fork_cancel_cgroup;
+       }
+
+
+       init_task_pid_links(p);
        if (likely(p->pid)) {
                ptrace_init_task(p, (clone_flags & CLONE_PTRACE) || trace);
 
                init_task_pid(p, PIDTYPE_PID, pid);
                if (thread_group_leader(p)) {
+                       init_task_pid(p, PIDTYPE_TGID, pid);
                        init_task_pid(p, PIDTYPE_PGID, task_pgrp(current));
                        init_task_pid(p, PIDTYPE_SID, task_session(current));
 
@@ -1971,8 +2004,7 @@ static __latent_entropy struct task_struct *copy_process(
                                ns_of_pid(pid)->child_reaper = p;
                                p->signal->flags |= SIGNAL_UNKILLABLE;
                        }
-
-                       p->signal->leader_pid = pid;
+                       p->signal->shared_pending.signal = delayed.signal;
                        p->signal->tty = tty_kref_get(current->signal->tty);
                        /*
                         * Inherit has_child_subreaper flag under the same
@@ -1983,6 +2015,7 @@ static __latent_entropy struct task_struct *copy_process(
                                                         p->real_parent->signal->is_child_subreaper;
                        list_add_tail(&p->sibling, &p->real_parent->children);
                        list_add_tail_rcu(&p->tasks, &init_task.tasks);
+                       attach_pid(p, PIDTYPE_TGID);
                        attach_pid(p, PIDTYPE_PGID);
                        attach_pid(p, PIDTYPE_SID);
                        __this_cpu_inc(process_counts);
@@ -1990,6 +2023,7 @@ static __latent_entropy struct task_struct *copy_process(
                        current->signal->nr_threads++;
                        atomic_inc(&current->signal->live);
                        atomic_inc(&current->signal->sigcnt);
+                       task_join_group_stop(p);
                        list_add_tail_rcu(&p->thread_group,
                                          &p->group_leader->thread_group);
                        list_add_tail_rcu(&p->thread_node,
@@ -1998,8 +2032,8 @@ static __latent_entropy struct task_struct *copy_process(
                attach_pid(p, PIDTYPE_PID);
                nr_threads++;
        }
-
        total_forks++;
+       hlist_del_init(&delayed.node);
        spin_unlock(&current->sighand->siglock);
        syscall_tracepoint_update(p);
        write_unlock_irq(&tasklist_lock);
@@ -2064,16 +2098,19 @@ bad_fork_free:
        put_task_stack(p);
        free_task(p);
 fork_out:
+       spin_lock_irq(&current->sighand->siglock);
+       hlist_del_init(&delayed.node);
+       spin_unlock_irq(&current->sighand->siglock);
        return ERR_PTR(retval);
 }
 
-static inline void init_idle_pids(struct pid_link *links)
+static inline void init_idle_pids(struct task_struct *idle)
 {
        enum pid_type type;
 
        for (type = PIDTYPE_PID; type < PIDTYPE_MAX; ++type) {
-               INIT_HLIST_NODE(&links[type].node); /* not really needed */
-               links[type].pid = &init_struct_pid;
+               INIT_HLIST_NODE(&idle->pid_links[type]); /* not really needed */
+               init_task_pid(idle, type, &init_struct_pid);
        }
 }
 
@@ -2083,7 +2120,7 @@ struct task_struct *fork_idle(int cpu)
        task = copy_process(CLONE_VM, 0, 0, NULL, &init_struct_pid, 0, 0,
                            cpu_to_node(cpu));
        if (!IS_ERR(task)) {
-               init_idle_pids(task->pids);
+               init_idle_pids(task);
                init_idle(task, cpu);
        }
 
index 1f450e0..11fc3bb 100644 (file)
@@ -3523,10 +3523,12 @@ long do_futex(u32 __user *uaddr, int op, u32 val, ktime_t *timeout,
        switch (cmd) {
        case FUTEX_WAIT:
                val3 = FUTEX_BITSET_MATCH_ANY;
+               /* fall through */
        case FUTEX_WAIT_BITSET:
                return futex_wait(uaddr, flags, val, timeout, val3);
        case FUTEX_WAKE:
                val3 = FUTEX_BITSET_MATCH_ANY;
+               /* fall through */
        case FUTEX_WAKE_BITSET:
                return futex_wake(uaddr, flags, val, val3);
        case FUTEX_REQUEUE:
index 32b4794..b9132d1 100644 (file)
@@ -40,6 +40,11 @@ int __read_mostly sysctl_hung_task_check_count = PID_MAX_LIMIT;
  */
 unsigned long __read_mostly sysctl_hung_task_timeout_secs = CONFIG_DEFAULT_HUNG_TASK_TIMEOUT;
 
+/*
+ * Zero (default value) means use sysctl_hung_task_timeout_secs:
+ */
+unsigned long __read_mostly sysctl_hung_task_check_interval_secs;
+
 int __read_mostly sysctl_hung_task_warnings = 10;
 
 static int __read_mostly did_panic;
@@ -98,8 +103,11 @@ static void check_hung_task(struct task_struct *t, unsigned long timeout)
 
        if (switch_count != t->last_switch_count) {
                t->last_switch_count = switch_count;
+               t->last_switch_time = jiffies;
                return;
        }
+       if (time_is_after_jiffies(t->last_switch_time + timeout * HZ))
+               return;
 
        trace_sched_process_hang(t);
 
@@ -245,8 +253,13 @@ static int watchdog(void *dummy)
 
        for ( ; ; ) {
                unsigned long timeout = sysctl_hung_task_timeout_secs;
-               long t = hung_timeout_jiffies(hung_last_checked, timeout);
+               unsigned long interval = sysctl_hung_task_check_interval_secs;
+               long t;
 
+               if (interval == 0)
+                       interval = timeout;
+               interval = min_t(unsigned long, interval, timeout);
+               t = hung_timeout_jiffies(hung_last_checked, interval);
                if (t <= 0) {
                        if (!atomic_xchg(&reset_hung_task, 0))
                                check_hung_uninterruptible_tasks(timeout);
index a23e21a..02a0b01 100644 (file)
@@ -432,6 +432,7 @@ int sprint_backtrace(char *buffer, unsigned long address)
 /* To avoid using get_symbol_offset for every symbol, we carry prefix along. */
 struct kallsym_iter {
        loff_t pos;
+       loff_t pos_arch_end;
        loff_t pos_mod_end;
        loff_t pos_ftrace_mod_end;
        unsigned long value;
@@ -443,9 +444,29 @@ struct kallsym_iter {
        int show_value;
 };
 
+int __weak arch_get_kallsym(unsigned int symnum, unsigned long *value,
+                           char *type, char *name)
+{
+       return -EINVAL;
+}
+
+static int get_ksymbol_arch(struct kallsym_iter *iter)
+{
+       int ret = arch_get_kallsym(iter->pos - kallsyms_num_syms,
+                                  &iter->value, &iter->type,
+                                  iter->name);
+
+       if (ret < 0) {
+               iter->pos_arch_end = iter->pos;
+               return 0;
+       }
+
+       return 1;
+}
+
 static int get_ksymbol_mod(struct kallsym_iter *iter)
 {
-       int ret = module_get_kallsym(iter->pos - kallsyms_num_syms,
+       int ret = module_get_kallsym(iter->pos - iter->pos_arch_end,
                                     &iter->value, &iter->type,
                                     iter->name, iter->module_name,
                                     &iter->exported);
@@ -501,32 +522,34 @@ static void reset_iter(struct kallsym_iter *iter, loff_t new_pos)
        iter->nameoff = get_symbol_offset(new_pos);
        iter->pos = new_pos;
        if (new_pos == 0) {
+               iter->pos_arch_end = 0;
                iter->pos_mod_end = 0;
                iter->pos_ftrace_mod_end = 0;
        }
 }
 
+/*
+ * The end position (last + 1) of each additional kallsyms section is recorded
+ * in iter->pos_..._end as each section is added, and so can be used to
+ * determine which get_ksymbol_...() function to call next.
+ */
 static int update_iter_mod(struct kallsym_iter *iter, loff_t pos)
 {
        iter->pos = pos;
 
-       if (iter->pos_ftrace_mod_end > 0 &&
-           iter->pos_ftrace_mod_end < iter->pos)
-               return get_ksymbol_bpf(iter);
+       if ((!iter->pos_arch_end || iter->pos_arch_end > pos) &&
+           get_ksymbol_arch(iter))
+               return 1;
 
-       if (iter->pos_mod_end > 0 &&
-           iter->pos_mod_end < iter->pos) {
-               if (!get_ksymbol_ftrace_mod(iter))
-                       return get_ksymbol_bpf(iter);
+       if ((!iter->pos_mod_end || iter->pos_mod_end > pos) &&
+           get_ksymbol_mod(iter))
                return 1;
-       }
 
-       if (!get_ksymbol_mod(iter)) {
-               if (!get_ksymbol_ftrace_mod(iter))
-                       return get_ksymbol_bpf(iter);
-       }
+       if ((!iter->pos_ftrace_mod_end || iter->pos_ftrace_mod_end > pos) &&
+           get_ksymbol_ftrace_mod(iter))
+               return 1;
 
-       return 1;
+       return get_ksymbol_bpf(iter);
 }
 
 /* Returns false if pos at or past end of file. */
index 3a4656f..5b77a73 100644 (file)
@@ -678,6 +678,9 @@ static int klp_init_func(struct klp_object *obj, struct klp_func *func)
        if (!func->old_name || !func->new_func)
                return -EINVAL;
 
+       if (strlen(func->old_name) >= KSYM_NAME_LEN)
+               return -EINVAL;
+
        INIT_LIST_HEAD(&func->stack_node);
        func->patched = false;
        func->transition = false;
@@ -751,6 +754,9 @@ static int klp_init_object(struct klp_patch *patch, struct klp_object *obj)
        if (!obj->funcs)
                return -EINVAL;
 
+       if (klp_is_module(obj) && strlen(obj->name) >= MODULE_NAME_LEN)
+               return -EINVAL;
+
        obj->patched = false;
        obj->mod = NULL;
 
index 7c6631e..5bc3498 100644 (file)
@@ -310,13 +310,6 @@ static bool klp_try_switch_task(struct task_struct *task)
                return true;
 
        /*
-        * For arches which don't have reliable stack traces, we have to rely
-        * on other methods (e.g., switching tasks at kernel exit).
-        */
-       if (!klp_have_reliable_stack())
-               return false;
-
-       /*
         * Now try to check the stack for any to-be-patched or to-be-unpatched
         * functions.  If all goes well, switch the task to the target patch
         * state.
index 5fa4d31..e406c5f 100644 (file)
@@ -55,6 +55,7 @@
 
 #include "lockdep_internals.h"
 
+#include <trace/events/preemptirq.h>
 #define CREATE_TRACE_POINTS
 #include <trace/events/lock.h>
 
@@ -248,12 +249,7 @@ void clear_lock_stats(struct lock_class *class)
 
 static struct lock_class_stats *get_lock_stats(struct lock_class *class)
 {
-       return &get_cpu_var(cpu_lock_stats)[class - lock_classes];
-}
-
-static void put_lock_stats(struct lock_class_stats *stats)
-{
-       put_cpu_var(cpu_lock_stats);
+       return &this_cpu_ptr(cpu_lock_stats)[class - lock_classes];
 }
 
 static void lock_release_holdtime(struct held_lock *hlock)
@@ -271,7 +267,6 @@ static void lock_release_holdtime(struct held_lock *hlock)
                lock_time_inc(&stats->read_holdtime, holdtime);
        else
                lock_time_inc(&stats->write_holdtime, holdtime);
-       put_lock_stats(stats);
 }
 #else
 static inline void lock_release_holdtime(struct held_lock *hlock)
@@ -2845,10 +2840,8 @@ static void __trace_hardirqs_on_caller(unsigned long ip)
        debug_atomic_inc(hardirqs_on_events);
 }
 
-__visible void trace_hardirqs_on_caller(unsigned long ip)
+void lockdep_hardirqs_on(unsigned long ip)
 {
-       time_hardirqs_on(CALLER_ADDR0, ip);
-
        if (unlikely(!debug_locks || current->lockdep_recursion))
                return;
 
@@ -2887,23 +2880,14 @@ __visible void trace_hardirqs_on_caller(unsigned long ip)
        __trace_hardirqs_on_caller(ip);
        current->lockdep_recursion = 0;
 }
-EXPORT_SYMBOL(trace_hardirqs_on_caller);
-
-void trace_hardirqs_on(void)
-{
-       trace_hardirqs_on_caller(CALLER_ADDR0);
-}
-EXPORT_SYMBOL(trace_hardirqs_on);
 
 /*
  * Hardirqs were disabled:
  */
-__visible void trace_hardirqs_off_caller(unsigned long ip)
+void lockdep_hardirqs_off(unsigned long ip)
 {
        struct task_struct *curr = current;
 
-       time_hardirqs_off(CALLER_ADDR0, ip);
-
        if (unlikely(!debug_locks || current->lockdep_recursion))
                return;
 
@@ -2925,13 +2909,6 @@ __visible void trace_hardirqs_off_caller(unsigned long ip)
        } else
                debug_atomic_inc(redundant_hardirqs_off);
 }
-EXPORT_SYMBOL(trace_hardirqs_off_caller);
-
-void trace_hardirqs_off(void)
-{
-       trace_hardirqs_off_caller(CALLER_ADDR0);
-}
-EXPORT_SYMBOL(trace_hardirqs_off);
 
 /*
  * Softirqs will be enabled:
@@ -4090,7 +4067,6 @@ __lock_contended(struct lockdep_map *lock, unsigned long ip)
                stats->contending_point[contending_point]++;
        if (lock->cpu != smp_processor_id())
                stats->bounces[bounce_contended + !!hlock->read]++;
-       put_lock_stats(stats);
 }
 
 static void
@@ -4138,7 +4114,6 @@ __lock_acquired(struct lockdep_map *lock, unsigned long ip)
        }
        if (lock->cpu != cpu)
                stats->bounces[bounce_acquired + !!hlock->read]++;
-       put_lock_stats(stats);
 
        lock->cpu = cpu;
        lock->ip = ip;
@@ -4338,7 +4313,7 @@ out_restore:
        raw_local_irq_restore(flags);
 }
 
-void __init lockdep_info(void)
+void __init lockdep_init(void)
 {
        printk("Lock dependency validator: Copyright (c) 2006 Red Hat, Inc., Ingo Molnar\n");
 
index 1f87ea6..5b8600d 100644 (file)
@@ -43,7 +43,7 @@ static unsigned long order_at(struct resource *res, unsigned long pgoff)
                        pgoff += 1UL << order, order = order_at((res), pgoff))
 
 #if IS_ENABLED(CONFIG_DEVICE_PRIVATE)
-int device_private_entry_fault(struct vm_area_struct *vma,
+vm_fault_t device_private_entry_fault(struct vm_area_struct *vma,
                       unsigned long addr,
                       swp_entry_t entry,
                       unsigned int flags,
@@ -365,7 +365,6 @@ void __put_devmap_managed_page(struct page *page)
                __ClearPageActive(page);
                __ClearPageWaiters(page);
 
-               page->mapping = NULL;
                mem_cgroup_uncharge(page);
 
                page->pgmap->page_free(page, page->pgmap->data);
index b046a32..6746c85 100644 (file)
@@ -529,12 +529,30 @@ static bool check_symbol(const struct symsearch *syms,
        return true;
 }
 
+static unsigned long kernel_symbol_value(const struct kernel_symbol *sym)
+{
+#ifdef CONFIG_HAVE_ARCH_PREL32_RELOCATIONS
+       return (unsigned long)offset_to_ptr(&sym->value_offset);
+#else
+       return sym->value;
+#endif
+}
+
+static const char *kernel_symbol_name(const struct kernel_symbol *sym)
+{
+#ifdef CONFIG_HAVE_ARCH_PREL32_RELOCATIONS
+       return offset_to_ptr(&sym->name_offset);
+#else
+       return sym->name;
+#endif
+}
+
 static int cmp_name(const void *va, const void *vb)
 {
        const char *a;
        const struct kernel_symbol *b;
        a = va; b = vb;
-       return strcmp(a, b->name);
+       return strcmp(a, kernel_symbol_name(b));
 }
 
 static bool find_symbol_in_section(const struct symsearch *syms,
@@ -2170,7 +2188,7 @@ void *__symbol_get(const char *symbol)
                sym = NULL;
        preempt_enable();
 
-       return sym ? (void *)sym->value : NULL;
+       return sym ? (void *)kernel_symbol_value(sym) : NULL;
 }
 EXPORT_SYMBOL_GPL(__symbol_get);
 
@@ -2200,10 +2218,12 @@ static int verify_export_symbols(struct module *mod)
 
        for (i = 0; i < ARRAY_SIZE(arr); i++) {
                for (s = arr[i].sym; s < arr[i].sym + arr[i].num; s++) {
-                       if (find_symbol(s->name, &owner, NULL, true, false)) {
+                       if (find_symbol(kernel_symbol_name(s), &owner, NULL,
+                                       true, false)) {
                                pr_err("%s: exports duplicate symbol %s"
                                       " (owned by %s)\n",
-                                      mod->name, s->name, module_name(owner));
+                                      mod->name, kernel_symbol_name(s),
+                                      module_name(owner));
                                return -ENOEXEC;
                        }
                }
@@ -2252,7 +2272,7 @@ static int simplify_symbols(struct module *mod, const struct load_info *info)
                        ksym = resolve_symbol_wait(mod, info, name);
                        /* Ok if resolved.  */
                        if (ksym && !IS_ERR(ksym)) {
-                               sym[i].st_value = ksym->value;
+                               sym[i].st_value = kernel_symbol_value(ksym);
                                break;
                        }
 
@@ -2516,7 +2536,7 @@ static int is_exported(const char *name, unsigned long value,
                ks = lookup_symbol(name, __start___ksymtab, __stop___ksymtab);
        else
                ks = lookup_symbol(name, mod->syms, mod->syms + mod->num_syms);
-       return ks != NULL && ks->value == value;
+       return ks != NULL && kernel_symbol_value(ks) == value;
 }
 
 /* As per nm */
index 157fe4b..de1cfc4 100644 (file)
@@ -265,27 +265,33 @@ struct pid *find_vpid(int nr)
 }
 EXPORT_SYMBOL_GPL(find_vpid);
 
+static struct pid **task_pid_ptr(struct task_struct *task, enum pid_type type)
+{
+       return (type == PIDTYPE_PID) ?
+               &task->thread_pid :
+               &task->signal->pids[type];
+}
+
 /*
  * attach_pid() must be called with the tasklist_lock write-held.
  */
 void attach_pid(struct task_struct *task, enum pid_type type)
 {
-       struct pid_link *link = &task->pids[type];
-       hlist_add_head_rcu(&link->node, &link->pid->tasks[type]);
+       struct pid *pid = *task_pid_ptr(task, type);
+       hlist_add_head_rcu(&task->pid_links[type], &pid->tasks[type]);
 }
 
 static void __change_pid(struct task_struct *task, enum pid_type type,
                        struct pid *new)
 {
-       struct pid_link *link;
+       struct pid **pid_ptr = task_pid_ptr(task, type);
        struct pid *pid;
        int tmp;
 
-       link = &task->pids[type];
-       pid = link->pid;
+       pid = *pid_ptr;
 
-       hlist_del_rcu(&link->node);
-       link->pid = new;
+       hlist_del_rcu(&task->pid_links[type]);
+       *pid_ptr = new;
 
        for (tmp = PIDTYPE_MAX; --tmp >= 0; )
                if (!hlist_empty(&pid->tasks[tmp]))
@@ -310,8 +316,9 @@ void change_pid(struct task_struct *task, enum pid_type type,
 void transfer_pid(struct task_struct *old, struct task_struct *new,
                           enum pid_type type)
 {
-       new->pids[type].pid = old->pids[type].pid;
-       hlist_replace_rcu(&old->pids[type].node, &new->pids[type].node);
+       if (type == PIDTYPE_PID)
+               new->thread_pid = old->thread_pid;
+       hlist_replace_rcu(&old->pid_links[type], &new->pid_links[type]);
 }
 
 struct task_struct *pid_task(struct pid *pid, enum pid_type type)
@@ -322,7 +329,7 @@ struct task_struct *pid_task(struct pid *pid, enum pid_type type)
                first = rcu_dereference_check(hlist_first_rcu(&pid->tasks[type]),
                                              lockdep_tasklist_lock_is_held());
                if (first)
-                       result = hlist_entry(first, struct task_struct, pids[(type)].node);
+                       result = hlist_entry(first, struct task_struct, pid_links[(type)]);
        }
        return result;
 }
@@ -360,9 +367,7 @@ struct pid *get_task_pid(struct task_struct *task, enum pid_type type)
 {
        struct pid *pid;
        rcu_read_lock();
-       if (type != PIDTYPE_PID)
-               task = task->group_leader;
-       pid = get_pid(rcu_dereference(task->pids[type].pid));
+       pid = get_pid(rcu_dereference(*task_pid_ptr(task, type)));
        rcu_read_unlock();
        return pid;
 }
@@ -420,15 +425,8 @@ pid_t __task_pid_nr_ns(struct task_struct *task, enum pid_type type,
        rcu_read_lock();
        if (!ns)
                ns = task_active_pid_ns(current);
-       if (likely(pid_alive(task))) {
-               if (type != PIDTYPE_PID) {
-                       if (type == __PIDTYPE_TGID)
-                               type = PIDTYPE_PID;
-
-                       task = task->group_leader;
-               }
-               nr = pid_nr_ns(rcu_dereference(task->pids[type].pid), ns);
-       }
+       if (likely(pid_alive(task)))
+               nr = pid_nr_ns(rcu_dereference(*task_pid_ptr(task, type)), ns);
        rcu_read_unlock();
 
        return nr;
index e880ca2..3a6c2f8 100644 (file)
@@ -105,6 +105,7 @@ config PM_SLEEP
        def_bool y
        depends on SUSPEND || HIBERNATE_CALLBACKS
        select PM
+       select SRCU
 
 config PM_SLEEP_SMP
        def_bool y
index 90b6ab0..924e37f 100644 (file)
@@ -66,6 +66,9 @@ int console_printk[4] = {
        CONSOLE_LOGLEVEL_DEFAULT,       /* default_console_loglevel */
 };
 
+atomic_t ignore_console_lock_warning __read_mostly = ATOMIC_INIT(0);
+EXPORT_SYMBOL(ignore_console_lock_warning);
+
 /*
  * Low level drivers may need that to know if they can schedule in
  * their unblank() callback or not. So let's export it.
@@ -2788,7 +2791,8 @@ EXPORT_SYMBOL(unregister_console);
 void __init console_init(void)
 {
        int ret;
-       initcall_t *call;
+       initcall_t call;
+       initcall_entry_t *ce;
 
        /* Setup the default TTY line discipline. */
        n_tty_init();
@@ -2797,13 +2801,14 @@ void __init console_init(void)
         * set up the console device so that later boot sequences can
         * inform about problems etc..
         */
-       call = __con_initcall_start;
+       ce = __con_initcall_start;
        trace_initcall_level("console");
-       while (call < __con_initcall_end) {
-               trace_initcall_start((*call));
-               ret = (*call)();
-               trace_initcall_finish((*call), ret);
-               call++;
+       while (ce < __con_initcall_end) {
+               call = initcall_from_entry(ce);
+               trace_initcall_start(call);
+               ret = call();
+               trace_initcall_finish(call, ret);
+               ce++;
        }
 }
 
index 454adf9..625bc98 100644 (file)
@@ -2774,6 +2774,8 @@ asmlinkage __visible void schedule_tail(struct task_struct *prev)
 
        if (current->set_child_tid)
                put_user(task_pid_vnr(current), current->set_child_tid);
+
+       calculate_sigpending();
 }
 
 /*
@@ -3159,7 +3161,7 @@ static inline void sched_tick_stop(int cpu) { }
 #endif
 
 #if defined(CONFIG_PREEMPT) && (defined(CONFIG_DEBUG_PREEMPT) || \
-                               defined(CONFIG_PREEMPT_TRACER))
+                               defined(CONFIG_TRACE_PREEMPT_TOGGLE))
 /*
  * If the value passed in is equal to the current preempt count
  * then we just disabled preemption. Start timing the latency.
index 1a3e9bd..16f8414 100644 (file)
@@ -190,7 +190,7 @@ static void cpuidle_idle_call(void)
                 */
                next_state = cpuidle_select(drv, dev, &stop_tick);
 
-               if (stop_tick)
+               if (stop_tick || tick_nohz_tick_stopped())
                        tick_nohz_idle_stop_tick();
                else
                        tick_nohz_idle_retain_tick();
index 870f97b..5dd47f1 100644 (file)
@@ -69,6 +69,8 @@ static int __wake_up_common(struct wait_queue_head *wq_head, unsigned int mode,
        wait_queue_entry_t *curr, *next;
        int cnt = 0;
 
+       lockdep_assert_held(&wq_head->lock);
+
        if (bookmark && (bookmark->flags & WQ_FLAG_BOOKMARK)) {
                curr = list_next_entry(bookmark, entry);
 
index 8d8a940..5843c54 100644 (file)
@@ -65,14 +65,14 @@ static void __user *sig_handler(struct task_struct *t, int sig)
        return t->sighand->action[sig - 1].sa.sa_handler;
 }
 
-static int sig_handler_ignored(void __user *handler, int sig)
+static inline bool sig_handler_ignored(void __user *handler, int sig)
 {
        /* Is it explicitly or implicitly ignored? */
        return handler == SIG_IGN ||
-               (handler == SIG_DFL && sig_kernel_ignore(sig));
+              (handler == SIG_DFL && sig_kernel_ignore(sig));
 }
 
-static int sig_task_ignored(struct task_struct *t, int sig, bool force)
+static bool sig_task_ignored(struct task_struct *t, int sig, bool force)
 {
        void __user *handler;
 
@@ -80,12 +80,12 @@ static int sig_task_ignored(struct task_struct *t, int sig, bool force)
 
        if (unlikely(t->signal->flags & SIGNAL_UNKILLABLE) &&
            handler == SIG_DFL && !(force && sig_kernel_only(sig)))
-               return 1;
+               return true;
 
        return sig_handler_ignored(handler, sig);
 }
 
-static int sig_ignored(struct task_struct *t, int sig, bool force)
+static bool sig_ignored(struct task_struct *t, int sig, bool force)
 {
        /*
         * Blocked signals are never ignored, since the
@@ -93,7 +93,7 @@ static int sig_ignored(struct task_struct *t, int sig, bool force)
         * unblocked.
         */
        if (sigismember(&t->blocked, sig) || sigismember(&t->real_blocked, sig))
-               return 0;
+               return false;
 
        /*
         * Tracers may want to know about even ignored signal unless it
@@ -101,7 +101,7 @@ static int sig_ignored(struct task_struct *t, int sig, bool force)
         * by SIGNAL_UNKILLABLE task.
         */
        if (t->ptrace && sig != SIGKILL)
-               return 0;
+               return false;
 
        return sig_task_ignored(t, sig, force);
 }
@@ -110,7 +110,7 @@ static int sig_ignored(struct task_struct *t, int sig, bool force)
  * Re-calculate pending state from the set of locally pending
  * signals, globally pending signals, and blocked signals.
  */
-static inline int has_pending_signals(sigset_t *signal, sigset_t *blocked)
+static inline bool has_pending_signals(sigset_t *signal, sigset_t *blocked)
 {
        unsigned long ready;
        long i;
@@ -138,20 +138,21 @@ static inline int has_pending_signals(sigset_t *signal, sigset_t *blocked)
 
 #define PENDING(p,b) has_pending_signals(&(p)->signal, (b))
 
-static int recalc_sigpending_tsk(struct task_struct *t)
+static bool recalc_sigpending_tsk(struct task_struct *t)
 {
        if ((t->jobctl & JOBCTL_PENDING_MASK) ||
            PENDING(&t->pending, &t->blocked) ||
            PENDING(&t->signal->shared_pending, &t->blocked)) {
                set_tsk_thread_flag(t, TIF_SIGPENDING);
-               return 1;
+               return true;
        }
+
        /*
         * We must never clear the flag in another thread, or in current
         * when it's possible the current syscall is returning -ERESTART*.
         * So we don't clear it here, and only callers who know they should do.
         */
-       return 0;
+       return false;
 }
 
 /*
@@ -172,6 +173,17 @@ void recalc_sigpending(void)
 
 }
 
+void calculate_sigpending(void)
+{
+       /* Have any signals or users of TIF_SIGPENDING been delayed
+        * until after fork?
+        */
+       spin_lock_irq(&current->sighand->siglock);
+       set_tsk_thread_flag(current, TIF_SIGPENDING);
+       recalc_sigpending();
+       spin_unlock_irq(&current->sighand->siglock);
+}
+
 /* Given the mask, find the first available signal that should be serviced. */
 
 #define SYNCHRONOUS_MASK \
@@ -362,6 +374,20 @@ static bool task_participate_group_stop(struct task_struct *task)
        return false;
 }
 
+void task_join_group_stop(struct task_struct *task)
+{
+       /* Have the new thread join an on-going signal group stop */
+       unsigned long jobctl = current->jobctl;
+       if (jobctl & JOBCTL_STOP_PENDING) {
+               struct signal_struct *sig = current->signal;
+               unsigned long signr = jobctl & JOBCTL_STOP_SIGMASK;
+               unsigned long gstop = JOBCTL_STOP_PENDING | JOBCTL_STOP_CONSUME;
+               if (task_set_jobctl_pending(task, signr | gstop)) {
+                       sig->group_stop_count++;
+               }
+       }
+}
+
 /*
  * allocate a new signal queue record
  * - this may be called without locks if and only if t == current, otherwise an
@@ -504,13 +530,15 @@ flush_signal_handlers(struct task_struct *t, int force_default)
        }
 }
 
-int unhandled_signal(struct task_struct *tsk, int sig)
+bool unhandled_signal(struct task_struct *tsk, int sig)
 {
        void __user *handler = tsk->sighand->action[sig-1].sa.sa_handler;
        if (is_global_init(tsk))
-               return 1;
+               return true;
+
        if (handler != SIG_IGN && handler != SIG_DFL)
-               return 0;
+               return false;
+
        /* if ptraced, let the tracer determine */
        return !tsk->ptrace;
 }
@@ -684,14 +712,14 @@ void signal_wake_up_state(struct task_struct *t, unsigned int state)
  *
  * All callers must be holding the siglock.
  */
-static int flush_sigqueue_mask(sigset_t *mask, struct sigpending *s)
+static void flush_sigqueue_mask(sigset_t *mask, struct sigpending *s)
 {
        struct sigqueue *q, *n;
        sigset_t m;
 
        sigandsets(&m, mask, &s->signal);
        if (sigisemptyset(&m))
-               return 0;
+               return;
 
        sigandnsets(&s->signal, &s->signal, mask);
        list_for_each_entry_safe(q, n, &s->list, list) {
@@ -700,7 +728,6 @@ static int flush_sigqueue_mask(sigset_t *mask, struct sigpending *s)
                        __sigqueue_free(q);
                }
        }
-       return 1;
 }
 
 static inline int is_si_special(const struct siginfo *info)
@@ -717,21 +744,16 @@ static inline bool si_fromuser(const struct siginfo *info)
 /*
  * called with RCU read lock from check_kill_permission()
  */
-static int kill_ok_by_cred(struct task_struct *t)
+static bool kill_ok_by_cred(struct task_struct *t)
 {
        const struct cred *cred = current_cred();
        const struct cred *tcred = __task_cred(t);
 
-       if (uid_eq(cred->euid, tcred->suid) ||
-           uid_eq(cred->euid, tcred->uid)  ||
-           uid_eq(cred->uid,  tcred->suid) ||
-           uid_eq(cred->uid,  tcred->uid))
-               return 1;
-
-       if (ns_capable(tcred->user_ns, CAP_KILL))
-               return 1;
-
-       return 0;
+       return uid_eq(cred->euid, tcred->suid) ||
+              uid_eq(cred->euid, tcred->uid) ||
+              uid_eq(cred->uid, tcred->suid) ||
+              uid_eq(cred->uid, tcred->uid) ||
+              ns_capable(tcred->user_ns, CAP_KILL);
 }
 
 /*
@@ -882,20 +904,24 @@ static bool prepare_signal(int sig, struct task_struct *p, bool force)
  * as soon as they're available, so putting the signal on the shared queue
  * will be equivalent to sending it to one such thread.
  */
-static inline int wants_signal(int sig, struct task_struct *p)
+static inline bool wants_signal(int sig, struct task_struct *p)
 {
        if (sigismember(&p->blocked, sig))
-               return 0;
+               return false;
+
        if (p->flags & PF_EXITING)
-               return 0;
+               return false;
+
        if (sig == SIGKILL)
-               return 1;
+               return true;
+
        if (task_is_stopped_or_traced(p))
-               return 0;
+               return false;
+
        return task_curr(p) || !signal_pending(p);
 }
 
-static void complete_signal(int sig, struct task_struct *p, int group)
+static void complete_signal(int sig, struct task_struct *p, enum pid_type type)
 {
        struct signal_struct *signal = p->signal;
        struct task_struct *t;
@@ -908,7 +934,7 @@ static void complete_signal(int sig, struct task_struct *p, int group)
         */
        if (wants_signal(sig, p))
                t = p;
-       else if (!group || thread_group_empty(p))
+       else if ((type == PIDTYPE_PID) || thread_group_empty(p))
                /*
                 * There is just one thread and it does not need to be woken.
                 * It will dequeue unblocked signals before it runs again.
@@ -971,7 +997,7 @@ static void complete_signal(int sig, struct task_struct *p, int group)
        return;
 }
 
-static inline int legacy_queue(struct sigpending *signals, int sig)
+static inline bool legacy_queue(struct sigpending *signals, int sig)
 {
        return (sig < SIGRTMIN) && sigismember(&signals->signal, sig);
 }
@@ -998,7 +1024,7 @@ static inline void userns_fixup_signal_uid(struct siginfo *info, struct task_str
 #endif
 
 static int __send_signal(int sig, struct siginfo *info, struct task_struct *t,
-                       int group, int from_ancestor_ns)
+                       enum pid_type type, int from_ancestor_ns)
 {
        struct sigpending *pending;
        struct sigqueue *q;
@@ -1012,7 +1038,7 @@ static int __send_signal(int sig, struct siginfo *info, struct task_struct *t,
                        from_ancestor_ns || (info == SEND_SIG_FORCED)))
                goto ret;
 
-       pending = group ? &t->signal->shared_pending : &t->pending;
+       pending = (type != PIDTYPE_PID) ? &t->signal->shared_pending : &t->pending;
        /*
         * Short-circuit ignored signals and support queuing
         * exactly one non-rt signal, so that we can get more
@@ -1096,14 +1122,29 @@ static int __send_signal(int sig, struct siginfo *info, struct task_struct *t,
 out_set:
        signalfd_notify(t, sig);
        sigaddset(&pending->signal, sig);
-       complete_signal(sig, t, group);
+
+       /* Let multiprocess signals appear after on-going forks */
+       if (type > PIDTYPE_TGID) {
+               struct multiprocess_signals *delayed;
+               hlist_for_each_entry(delayed, &t->signal->multiprocess, node) {
+                       sigset_t *signal = &delayed->signal;
+                       /* Can't queue both a stop and a continue signal */
+                       if (sig == SIGCONT)
+                               sigdelsetmask(signal, SIG_KERNEL_STOP_MASK);
+                       else if (sig_kernel_stop(sig))
+                               sigdelset(signal, SIGCONT);
+                       sigaddset(signal, sig);
+               }
+       }
+
+       complete_signal(sig, t, type);
 ret:
-       trace_signal_generate(sig, info, t, group, result);
+       trace_signal_generate(sig, info, t, type != PIDTYPE_PID, result);
        return ret;
 }
 
 static int send_signal(int sig, struct siginfo *info, struct task_struct *t,
-                       int group)
+                       enum pid_type type)
 {
        int from_ancestor_ns = 0;
 
@@ -1112,7 +1153,7 @@ static int send_signal(int sig, struct siginfo *info, struct task_struct *t,
                           !task_pid_nr_ns(current, task_active_pid_ns(t));
 #endif
 
-       return __send_signal(sig, info, t, group, from_ancestor_ns);
+       return __send_signal(sig, info, t, type, from_ancestor_ns);
 }
 
 static void print_fatal_signal(int signr)
@@ -1151,23 +1192,23 @@ __setup("print-fatal-signals=", setup_print_fatal_signals);
 int
 __group_send_sig_info(int sig, struct siginfo *info, struct task_struct *p)
 {
-       return send_signal(sig, info, p, 1);
+       return send_signal(sig, info, p, PIDTYPE_TGID);
 }
 
 static int
 specific_send_sig_info(int sig, struct siginfo *info, struct task_struct *t)
 {
-       return send_signal(sig, info, t, 0);
+       return send_signal(sig, info, t, PIDTYPE_PID);
 }
 
 int do_send_sig_info(int sig, struct siginfo *info, struct task_struct *p,
-                       bool group)
+                       enum pid_type type)
 {
        unsigned long flags;
        int ret = -ESRCH;
 
        if (lock_task_sighand(p, &flags)) {
-               ret = send_signal(sig, info, p, group);
+               ret = send_signal(sig, info, p, type);
                unlock_task_sighand(p, &flags);
        }
 
@@ -1274,7 +1315,8 @@ struct sighand_struct *__lock_task_sighand(struct task_struct *tsk,
 /*
  * send signal info to all the members of a group
  */
-int group_send_sig_info(int sig, struct siginfo *info, struct task_struct *p)
+int group_send_sig_info(int sig, struct siginfo *info, struct task_struct *p,
+                       enum pid_type type)
 {
        int ret;
 
@@ -1283,7 +1325,7 @@ int group_send_sig_info(int sig, struct siginfo *info, struct task_struct *p)
        rcu_read_unlock();
 
        if (!ret && sig)
-               ret = do_send_sig_info(sig, info, p, true);
+               ret = do_send_sig_info(sig, info, p, type);
 
        return ret;
 }
@@ -1301,7 +1343,7 @@ int __kill_pgrp_info(int sig, struct siginfo *info, struct pid *pgrp)
        success = 0;
        retval = -ESRCH;
        do_each_pid_task(pgrp, PIDTYPE_PGID, p) {
-               int err = group_send_sig_info(sig, info, p);
+               int err = group_send_sig_info(sig, info, p, PIDTYPE_PGID);
                success |= !err;
                retval = err;
        } while_each_pid_task(pgrp, PIDTYPE_PGID, p);
@@ -1317,7 +1359,7 @@ int kill_pid_info(int sig, struct siginfo *info, struct pid *pid)
                rcu_read_lock();
                p = pid_task(pid, PIDTYPE_PID);
                if (p)
-                       error = group_send_sig_info(sig, info, p);
+                       error = group_send_sig_info(sig, info, p, PIDTYPE_TGID);
                rcu_read_unlock();
                if (likely(!p || error != -ESRCH))
                        return error;
@@ -1339,14 +1381,15 @@ static int kill_proc_info(int sig, struct siginfo *info, pid_t pid)
        return error;
 }
 
-static int kill_as_cred_perm(const struct cred *cred,
-                            struct task_struct *target)
+static inline bool kill_as_cred_perm(const struct cred *cred,
+                                    struct task_struct *target)
 {
        const struct cred *pcred = __task_cred(target);
-       if (!uid_eq(cred->euid, pcred->suid) && !uid_eq(cred->euid, pcred->uid) &&
-           !uid_eq(cred->uid,  pcred->suid) && !uid_eq(cred->uid,  pcred->uid))
-               return 0;
-       return 1;
+
+       return uid_eq(cred->euid, pcred->suid) ||
+              uid_eq(cred->euid, pcred->uid) ||
+              uid_eq(cred->uid, pcred->suid) ||
+              uid_eq(cred->uid, pcred->uid);
 }
 
 /* like kill_pid_info(), but doesn't use uid/euid of "current" */
@@ -1376,7 +1419,7 @@ int kill_pid_info_as_cred(int sig, struct siginfo *info, struct pid *pid,
 
        if (sig) {
                if (lock_task_sighand(p, &flags)) {
-                       ret = __send_signal(sig, info, p, 1, 0);
+                       ret = __send_signal(sig, info, p, PIDTYPE_TGID, 0);
                        unlock_task_sighand(p, &flags);
                } else
                        ret = -ESRCH;
@@ -1420,7 +1463,8 @@ static int kill_something_info(int sig, struct siginfo *info, pid_t pid)
                for_each_process(p) {
                        if (task_pid_vnr(p) > 1 &&
                                        !same_thread_group(p, current)) {
-                               int err = group_send_sig_info(sig, info, p);
+                               int err = group_send_sig_info(sig, info, p,
+                                                             PIDTYPE_MAX);
                                ++count;
                                if (err != -EPERM)
                                        retval = err;
@@ -1446,7 +1490,7 @@ int send_sig_info(int sig, struct siginfo *info, struct task_struct *p)
        if (!valid_signal(sig))
                return -EINVAL;
 
-       return do_send_sig_info(sig, info, p, false);
+       return do_send_sig_info(sig, info, p, PIDTYPE_PID);
 }
 
 #define __si_special(priv) \
@@ -1458,8 +1502,7 @@ send_sig(int sig, struct task_struct *p, int priv)
        return send_sig_info(sig, __si_special(priv), p);
 }
 
-void
-force_sig(int sig, struct task_struct *p)
+void force_sig(int sig, struct task_struct *p)
 {
        force_sig_info(sig, SEND_SIG_PRIV, p);
 }
@@ -1470,8 +1513,7 @@ force_sig(int sig, struct task_struct *p)
  * the problem was already a SIGSEGV, we'll want to
  * make sure we don't even try to deliver the signal..
  */
-int
-force_sigsegv(int sig, struct task_struct *p)
+void force_sigsegv(int sig, struct task_struct *p)
 {
        if (sig == SIGSEGV) {
                unsigned long flags;
@@ -1480,7 +1522,6 @@ force_sigsegv(int sig, struct task_struct *p)
                spin_unlock_irqrestore(&p->sighand->siglock, flags);
        }
        force_sig(SIGSEGV, p);
-       return 0;
 }
 
 int force_sig_fault(int sig, int code, void __user *addr
@@ -1664,17 +1705,20 @@ void sigqueue_free(struct sigqueue *q)
                __sigqueue_free(q);
 }
 
-int send_sigqueue(struct sigqueue *q, struct task_struct *t, int group)
+int send_sigqueue(struct sigqueue *q, struct pid *pid, enum pid_type type)
 {
        int sig = q->info.si_signo;
        struct sigpending *pending;
+       struct task_struct *t;
        unsigned long flags;
        int ret, result;
 
        BUG_ON(!(q->flags & SIGQUEUE_PREALLOC));
 
        ret = -1;
-       if (!likely(lock_task_sighand(t, &flags)))
+       rcu_read_lock();
+       t = pid_task(pid, type);
+       if (!t || !likely(lock_task_sighand(t, &flags)))
                goto ret;
 
        ret = 1; /* the signal is ignored */
@@ -1696,15 +1740,16 @@ int send_sigqueue(struct sigqueue *q, struct task_struct *t, int group)
        q->info.si_overrun = 0;
 
        signalfd_notify(t, sig);
-       pending = group ? &t->signal->shared_pending : &t->pending;
+       pending = (type != PIDTYPE_PID) ? &t->signal->shared_pending : &t->pending;
        list_add_tail(&q->list, &pending->list);
        sigaddset(&pending->signal, sig);
-       complete_signal(sig, t, group);
+       complete_signal(sig, t, type);
        result = TRACE_SIGNAL_DELIVERED;
 out:
-       trace_signal_generate(sig, &q->info, t, group, result);
+       trace_signal_generate(sig, &q->info, t, type != PIDTYPE_PID, result);
        unlock_task_sighand(t, &flags);
 ret:
+       rcu_read_unlock();
        return ret;
 }
 
@@ -1877,10 +1922,10 @@ static void do_notify_parent_cldstop(struct task_struct *tsk,
        spin_unlock_irqrestore(&sighand->siglock, flags);
 }
 
-static inline int may_ptrace_stop(void)
+static inline bool may_ptrace_stop(void)
 {
        if (!likely(current->ptrace))
-               return 0;
+               return false;
        /*
         * Are we in the middle of do_coredump?
         * If so and our tracer is also part of the coredump stopping
@@ -1896,19 +1941,19 @@ static inline int may_ptrace_stop(void)
         */
        if (unlikely(current->mm->core_state) &&
            unlikely(current->mm == current->parent->mm))
-               return 0;
+               return false;
 
-       return 1;
+       return true;
 }
 
 /*
  * Return non-zero if there is a SIGKILL that should be waking us up.
  * Called with the siglock held.
  */
-static int sigkill_pending(struct task_struct *tsk)
+static bool sigkill_pending(struct task_struct *tsk)
 {
-       return  sigismember(&tsk->pending.signal, SIGKILL) ||
-               sigismember(&tsk->signal->shared_pending.signal, SIGKILL);
+       return sigismember(&tsk->pending.signal, SIGKILL) ||
+              sigismember(&tsk->signal->shared_pending.signal, SIGKILL);
 }
 
 /*
@@ -2288,7 +2333,7 @@ static int ptrace_signal(int signr, siginfo_t *info)
        return signr;
 }
 
-int get_signal(struct ksignal *ksig)
+bool get_signal(struct ksignal *ksig)
 {
        struct sighand_struct *sighand = current->sighand;
        struct signal_struct *signal = current->signal;
@@ -2298,7 +2343,7 @@ int get_signal(struct ksignal *ksig)
                task_work_run();
 
        if (unlikely(uprobe_deny_signal()))
-               return 0;
+               return false;
 
        /*
         * Do this once, we can't return to user-mode if freezing() == T.
@@ -2755,7 +2800,7 @@ COMPAT_SYSCALL_DEFINE4(rt_sigprocmask, int, how, compat_sigset_t __user *, nset,
 }
 #endif
 
-static int do_sigpending(sigset_t *set)
+static void do_sigpending(sigset_t *set)
 {
        spin_lock_irq(&current->sighand->siglock);
        sigorsets(set, &current->pending.signal,
@@ -2764,7 +2809,6 @@ static int do_sigpending(sigset_t *set)
 
        /* Outside the lock because only this thread touches it.  */
        sigandsets(set, &current->blocked, set);
-       return 0;
 }
 
 /**
@@ -2776,15 +2820,16 @@ static int do_sigpending(sigset_t *set)
 SYSCALL_DEFINE2(rt_sigpending, sigset_t __user *, uset, size_t, sigsetsize)
 {
        sigset_t set;
-       int err;
 
        if (sigsetsize > sizeof(*uset))
                return -EINVAL;
 
-       err = do_sigpending(&set);
-       if (!err && copy_to_user(uset, &set, sigsetsize))
-               err = -EFAULT;
-       return err;
+       do_sigpending(&set);
+
+       if (copy_to_user(uset, &set, sigsetsize))
+               return -EFAULT;
+
+       return 0;
 }
 
 #ifdef CONFIG_COMPAT
@@ -2792,15 +2837,13 @@ COMPAT_SYSCALL_DEFINE2(rt_sigpending, compat_sigset_t __user *, uset,
                compat_size_t, sigsetsize)
 {
        sigset_t set;
-       int err;
 
        if (sigsetsize > sizeof(*uset))
                return -EINVAL;
 
-       err = do_sigpending(&set);
-       if (!err)
-               err = put_compat_sigset(uset, &set, sigsetsize);
-       return err;
+       do_sigpending(&set);
+
+       return put_compat_sigset(uset, &set, sigsetsize);
 }
 #endif
 
@@ -3193,7 +3236,7 @@ do_send_specific(pid_t tgid, pid_t pid, int sig, struct siginfo *info)
                 * probe.  No signal is actually delivered.
                 */
                if (!error && sig) {
-                       error = do_send_sig_info(sig, info, p, false);
+                       error = do_send_sig_info(sig, info, p, PIDTYPE_PID);
                        /*
                         * If lock_task_sighand() failed we pretend the task
                         * dies after receiving the signal. The window is tiny,
@@ -3562,25 +3605,26 @@ int __compat_save_altstack(compat_stack_t __user *uss, unsigned long sp)
 SYSCALL_DEFINE1(sigpending, old_sigset_t __user *, uset)
 {
        sigset_t set;
-       int err;
 
        if (sizeof(old_sigset_t) > sizeof(*uset))
                return -EINVAL;
 
-       err = do_sigpending(&set);
-       if (!err && copy_to_user(uset, &set, sizeof(old_sigset_t)))
-               err = -EFAULT;
-       return err;
+       do_sigpending(&set);
+
+       if (copy_to_user(uset, &set, sizeof(old_sigset_t)))
+               return -EFAULT;
+
+       return 0;
 }
 
 #ifdef CONFIG_COMPAT
 COMPAT_SYSCALL_DEFINE1(sigpending, compat_old_sigset_t __user *, set32)
 {
        sigset_t set;
-       int err = do_sigpending(&set);
-       if (!err)
-               err = put_user(set.sig[0], set32);
-       return err;
+
+       do_sigpending(&set);
+
+       return put_user(set.sig[0], set32);
 }
 #endif
 
@@ -3651,25 +3695,23 @@ SYSCALL_DEFINE4(rt_sigaction, int, sig,
                size_t, sigsetsize)
 {
        struct k_sigaction new_sa, old_sa;
-       int ret = -EINVAL;
+       int ret;
 
        /* XXX: Don't preclude handling different sized sigset_t's.  */
        if (sigsetsize != sizeof(sigset_t))
-               goto out;
+               return -EINVAL;
 
-       if (act) {
-               if (copy_from_user(&new_sa.sa, act, sizeof(new_sa.sa)))
-                       return -EFAULT;
-       }
+       if (act && copy_from_user(&new_sa.sa, act, sizeof(new_sa.sa)))
+               return -EFAULT;
 
        ret = do_sigaction(sig, act ? &new_sa : NULL, oact ? &old_sa : NULL);
+       if (ret)
+               return ret;
 
-       if (!ret && oact) {
-               if (copy_to_user(oact, &old_sa.sa, sizeof(old_sa.sa)))
-                       return -EFAULT;
-       }
-out:
-       return ret;
+       if (oact && copy_to_user(oact, &old_sa.sa, sizeof(old_sa.sa)))
+               return -EFAULT;
+
+       return 0;
 }
 #ifdef CONFIG_COMPAT
 COMPAT_SYSCALL_DEFINE4(rt_sigaction, int, sig,
@@ -3960,7 +4002,7 @@ void kdb_send_sig(struct task_struct *t, int sig)
                           "the deadlock.\n");
                return;
        }
-       ret = send_signal(sig, SEND_SIG_PRIV, t, false);
+       ret = send_signal(sig, SEND_SIG_PRIV, t, PIDTYPE_PID);
        spin_unlock(&t->sighand->siglock);
        if (ret)
                kdb_printf("Fail to deliver Signal %d to process %d.\n",
index e27b51d..cf5c675 100644 (file)
@@ -1237,18 +1237,19 @@ static int override_release(char __user *release, size_t len)
 
 SYSCALL_DEFINE1(newuname, struct new_utsname __user *, name)
 {
-       int errno = 0;
+       struct new_utsname tmp;
 
        down_read(&uts_sem);
-       if (copy_to_user(name, utsname(), sizeof *name))
-               errno = -EFAULT;
+       memcpy(&tmp, utsname(), sizeof(tmp));
        up_read(&uts_sem);
+       if (copy_to_user(name, &tmp, sizeof(tmp)))
+               return -EFAULT;
 
-       if (!errno && override_release(name->release, sizeof(name->release)))
-               errno = -EFAULT;
-       if (!errno && override_architecture(name))
-               errno = -EFAULT;
-       return errno;
+       if (override_release(name->release, sizeof(name->release)))
+               return -EFAULT;
+       if (override_architecture(name))
+               return -EFAULT;
+       return 0;
 }
 
 #ifdef __ARCH_WANT_SYS_OLD_UNAME
@@ -1257,55 +1258,46 @@ SYSCALL_DEFINE1(newuname, struct new_utsname __user *, name)
  */
 SYSCALL_DEFINE1(uname, struct old_utsname __user *, name)
 {
-       int error = 0;
+       struct old_utsname tmp;
 
        if (!name)
                return -EFAULT;
 
        down_read(&uts_sem);
-       if (copy_to_user(name, utsname(), sizeof(*name)))
-               error = -EFAULT;
+       memcpy(&tmp, utsname(), sizeof(tmp));
        up_read(&uts_sem);
+       if (copy_to_user(name, &tmp, sizeof(tmp)))
+               return -EFAULT;
 
-       if (!error && override_release(name->release, sizeof(name->release)))
-               error = -EFAULT;
-       if (!error && override_architecture(name))
-               error = -EFAULT;
-       return error;
+       if (override_release(name->release, sizeof(name->release)))
+               return -EFAULT;
+       if (override_architecture(name))
+               return -EFAULT;
+       return 0;
 }
 
 SYSCALL_DEFINE1(olduname, struct oldold_utsname __user *, name)
 {
-       int error;
+       struct oldold_utsname tmp = {};
 
        if (!name)
                return -EFAULT;
-       if (!access_ok(VERIFY_WRITE, name, sizeof(struct oldold_utsname)))
-               return -EFAULT;
 
        down_read(&uts_sem);
-       error = __copy_to_user(&name->sysname, &utsname()->sysname,
-                              __OLD_UTS_LEN);
-       error |= __put_user(0, name->sysname + __OLD_UTS_LEN);
-       error |= __copy_to_user(&name->nodename, &utsname()->nodename,
-                               __OLD_UTS_LEN);
-       error |= __put_user(0, name->nodename + __OLD_UTS_LEN);
-       error |= __copy_to_user(&name->release, &utsname()->release,
-                               __OLD_UTS_LEN);
-       error |= __put_user(0, name->release + __OLD_UTS_LEN);
-       error |= __copy_to_user(&name->version, &utsname()->version,
-                               __OLD_UTS_LEN);
-       error |= __put_user(0, name->version + __OLD_UTS_LEN);
-       error |= __copy_to_user(&name->machine, &utsname()->machine,
-                               __OLD_UTS_LEN);
-       error |= __put_user(0, name->machine + __OLD_UTS_LEN);
+       memcpy(&tmp.sysname, &utsname()->sysname, __OLD_UTS_LEN);
+       memcpy(&tmp.nodename, &utsname()->nodename, __OLD_UTS_LEN);
+       memcpy(&tmp.release, &utsname()->release, __OLD_UTS_LEN);
+       memcpy(&tmp.version, &utsname()->version, __OLD_UTS_LEN);
+       memcpy(&tmp.machine, &utsname()->machine, __OLD_UTS_LEN);
        up_read(&uts_sem);
+       if (copy_to_user(name, &tmp, sizeof(tmp)))
+               return -EFAULT;
 
-       if (!error && override_architecture(name))
-               error = -EFAULT;
-       if (!error && override_release(name->release, sizeof(name->release)))
-               error = -EFAULT;
-       return error ? -EFAULT : 0;
+       if (override_architecture(name))
+               return -EFAULT;
+       if (override_release(name->release, sizeof(name->release)))
+               return -EFAULT;
+       return 0;
 }
 #endif
 
@@ -1319,17 +1311,18 @@ SYSCALL_DEFINE2(sethostname, char __user *, name, int, len)
 
        if (len < 0 || len > __NEW_UTS_LEN)
                return -EINVAL;
-       down_write(&uts_sem);
        errno = -EFAULT;
        if (!copy_from_user(tmp, name, len)) {
-               struct new_utsname *u = utsname();
+               struct new_utsname *u;
 
+               down_write(&uts_sem);
+               u = utsname();
                memcpy(u->nodename, tmp, len);
                memset(u->nodename + len, 0, sizeof(u->nodename) - len);
                errno = 0;
                uts_proc_notify(UTS_PROC_HOSTNAME);
+               up_write(&uts_sem);
        }
-       up_write(&uts_sem);
        return errno;
 }
 
@@ -1337,8 +1330,9 @@ SYSCALL_DEFINE2(sethostname, char __user *, name, int, len)
 
 SYSCALL_DEFINE2(gethostname, char __user *, name, int, len)
 {
-       int i, errno;
+       int i;
        struct new_utsname *u;
+       char tmp[__NEW_UTS_LEN + 1];
 
        if (len < 0)
                return -EINVAL;
@@ -1347,11 +1341,11 @@ SYSCALL_DEFINE2(gethostname, char __user *, name, int, len)
        i = 1 + strlen(u->nodename);
        if (i > len)
                i = len;
-       errno = 0;
-       if (copy_to_user(name, u->nodename, i))
-               errno = -EFAULT;
+       memcpy(tmp, u->nodename, i);
        up_read(&uts_sem);
-       return errno;
+       if (copy_to_user(name, tmp, i))
+               return -EFAULT;
+       return 0;
 }
 
 #endif
@@ -1370,17 +1364,18 @@ SYSCALL_DEFINE2(setdomainname, char __user *, name, int, len)
        if (len < 0 || len > __NEW_UTS_LEN)
                return -EINVAL;
 
-       down_write(&uts_sem);
        errno = -EFAULT;
        if (!copy_from_user(tmp, name, len)) {
-               struct new_utsname *u = utsname();
+               struct new_utsname *u;
 
+               down_write(&uts_sem);
+               u = utsname();
                memcpy(u->domainname, tmp, len);
                memset(u->domainname + len, 0, sizeof(u->domainname) - len);
                errno = 0;
                uts_proc_notify(UTS_PROC_DOMAINNAME);
+               up_write(&uts_sem);
        }
-       up_write(&uts_sem);
        return errno;
 }
 
index f22f76b..cc02050 100644 (file)
@@ -145,7 +145,10 @@ static int minolduid;
 static int ngroups_max = NGROUPS_MAX;
 static const int cap_last_cap = CAP_LAST_CAP;
 
-/*this is needed for proc_doulongvec_minmax of sysctl_hung_task_timeout_secs */
+/*
+ * This is needed for proc_doulongvec_minmax of sysctl_hung_task_timeout_secs
+ * and hung_task_check_interval_secs
+ */
 #ifdef CONFIG_DETECT_HUNG_TASK
 static unsigned long hung_task_timeout_max = (LONG_MAX/HZ);
 #endif
@@ -222,7 +225,7 @@ static int proc_dopipe_max_size(struct ctl_table *table, int write,
                void __user *buffer, size_t *lenp, loff_t *ppos);
 
 #ifdef CONFIG_MAGIC_SYSRQ
-/* Note: sysrq code uses it's own private copy */
+/* Note: sysrq code uses its own private copy */
 static int __sysrq_enabled = CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE;
 
 static int sysrq_sysctl_handler(struct ctl_table *table, int write,
@@ -1091,6 +1094,14 @@ static struct ctl_table kern_table[] = {
                .extra2         = &hung_task_timeout_max,
        },
        {
+               .procname       = "hung_task_check_interval_secs",
+               .data           = &sysctl_hung_task_check_interval_secs,
+               .maxlen         = sizeof(unsigned long),
+               .mode           = 0644,
+               .proc_handler   = proc_dohung_task_timeout_secs,
+               .extra2         = &hung_task_timeout_max,
+       },
+       {
                .procname       = "hung_task_warnings",
                .data           = &sysctl_hung_task_warnings,
                .maxlen         = sizeof(int),
@@ -1797,6 +1808,24 @@ static struct ctl_table fs_table[] = {
                .extra2         = &one,
        },
        {
+               .procname       = "protected_fifos",
+               .data           = &sysctl_protected_fifos,
+               .maxlen         = sizeof(int),
+               .mode           = 0600,
+               .proc_handler   = proc_dointvec_minmax,
+               .extra1         = &zero,
+               .extra2         = &two,
+       },
+       {
+               .procname       = "protected_regular",
+               .data           = &sysctl_protected_regular,
+               .maxlen         = sizeof(int),
+               .mode           = 0600,
+               .proc_handler   = proc_dointvec_minmax,
+               .extra1         = &zero,
+               .extra2         = &two,
+       },
+       {
                .procname       = "suid_dumpable",
                .data           = &suid_dumpable,
                .maxlen         = sizeof(int),
@@ -1965,13 +1994,13 @@ static void warn_sysctl_write(struct ctl_table *table)
 }
 
 /**
- * proc_first_pos_non_zero_ignore - check if firs position is allowed
+ * proc_first_pos_non_zero_ignore - check if first position is allowed
  * @ppos: file position
  * @table: the sysctl table
  *
  * Returns true if the first position is non-zero and the sysctl_writes_strict
  * mode indicates this is not allowed for numeric input types. String proc
- * hadlers can ignore the return value.
+ * handlers can ignore the return value.
  */
 static bool proc_first_pos_non_zero_ignore(loff_t *ppos,
                                           struct ctl_table *table)
index f26acef..9a65713 100644 (file)
@@ -139,9 +139,10 @@ enum hrtimer_restart it_real_fn(struct hrtimer *timer)
 {
        struct signal_struct *sig =
                container_of(timer, struct signal_struct, real_timer);
+       struct pid *leader_pid = sig->pids[PIDTYPE_TGID];
 
-       trace_itimer_expire(ITIMER_REAL, sig->leader_pid, 0);
-       kill_pid_info(SIGALRM, SEND_SIG_PRIV, sig->leader_pid);
+       trace_itimer_expire(ITIMER_REAL, leader_pid, 0);
+       kill_pid_info(SIGALRM, SEND_SIG_PRIV, leader_pid);
 
        return HRTIMER_NORESTART;
 }
index 294d7b6..ce32cf7 100644 (file)
@@ -894,7 +894,7 @@ static void check_cpu_itimer(struct task_struct *tsk, struct cpu_itimer *it,
 
                trace_itimer_expire(signo == SIGPROF ?
                                    ITIMER_PROF : ITIMER_VIRTUAL,
-                                   tsk->signal->leader_pid, cur_time);
+                                   task_tgid(tsk), cur_time);
                __group_send_sig_info(signo, SEND_SIG_PRIV, tsk);
        }
 
index f23cc46..4b9127e 100644 (file)
@@ -333,8 +333,8 @@ void posixtimer_rearm(struct siginfo *info)
 
 int posix_timer_event(struct k_itimer *timr, int si_private)
 {
-       struct task_struct *task;
-       int shared, ret = -1;
+       enum pid_type type;
+       int ret = -1;
        /*
         * FIXME: if ->sigq is queued we can race with
         * dequeue_signal()->posixtimer_rearm().
@@ -348,13 +348,8 @@ int posix_timer_event(struct k_itimer *timr, int si_private)
         */
        timr->sigq->info.si_sys_private = si_private;
 
-       rcu_read_lock();
-       task = pid_task(timr->it_pid, PIDTYPE_PID);
-       if (task) {
-               shared = !(timr->it_sigev_notify & SIGEV_THREAD_ID);
-               ret = send_sigqueue(timr->sigq, task, shared);
-       }
-       rcu_read_unlock();
+       type = !(timr->it_sigev_notify & SIGEV_THREAD_ID) ? PIDTYPE_TGID : PIDTYPE_PID;
+       ret = send_sigqueue(timr->sigq, timr->it_pid, type);
        /* If we failed to send the signal the timer stops. */
        return ret > 0;
 }
@@ -433,11 +428,13 @@ static enum hrtimer_restart posix_timer_fn(struct hrtimer *timer)
 
 static struct pid *good_sigevent(sigevent_t * event)
 {
-       struct task_struct *rtn = current->group_leader;
+       struct pid *pid = task_tgid(current);
+       struct task_struct *rtn;
 
        switch (event->sigev_notify) {
        case SIGEV_SIGNAL | SIGEV_THREAD_ID:
-               rtn = find_task_by_vpid(event->sigev_notify_thread_id);
+               pid = find_vpid(event->sigev_notify_thread_id);
+               rtn = pid_task(pid, PIDTYPE_PID);
                if (!rtn || !same_thread_group(rtn, current))
                        return NULL;
                /* FALLTHRU */
@@ -447,7 +444,7 @@ static struct pid *good_sigevent(sigevent_t * event)
                        return NULL;
                /* FALLTHRU */
        case SIGEV_NONE:
-               return task_pid(rtn);
+               return pid;
        default:
                return NULL;
        }
index 9a27f14..5e3de28 100644 (file)
@@ -47,6 +47,11 @@ config HAVE_FENTRY
        help
          Arch supports the gcc options -pg with -mfentry
 
+config HAVE_NOP_MCOUNT
+       bool
+       help
+         Arch supports the gcc options -pg with -mrecord-mcount and -nop-mcount
+
 config HAVE_C_RECORDMCOUNT
        bool
        help
@@ -82,6 +87,15 @@ config RING_BUFFER_ALLOW_SWAP
         Allow the use of ring_buffer_swap_cpu.
         Adds a very slight overhead to tracing when enabled.
 
+config PREEMPTIRQ_TRACEPOINTS
+       bool
+       depends on TRACE_PREEMPT_TOGGLE || TRACE_IRQFLAGS
+       select TRACING
+       default y
+       help
+         Create preempt/irq toggle tracepoints if needed, so that other parts
+         of the kernel can use them to generate or add hooks to them.
+
 # All tracer options should select GENERIC_TRACER. For those options that are
 # enabled by all tracers (context switch and event tracer) they select TRACING.
 # This allows those options to appear when no other tracer is selected. But the
@@ -155,18 +169,20 @@ config FUNCTION_GRAPH_TRACER
          the return value. This is done by setting the current return
          address on the current task structure into a stack of calls.
 
+config TRACE_PREEMPT_TOGGLE
+       bool
+       help
+         Enables hooks which will be called when preemption is first disabled,
+         and last enabled.
 
 config PREEMPTIRQ_EVENTS
        bool "Enable trace events for preempt and irq disable/enable"
        select TRACE_IRQFLAGS
-       depends on DEBUG_PREEMPT || !PROVE_LOCKING
-       depends on TRACING
+       select TRACE_PREEMPT_TOGGLE if PREEMPT
+       select GENERIC_TRACER
        default n
        help
          Enable tracing of disable and enable events for preemption and irqs.
-         For tracing preempt disable/enable events, DEBUG_PREEMPT must be
-         enabled. For tracing irq disable/enable events, PROVE_LOCKING must
-         be disabled.
 
 config IRQSOFF_TRACER
        bool "Interrupts-off Latency Tracer"
@@ -203,6 +219,7 @@ config PREEMPT_TRACER
        select RING_BUFFER_ALLOW_SWAP
        select TRACER_SNAPSHOT
        select TRACER_SNAPSHOT_PER_CPU_SWAP
+       select TRACE_PREEMPT_TOGGLE
        help
          This option measures the time spent in preemption-off critical
          sections, with microsecond accuracy.
@@ -456,6 +473,26 @@ config KPROBE_EVENTS
          This option is also required by perf-probe subcommand of perf tools.
          If you want to use perf tools, this option is strongly recommended.
 
+config KPROBE_EVENTS_ON_NOTRACE
+       bool "Do NOT protect notrace function from kprobe events"
+       depends on KPROBE_EVENTS
+       depends on KPROBES_ON_FTRACE
+       default n
+       help
+         This is only for the developers who want to debug ftrace itself
+         using kprobe events.
+
+         If kprobes can use ftrace instead of breakpoint, ftrace related
+         functions are protected from kprobe-events to prevent an infinit
+         recursion or any unexpected execution path which leads to a kernel
+         crash.
+
+         This option disables such protection and allows you to put kprobe
+         events on ftrace functions for debugging ftrace by itself.
+         Note that this might let you shoot yourself in the foot.
+
+         If unsure, say N.
+
 config UPROBE_EVENTS
        bool "Enable uprobes-based dynamic events"
        depends on ARCH_SUPPORTS_UPROBES
@@ -687,6 +724,21 @@ config RING_BUFFER_STARTUP_TEST
 
         If unsure, say N
 
+config PREEMPTIRQ_DELAY_TEST
+       tristate "Preempt / IRQ disable delay thread to test latency tracers"
+       depends on m
+       help
+         Select this option to build a test module that can help test latency
+         tracers by executing a preempt or irq disable section with a user
+         configurable delay. The module busy waits for the duration of the
+         critical section.
+
+         For example, the following invocation forces a one-time irq-disabled
+         critical section for 500us:
+         modprobe preemptirq_delay_test test_mode=irq delay=500000
+
+         If unsure, say N
+
 config TRACE_EVAL_MAP_FILE
        bool "Show eval mappings for trace events"
        depends on TRACING
@@ -722,6 +774,18 @@ config TRACING_EVENTS_GPIO
        help
          Enable tracing events for gpio subsystem
 
+config GCOV_PROFILE_FTRACE
+       bool "Enable GCOV profiling on ftrace subsystem"
+       depends on GCOV_KERNEL
+       help
+         Enable GCOV profiling on ftrace subsystem for checking
+         which functions/lines are tested.
+
+         If unsure, say N.
+
+         Note that on a kernel compiled with this config, ftrace will
+         run significantly slower.
+
 endif # FTRACE
 
 endif # TRACING_SUPPORT
index e2538c7..f81dadb 100644 (file)
@@ -13,11 +13,21 @@ obj-y += trace_selftest_dynamic.o
 endif
 endif
 
+ifdef CONFIG_FTRACE_STARTUP_TEST
+CFLAGS_trace_kprobe_selftest.o = $(CC_FLAGS_FTRACE)
+obj-$(CONFIG_KPROBE_EVENTS) += trace_kprobe_selftest.o
+endif
+
 # If unlikely tracing is enabled, do not trace these files
 ifdef CONFIG_TRACING_BRANCHES
 KBUILD_CFLAGS += -DDISABLE_BRANCH_PROFILING
 endif
 
+# for GCOV coverage profiling
+ifdef CONFIG_GCOV_PROFILE_FTRACE
+GCOV_PROFILE := y
+endif
+
 CFLAGS_trace_benchmark.o := -I$(src)
 CFLAGS_trace_events_filter.o := -I$(src)
 
@@ -33,9 +43,10 @@ obj-$(CONFIG_TRACING) += trace_seq.o
 obj-$(CONFIG_TRACING) += trace_stat.o
 obj-$(CONFIG_TRACING) += trace_printk.o
 obj-$(CONFIG_TRACING_MAP) += tracing_map.o
+obj-$(CONFIG_PREEMPTIRQ_DELAY_TEST) += preemptirq_delay_test.o
 obj-$(CONFIG_CONTEXT_SWITCH_TRACER) += trace_sched_switch.o
 obj-$(CONFIG_FUNCTION_TRACER) += trace_functions.o
-obj-$(CONFIG_PREEMPTIRQ_EVENTS) += trace_irqsoff.o
+obj-$(CONFIG_PREEMPTIRQ_TRACEPOINTS) += trace_preemptirq.o
 obj-$(CONFIG_IRQSOFF_TRACER) += trace_irqsoff.o
 obj-$(CONFIG_PREEMPT_TRACER) += trace_irqsoff.o
 obj-$(CONFIG_SCHED_TRACER) += trace_sched_wakeup.o
index b951aa1..2868d85 100644 (file)
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2006 Jens Axboe <axboe@kernel.dk>
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- *
  */
 #include <linux/kernel.h>
 #include <linux/blkdev.h>
@@ -1841,6 +1829,10 @@ static ssize_t sysfs_blk_trace_attr_store(struct device *dev,
        mutex_lock(&q->blk_trace_mutex);
 
        if (attr == &dev_attr_enable) {
+               if (!!value == !!q->blk_trace) {
+                       ret = 0;
+                       goto out_unlock_bdev;
+               }
                if (value)
                        ret = blk_trace_setup_queue(q, bdev);
                else
index 0ae6829..08fcfe4 100644 (file)
@@ -1,9 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
 /* Copyright (c) 2011-2015 PLUMgrid, http://plumgrid.com
  * Copyright (c) 2016 Facebook
- *
- * 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/kernel.h>
 #include <linux/types.h>
index caf9cbf..f536f60 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Infrastructure for profiling code inserted by 'gcc -pg'.
  *
@@ -157,30 +158,6 @@ static inline void ftrace_ops_init(struct ftrace_ops *ops)
 #endif
 }
 
-/**
- * ftrace_nr_registered_ops - return number of ops registered
- *
- * Returns the number of ftrace_ops registered and tracing functions
- */
-int ftrace_nr_registered_ops(void)
-{
-       struct ftrace_ops *ops;
-       int cnt = 0;
-
-       mutex_lock(&ftrace_lock);
-
-       for (ops = rcu_dereference_protected(ftrace_ops_list,
-                                            lockdep_is_held(&ftrace_lock));
-            ops != &ftrace_list_end;
-            ops = rcu_dereference_protected(ops->next,
-                                            lockdep_is_held(&ftrace_lock)))
-               cnt++;
-
-       mutex_unlock(&ftrace_lock);
-
-       return cnt;
-}
-
 static void ftrace_pid_func(unsigned long ip, unsigned long parent_ip,
                            struct ftrace_ops *op, struct pt_regs *regs)
 {
@@ -313,11 +290,6 @@ static void update_ftrace_function(void)
        ftrace_trace_function = func;
 }
 
-int using_ftrace_ops_list_func(void)
-{
-       return ftrace_trace_function == ftrace_ops_list_func;
-}
-
 static void add_ftrace_ops(struct ftrace_ops __rcu **list,
                           struct ftrace_ops *ops)
 {
@@ -1049,8 +1021,6 @@ static __init void ftrace_profile_tracefs(struct dentry *d_tracer)
 }
 #endif /* CONFIG_FUNCTION_PROFILER */
 
-static struct pid * const ftrace_swapper_pid = &init_struct_pid;
-
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
 static int ftrace_graph_active;
 #else
@@ -2927,22 +2897,22 @@ ops_references_rec(struct ftrace_ops *ops, struct dyn_ftrace *rec)
 {
        /* If ops isn't enabled, ignore it */
        if (!(ops->flags & FTRACE_OPS_FL_ENABLED))
-               return 0;
+               return false;
 
        /* If ops traces all then it includes this function */
        if (ops_traces_mod(ops))
-               return 1;
+               return true;
 
        /* The function must be in the filter */
        if (!ftrace_hash_empty(ops->func_hash->filter_hash) &&
            !__ftrace_lookup_ip(ops->func_hash->filter_hash, rec->ip))
-               return 0;
+               return false;
 
        /* If in notrace hash, we ignore it too */
        if (ftrace_lookup_ip(ops->func_hash->notrace_hash, rec->ip))
-               return 0;
+               return false;
 
-       return 1;
+       return true;
 }
 
 static int ftrace_update_code(struct module *mod, struct ftrace_page *new_pgs)
@@ -2981,12 +2951,14 @@ static int ftrace_update_code(struct module *mod, struct ftrace_page *new_pgs)
                        p = &pg->records[i];
                        p->flags = rec_flags;
 
+#ifndef CC_USING_NOP_MCOUNT
                        /*
                         * Do the initial record conversion from mcount jump
                         * to the NOP instructions.
                         */
                        if (!ftrace_code_disable(mod, p))
                                break;
+#endif
 
                        update_cnt++;
                }
diff --git a/kernel/trace/preemptirq_delay_test.c b/kernel/trace/preemptirq_delay_test.c
new file mode 100644 (file)
index 0000000..f704390
--- /dev/null
@@ -0,0 +1,72 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Preempt / IRQ disable delay thread to test latency tracers
+ *
+ * Copyright (C) 2018 Joel Fernandes (Google) <joel@joelfernandes.org>
+ */
+
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/kthread.h>
+#include <linux/ktime.h>
+#include <linux/module.h>
+#include <linux/printk.h>
+#include <linux/string.h>
+
+static ulong delay = 100;
+static char test_mode[10] = "irq";
+
+module_param_named(delay, delay, ulong, S_IRUGO);
+module_param_string(test_mode, test_mode, 10, S_IRUGO);
+MODULE_PARM_DESC(delay, "Period in microseconds (100 uS default)");
+MODULE_PARM_DESC(test_mode, "Mode of the test such as preempt or irq (default irq)");
+
+static void busy_wait(ulong time)
+{
+       ktime_t start, end;
+       start = ktime_get();
+       do {
+               end = ktime_get();
+               if (kthread_should_stop())
+                       break;
+       } while (ktime_to_ns(ktime_sub(end, start)) < (time * 1000));
+}
+
+static int preemptirq_delay_run(void *data)
+{
+       unsigned long flags;
+
+       if (!strcmp(test_mode, "irq")) {
+               local_irq_save(flags);
+               busy_wait(delay);
+               local_irq_restore(flags);
+       } else if (!strcmp(test_mode, "preempt")) {
+               preempt_disable();
+               busy_wait(delay);
+               preempt_enable();
+       }
+
+       return 0;
+}
+
+static int __init preemptirq_delay_init(void)
+{
+       char task_name[50];
+       struct task_struct *test_task;
+
+       snprintf(task_name, sizeof(task_name), "%s_test", test_mode);
+
+       test_task = kthread_run(preemptirq_delay_run, NULL, task_name);
+       return PTR_ERR_OR_ZERO(test_task);
+}
+
+static void __exit preemptirq_delay_exit(void)
+{
+       return;
+}
+
+module_init(preemptirq_delay_init)
+module_exit(preemptirq_delay_exit)
+MODULE_LICENSE("GPL v2");
index 0b0b688..1d92d4a 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Generic ring buffer
  *
@@ -3221,7 +3222,7 @@ EXPORT_SYMBOL_GPL(ring_buffer_record_on);
  *
  * Returns true if the ring buffer is in a state that it accepts writes.
  */
-int ring_buffer_record_is_on(struct ring_buffer *buffer)
+bool ring_buffer_record_is_on(struct ring_buffer *buffer)
 {
        return !atomic_read(&buffer->record_disabled);
 }
@@ -3237,7 +3238,7 @@ int ring_buffer_record_is_on(struct ring_buffer *buffer)
  * ring_buffer_record_disable(), as that is a temporary disabling of
  * the ring buffer.
  */
-int ring_buffer_record_is_set_on(struct ring_buffer *buffer)
+bool ring_buffer_record_is_set_on(struct ring_buffer *buffer)
 {
        return !(atomic_read(&buffer->record_disabled) & RB_BUFFER_OFF);
 }
index 68ee79a..ffba678 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * ring buffer tester and benchmark
  *
index 176debd..bf6f1d7 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * ring buffer based function tracer
  *
@@ -1087,7 +1088,7 @@ void disable_trace_on_warning(void)
  *
  * Shows real state of the ring buffer if it is enabled or not.
  */
-int tracer_tracing_is_on(struct trace_array *tr)
+bool tracer_tracing_is_on(struct trace_array *tr)
 {
        if (tr->trace_buffer.buffer)
                return ring_buffer_record_is_on(tr->trace_buffer.buffer);
@@ -7628,7 +7629,9 @@ rb_simple_write(struct file *filp, const char __user *ubuf,
 
        if (buffer) {
                mutex_lock(&trace_types_lock);
-               if (val) {
+               if (!!val == tracer_tracing_is_on(tr)) {
+                       val = 0; /* do nothing */
+               } else if (val) {
                        tracer_tracing_on(tr);
                        if (tr->current_trace->start)
                                tr->current_trace->start(tr);
index f8f8623..3b8c0e2 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+// SPDX-License-Identifier: GPL-2.0
 
 #ifndef _LINUX_KERNEL_TRACE_H
 #define _LINUX_KERNEL_TRACE_H
@@ -594,7 +594,7 @@ void tracing_reset_current(int cpu);
 void tracing_reset_all_online_cpus(void);
 int tracing_open_generic(struct inode *inode, struct file *filp);
 bool tracing_is_disabled(void);
-int tracer_tracing_is_on(struct trace_array *tr);
+bool tracer_tracing_is_on(struct trace_array *tr);
 void tracer_tracing_on(struct trace_array *tr);
 void tracer_tracing_off(struct trace_array *tr);
 struct dentry *trace_create_file(const char *name,
@@ -937,7 +937,6 @@ void ftrace_destroy_function_files(struct trace_array *tr);
 void ftrace_init_global_array_ops(struct trace_array *tr);
 void ftrace_init_array_ops(struct trace_array *tr, ftrace_func_t func);
 void ftrace_reset_array_ops(struct trace_array *tr);
-int using_ftrace_ops_list_func(void);
 void ftrace_init_tracefs(struct trace_array *tr, struct dentry *d_tracer);
 void ftrace_init_tracefs_toplevel(struct trace_array *tr,
                                  struct dentry *d_tracer);
@@ -1533,9 +1532,6 @@ extern int event_trigger_init(struct event_trigger_ops *ops,
 extern int trace_event_trigger_enable_disable(struct trace_event_file *file,
                                              int trigger_enable);
 extern void update_cond_flag(struct trace_event_file *file);
-extern void unregister_trigger(char *glob, struct event_trigger_ops *ops,
-                              struct event_trigger_data *test,
-                              struct trace_event_file *file);
 extern int set_trigger_filter(char *filter_str,
                              struct event_trigger_data *trigger_data,
                              struct trace_event_file *file);
@@ -1831,6 +1827,21 @@ static inline int tracing_alloc_snapshot_instance(struct trace_array *tr)
 }
 #endif
 
+#ifdef CONFIG_PREEMPT_TRACER
+void tracer_preempt_on(unsigned long a0, unsigned long a1);
+void tracer_preempt_off(unsigned long a0, unsigned long a1);
+#else
+static inline void tracer_preempt_on(unsigned long a0, unsigned long a1) { }
+static inline void tracer_preempt_off(unsigned long a0, unsigned long a1) { }
+#endif
+#ifdef CONFIG_IRQSOFF_TRACER
+void tracer_hardirqs_on(unsigned long a0, unsigned long a1);
+void tracer_hardirqs_off(unsigned long a0, unsigned long a1);
+#else
+static inline void tracer_hardirqs_on(unsigned long a0, unsigned long a1) { }
+static inline void tracer_hardirqs_off(unsigned long a0, unsigned long a1) { }
+#endif
+
 extern struct trace_iterator *tracepoint_print_iter;
 
 #endif /* _LINUX_KERNEL_TRACE_H */
index be1d86f..79e6fbe 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+// SPDX-License-Identifier: GPL-2.0
 #undef TRACE_SYSTEM
 #define TRACE_SYSTEM benchmark
 
index d8a188e..aaf6793 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * tracing clocks
  *
index 1d67464..06bb2fd 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+// SPDX-License-Identifier: GPL-2.0
 /*
  * This file defines the trace event structures that go into the ring
  * buffer directly. They are created via macros so that changes for them
index c79193e..69a3fe9 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * trace event based perf event profiling/tracing
  *
index 14ff4ff..f94be0c 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * event tracer
  *
@@ -239,7 +240,7 @@ bool trace_event_ignore_this_pid(struct trace_event_file *trace_file)
        struct trace_array_cpu *data;
        struct trace_pid_list *pid_list;
 
-       pid_list = rcu_dereference_sched(tr->filtered_pids);
+       pid_list = rcu_dereference_raw(tr->filtered_pids);
        if (!pid_list)
                return false;
 
@@ -512,7 +513,7 @@ event_filter_pid_sched_process_exit(void *data, struct task_struct *task)
        struct trace_pid_list *pid_list;
        struct trace_array *tr = data;
 
-       pid_list = rcu_dereference_sched(tr->filtered_pids);
+       pid_list = rcu_dereference_raw(tr->filtered_pids);
        trace_filter_add_remove_task(pid_list, NULL, task);
 }
 
@@ -636,7 +637,7 @@ static void __ftrace_clear_event_pids(struct trace_array *tr)
        rcu_assign_pointer(tr->filtered_pids, NULL);
 
        /* Wait till all users are no longer using pid filtering */
-       synchronize_sched();
+       tracepoint_synchronize_unregister();
 
        trace_free_pid_list(pid_list);
 }
@@ -1622,7 +1623,7 @@ ftrace_event_pid_write(struct file *filp, const char __user *ubuf,
        }
 
        if (filtered_pids) {
-               synchronize_sched();
+               tracepoint_synchronize_unregister();
                trace_free_pid_list(filtered_pids);
        } else if (pid_list) {
                /*
@@ -3036,8 +3037,8 @@ int event_trace_del_tracer(struct trace_array *tr)
        /* Disable any running events */
        __ftrace_set_clr_event_nolock(tr, NULL, NULL, NULL, 0);
 
-       /* Access to events are within rcu_read_lock_sched() */
-       synchronize_sched();
+       /* Make sure no more events are being executed */
+       tracepoint_synchronize_unregister();
 
        down_write(&trace_event_sem);
        __trace_remove_event_dirs(tr);
index 893a206..84a6517 100644 (file)
@@ -1,20 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * trace_events_filter - generic event filtering
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
  * Copyright (C) 2009 Tom Zanussi <tzanussi@gmail.com>
  */
 
@@ -899,7 +886,8 @@ int filter_match_preds(struct event_filter *filter, void *rec)
        if (!filter)
                return 1;
 
-       prog = rcu_dereference_sched(filter->prog);
+       /* Protected by either SRCU(tracepoint_srcu) or preempt_disable */
+       prog = rcu_dereference_raw(filter->prog);
        if (!prog)
                return 1;
 
@@ -1626,10 +1614,10 @@ static int process_system_preds(struct trace_subsystem_dir *dir,
 
        /*
         * The calls can still be using the old filters.
-        * Do a synchronize_sched() to ensure all calls are
+        * Do a synchronize_sched() and to ensure all calls are
         * done with them before we free them.
         */
-       synchronize_sched();
+       tracepoint_synchronize_unregister();
        list_for_each_entry_safe(filter_item, tmp, &filter_list, list) {
                __free_filter(filter_item->filter);
                list_del(&filter_item->list);
@@ -1648,7 +1636,7 @@ static int process_system_preds(struct trace_subsystem_dir *dir,
        kfree(filter);
        /* If any call succeeded, we still need to sync */
        if (!fail)
-               synchronize_sched();
+               tracepoint_synchronize_unregister();
        list_for_each_entry_safe(filter_item, tmp, &filter_list, list) {
                __free_filter(filter_item->filter);
                list_del(&filter_item->list);
@@ -1790,7 +1778,7 @@ int apply_event_filter(struct trace_event_file *file, char *filter_string)
                event_clear_filter(file);
 
                /* Make sure the filter is not being used */
-               synchronize_sched();
+               tracepoint_synchronize_unregister();
                __free_filter(filter);
 
                return 0;
@@ -1817,7 +1805,7 @@ int apply_event_filter(struct trace_event_file *file, char *filter_string)
 
                if (tmp) {
                        /* Make sure the call is done with the filter */
-                       synchronize_sched();
+                       tracepoint_synchronize_unregister();
                        __free_filter(tmp);
                }
        }
@@ -1847,7 +1835,7 @@ int apply_subsystem_event_filter(struct trace_subsystem_dir *dir,
                filter = system->filter;
                system->filter = NULL;
                /* Ensure all filters are no longer used */
-               synchronize_sched();
+               tracepoint_synchronize_unregister();
                filter_free_subsystem_filters(dir, tr);
                __free_filter(filter);
                goto out_unlock;
index 39d7ef4..e651dfb 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+// SPDX-License-Identifier: GPL-2.0
 #undef TRACE_SYSTEM
 #define TRACE_SYSTEM test
 
index aae18af..85f6b01 100644 (file)
@@ -1,16 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * trace_events_hist - trace event hist triggers
  *
- * 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.
- *
  * Copyright (C) 2015 Tom Zanussi <tom.zanussi@linux.intel.com>
  */
 
@@ -5141,7 +5132,7 @@ static void hist_clear(struct event_trigger_data *data)
        if (data->name)
                pause_named_trigger(data);
 
-       synchronize_sched();
+       tracepoint_synchronize_unregister();
 
        tracing_map_clear(hist_data->map);
 
index 5dea177..2152d1e 100644 (file)
@@ -1,20 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * trace_events_trigger - trace event triggers
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
  * Copyright (C) 2013 Tom Zanussi <tom.zanussi@linux.intel.com>
  */
 
@@ -34,7 +21,9 @@ void trigger_data_free(struct event_trigger_data *data)
        if (data->cmd_ops->set_filter)
                data->cmd_ops->set_filter(NULL, data, NULL);
 
-       synchronize_sched(); /* make sure current triggers exit before free */
+       /* make sure current triggers exit before free */
+       tracepoint_synchronize_unregister();
+
        kfree(data);
 }
 
@@ -579,9 +568,9 @@ out:
  * Usually used directly as the @unreg method in event command
  * implementations.
  */
-void unregister_trigger(char *glob, struct event_trigger_ops *ops,
-                       struct event_trigger_data *test,
-                       struct trace_event_file *file)
+static void unregister_trigger(char *glob, struct event_trigger_ops *ops,
+                              struct event_trigger_data *test,
+                              struct trace_event_file *file)
 {
        struct event_trigger_data *data;
        bool unregistered = false;
@@ -752,7 +741,7 @@ int set_trigger_filter(char *filter_str,
 
        if (tmp) {
                /* Make sure the call is done with the filter */
-               synchronize_sched();
+               tracepoint_synchronize_unregister();
                free_event_filter(tmp);
        }
 
index d7c8e4e..1e6db9c 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * trace_hwlatdetect.c - A simple Hardware Latency detector.
  *
@@ -35,9 +36,6 @@
  *
  * Includes useful feedback from Clark Williams <clark@redhat.com>
  *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
  */
 #include <linux/kthread.h>
 #include <linux/tracefs.h>
@@ -354,6 +352,9 @@ static int start_kthread(struct trace_array *tr)
        struct task_struct *kthread;
        int next_cpu;
 
+       if (WARN_ON(hwlat_kthread))
+               return 0;
+
        /* Just pick the first CPU on first iteration */
        current_mask = &save_cpumask;
        get_online_cpus();
index 03ecb44..b7357f9 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * trace irqs off critical timings
  *
@@ -16,7 +17,6 @@
 
 #include "trace.h"
 
-#define CREATE_TRACE_POINTS
 #include <trace/events/preemptirq.h>
 
 #if defined(CONFIG_IRQSOFF_TRACER) || defined(CONFIG_PREEMPT_TRACER)
@@ -41,12 +41,12 @@ static int start_irqsoff_tracer(struct trace_array *tr, int graph);
 
 #ifdef CONFIG_PREEMPT_TRACER
 static inline int
-preempt_trace(void)
+preempt_trace(int pc)
 {
-       return ((trace_type & TRACER_PREEMPT_OFF) && preempt_count());
+       return ((trace_type & TRACER_PREEMPT_OFF) && pc);
 }
 #else
-# define preempt_trace() (0)
+# define preempt_trace(pc) (0)
 #endif
 
 #ifdef CONFIG_IRQSOFF_TRACER
@@ -367,7 +367,7 @@ out:
 }
 
 static inline void
-start_critical_timing(unsigned long ip, unsigned long parent_ip)
+start_critical_timing(unsigned long ip, unsigned long parent_ip, int pc)
 {
        int cpu;
        struct trace_array *tr = irqsoff_trace;
@@ -395,7 +395,7 @@ start_critical_timing(unsigned long ip, unsigned long parent_ip)
 
        local_save_flags(flags);
 
-       __trace_function(tr, ip, parent_ip, flags, preempt_count());
+       __trace_function(tr, ip, parent_ip, flags, pc);
 
        per_cpu(tracing_cpu, cpu) = 1;
 
@@ -403,7 +403,7 @@ start_critical_timing(unsigned long ip, unsigned long parent_ip)
 }
 
 static inline void
-stop_critical_timing(unsigned long ip, unsigned long parent_ip)
+stop_critical_timing(unsigned long ip, unsigned long parent_ip, int pc)
 {
        int cpu;
        struct trace_array *tr = irqsoff_trace;
@@ -429,7 +429,7 @@ stop_critical_timing(unsigned long ip, unsigned long parent_ip)
        atomic_inc(&data->disabled);
 
        local_save_flags(flags);
-       __trace_function(tr, ip, parent_ip, flags, preempt_count());
+       __trace_function(tr, ip, parent_ip, flags, pc);
        check_critical_timing(tr, data, parent_ip ? : ip, cpu);
        data->critical_start = 0;
        atomic_dec(&data->disabled);
@@ -438,77 +438,21 @@ stop_critical_timing(unsigned long ip, unsigned long parent_ip)
 /* start and stop critical timings used to for stoppage (in idle) */
 void start_critical_timings(void)
 {
-       if (preempt_trace() || irq_trace())
-               start_critical_timing(CALLER_ADDR0, CALLER_ADDR1);
+       int pc = preempt_count();
+
+       if (preempt_trace(pc) || irq_trace())
+               start_critical_timing(CALLER_ADDR0, CALLER_ADDR1, pc);
 }
 EXPORT_SYMBOL_GPL(start_critical_timings);
 
 void stop_critical_timings(void)
 {
-       if (preempt_trace() || irq_trace())
-               stop_critical_timing(CALLER_ADDR0, CALLER_ADDR1);
-}
-EXPORT_SYMBOL_GPL(stop_critical_timings);
-
-#ifdef CONFIG_IRQSOFF_TRACER
-#ifdef CONFIG_PROVE_LOCKING
-void time_hardirqs_on(unsigned long a0, unsigned long a1)
-{
-       if (!preempt_trace() && irq_trace())
-               stop_critical_timing(a0, a1);
-}
-
-void time_hardirqs_off(unsigned long a0, unsigned long a1)
-{
-       if (!preempt_trace() && irq_trace())
-               start_critical_timing(a0, a1);
-}
-
-#else /* !CONFIG_PROVE_LOCKING */
-
-/*
- * We are only interested in hardirq on/off events:
- */
-static inline void tracer_hardirqs_on(void)
-{
-       if (!preempt_trace() && irq_trace())
-               stop_critical_timing(CALLER_ADDR0, CALLER_ADDR1);
-}
+       int pc = preempt_count();
 
-static inline void tracer_hardirqs_off(void)
-{
-       if (!preempt_trace() && irq_trace())
-               start_critical_timing(CALLER_ADDR0, CALLER_ADDR1);
-}
-
-static inline void tracer_hardirqs_on_caller(unsigned long caller_addr)
-{
-       if (!preempt_trace() && irq_trace())
-               stop_critical_timing(CALLER_ADDR0, caller_addr);
-}
-
-static inline void tracer_hardirqs_off_caller(unsigned long caller_addr)
-{
-       if (!preempt_trace() && irq_trace())
-               start_critical_timing(CALLER_ADDR0, caller_addr);
-}
-
-#endif /* CONFIG_PROVE_LOCKING */
-#endif /*  CONFIG_IRQSOFF_TRACER */
-
-#ifdef CONFIG_PREEMPT_TRACER
-static inline void tracer_preempt_on(unsigned long a0, unsigned long a1)
-{
-       if (preempt_trace() && !irq_trace())
-               stop_critical_timing(a0, a1);
-}
-
-static inline void tracer_preempt_off(unsigned long a0, unsigned long a1)
-{
-       if (preempt_trace() && !irq_trace())
-               start_critical_timing(a0, a1);
+       if (preempt_trace(pc) || irq_trace())
+               stop_critical_timing(CALLER_ADDR0, CALLER_ADDR1, pc);
 }
-#endif /* CONFIG_PREEMPT_TRACER */
+EXPORT_SYMBOL_GPL(stop_critical_timings);
 
 #ifdef CONFIG_FUNCTION_TRACER
 static bool function_enabled;
@@ -634,7 +578,7 @@ static int __irqsoff_tracer_init(struct trace_array *tr)
        return 0;
 }
 
-static void irqsoff_tracer_reset(struct trace_array *tr)
+static void __irqsoff_tracer_reset(struct trace_array *tr)
 {
        int lat_flag = save_flags & TRACE_ITER_LATENCY_FMT;
        int overwrite_flag = save_flags & TRACE_ITER_OVERWRITE;
@@ -659,12 +603,37 @@ static void irqsoff_tracer_stop(struct trace_array *tr)
 }
 
 #ifdef CONFIG_IRQSOFF_TRACER
+/*
+ * We are only interested in hardirq on/off events:
+ */
+void tracer_hardirqs_on(unsigned long a0, unsigned long a1)
+{
+       unsigned int pc = preempt_count();
+
+       if (!preempt_trace(pc) && irq_trace())
+               stop_critical_timing(a0, a1, pc);
+}
+
+void tracer_hardirqs_off(unsigned long a0, unsigned long a1)
+{
+       unsigned int pc = preempt_count();
+
+       if (!preempt_trace(pc) && irq_trace())
+               start_critical_timing(a0, a1, pc);
+}
+
 static int irqsoff_tracer_init(struct trace_array *tr)
 {
        trace_type = TRACER_IRQS_OFF;
 
        return __irqsoff_tracer_init(tr);
 }
+
+static void irqsoff_tracer_reset(struct trace_array *tr)
+{
+       __irqsoff_tracer_reset(tr);
+}
+
 static struct tracer irqsoff_tracer __read_mostly =
 {
        .name           = "irqsoff",
@@ -684,12 +653,25 @@ static struct tracer irqsoff_tracer __read_mostly =
        .allow_instances = true,
        .use_max_tr     = true,
 };
-# define register_irqsoff(trace) register_tracer(&trace)
-#else
-# define register_irqsoff(trace) do { } while (0)
-#endif
+#endif /*  CONFIG_IRQSOFF_TRACER */
 
 #ifdef CONFIG_PREEMPT_TRACER
+void tracer_preempt_on(unsigned long a0, unsigned long a1)
+{
+       int pc = preempt_count();
+
+       if (preempt_trace(pc) && !irq_trace())
+               stop_critical_timing(a0, a1, pc);
+}
+
+void tracer_preempt_off(unsigned long a0, unsigned long a1)
+{
+       int pc = preempt_count();
+
+       if (preempt_trace(pc) && !irq_trace())
+               start_critical_timing(a0, a1, pc);
+}
+
 static int preemptoff_tracer_init(struct trace_array *tr)
 {
        trace_type = TRACER_PREEMPT_OFF;
@@ -697,11 +679,16 @@ static int preemptoff_tracer_init(struct trace_array *tr)
        return __irqsoff_tracer_init(tr);
 }
 
+static void preemptoff_tracer_reset(struct trace_array *tr)
+{
+       __irqsoff_tracer_reset(tr);
+}
+
 static struct tracer preemptoff_tracer __read_mostly =
 {
        .name           = "preemptoff",
        .init           = preemptoff_tracer_init,
-       .reset          = irqsoff_tracer_reset,
+       .reset          = preemptoff_tracer_reset,
        .start          = irqsoff_tracer_start,
        .stop           = irqsoff_tracer_stop,
        .print_max      = true,
@@ -716,13 +703,9 @@ static struct tracer preemptoff_tracer __read_mostly =
        .allow_instances = true,
        .use_max_tr     = true,
 };
-# define register_preemptoff(trace) register_tracer(&trace)
-#else
-# define register_preemptoff(trace) do { } while (0)
-#endif
+#endif /* CONFIG_PREEMPT_TRACER */
 
-#if defined(CONFIG_IRQSOFF_TRACER) && \
-       defined(CONFIG_PREEMPT_TRACER)
+#if defined(CONFIG_IRQSOFF_TRACER) && defined(CONFIG_PREEMPT_TRACER)
 
 static int preemptirqsoff_tracer_init(struct trace_array *tr)
 {
@@ -731,11 +714,16 @@ static int preemptirqsoff_tracer_init(struct trace_array *tr)
        return __irqsoff_tracer_init(tr);
 }
 
+static void preemptirqsoff_tracer_reset(struct trace_array *tr)
+{
+       __irqsoff_tracer_reset(tr);
+}
+
 static struct tracer preemptirqsoff_tracer __read_mostly =
 {
        .name           = "preemptirqsoff",
        .init           = preemptirqsoff_tracer_init,
-       .reset          = irqsoff_tracer_reset,
+       .reset          = preemptirqsoff_tracer_reset,
        .start          = irqsoff_tracer_start,
        .stop           = irqsoff_tracer_stop,
        .print_max      = true,
@@ -750,115 +738,21 @@ static struct tracer preemptirqsoff_tracer __read_mostly =
        .allow_instances = true,
        .use_max_tr     = true,
 };
-
-# define register_preemptirqsoff(trace) register_tracer(&trace)
-#else
-# define register_preemptirqsoff(trace) do { } while (0)
 #endif
 
 __init static int init_irqsoff_tracer(void)
 {
-       register_irqsoff(irqsoff_tracer);
-       register_preemptoff(preemptoff_tracer);
-       register_preemptirqsoff(preemptirqsoff_tracer);
-
-       return 0;
-}
-core_initcall(init_irqsoff_tracer);
-#endif /* IRQSOFF_TRACER || PREEMPTOFF_TRACER */
-
-#ifndef CONFIG_IRQSOFF_TRACER
-static inline void tracer_hardirqs_on(void) { }
-static inline void tracer_hardirqs_off(void) { }
-static inline void tracer_hardirqs_on_caller(unsigned long caller_addr) { }
-static inline void tracer_hardirqs_off_caller(unsigned long caller_addr) { }
+#ifdef CONFIG_IRQSOFF_TRACER
+       register_tracer(&irqsoff_tracer);
 #endif
-
-#ifndef CONFIG_PREEMPT_TRACER
-static inline void tracer_preempt_on(unsigned long a0, unsigned long a1) { }
-static inline void tracer_preempt_off(unsigned long a0, unsigned long a1) { }
+#ifdef CONFIG_PREEMPT_TRACER
+       register_tracer(&preemptoff_tracer);
 #endif
-
-#if defined(CONFIG_TRACE_IRQFLAGS) && !defined(CONFIG_PROVE_LOCKING)
-/* Per-cpu variable to prevent redundant calls when IRQs already off */
-static DEFINE_PER_CPU(int, tracing_irq_cpu);
-
-void trace_hardirqs_on(void)
-{
-       if (!this_cpu_read(tracing_irq_cpu))
-               return;
-
-       trace_irq_enable_rcuidle(CALLER_ADDR0, CALLER_ADDR1);
-       tracer_hardirqs_on();
-
-       this_cpu_write(tracing_irq_cpu, 0);
-}
-EXPORT_SYMBOL(trace_hardirqs_on);
-
-void trace_hardirqs_off(void)
-{
-       if (this_cpu_read(tracing_irq_cpu))
-               return;
-
-       this_cpu_write(tracing_irq_cpu, 1);
-
-       trace_irq_disable_rcuidle(CALLER_ADDR0, CALLER_ADDR1);
-       tracer_hardirqs_off();
-}
-EXPORT_SYMBOL(trace_hardirqs_off);
-
-__visible void trace_hardirqs_on_caller(unsigned long caller_addr)
-{
-       if (!this_cpu_read(tracing_irq_cpu))
-               return;
-
-       trace_irq_enable_rcuidle(CALLER_ADDR0, caller_addr);
-       tracer_hardirqs_on_caller(caller_addr);
-
-       this_cpu_write(tracing_irq_cpu, 0);
-}
-EXPORT_SYMBOL(trace_hardirqs_on_caller);
-
-__visible void trace_hardirqs_off_caller(unsigned long caller_addr)
-{
-       if (this_cpu_read(tracing_irq_cpu))
-               return;
-
-       this_cpu_write(tracing_irq_cpu, 1);
-
-       trace_irq_disable_rcuidle(CALLER_ADDR0, caller_addr);
-       tracer_hardirqs_off_caller(caller_addr);
-}
-EXPORT_SYMBOL(trace_hardirqs_off_caller);
-
-/*
- * Stubs:
- */
-
-void trace_softirqs_on(unsigned long ip)
-{
-}
-
-void trace_softirqs_off(unsigned long ip)
-{
-}
-
-inline void print_irqtrace_events(struct task_struct *curr)
-{
-}
+#if defined(CONFIG_IRQSOFF_TRACER) && defined(CONFIG_PREEMPT_TRACER)
+       register_tracer(&preemptirqsoff_tracer);
 #endif
 
-#if defined(CONFIG_PREEMPT_TRACER) || \
-       (defined(CONFIG_DEBUG_PREEMPT) && defined(CONFIG_PREEMPTIRQ_EVENTS))
-void trace_preempt_on(unsigned long a0, unsigned long a1)
-{
-       trace_preempt_enable_rcuidle(a0, a1);
-       tracer_preempt_on(a0, a1);
-}
-
-void trace_preempt_off(unsigned long a0, unsigned long a1)
-{
-       trace_preempt_disable_rcuidle(a0, a1);
-       tracer_preempt_off(a0, a1);
+       return 0;
 }
-#endif
+core_initcall(init_irqsoff_tracer);
+#endif /* IRQSOFF_TRACER || PREEMPTOFF_TRACER */
index e9d9946..c300323 100644 (file)
@@ -1,20 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Kprobes-based tracing events
  *
  * Created by Masami Hiramatsu <mhiramat@redhat.com>
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 #define pr_fmt(fmt)    "trace_kprobe: " fmt
 
@@ -23,6 +12,7 @@
 #include <linux/rculist.h>
 #include <linux/error-injection.h>
 
+#include "trace_kprobe_selftest.h"
 #include "trace_probe.h"
 
 #define KPROBE_EVENT_SYSTEM "kprobes"
@@ -87,6 +77,23 @@ static nokprobe_inline unsigned long trace_kprobe_nhit(struct trace_kprobe *tk)
        return nhit;
 }
 
+/* Return 0 if it fails to find the symbol address */
+static nokprobe_inline
+unsigned long trace_kprobe_address(struct trace_kprobe *tk)
+{
+       unsigned long addr;
+
+       if (tk->symbol) {
+               addr = (unsigned long)
+                       kallsyms_lookup_name(trace_kprobe_symbol(tk));
+               if (addr)
+                       addr += tk->rp.kp.offset;
+       } else {
+               addr = (unsigned long)tk->rp.kp.addr;
+       }
+       return addr;
+}
+
 bool trace_kprobe_on_func_entry(struct trace_event_call *call)
 {
        struct trace_kprobe *tk = (struct trace_kprobe *)call->data;
@@ -99,16 +106,8 @@ bool trace_kprobe_on_func_entry(struct trace_event_call *call)
 bool trace_kprobe_error_injectable(struct trace_event_call *call)
 {
        struct trace_kprobe *tk = (struct trace_kprobe *)call->data;
-       unsigned long addr;
 
-       if (tk->symbol) {
-               addr = (unsigned long)
-                       kallsyms_lookup_name(trace_kprobe_symbol(tk));
-               addr += tk->rp.kp.offset;
-       } else {
-               addr = (unsigned long)tk->rp.kp.addr;
-       }
-       return within_error_injection_list(addr);
+       return within_error_injection_list(trace_kprobe_address(tk));
 }
 
 static int register_kprobe_event(struct trace_kprobe *tk);
@@ -393,6 +392,20 @@ static struct trace_kprobe *find_trace_kprobe(const char *event,
        return NULL;
 }
 
+static inline int __enable_trace_kprobe(struct trace_kprobe *tk)
+{
+       int ret = 0;
+
+       if (trace_probe_is_registered(&tk->tp) && !trace_kprobe_has_gone(tk)) {
+               if (trace_kprobe_is_return(tk))
+                       ret = enable_kretprobe(&tk->rp);
+               else
+                       ret = enable_kprobe(&tk->rp.kp);
+       }
+
+       return ret;
+}
+
 /*
  * Enable trace_probe
  * if the file is NULL, enable "perf" handler, or enable "trace" handler.
@@ -400,7 +413,7 @@ static struct trace_kprobe *find_trace_kprobe(const char *event,
 static int
 enable_trace_kprobe(struct trace_kprobe *tk, struct trace_event_file *file)
 {
-       struct event_file_link *link = NULL;
+       struct event_file_link *link;
        int ret = 0;
 
        if (file) {
@@ -414,26 +427,18 @@ enable_trace_kprobe(struct trace_kprobe *tk, struct trace_event_file *file)
                list_add_tail_rcu(&link->list, &tk->tp.files);
 
                tk->tp.flags |= TP_FLAG_TRACE;
-       } else
-               tk->tp.flags |= TP_FLAG_PROFILE;
-
-       if (trace_probe_is_registered(&tk->tp) && !trace_kprobe_has_gone(tk)) {
-               if (trace_kprobe_is_return(tk))
-                       ret = enable_kretprobe(&tk->rp);
-               else
-                       ret = enable_kprobe(&tk->rp.kp);
-       }
-
-       if (ret) {
-               if (file) {
-                       /* Notice the if is true on not WARN() */
-                       if (!WARN_ON_ONCE(!link))
-                               list_del_rcu(&link->list);
+               ret = __enable_trace_kprobe(tk);
+               if (ret) {
+                       list_del_rcu(&link->list);
                        kfree(link);
                        tk->tp.flags &= ~TP_FLAG_TRACE;
-               } else {
-                       tk->tp.flags &= ~TP_FLAG_PROFILE;
                }
+
+       } else {
+               tk->tp.flags |= TP_FLAG_PROFILE;
+               ret = __enable_trace_kprobe(tk);
+               if (ret)
+                       tk->tp.flags &= ~TP_FLAG_PROFILE;
        }
  out:
        return ret;
@@ -498,6 +503,29 @@ disable_trace_kprobe(struct trace_kprobe *tk, struct trace_event_file *file)
        return ret;
 }
 
+#if defined(CONFIG_KPROBES_ON_FTRACE) && \
+       !defined(CONFIG_KPROBE_EVENTS_ON_NOTRACE)
+static bool within_notrace_func(struct trace_kprobe *tk)
+{
+       unsigned long offset, size, addr;
+
+       addr = trace_kprobe_address(tk);
+       if (!addr || !kallsyms_lookup_size_offset(addr, &size, &offset))
+               return false;
+
+       /* Get the entry address of the target function */
+       addr -= offset;
+
+       /*
+        * Since ftrace_location_range() does inclusive range check, we need
+        * to subtract 1 byte from the end address.
+        */
+       return !ftrace_location_range(addr, addr + size - 1);
+}
+#else
+#define within_notrace_func(tk)        (false)
+#endif
+
 /* Internal register function - just handle k*probes and flags */
 static int __register_trace_kprobe(struct trace_kprobe *tk)
 {
@@ -506,6 +534,12 @@ static int __register_trace_kprobe(struct trace_kprobe *tk)
        if (trace_probe_is_registered(&tk->tp))
                return -EINVAL;
 
+       if (within_notrace_func(tk)) {
+               pr_warn("Could not probe notrace function %s\n",
+                       trace_kprobe_symbol(tk));
+               return -EINVAL;
+       }
+
        for (i = 0; i < tk->tp.nr_args; i++)
                traceprobe_update_arg(&tk->tp.args[i]);
 
@@ -1547,17 +1581,6 @@ fs_initcall(init_kprobe_trace);
 
 
 #ifdef CONFIG_FTRACE_STARTUP_TEST
-/*
- * The "__used" keeps gcc from removing the function symbol
- * from the kallsyms table. 'noinline' makes sure that there
- * isn't an inlined version used by the test method below
- */
-static __used __init noinline int
-kprobe_trace_selftest_target(int a1, int a2, int a3, int a4, int a5, int a6)
-{
-       return a1 + a2 + a3 + a4 + a5 + a6;
-}
-
 static __init struct trace_event_file *
 find_trace_probe_file(struct trace_kprobe *tk, struct trace_array *tr)
 {
diff --git a/kernel/trace/trace_kprobe_selftest.c b/kernel/trace/trace_kprobe_selftest.c
new file mode 100644 (file)
index 0000000..16548ee
--- /dev/null
@@ -0,0 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Function used during the kprobe self test. This function is in a separate
+ * compile unit so it can be compile with CC_FLAGS_FTRACE to ensure that it
+ * can be probed by the selftests.
+ */
+int kprobe_trace_selftest_target(int a1, int a2, int a3, int a4, int a5, int a6)
+{
+       return a1 + a2 + a3 + a4 + a5 + a6;
+}
diff --git a/kernel/trace/trace_kprobe_selftest.h b/kernel/trace/trace_kprobe_selftest.h
new file mode 100644 (file)
index 0000000..c4fc726
--- /dev/null
@@ -0,0 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Function used during the kprobe self test. This function is in a separate
+ * compile unit so it can be compile with CC_FLAGS_FTRACE to ensure that it
+ * can be probed by the selftests.
+ */
+int kprobe_trace_selftest_target(int a1, int a2, int a3, int a4, int a5, int a6);
index 1c8e30f..6e6cc64 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * trace_output.c
  *
index dbba03e..2f742b7 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+// SPDX-License-Identifier: GPL-2.0
 #ifndef __TRACE_EVENTS_H
 #define __TRACE_EVENTS_H
 
diff --git a/kernel/trace/trace_preemptirq.c b/kernel/trace/trace_preemptirq.c
new file mode 100644 (file)
index 0000000..71f553c
--- /dev/null
@@ -0,0 +1,89 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * preemptoff and irqoff tracepoints
+ *
+ * Copyright (C) Joel Fernandes (Google) <joel@joelfernandes.org>
+ */
+
+#include <linux/kallsyms.h>
+#include <linux/uaccess.h>
+#include <linux/module.h>
+#include <linux/ftrace.h>
+#include "trace.h"
+
+#define CREATE_TRACE_POINTS
+#include <trace/events/preemptirq.h>
+
+#ifdef CONFIG_TRACE_IRQFLAGS
+/* Per-cpu variable to prevent redundant calls when IRQs already off */
+static DEFINE_PER_CPU(int, tracing_irq_cpu);
+
+void trace_hardirqs_on(void)
+{
+       if (this_cpu_read(tracing_irq_cpu)) {
+               if (!in_nmi())
+                       trace_irq_enable_rcuidle(CALLER_ADDR0, CALLER_ADDR1);
+               tracer_hardirqs_on(CALLER_ADDR0, CALLER_ADDR1);
+               this_cpu_write(tracing_irq_cpu, 0);
+       }
+
+       lockdep_hardirqs_on(CALLER_ADDR0);
+}
+EXPORT_SYMBOL(trace_hardirqs_on);
+
+void trace_hardirqs_off(void)
+{
+       if (!this_cpu_read(tracing_irq_cpu)) {
+               this_cpu_write(tracing_irq_cpu, 1);
+               tracer_hardirqs_off(CALLER_ADDR0, CALLER_ADDR1);
+               if (!in_nmi())
+                       trace_irq_disable_rcuidle(CALLER_ADDR0, CALLER_ADDR1);
+       }
+
+       lockdep_hardirqs_off(CALLER_ADDR0);
+}
+EXPORT_SYMBOL(trace_hardirqs_off);
+
+__visible void trace_hardirqs_on_caller(unsigned long caller_addr)
+{
+       if (this_cpu_read(tracing_irq_cpu)) {
+               if (!in_nmi())
+                       trace_irq_enable_rcuidle(CALLER_ADDR0, caller_addr);
+               tracer_hardirqs_on(CALLER_ADDR0, caller_addr);
+               this_cpu_write(tracing_irq_cpu, 0);
+       }
+
+       lockdep_hardirqs_on(CALLER_ADDR0);
+}
+EXPORT_SYMBOL(trace_hardirqs_on_caller);
+
+__visible void trace_hardirqs_off_caller(unsigned long caller_addr)
+{
+       if (!this_cpu_read(tracing_irq_cpu)) {
+               this_cpu_write(tracing_irq_cpu, 1);
+               tracer_hardirqs_off(CALLER_ADDR0, caller_addr);
+               if (!in_nmi())
+                       trace_irq_disable_rcuidle(CALLER_ADDR0, caller_addr);
+       }
+
+       lockdep_hardirqs_off(CALLER_ADDR0);
+}
+EXPORT_SYMBOL(trace_hardirqs_off_caller);
+#endif /* CONFIG_TRACE_IRQFLAGS */
+
+#ifdef CONFIG_TRACE_PREEMPT_TOGGLE
+
+void trace_preempt_on(unsigned long a0, unsigned long a1)
+{
+       if (!in_nmi())
+               trace_preempt_enable_rcuidle(a0, a1);
+       tracer_preempt_on(a0, a1);
+}
+
+void trace_preempt_off(unsigned long a0, unsigned long a1)
+{
+       if (!in_nmi())
+               trace_preempt_disable_rcuidle(a0, a1);
+       tracer_preempt_off(a0, a1);
+}
+#endif
index 50f44b7..b0875b3 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * trace binary printk
  *
index daf54bd..e99c3ce 100644 (file)
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Common code for probe-based Dynamic events.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
  * This code was copied from kernel/trace/trace_kprobe.c written by
  * Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
  *
index 75daff2..5f52668 100644 (file)
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Common header file for probe-based Dynamic events.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
  * This code was copied from kernel/trace/trace_kprobe.h written by
  * Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
  *
index e694c9f..6b1c562 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * trace_seq.c
  *
index 76d30b4..8786d17 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+// SPDX-License-Identifier: GPL-2.0
 #ifndef __TRACE_STAT_H
 #define __TRACE_STAT_H
 
index bf89a51..e696667 100644 (file)
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * uprobes-based tracing events
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
  * Copyright (C) IBM Corporation, 2010-2012
  * Author:     Srikar Dronamraju <srikar@linux.vnet.ibm.com>
  */
@@ -952,7 +940,7 @@ probe_event_disable(struct trace_uprobe *tu, struct trace_event_file *file)
 
                list_del_rcu(&link->list);
                /* synchronize with u{,ret}probe_trace_func */
-               synchronize_sched();
+               synchronize_rcu();
                kfree(link);
 
                if (!list_empty(&tu->tp.files))
index 752d804..9a1c223 100644 (file)
@@ -1,16 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * tracing_map - lock-free map for tracing
  *
- * 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.
- *
  * Copyright (C) 2015 Tom Zanussi <tom.zanussi@linux.intel.com>
  *
  * tracing_map implementation inspired by lock-free map algorithms
index 053eb92..a6de61f 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+// SPDX-License-Identifier: GPL-2.0
 #ifndef __TRACING_MAP_H
 #define __TRACING_MAP_H
 
index 6dc6356..bf2c06e 100644 (file)
@@ -31,6 +31,9 @@
 extern struct tracepoint * const __start___tracepoints_ptrs[];
 extern struct tracepoint * const __stop___tracepoints_ptrs[];
 
+DEFINE_SRCU(tracepoint_srcu);
+EXPORT_SYMBOL_GPL(tracepoint_srcu);
+
 /* Set to 1 to enable tracepoint debug output */
 static const int tracepoint_debug;
 
@@ -50,6 +53,9 @@ static LIST_HEAD(tracepoint_module_list);
  */
 static DEFINE_MUTEX(tracepoints_mutex);
 
+static struct rcu_head *early_probes;
+static bool ok_to_free_tracepoints;
+
 /*
  * Note about RCU :
  * It is used to delay the free of multiple probes array until a quiescent
@@ -67,16 +73,56 @@ static inline void *allocate_probes(int count)
        return p == NULL ? NULL : p->probes;
 }
 
-static void rcu_free_old_probes(struct rcu_head *head)
+static void srcu_free_old_probes(struct rcu_head *head)
 {
        kfree(container_of(head, struct tp_probes, rcu));
 }
 
+static void rcu_free_old_probes(struct rcu_head *head)
+{
+       call_srcu(&tracepoint_srcu, head, srcu_free_old_probes);
+}
+
+static __init int release_early_probes(void)
+{
+       struct rcu_head *tmp;
+
+       ok_to_free_tracepoints = true;
+
+       while (early_probes) {
+               tmp = early_probes;
+               early_probes = tmp->next;
+               call_rcu_sched(tmp, rcu_free_old_probes);
+       }
+
+       return 0;
+}
+
+/* SRCU is initialized at core_initcall */
+postcore_initcall(release_early_probes);
+
 static inline void release_probes(struct tracepoint_func *old)
 {
        if (old) {
                struct tp_probes *tp_probes = container_of(old,
                        struct tp_probes, probes[0]);
+
+               /*
+                * We can't free probes if SRCU is not initialized yet.
+                * Postpone the freeing till after SRCU is initialized.
+                */
+               if (unlikely(!ok_to_free_tracepoints)) {
+                       tp_probes->rcu.next = early_probes;
+                       early_probes = &tp_probes->rcu;
+                       return;
+               }
+
+               /*
+                * Tracepoint probes are protected by both sched RCU and SRCU,
+                * by calling the SRCU callback in the sched RCU callback we
+                * cover both cases. So let us chain the SRCU and sched RCU
+                * callbacks to wait for both grace periods.
+                */
                call_rcu_sched(&tp_probes->rcu, rcu_free_old_probes);
        }
 }
@@ -325,6 +371,27 @@ int tracepoint_probe_unregister(struct tracepoint *tp, void *probe, void *data)
 }
 EXPORT_SYMBOL_GPL(tracepoint_probe_unregister);
 
+static void for_each_tracepoint_range(struct tracepoint * const *begin,
+               struct tracepoint * const *end,
+               void (*fct)(struct tracepoint *tp, void *priv),
+               void *priv)
+{
+       if (!begin)
+               return;
+
+       if (IS_ENABLED(CONFIG_HAVE_ARCH_PREL32_RELOCATIONS)) {
+               const int *iter;
+
+               for (iter = (const int *)begin; iter < (const int *)end; iter++)
+                       fct(offset_to_ptr(iter), priv);
+       } else {
+               struct tracepoint * const *iter;
+
+               for (iter = begin; iter < end; iter++)
+                       fct(*iter, priv);
+       }
+}
+
 #ifdef CONFIG_MODULES
 bool trace_module_has_bad_taint(struct module *mod)
 {
@@ -389,15 +456,9 @@ EXPORT_SYMBOL_GPL(unregister_tracepoint_module_notifier);
  * Ensure the tracer unregistered the module's probes before the module
  * teardown is performed. Prevents leaks of probe and data pointers.
  */
-static void tp_module_going_check_quiescent(struct tracepoint * const *begin,
-               struct tracepoint * const *end)
+static void tp_module_going_check_quiescent(struct tracepoint *tp, void *priv)
 {
-       struct tracepoint * const *iter;
-
-       if (!begin)
-               return;
-       for (iter = begin; iter < end; iter++)
-               WARN_ON_ONCE((*iter)->funcs);
+       WARN_ON_ONCE(tp->funcs);
 }
 
 static int tracepoint_module_coming(struct module *mod)
@@ -448,8 +509,9 @@ static void tracepoint_module_going(struct module *mod)
                         * Called the going notifier before checking for
                         * quiescence.
                         */
-                       tp_module_going_check_quiescent(mod->tracepoints_ptrs,
-                               mod->tracepoints_ptrs + mod->num_tracepoints);
+                       for_each_tracepoint_range(mod->tracepoints_ptrs,
+                               mod->tracepoints_ptrs + mod->num_tracepoints,
+                               tp_module_going_check_quiescent, NULL);
                        break;
                }
        }
@@ -501,19 +563,6 @@ static __init int init_tracepoints(void)
 __initcall(init_tracepoints);
 #endif /* CONFIG_MODULES */
 
-static void for_each_tracepoint_range(struct tracepoint * const *begin,
-               struct tracepoint * const *end,
-               void (*fct)(struct tracepoint *tp, void *priv),
-               void *priv)
-{
-       struct tracepoint * const *iter;
-
-       if (!begin)
-               return;
-       for (iter = begin; iter < end; iter++)
-               fct(*iter, priv);
-}
-
 /**
  * for_each_kernel_tracepoint - iteration on all kernel tracepoints
  * @fct: callback
index 36288d8..0df9b16 100644 (file)
@@ -96,7 +96,7 @@ static DEFINE_SPINLOCK(uidhash_lock);
 
 /* root_user.__count is 1, for init task cred */
 struct user_struct root_user = {
-       .__count        = ATOMIC_INIT(1),
+       .__count        = REFCOUNT_INIT(1),
        .processes      = ATOMIC_INIT(1),
        .sigpending     = ATOMIC_INIT(0),
        .locked_shm     = 0,
@@ -123,7 +123,7 @@ static struct user_struct *uid_hash_find(kuid_t uid, struct hlist_head *hashent)
 
        hlist_for_each_entry(user, hashent, uidhash_node) {
                if (uid_eq(user->uid, uid)) {
-                       atomic_inc(&user->__count);
+                       refcount_inc(&user->__count);
                        return user;
                }
        }
@@ -169,11 +169,8 @@ void free_uid(struct user_struct *up)
        if (!up)
                return;
 
-       local_irq_save(flags);
-       if (atomic_dec_and_lock(&up->__count, &uidhash_lock))
+       if (refcount_dec_and_lock_irqsave(&up->__count, &uidhash_lock, &flags))
                free_user(up, flags);
-       else
-               local_irq_restore(flags);
 }
 
 struct user_struct *alloc_uid(kuid_t uid)
@@ -191,7 +188,7 @@ struct user_struct *alloc_uid(kuid_t uid)
                        goto out_unlock;
 
                new->uid = uid;
-               atomic_set(&new->__count, 1);
+               refcount_set(&new->__count, 1);
                ratelimit_state_init(&new->ratelimit, HZ, 100);
                ratelimit_set_flags(&new->ratelimit, RATELIMIT_MSG_ON_RELEASE);
 
index c3d7583..e5222b5 100644 (file)
@@ -859,7 +859,16 @@ static ssize_t map_write(struct file *file, const char __user *buf,
        unsigned idx;
        struct uid_gid_extent extent;
        char *kbuf = NULL, *pos, *next_line;
-       ssize_t ret = -EINVAL;
+       ssize_t ret;
+
+       /* Only allow < page size writes at the beginning of the file */
+       if ((*ppos != 0) || (count >= PAGE_SIZE))
+               return -EINVAL;
+
+       /* Slurp in the user data */
+       kbuf = memdup_user_nul(buf, count);
+       if (IS_ERR(kbuf))
+               return PTR_ERR(kbuf);
 
        /*
         * The userns_state_mutex serializes all writes to any given map.
@@ -895,19 +904,6 @@ static ssize_t map_write(struct file *file, const char __user *buf,
        if (cap_valid(cap_setid) && !file_ns_capable(file, ns, CAP_SYS_ADMIN))
                goto out;
 
-       /* Only allow < page size writes at the beginning of the file */
-       ret = -EINVAL;
-       if ((*ppos != 0) || (count >= PAGE_SIZE))
-               goto out;
-
-       /* Slurp in the user data */
-       kbuf = memdup_user_nul(buf, count);
-       if (IS_ERR(kbuf)) {
-               ret = PTR_ERR(kbuf);
-               kbuf = NULL;
-               goto out;
-       }
-
        /* Parse the user data */
        ret = -EINVAL;
        pos = kbuf;
index 233cd8f..258033d 100644 (file)
@@ -18,7 +18,7 @@
 
 #ifdef CONFIG_PROC_SYSCTL
 
-static void *get_uts(struct ctl_table *table, int write)
+static void *get_uts(struct ctl_table *table)
 {
        char *which = table->data;
        struct uts_namespace *uts_ns;
@@ -26,21 +26,9 @@ static void *get_uts(struct ctl_table *table, int write)
        uts_ns = current->nsproxy->uts_ns;
        which = (which - (char *)&init_uts_ns) + (char *)uts_ns;
 
-       if (!write)
-               down_read(&uts_sem);
-       else
-               down_write(&uts_sem);
        return which;
 }
 
-static void put_uts(struct ctl_table *table, int write, void *which)
-{
-       if (!write)
-               up_read(&uts_sem);
-       else
-               up_write(&uts_sem);
-}
-
 /*
  *     Special case of dostring for the UTS structure. This has locks
  *     to observe. Should this be in kernel/sys.c ????
@@ -50,13 +38,34 @@ static int proc_do_uts_string(struct ctl_table *table, int write,
 {
        struct ctl_table uts_table;
        int r;
+       char tmp_data[__NEW_UTS_LEN + 1];
+
        memcpy(&uts_table, table, sizeof(uts_table));
-       uts_table.data = get_uts(table, write);
+       uts_table.data = tmp_data;
+
+       /*
+        * Buffer the value in tmp_data so that proc_dostring() can be called
+        * without holding any locks.
+        * We also need to read the original value in the write==1 case to
+        * support partial writes.
+        */
+       down_read(&uts_sem);
+       memcpy(tmp_data, get_uts(table), sizeof(tmp_data));
+       up_read(&uts_sem);
        r = proc_dostring(&uts_table, write, buffer, lenp, ppos);
-       put_uts(table, write, uts_table.data);
 
-       if (write)
+       if (write) {
+               /*
+                * Write back the new value.
+                * Note that, since we dropped uts_sem, the result can
+                * theoretically be incorrect if there are two parallel writes
+                * at non-zero offsets to the same sysctl.
+                */
+               down_write(&uts_sem);
+               memcpy(get_uts(table), tmp_data, sizeof(tmp_data));
+               up_write(&uts_sem);
                proc_sys_poll_notify(table->poll);
+       }
 
        return r;
 }
index 78b1920..60e8019 100644 (file)
@@ -2652,6 +2652,9 @@ void flush_workqueue(struct workqueue_struct *wq)
        if (WARN_ON(!wq_online))
                return;
 
+       lock_map_acquire(&wq->lockdep_map);
+       lock_map_release(&wq->lockdep_map);
+
        mutex_lock(&wq->mutex);
 
        /*
@@ -2843,7 +2846,8 @@ reflush:
 }
 EXPORT_SYMBOL_GPL(drain_workqueue);
 
-static bool start_flush_work(struct work_struct *work, struct wq_barrier *barr)
+static bool start_flush_work(struct work_struct *work, struct wq_barrier *barr,
+                            bool from_cancel)
 {
        struct worker *worker = NULL;
        struct worker_pool *pool;
@@ -2885,7 +2889,8 @@ static bool start_flush_work(struct work_struct *work, struct wq_barrier *barr)
         * workqueues the deadlock happens when the rescuer stalls, blocking
         * forward progress.
         */
-       if (pwq->wq->saved_max_active == 1 || pwq->wq->rescuer) {
+       if (!from_cancel &&
+           (pwq->wq->saved_max_active == 1 || pwq->wq->rescuer)) {
                lock_map_acquire(&pwq->wq->lockdep_map);
                lock_map_release(&pwq->wq->lockdep_map);
        }
@@ -2896,6 +2901,27 @@ already_gone:
        return false;
 }
 
+static bool __flush_work(struct work_struct *work, bool from_cancel)
+{
+       struct wq_barrier barr;
+
+       if (WARN_ON(!wq_online))
+               return false;
+
+       if (!from_cancel) {
+               lock_map_acquire(&work->lockdep_map);
+               lock_map_release(&work->lockdep_map);
+       }
+
+       if (start_flush_work(work, &barr, from_cancel)) {
+               wait_for_completion(&barr.done);
+               destroy_work_on_stack(&barr.work);
+               return true;
+       } else {
+               return false;
+       }
+}
+
 /**
  * flush_work - wait for a work to finish executing the last queueing instance
  * @work: the work to flush
@@ -2909,18 +2935,7 @@ already_gone:
  */
 bool flush_work(struct work_struct *work)
 {
-       struct wq_barrier barr;
-
-       if (WARN_ON(!wq_online))
-               return false;
-
-       if (start_flush_work(work, &barr)) {
-               wait_for_completion(&barr.done);
-               destroy_work_on_stack(&barr.work);
-               return true;
-       } else {
-               return false;
-       }
+       return __flush_work(work, false);
 }
 EXPORT_SYMBOL_GPL(flush_work);
 
@@ -2986,7 +3001,7 @@ static bool __cancel_work_timer(struct work_struct *work, bool is_dwork)
         * isn't executing.
         */
        if (wq_online)
-               flush_work(work);
+               __flush_work(work, true);
 
        clear_work_data(work);
 
index 09aae85..f2a39c9 100644 (file)
@@ -2,5 +2,7 @@
 # Generated files
 #
 gen_crc32table
+gen_crc64table
 crc32table.h
+crc64table.h
 oid_registry_data.c
index 706836e..a3928d4 100644 (file)
@@ -170,6 +170,14 @@ config CRC32_BIT
 
 endchoice
 
+config CRC64
+       tristate "CRC64 functions"
+       help
+         This option is provided for the case where no in-kernel-tree
+         modules require CRC64 functions, but a module built outside
+         the kernel tree does. Such modules that use library CRC64
+         functions require M here.
+
 config CRC4
        tristate "CRC4 functions"
        help
@@ -223,7 +231,6 @@ config AUDIT_COMPAT_GENERIC
 
 config RANDOM32_SELFTEST
        bool "PRNG perform self test on init"
-       default n
        help
          This option enables the 32 bit PRNG library functions to perform a
          self test on initialization.
index ab1b599..6133167 100644 (file)
@@ -1220,7 +1220,6 @@ config LOCK_TORTURE_TEST
        tristate "torture tests for locking"
        depends on DEBUG_KERNEL
        select TORTURE_TEST
-       default n
        help
          This option provides a kernel module that runs torture tests
          on kernel locking primitives.  The kernel module may be built
@@ -1687,7 +1686,6 @@ config LKDTM
        tristate "Linux Kernel Dump Test Tool Module"
        depends on DEBUG_FS
        depends on BLOCK
-       default n
        help
        This module enables testing of the different dumping mechanisms by
        inducing system failures at predefined crash points.
@@ -1721,7 +1719,6 @@ config KPROBES_SANITY_TEST
        bool "Kprobes sanity tests"
        depends on DEBUG_KERNEL
        depends on KPROBES
-       default n
        help
          This option provides for testing basic kprobes functionality on
          boot. Samples of kprobe and kretprobe are inserted and
@@ -1732,7 +1729,6 @@ config KPROBES_SANITY_TEST
 config BACKTRACE_SELF_TEST
        tristate "Self test for the backtrace code"
        depends on DEBUG_KERNEL
-       default n
        help
          This option provides a kernel module that can be used to test
          the kernel stack backtrace code. This option is not useful
@@ -1802,7 +1798,6 @@ config TEST_PRINTF
 
 config TEST_BITMAP
        tristate "Test bitmap_*() family of functions at runtime"
-       default n
        help
          Enable this option to test the bitmap functions at boot.
 
@@ -1823,7 +1818,6 @@ config TEST_OVERFLOW
 
 config TEST_RHASHTABLE
        tristate "Perform selftest on resizable hash table"
-       default n
        help
          Enable this option to test the rhashtable functions at boot.
 
@@ -1831,7 +1825,6 @@ config TEST_RHASHTABLE
 
 config TEST_HASH
        tristate "Perform selftest on hash functions"
-       default n
        help
          Enable this option to test the kernel's integer (<linux/hash.h>),
          string (<linux/stringhash.h>), and siphash (<linux/siphash.h>)
@@ -1840,9 +1833,11 @@ config TEST_HASH
          This is intended to help people writing architecture-specific
          optimized versions.  If unsure, say N.
 
+config TEST_IDA
+       tristate "Perform selftest on IDA functions"
+
 config TEST_PARMAN
        tristate "Perform selftest on priority array manager"
-       default n
        depends on PARMAN
        help
          Enable this option to test priority array manager on boot
@@ -1852,7 +1847,6 @@ config TEST_PARMAN
 
 config TEST_LKM
        tristate "Test module loading with 'hello world' module"
-       default n
        depends on m
        help
          This builds the "test_module" module that emits "Hello, world"
@@ -1866,7 +1860,6 @@ config TEST_LKM
 
 config TEST_USER_COPY
        tristate "Test user/kernel boundary protections"
-       default n
        depends on m
        help
          This builds the "test_user_copy" module that runs sanity checks
@@ -1879,7 +1872,6 @@ config TEST_USER_COPY
 
 config TEST_BPF
        tristate "Test BPF filter functionality"
-       default n
        depends on m && NET
        help
          This builds the "test_bpf" module that runs various test vectors
@@ -1893,7 +1885,6 @@ config TEST_BPF
 
 config FIND_BIT_BENCHMARK
        tristate "Test find_bit functions"
-       default n
        help
          This builds the "test_find_bit" module that measure find_*_bit()
          functions performance.
@@ -1902,7 +1893,6 @@ config FIND_BIT_BENCHMARK
 
 config TEST_FIRMWARE
        tristate "Test firmware loading via userspace interface"
-       default n
        depends on FW_LOADER
        help
          This builds the "test_firmware" module that creates a userspace
@@ -1915,7 +1905,6 @@ config TEST_FIRMWARE
 
 config TEST_SYSCTL
        tristate "sysctl test driver"
-       default n
        depends on PROC_SYSCTL
        help
          This builds the "test_sysctl" module. This driver enables to test the
@@ -1926,7 +1915,6 @@ config TEST_SYSCTL
 
 config TEST_UDELAY
        tristate "udelay test driver"
-       default n
        help
          This builds the "udelay_test" module that helps to make sure
          that udelay() is working properly.
@@ -1935,7 +1923,6 @@ config TEST_UDELAY
 
 config TEST_STATIC_KEYS
        tristate "Test static keys"
-       default n
        depends on m
        help
          Test the static key interfaces.
@@ -1944,7 +1931,6 @@ config TEST_STATIC_KEYS
 
 config TEST_KMOD
        tristate "kmod stress tester"
-       default n
        depends on m
        depends on BLOCK && (64BIT || LBDAF)      # for XFS, BTRFS
        depends on NETDEVICES && NET_CORE && INET # for TUN
index d95bb25..ca3f7eb 100644 (file)
@@ -50,6 +50,7 @@ obj-$(CONFIG_TEST_BPF) += test_bpf.o
 obj-$(CONFIG_TEST_FIRMWARE) += test_firmware.o
 obj-$(CONFIG_TEST_SYSCTL) += test_sysctl.o
 obj-$(CONFIG_TEST_HASH) += test_hash.o test_siphash.o
+obj-$(CONFIG_TEST_IDA) += test_ida.o
 obj-$(CONFIG_TEST_KASAN) += test_kasan.o
 CFLAGS_test_kasan.o += -fno-builtin
 obj-$(CONFIG_TEST_UBSAN) += test_ubsan.o
@@ -103,6 +104,7 @@ obj-$(CONFIG_CRC16) += crc16.o
 obj-$(CONFIG_CRC_T10DIF)+= crc-t10dif.o
 obj-$(CONFIG_CRC_ITU_T)        += crc-itu-t.o
 obj-$(CONFIG_CRC32)    += crc32.o
+obj-$(CONFIG_CRC64)     += crc64.o
 obj-$(CONFIG_CRC32_SELFTEST)   += crc32test.o
 obj-$(CONFIG_CRC4)     += crc4.o
 obj-$(CONFIG_CRC7)     += crc7.o
@@ -217,7 +219,9 @@ obj-$(CONFIG_FONT_SUPPORT) += fonts/
 obj-$(CONFIG_PRIME_NUMBERS) += prime_numbers.o
 
 hostprogs-y    := gen_crc32table
+hostprogs-y    += gen_crc64table
 clean-files    := crc32table.h
+clean-files    += crc64table.h
 
 $(obj)/crc32.o: $(obj)/crc32table.h
 
@@ -227,6 +231,14 @@ quiet_cmd_crc32 = GEN     $@
 $(obj)/crc32table.h: $(obj)/gen_crc32table
        $(call cmd,crc32)
 
+$(obj)/crc64.o: $(obj)/crc64table.h
+
+quiet_cmd_crc64 = GEN     $@
+      cmd_crc64 = $< > $@
+
+$(obj)/crc64table.h: $(obj)/gen_crc64table
+       $(call cmd,crc64)
+
 #
 # Build a fast OID lookip registry from include/linux/oid_registry.h
 #
index 730969c..2fd07f6 100644 (file)
@@ -1152,14 +1152,10 @@ EXPORT_SYMBOL(bitmap_free);
  *     @buf: array of u32 (in host byte order), the source bitmap
  *     @nbits: number of bits in @bitmap
  */
-void bitmap_from_arr32(unsigned long *bitmap, const u32 *buf,
-                                               unsigned int nbits)
+void bitmap_from_arr32(unsigned long *bitmap, const u32 *buf, unsigned int nbits)
 {
        unsigned int i, halfwords;
 
-       if (!nbits)
-               return;
-
        halfwords = DIV_ROUND_UP(nbits, 32);
        for (i = 0; i < halfwords; i++) {
                bitmap[i/2] = (unsigned long) buf[i];
@@ -1183,9 +1179,6 @@ void bitmap_to_arr32(u32 *buf, const unsigned long *bitmap, unsigned int nbits)
 {
        unsigned int i, halfwords;
 
-       if (!nbits)
-               return;
-
        halfwords = DIV_ROUND_UP(nbits, 32);
        for (i = 0; i < halfwords; i++) {
                buf[i] = (u32) (bitmap[i/2] & UINT_MAX);
diff --git a/lib/crc64.c b/lib/crc64.c
new file mode 100644 (file)
index 0000000..0ef8ae6
--- /dev/null
@@ -0,0 +1,56 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Normal 64-bit CRC calculation.
+ *
+ * This is a basic crc64 implementation following ECMA-182 specification,
+ * which can be found from,
+ * http://www.ecma-international.org/publications/standards/Ecma-182.htm
+ *
+ * Dr. Ross N. Williams has a great document to introduce the idea of CRC
+ * algorithm, here the CRC64 code is also inspired by the table-driven
+ * algorithm and detail example from this paper. This paper can be found
+ * from,
+ * http://www.ross.net/crc/download/crc_v3.txt
+ *
+ * crc64table[256] is the lookup table of a table-driven 64-bit CRC
+ * calculation, which is generated by gen_crc64table.c in kernel build
+ * time. The polynomial of crc64 arithmetic is from ECMA-182 specification
+ * as well, which is defined as,
+ *
+ * x^64 + x^62 + x^57 + x^55 + x^54 + x^53 + x^52 + x^47 + x^46 + x^45 +
+ * x^40 + x^39 + x^38 + x^37 + x^35 + x^33 + x^32 + x^31 + x^29 + x^27 +
+ * x^24 + x^23 + x^22 + x^21 + x^19 + x^17 + x^13 + x^12 + x^10 + x^9 +
+ * x^7 + x^4 + x + 1
+ *
+ * Copyright 2018 SUSE Linux.
+ *   Author: Coly Li <colyli@suse.de>
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include "crc64table.h"
+
+MODULE_DESCRIPTION("CRC64 calculations");
+MODULE_LICENSE("GPL v2");
+
+/**
+ * crc64_be - Calculate bitwise big-endian ECMA-182 CRC64
+ * @crc: seed value for computation. 0 or (u64)~0 for a new CRC calculation,
+       or the previous crc64 value if computing incrementally.
+ * @p: pointer to buffer over which CRC64 is run
+ * @len: length of buffer @p
+ */
+u64 __pure crc64_be(u64 crc, const void *p, size_t len)
+{
+       size_t i, t;
+
+       const unsigned char *_p = p;
+
+       for (i = 0; i < len; i++) {
+               t = ((crc >> 56) ^ (*_p++)) & 0xFF;
+               crc = crc64table[t] ^ (crc << 8);
+       }
+
+       return crc;
+}
+EXPORT_SYMBOL_GPL(crc64_be);
index 9ae5b62..89752d0 100644 (file)
@@ -2058,7 +2058,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x00, /* 0000000 */
        0x00, /* 0000000 */
 
-       /* 128 0x80 '\80' */
+       /* 128 0x80 'Ç' */
        0x00, /* 0000000 */
        0x38, /* 0011100 */
        0x6c, /* 0110110 */
@@ -2074,7 +2074,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x70, /* 0111000 */
        0x00, /* 0000000 */
 
-       /* 129 0x81 '\81' */
+       /* 129 0x81 'ü' */
        0x00, /* 0000000 */
        0xcc, /* 1100110 */
        0x00, /* 0000000 */
@@ -2090,7 +2090,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x00, /* 0000000 */
        0x00, /* 0000000 */
 
-       /* 130 0x82 '\82' */
+       /* 130 0x82 'é' */
        0x0c, /* 0000110 */
        0x18, /* 0001100 */
        0x30, /* 0011000 */
@@ -2106,7 +2106,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x00, /* 0000000 */
        0x00, /* 0000000 */
 
-       /* 131 0x83 '\83' */
+       /* 131 0x83 'â' */
        0x10, /* 0001000 */
        0x38, /* 0011100 */
        0x6c, /* 0110110 */
@@ -2122,7 +2122,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x00, /* 0000000 */
        0x00, /* 0000000 */
 
-       /* 132 0x84 '\84' */
+       /* 132 0x84 'ä' */
        0x00, /* 0000000 */
        0xcc, /* 1100110 */
        0x00, /* 0000000 */
@@ -2138,7 +2138,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x00, /* 0000000 */
        0x00, /* 0000000 */
 
-       /* 133 0x85 '\85' */
+       /* 133 0x85 'à' */
        0x60, /* 0110000 */
        0x30, /* 0011000 */
        0x18, /* 0001100 */
@@ -2154,7 +2154,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x00, /* 0000000 */
        0x00, /* 0000000 */
 
-       /* 134 0x86 '\86' */
+       /* 134 0x86 'å' */
        0x38, /* 0011100 */
        0x6c, /* 0110110 */
        0x38, /* 0011100 */
@@ -2170,7 +2170,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x00, /* 0000000 */
        0x00, /* 0000000 */
 
-       /* 135 0x87 '\87' */
+       /* 135 0x87 'ç' */
        0x00, /* 0000000 */
        0x00, /* 0000000 */
        0x00, /* 0000000 */
@@ -2186,7 +2186,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x30, /* 0011000 */
        0xe0, /* 1110000 */
 
-       /* 136 0x88 '\88' */
+       /* 136 0x88 'ê' */
        0x10, /* 0001000 */
        0x38, /* 0011100 */
        0x6c, /* 0110110 */
@@ -2202,7 +2202,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x00, /* 0000000 */
        0x00, /* 0000000 */
 
-       /* 137 0x89 '\89' */
+       /* 137 0x89 'ë' */
        0x00, /* 0000000 */
        0xcc, /* 1100110 */
        0x00, /* 0000000 */
@@ -2218,7 +2218,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x00, /* 0000000 */
        0x00, /* 0000000 */
 
-       /* 138 0x8a '\8a' */
+       /* 138 0x8a 'è' */
        0xc0, /* 1100000 */
        0x60, /* 0110000 */
        0x30, /* 0011000 */
@@ -2234,7 +2234,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x00, /* 0000000 */
        0x00, /* 0000000 */
 
-       /* 139 0x8b '\8b' */
+       /* 139 0x8b 'ï' */
        0x00, /* 0000000 */
        0x6c, /* 0110110 */
        0x00, /* 0000000 */
@@ -2250,7 +2250,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x00, /* 0000000 */
        0x00, /* 0000000 */
 
-       /* 140 0x8c '\8c' */
+       /* 140 0x8c 'î' */
        0x30, /* 0011000 */
        0x78, /* 0111100 */
        0xcc, /* 1100110 */
@@ -2266,7 +2266,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x00, /* 0000000 */
        0x00, /* 0000000 */
 
-       /* 141 0x8d '\8d' */
+       /* 141 0x8d 'ì' */
        0xc0, /* 1100000 */
        0x60, /* 0110000 */
        0x30, /* 0011000 */
@@ -2282,7 +2282,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x00, /* 0000000 */
        0x00, /* 0000000 */
 
-       /* 142 0x8e '\8e' */
+       /* 142 0x8e 'Ä' */
        0x00, /* 0000000 */
        0xcc, /* 1100110 */
        0x00, /* 0000000 */
@@ -2298,7 +2298,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x00, /* 0000000 */
        0x00, /* 0000000 */
 
-       /* 143 0x8f '\8f' */
+       /* 143 0x8f 'Å' */
        0x30, /* 0011000 */
        0x48, /* 0100100 */
        0x48, /* 0100100 */
@@ -2314,7 +2314,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x00, /* 0000000 */
        0x00, /* 0000000 */
 
-       /* 144 0x90 '\90' */
+       /* 144 0x90 'É' */
        0x18, /* 0001100 */
        0x30, /* 0011000 */
        0xfc, /* 1111110 */
@@ -2330,7 +2330,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x00, /* 0000000 */
        0x00, /* 0000000 */
 
-       /* 145 0x91 '\91' */
+       /* 145 0x91 'æ' */
        0x00, /* 0000000 */
        0x00, /* 0000000 */
        0x00, /* 0000000 */
@@ -2346,7 +2346,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x00, /* 0000000 */
        0x00, /* 0000000 */
 
-       /* 146 0x92 '\92' */
+       /* 146 0x92 'Æ' */
        0x00, /* 0000000 */
        0x3e, /* 0011111 */
        0x6c, /* 0110110 */
@@ -2362,7 +2362,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x00, /* 0000000 */
        0x00, /* 0000000 */
 
-       /* 147 0x93 '\93' */
+       /* 147 0x93 'ô' */
        0x10, /* 0001000 */
        0x38, /* 0011100 */
        0x6c, /* 0110110 */
@@ -2378,7 +2378,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x00, /* 0000000 */
        0x00, /* 0000000 */
 
-       /* 148 0x94 '\94' */
+       /* 148 0x94 'ö' */
        0x00, /* 0000000 */
        0xcc, /* 1100110 */
        0x00, /* 0000000 */
@@ -2394,7 +2394,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x00, /* 0000000 */
        0x00, /* 0000000 */
 
-       /* 149 0x95 '\95' */
+       /* 149 0x95 'ò' */
        0xc0, /* 1100000 */
        0x60, /* 0110000 */
        0x30, /* 0011000 */
@@ -2410,7 +2410,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x00, /* 0000000 */
        0x00, /* 0000000 */
 
-       /* 150 0x96 '\96' */
+       /* 150 0x96 'û' */
        0x30, /* 0011000 */
        0x78, /* 0111100 */
        0xcc, /* 1100110 */
@@ -2426,7 +2426,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x00, /* 0000000 */
        0x00, /* 0000000 */
 
-       /* 151 0x97 '\97' */
+       /* 151 0x97 'ù' */
        0x60, /* 0110000 */
        0x30, /* 0011000 */
        0x18, /* 0001100 */
@@ -2442,7 +2442,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x00, /* 0000000 */
        0x00, /* 0000000 */
 
-       /* 152 0x98 '\98' */
+       /* 152 0x98 'ÿ' */
        0x00, /* 0000000 */
        0xcc, /* 1100110 */
        0x00, /* 0000000 */
@@ -2458,7 +2458,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x18, /* 0001100 */
        0x70, /* 0111000 */
 
-       /* 153 0x99 '\99' */
+       /* 153 0x99 'Ö' */
        0xcc, /* 1100110 */
        0x00, /* 0000000 */
        0x78, /* 0111100 */
@@ -2474,7 +2474,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x00, /* 0000000 */
        0x00, /* 0000000 */
 
-       /* 154 0x9a '\9a' */
+       /* 154 0x9a 'Ü' */
        0xcc, /* 1100110 */
        0x00, /* 0000000 */
        0xcc, /* 1100110 */
@@ -2490,7 +2490,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x00, /* 0000000 */
        0x00, /* 0000000 */
 
-       /* 155 0x9b '\9b' */
+       /* 155 0x9b '¢' */
        0x30, /* 0011000 */
        0x30, /* 0011000 */
        0x7c, /* 0111110 */
@@ -2506,7 +2506,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x00, /* 0000000 */
        0x00, /* 0000000 */
 
-       /* 156 0x9c '\9c' */
+       /* 156 0x9c '£' */
        0x38, /* 0011100 */
        0x6c, /* 0110110 */
        0x64, /* 0110010 */
@@ -2522,7 +2522,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x00, /* 0000000 */
        0x00, /* 0000000 */
 
-       /* 157 0x9d '\9d' */
+       /* 157 0x9d '¥' */
        0x00, /* 0000000 */
        0xcc, /* 1100110 */
        0xcc, /* 1100110 */
@@ -2538,7 +2538,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x00, /* 0000000 */
        0x00, /* 0000000 */
 
-       /* 158 0x9e '\9e' */
+       /* 158 0x9e '' */
        0xf8, /* 1111100 */
        0xcc, /* 1100110 */
        0xcc, /* 1100110 */
@@ -2554,7 +2554,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x00, /* 0000000 */
        0x00, /* 0000000 */
 
-       /* 159 0x9f '\9f' */
+       /* 159 0x9f 'ƒ' */
        0x1c, /* 0001110 */
        0x36, /* 0011011 */
        0x30, /* 0011000 */
@@ -2570,7 +2570,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x00, /* 0000000 */
        0x00, /* 0000000 */
 
-       /* 160 0xa0 ' ' */
+       /* 160 0xa0 'á' */
        0x18, /* 0001100 */
        0x30, /* 0011000 */
        0x60, /* 0110000 */
@@ -2586,7 +2586,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x00, /* 0000000 */
        0x00, /* 0000000 */
 
-       /* 161 0xa1 '¡' */
+       /* 161 0xa1 'í' */
        0x18, /* 0001100 */
        0x30, /* 0011000 */
        0x60, /* 0110000 */
@@ -2602,7 +2602,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x00, /* 0000000 */
        0x00, /* 0000000 */
 
-       /* 162 0xa2 '¢' */
+       /* 162 0xa2 'ó' */
        0x18, /* 0001100 */
        0x30, /* 0011000 */
        0x60, /* 0110000 */
@@ -2618,7 +2618,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x00, /* 0000000 */
        0x00, /* 0000000 */
 
-       /* 163 0xa3 '£' */
+       /* 163 0xa3 'ú' */
        0x18, /* 0001100 */
        0x30, /* 0011000 */
        0x60, /* 0110000 */
@@ -2634,7 +2634,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x00, /* 0000000 */
        0x00, /* 0000000 */
 
-       /* 164 0xa4 '¤' */
+       /* 164 0xa4 'ñ' */
        0x00, /* 0000000 */
        0x76, /* 0111011 */
        0xdc, /* 1101110 */
@@ -2650,7 +2650,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x00, /* 0000000 */
        0x00, /* 0000000 */
 
-       /* 165 0xa5 '¥' */
+       /* 165 0xa5 'Ñ' */
        0x76, /* 0111011 */
        0xdc, /* 1101110 */
        0x00, /* 0000000 */
@@ -2666,7 +2666,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x00, /* 0000000 */
        0x00, /* 0000000 */
 
-       /* 166 0xa6 '¦' */
+       /* 166 0xa6 'ª' */
        0x00, /* 0000000 */
        0x78, /* 0111100 */
        0xd8, /* 1101100 */
@@ -2682,7 +2682,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x00, /* 0000000 */
        0x00, /* 0000000 */
 
-       /* 167 0xa7 '§' */
+       /* 167 0xa7 'º' */
        0x00, /* 0000000 */
        0x70, /* 0111000 */
        0xd8, /* 1101100 */
@@ -2698,7 +2698,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x00, /* 0000000 */
        0x00, /* 0000000 */
 
-       /* 168 0xa8 '¨' */
+       /* 168 0xa8 '¿' */
        0x00, /* 0000000 */
        0x30, /* 0011000 */
        0x30, /* 0011000 */
@@ -2714,7 +2714,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x00, /* 0000000 */
        0x00, /* 0000000 */
 
-       /* 169 0xa9 '©' */
+       /* 169 0xa9 '' */
        0x00, /* 0000000 */
        0x00, /* 0000000 */
        0x00, /* 0000000 */
@@ -2730,7 +2730,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x00, /* 0000000 */
        0x00, /* 0000000 */
 
-       /* 170 0xaa 'ª' */
+       /* 170 0xaa '¬' */
        0x00, /* 0000000 */
        0x00, /* 0000000 */
        0x00, /* 0000000 */
@@ -2746,7 +2746,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x00, /* 0000000 */
        0x00, /* 0000000 */
 
-       /* 171 0xab '«' */
+       /* 171 0xab '½' */
        0x60, /* 0110000 */
        0xe0, /* 1110000 */
        0x62, /* 0110001 */
@@ -2762,7 +2762,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x30, /* 0011000 */
        0x7c, /* 0111110 */
 
-       /* 172 0xac '¬' */
+       /* 172 0xac '¼' */
        0x60, /* 0110000 */
        0xe0, /* 1110000 */
        0x62, /* 0110001 */
@@ -2778,7 +2778,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x0c, /* 0000110 */
        0x00, /* 0000000 */
 
-       /* 173 0xad '­' */
+       /* 173 0xad '¡' */
        0x00, /* 0000000 */
        0x30, /* 0011000 */
        0x30, /* 0011000 */
@@ -2794,7 +2794,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x00, /* 0000000 */
        0x00, /* 0000000 */
 
-       /* 174 0xae '®' */
+       /* 174 0xae '«' */
        0x00, /* 0000000 */
        0x00, /* 0000000 */
        0x00, /* 0000000 */
@@ -2810,7 +2810,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x00, /* 0000000 */
        0x00, /* 0000000 */
 
-       /* 175 0xaf '¯' */
+       /* 175 0xaf '»' */
        0x00, /* 0000000 */
        0x00, /* 0000000 */
        0x00, /* 0000000 */
@@ -2826,7 +2826,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x00, /* 0000000 */
        0x00, /* 0000000 */
 
-       /* 176 0xb0 '°' */
+       /* 176 0xb0 '' */
        0x88, /* 1000100 */
        0x22, /* 0010001 */
        0x88, /* 1000100 */
@@ -2842,7 +2842,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x88, /* 1000100 */
        0x22, /* 0010001 */
 
-       /* 177 0xb1 '±' */
+       /* 177 0xb1 '' */
        0x54, /* 0101010 */
        0xaa, /* 1010101 */
        0x54, /* 0101010 */
@@ -2858,7 +2858,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x54, /* 0101010 */
        0xaa, /* 1010101 */
 
-       /* 178 0xb2 '²' */
+       /* 178 0xb2 '' */
        0xee, /* 1110111 */
        0xba, /* 1011101 */
        0xee, /* 1110111 */
@@ -2874,7 +2874,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0xee, /* 1110111 */
        0xba, /* 1011101 */
 
-       /* 179 0xb3 '³' */
+       /* 179 0xb3 '' */
        0x30, /* 0011000 */
        0x30, /* 0011000 */
        0x30, /* 0011000 */
@@ -2890,7 +2890,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x30, /* 0011000 */
        0x30, /* 0011000 */
 
-       /* 180 0xb4 '´' */
+       /* 180 0xb4 '' */
        0x30, /* 0011000 */
        0x30, /* 0011000 */
        0x30, /* 0011000 */
@@ -2906,7 +2906,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x30, /* 0011000 */
        0x30, /* 0011000 */
 
-       /* 181 0xb5 'µ' */
+       /* 181 0xb5 '' */
        0x30, /* 0011000 */
        0x30, /* 0011000 */
        0x30, /* 0011000 */
@@ -2922,7 +2922,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x30, /* 0011000 */
        0x30, /* 0011000 */
 
-       /* 182 0xb6 '' */
+       /* 182 0xb6 '' */
        0x6c, /* 0110110 */
        0x6c, /* 0110110 */
        0x6c, /* 0110110 */
@@ -2938,7 +2938,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x6c, /* 0110110 */
        0x6c, /* 0110110 */
 
-       /* 183 0xb7 '·' */
+       /* 183 0xb7 '' */
        0x00, /* 0000000 */
        0x00, /* 0000000 */
        0x00, /* 0000000 */
@@ -2954,7 +2954,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x6c, /* 0110110 */
        0x6c, /* 0110110 */
 
-       /* 184 0xb8 '¸' */
+       /* 184 0xb8 '' */
        0x00, /* 0000000 */
        0x00, /* 0000000 */
        0x00, /* 0000000 */
@@ -2970,7 +2970,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x30, /* 0011000 */
        0x30, /* 0011000 */
 
-       /* 185 0xb9 '¹' */
+       /* 185 0xb9 '' */
        0x6c, /* 0110110 */
        0x6c, /* 0110110 */
        0x6c, /* 0110110 */
@@ -2986,7 +2986,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x6c, /* 0110110 */
        0x6c, /* 0110110 */
 
-       /* 186 0xba 'º' */
+       /* 186 0xba '' */
        0x6c, /* 0110110 */
        0x6c, /* 0110110 */
        0x6c, /* 0110110 */
@@ -3002,7 +3002,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x6c, /* 0110110 */
        0x6c, /* 0110110 */
 
-       /* 187 0xbb '»' */
+       /* 187 0xbb '' */
        0x00, /* 0000000 */
        0x00, /* 0000000 */
        0x00, /* 0000000 */
@@ -3018,7 +3018,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x6c, /* 0110110 */
        0x6c, /* 0110110 */
 
-       /* 188 0xbc '¼' */
+       /* 188 0xbc '' */
        0x6c, /* 0110110 */
        0x6c, /* 0110110 */
        0x6c, /* 0110110 */
@@ -3034,7 +3034,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x00, /* 0000000 */
        0x00, /* 0000000 */
 
-       /* 189 0xbd '½' */
+       /* 189 0xbd '' */
        0x6c, /* 0110110 */
        0x6c, /* 0110110 */
        0x6c, /* 0110110 */
@@ -3050,7 +3050,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x00, /* 0000000 */
        0x00, /* 0000000 */
 
-       /* 190 0xbe '¾' */
+       /* 190 0xbe '' */
        0x30, /* 0011000 */
        0x30, /* 0011000 */
        0x30, /* 0011000 */
@@ -3066,7 +3066,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x00, /* 0000000 */
        0x00, /* 0000000 */
 
-       /* 191 0xbf '¿' */
+       /* 191 0xbf '' */
        0x00, /* 0000000 */
        0x00, /* 0000000 */
        0x00, /* 0000000 */
@@ -3082,7 +3082,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x30, /* 0011000 */
        0x30, /* 0011000 */
 
-       /* 192 0xc0 'À' */
+       /* 192 0xc0 '' */
        0x30, /* 0011000 */
        0x30, /* 0011000 */
        0x30, /* 0011000 */
@@ -3098,7 +3098,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x00, /* 0000000 */
        0x00, /* 0000000 */
 
-       /* 193 0xc1 'Á' */
+       /* 193 0xc1 '' */
        0x30, /* 0011000 */
        0x30, /* 0011000 */
        0x30, /* 0011000 */
@@ -3114,7 +3114,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x00, /* 0000000 */
        0x00, /* 0000000 */
 
-       /* 194 0xc2 'Â' */
+       /* 194 0xc2 '' */
        0x00, /* 0000000 */
        0x00, /* 0000000 */
        0x00, /* 0000000 */
@@ -3130,7 +3130,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x30, /* 0011000 */
        0x30, /* 0011000 */
 
-       /* 195 0xc3 'Ã' */
+       /* 195 0xc3 '' */
        0x30, /* 0011000 */
        0x30, /* 0011000 */
        0x30, /* 0011000 */
@@ -3146,7 +3146,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x30, /* 0011000 */
        0x30, /* 0011000 */
 
-       /* 196 0xc4 'Ä' */
+       /* 196 0xc4 '' */
        0x00, /* 0000000 */
        0x00, /* 0000000 */
        0x00, /* 0000000 */
@@ -3162,7 +3162,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x00, /* 0000000 */
        0x00, /* 0000000 */
 
-       /* 197 0xc5 'Å' */
+       /* 197 0xc5 '' */
        0x30, /* 0011000 */
        0x30, /* 0011000 */
        0x30, /* 0011000 */
@@ -3178,7 +3178,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x30, /* 0011000 */
        0x30, /* 0011000 */
 
-       /* 198 0xc6 'Æ' */
+       /* 198 0xc6 '' */
        0x30, /* 0011000 */
        0x30, /* 0011000 */
        0x30, /* 0011000 */
@@ -3194,7 +3194,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x30, /* 0011000 */
        0x30, /* 0011000 */
 
-       /* 199 0xc7 'Ç' */
+       /* 199 0xc7 '' */
        0x6c, /* 0110110 */
        0x6c, /* 0110110 */
        0x6c, /* 0110110 */
@@ -3210,7 +3210,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x6c, /* 0110110 */
        0x6c, /* 0110110 */
 
-       /* 200 0xc8 'È' */
+       /* 200 0xc8 '' */
        0x6c, /* 0110110 */
        0x6c, /* 0110110 */
        0x6c, /* 0110110 */
@@ -3226,7 +3226,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x00, /* 0000000 */
        0x00, /* 0000000 */
 
-       /* 201 0xc9 'É' */
+       /* 201 0xc9 '' */
        0x00, /* 0000000 */
        0x00, /* 0000000 */
        0x00, /* 0000000 */
@@ -3242,7 +3242,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x6c, /* 0110110 */
        0x6c, /* 0110110 */
 
-       /* 202 0xca 'Ê' */
+       /* 202 0xca '' */
        0x6c, /* 0110110 */
        0x6c, /* 0110110 */
        0x6c, /* 0110110 */
@@ -3258,7 +3258,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x00, /* 0000000 */
        0x00, /* 0000000 */
 
-       /* 203 0xcb 'Ë' */
+       /* 203 0xcb '' */
        0x00, /* 0000000 */
        0x00, /* 0000000 */
        0x00, /* 0000000 */
@@ -3274,7 +3274,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x6c, /* 0110110 */
        0x6c, /* 0110110 */
 
-       /* 204 0xcc 'Ì' */
+       /* 204 0xcc '' */
        0x6c, /* 0110110 */
        0x6c, /* 0110110 */
        0x6c, /* 0110110 */
@@ -3290,7 +3290,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x6c, /* 0110110 */
        0x6c, /* 0110110 */
 
-       /* 205 0xcd 'Í' */
+       /* 205 0xcd '' */
        0x00, /* 0000000 */
        0x00, /* 0000000 */
        0x00, /* 0000000 */
@@ -3306,7 +3306,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x00, /* 0000000 */
        0x00, /* 0000000 */
 
-       /* 206 0xce 'Î' */
+       /* 206 0xce '' */
        0x6c, /* 0110110 */
        0x6c, /* 0110110 */
        0x6c, /* 0110110 */
@@ -3322,7 +3322,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x6c, /* 0110110 */
        0x6c, /* 0110110 */
 
-       /* 207 0xcf 'Ï' */
+       /* 207 0xcf '' */
        0x30, /* 0011000 */
        0x30, /* 0011000 */
        0x30, /* 0011000 */
@@ -3338,7 +3338,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x00, /* 0000000 */
        0x00, /* 0000000 */
 
-       /* 208 0xd0 'Ð' */
+       /* 208 0xd0 '' */
        0x6c, /* 0110110 */
        0x6c, /* 0110110 */
        0x6c, /* 0110110 */
@@ -3354,7 +3354,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x00, /* 0000000 */
        0x00, /* 0000000 */
 
-       /* 209 0xd1 'Ñ' */
+       /* 209 0xd1 '' */
        0x00, /* 0000000 */
        0x00, /* 0000000 */
        0x00, /* 0000000 */
@@ -3370,7 +3370,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x30, /* 0011000 */
        0x30, /* 0011000 */
 
-       /* 210 0xd2 'Ò' */
+       /* 210 0xd2 '' */
        0x00, /* 0000000 */
        0x00, /* 0000000 */
        0x00, /* 0000000 */
@@ -3386,7 +3386,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x6c, /* 0110110 */
        0x6c, /* 0110110 */
 
-       /* 211 0xd3 'Ó' */
+       /* 211 0xd3 '' */
        0x6c, /* 0110110 */
        0x6c, /* 0110110 */
        0x6c, /* 0110110 */
@@ -3402,7 +3402,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x00, /* 0000000 */
        0x00, /* 0000000 */
 
-       /* 212 0xd4 'Ô' */
+       /* 212 0xd4 '' */
        0x30, /* 0011000 */
        0x30, /* 0011000 */
        0x30, /* 0011000 */
@@ -3418,7 +3418,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x00, /* 0000000 */
        0x00, /* 0000000 */
 
-       /* 213 0xd5 'Õ' */
+       /* 213 0xd5 '' */
        0x00, /* 0000000 */
        0x00, /* 0000000 */
        0x00, /* 0000000 */
@@ -3434,7 +3434,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x30, /* 0011000 */
        0x30, /* 0011000 */
 
-       /* 214 0xd6 'Ö' */
+       /* 214 0xd6 '' */
        0x00, /* 0000000 */
        0x00, /* 0000000 */
        0x00, /* 0000000 */
@@ -3450,7 +3450,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x6c, /* 0110110 */
        0x6c, /* 0110110 */
 
-       /* 215 0xd7 '×' */
+       /* 215 0xd7 '' */
        0x6c, /* 0110110 */
        0x6c, /* 0110110 */
        0x6c, /* 0110110 */
@@ -3466,7 +3466,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x6c, /* 0110110 */
        0x6c, /* 0110110 */
 
-       /* 216 0xd8 'Ø' */
+       /* 216 0xd8 '' */
        0x30, /* 0011000 */
        0x30, /* 0011000 */
        0x30, /* 0011000 */
@@ -3482,7 +3482,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x30, /* 0011000 */
        0x30, /* 0011000 */
 
-       /* 217 0xd9 'Ù' */
+       /* 217 0xd9 '' */
        0x30, /* 0011000 */
        0x30, /* 0011000 */
        0x30, /* 0011000 */
@@ -3498,7 +3498,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x00, /* 0000000 */
        0x00, /* 0000000 */
 
-       /* 218 0xda 'Ú' */
+       /* 218 0xda '' */
        0x00, /* 0000000 */
        0x00, /* 0000000 */
        0x00, /* 0000000 */
@@ -3514,7 +3514,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x30, /* 0011000 */
        0x30, /* 0011000 */
 
-       /* 219 0xdb 'Û' */
+       /* 219 0xdb '' */
        0xfe, /* 1111111 */
        0xfe, /* 1111111 */
        0xfe, /* 1111111 */
@@ -3530,7 +3530,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0xfe, /* 1111111 */
        0xfe, /* 1111111 */
 
-       /* 220 0xdc 'Ü' */
+       /* 220 0xdc '' */
        0x00, /* 0000000 */
        0x00, /* 0000000 */
        0x00, /* 0000000 */
@@ -3546,7 +3546,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0xfe, /* 1111111 */
        0xfe, /* 1111111 */
 
-       /* 221 0xdd 'Ý' */
+       /* 221 0xdd '' */
        0xe0, /* 1110000 */
        0xe0, /* 1110000 */
        0xe0, /* 1110000 */
@@ -3562,7 +3562,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0xe0, /* 1110000 */
        0xe0, /* 1110000 */
 
-       /* 222 0xde 'Þ' */
+       /* 222 0xde '' */
        0x1e, /* 0001111 */
        0x1e, /* 0001111 */
        0x1e, /* 0001111 */
@@ -3578,7 +3578,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x1e, /* 0001111 */
        0x1e, /* 0001111 */
 
-       /* 223 0xdf 'ß' */
+       /* 223 0xdf '' */
        0xfe, /* 1111111 */
        0xfe, /* 1111111 */
        0xfe, /* 1111111 */
@@ -3594,7 +3594,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x00, /* 0000000 */
        0x00, /* 0000000 */
 
-       /* 224 0xe0 'à' */
+       /* 224 0xe0 'α' */
        0x00, /* 0000000 */
        0x00, /* 0000000 */
        0x00, /* 0000000 */
@@ -3610,7 +3610,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x00, /* 0000000 */
        0x00, /* 0000000 */
 
-       /* 225 0xe1 'á' */
+       /* 225 0xe1 'ß' */
        0x00, /* 0000000 */
        0x78, /* 0111100 */
        0xcc, /* 1100110 */
@@ -3626,7 +3626,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x00, /* 0000000 */
        0x00, /* 0000000 */
 
-       /* 226 0xe2 'â' */
+       /* 226 0xe2 'Γ' */
        0x00, /* 0000000 */
        0xfc, /* 1111110 */
        0xcc, /* 1100110 */
@@ -3642,7 +3642,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x00, /* 0000000 */
        0x00, /* 0000000 */
 
-       /* 227 0xe3 'ã' */
+       /* 227 0xe3 'π' */
        0x00, /* 0000000 */
        0x00, /* 0000000 */
        0xfe, /* 1111111 */
@@ -3658,7 +3658,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x00, /* 0000000 */
        0x00, /* 0000000 */
 
-       /* 228 0xe4 'ä' */
+       /* 228 0xe4 'Σ' */
        0x00, /* 0000000 */
        0xfc, /* 1111110 */
        0xcc, /* 1100110 */
@@ -3674,7 +3674,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x00, /* 0000000 */
        0x00, /* 0000000 */
 
-       /* 229 0xe5 'å' */
+       /* 229 0xe5 'σ' */
        0x00, /* 0000000 */
        0x00, /* 0000000 */
        0x00, /* 0000000 */
@@ -3690,7 +3690,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x00, /* 0000000 */
        0x00, /* 0000000 */
 
-       /* 230 0xe6 'æ' */
+       /* 230 0xe6 'µ' */
        0x00, /* 0000000 */
        0x00, /* 0000000 */
        0x00, /* 0000000 */
@@ -3706,7 +3706,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0xc0, /* 1100000 */
        0x80, /* 1000000 */
 
-       /* 231 0xe7 'ç' */
+       /* 231 0xe7 'τ' */
        0x00, /* 0000000 */
        0x00, /* 0000000 */
        0x00, /* 0000000 */
@@ -3722,7 +3722,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x00, /* 0000000 */
        0x00, /* 0000000 */
 
-       /* 232 0xe8 'è' */
+       /* 232 0xe8 'Φ' */
        0x00, /* 0000000 */
        0xfc, /* 1111110 */
        0x30, /* 0011000 */
@@ -3738,7 +3738,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x00, /* 0000000 */
        0x00, /* 0000000 */
 
-       /* 233 0xe9 'é' */
+       /* 233 0xe9 'Θ' */
        0x00, /* 0000000 */
        0x38, /* 0011100 */
        0x6c, /* 0110110 */
@@ -3754,7 +3754,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x00, /* 0000000 */
        0x00, /* 0000000 */
 
-       /* 234 0xea 'ê' */
+       /* 234 0xea 'Ω' */
        0x00, /* 0000000 */
        0x38, /* 0011100 */
        0x6c, /* 0110110 */
@@ -3770,7 +3770,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x00, /* 0000000 */
        0x00, /* 0000000 */
 
-       /* 235 0xeb 'ë' */
+       /* 235 0xeb 'δ' */
        0x00, /* 0000000 */
        0x3c, /* 0011110 */
        0x60, /* 0110000 */
@@ -3786,7 +3786,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x00, /* 0000000 */
        0x00, /* 0000000 */
 
-       /* 236 0xec 'ì' */
+       /* 236 0xec '' */
        0x00, /* 0000000 */
        0x00, /* 0000000 */
        0x00, /* 0000000 */
@@ -3802,7 +3802,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x00, /* 0000000 */
        0x00, /* 0000000 */
 
-       /* 237 0xed 'í' */
+       /* 237 0xed 'φ' */
        0x00, /* 0000000 */
        0x00, /* 0000000 */
        0x06, /* 0000011 */
@@ -3818,7 +3818,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x00, /* 0000000 */
        0x00, /* 0000000 */
 
-       /* 238 0xee 'î' */
+       /* 238 0xee 'ε' */
        0x00, /* 0000000 */
        0x1c, /* 0001110 */
        0x30, /* 0011000 */
@@ -3834,7 +3834,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x00, /* 0000000 */
        0x00, /* 0000000 */
 
-       /* 239 0xef 'ï' */
+       /* 239 0xef '' */
        0x00, /* 0000000 */
        0x00, /* 0000000 */
        0x78, /* 0111100 */
@@ -3850,7 +3850,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x00, /* 0000000 */
        0x00, /* 0000000 */
 
-       /* 240 0xf0 'ð' */
+       /* 240 0xf0 '' */
        0x00, /* 0000000 */
        0x00, /* 0000000 */
        0x00, /* 0000000 */
@@ -3866,7 +3866,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x00, /* 0000000 */
        0x00, /* 0000000 */
 
-       /* 241 0xf1 'ñ' */
+       /* 241 0xf1 '±' */
        0x00, /* 0000000 */
        0x00, /* 0000000 */
        0x00, /* 0000000 */
@@ -3882,7 +3882,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x00, /* 0000000 */
        0x00, /* 0000000 */
 
-       /* 242 0xf2 'ò' */
+       /* 242 0xf2 '' */
        0x00, /* 0000000 */
        0x00, /* 0000000 */
        0x60, /* 0110000 */
@@ -3898,7 +3898,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x00, /* 0000000 */
        0x00, /* 0000000 */
 
-       /* 243 0xf3 'ó' */
+       /* 243 0xf3 '' */
        0x00, /* 0000000 */
        0x00, /* 0000000 */
        0x18, /* 0001100 */
@@ -3914,7 +3914,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x00, /* 0000000 */
        0x00, /* 0000000 */
 
-       /* 244 0xf4 'ô' */
+       /* 244 0xf4 '' */
        0x00, /* 0000000 */
        0x1c, /* 0001110 */
        0x36, /* 0011011 */
@@ -3930,7 +3930,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x30, /* 0011000 */
        0x30, /* 0011000 */
 
-       /* 245 0xf5 'õ' */
+       /* 245 0xf5 '' */
        0x18, /* 0001100 */
        0x18, /* 0001100 */
        0x18, /* 0001100 */
@@ -3946,7 +3946,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x00, /* 0000000 */
        0x00, /* 0000000 */
 
-       /* 246 0xf6 'ö' */
+       /* 246 0xf6 '÷' */
        0x00, /* 0000000 */
        0x00, /* 0000000 */
        0x00, /* 0000000 */
@@ -3962,7 +3962,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x00, /* 0000000 */
        0x00, /* 0000000 */
 
-       /* 247 0xf7 '÷' */
+       /* 247 0xf7 '' */
        0x00, /* 0000000 */
        0x00, /* 0000000 */
        0x00, /* 0000000 */
@@ -3978,7 +3978,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x00, /* 0000000 */
        0x00, /* 0000000 */
 
-       /* 248 0xf8 'ø' */
+       /* 248 0xf8 '°' */
        0x38, /* 0011100 */
        0x6c, /* 0110110 */
        0x6c, /* 0110110 */
@@ -3994,7 +3994,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x00, /* 0000000 */
        0x00, /* 0000000 */
 
-       /* 249 0xf9 'ù' */
+       /* 249 0xf9 '·' */
        0x00, /* 0000000 */
        0x00, /* 0000000 */
        0x00, /* 0000000 */
@@ -4010,7 +4010,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x00, /* 0000000 */
        0x00, /* 0000000 */
 
-       /* 250 0xfa 'ú' */
+       /* 250 0xfa '' */
        0x00, /* 0000000 */
        0x00, /* 0000000 */
        0x00, /* 0000000 */
@@ -4026,7 +4026,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x00, /* 0000000 */
        0x00, /* 0000000 */
 
-       /* 251 0xfb 'û' */
+       /* 251 0xfb '' */
        0x1e, /* 0001111 */
        0x18, /* 0001100 */
        0x18, /* 0001100 */
@@ -4042,7 +4042,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x00, /* 0000000 */
        0x00, /* 0000000 */
 
-       /* 252 0xfc 'ü' */
+       /* 252 0xfc '' */
        0xd8, /* 1101100 */
        0x6c, /* 0110110 */
        0x6c, /* 0110110 */
@@ -4058,7 +4058,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x00, /* 0000000 */
        0x00, /* 0000000 */
 
-       /* 253 0xfd 'ý' */
+       /* 253 0xfd '²' */
        0x78, /* 0111100 */
        0xcc, /* 1100110 */
        0x18, /* 0001100 */
@@ -4074,7 +4074,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x00, /* 0000000 */
        0x00, /* 0000000 */
 
-       /* 254 0xfe 'þ' */
+       /* 254 0xfe '' */
        0x00, /* 0000000 */
        0x00, /* 0000000 */
        0x00, /* 0000000 */
@@ -4090,7 +4090,7 @@ static const unsigned char fontdata_7x14[FONTDATAMAX] = {
        0x00, /* 0000000 */
        0x00, /* 0000000 */
 
-       /* 255 0xff 'ÿ' */
+       /* 255 0xff ' ' */
        0x00, /* 0000000 */
        0x00, /* 0000000 */
        0x00, /* 0000000 */
index 34292cd..b7ab1f5 100644 (file)
@@ -2316,7 +2316,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 128 0x80 '\80' */
+       /* 128 0x80 'Ç' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0x3c, /* 00111100 */
@@ -2334,7 +2334,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 129 0x81 '\81' */
+       /* 129 0x81 'ü' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0xcc, /* 11001100 */
@@ -2352,7 +2352,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 130 0x82 '\82' */
+       /* 130 0x82 'é' */
        0x00, /* 00000000 */
        0x0c, /* 00001100 */
        0x18, /* 00011000 */
@@ -2370,7 +2370,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 131 0x83 '\83' */
+       /* 131 0x83 'â' */
        0x00, /* 00000000 */
        0x10, /* 00010000 */
        0x38, /* 00111000 */
@@ -2388,7 +2388,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 132 0x84 '\84' */
+       /* 132 0x84 'ä' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0xcc, /* 11001100 */
@@ -2406,7 +2406,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 133 0x85 '\85' */
+       /* 133 0x85 'à' */
        0x00, /* 00000000 */
        0x60, /* 01100000 */
        0x30, /* 00110000 */
@@ -2424,7 +2424,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 134 0x86 '\86' */
+       /* 134 0x86 'å' */
        0x00, /* 00000000 */
        0x38, /* 00111000 */
        0x6c, /* 01101100 */
@@ -2442,7 +2442,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 135 0x87 '\87' */
+       /* 135 0x87 'ç' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
@@ -2460,7 +2460,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 136 0x88 '\88' */
+       /* 136 0x88 'ê' */
        0x00, /* 00000000 */
        0x10, /* 00010000 */
        0x38, /* 00111000 */
@@ -2478,7 +2478,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 137 0x89 '\89' */
+       /* 137 0x89 'ë' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0xc6, /* 11000110 */
@@ -2496,7 +2496,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 138 0x8a '\8a' */
+       /* 138 0x8a 'è' */
        0x00, /* 00000000 */
        0x60, /* 01100000 */
        0x30, /* 00110000 */
@@ -2514,7 +2514,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 139 0x8b '\8b' */
+       /* 139 0x8b 'ï' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0x66, /* 01100110 */
@@ -2532,7 +2532,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 140 0x8c '\8c' */
+       /* 140 0x8c 'î' */
        0x00, /* 00000000 */
        0x18, /* 00011000 */
        0x3c, /* 00111100 */
@@ -2550,7 +2550,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 141 0x8d '\8d' */
+       /* 141 0x8d 'ì' */
        0x00, /* 00000000 */
        0x60, /* 01100000 */
        0x30, /* 00110000 */
@@ -2568,7 +2568,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 142 0x8e '\8e' */
+       /* 142 0x8e 'Ä' */
        0x00, /* 00000000 */
        0xc6, /* 11000110 */
        0x00, /* 00000000 */
@@ -2586,7 +2586,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 143 0x8f '\8f' */
+       /* 143 0x8f 'Å' */
        0x38, /* 00111000 */
        0x6c, /* 01101100 */
        0x38, /* 00111000 */
@@ -2604,7 +2604,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 144 0x90 '\90' */
+       /* 144 0x90 'É' */
        0x0c, /* 00001100 */
        0x18, /* 00011000 */
        0x00, /* 00000000 */
@@ -2622,7 +2622,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 145 0x91 '\91' */
+       /* 145 0x91 'æ' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
@@ -2640,7 +2640,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 146 0x92 '\92' */
+       /* 146 0x92 'Æ' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0x3e, /* 00111110 */
@@ -2658,7 +2658,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 147 0x93 '\93' */
+       /* 147 0x93 'ô' */
        0x00, /* 00000000 */
        0x10, /* 00010000 */
        0x38, /* 00111000 */
@@ -2676,7 +2676,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 148 0x94 '\94' */
+       /* 148 0x94 'ö' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0xc6, /* 11000110 */
@@ -2694,7 +2694,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 149 0x95 '\95' */
+       /* 149 0x95 'ò' */
        0x00, /* 00000000 */
        0x60, /* 01100000 */
        0x30, /* 00110000 */
@@ -2712,7 +2712,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 150 0x96 '\96' */
+       /* 150 0x96 'û' */
        0x00, /* 00000000 */
        0x30, /* 00110000 */
        0x78, /* 01111000 */
@@ -2730,7 +2730,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 151 0x97 '\97' */
+       /* 151 0x97 'ù' */
        0x00, /* 00000000 */
        0x60, /* 01100000 */
        0x30, /* 00110000 */
@@ -2748,7 +2748,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 152 0x98 '\98' */
+       /* 152 0x98 'ÿ' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0xc6, /* 11000110 */
@@ -2766,7 +2766,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x78, /* 01111000 */
        0x00, /* 00000000 */
 
-       /* 153 0x99 '\99' */
+       /* 153 0x99 'Ö' */
        0x00, /* 00000000 */
        0xc6, /* 11000110 */
        0x00, /* 00000000 */
@@ -2784,7 +2784,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 154 0x9a '\9a' */
+       /* 154 0x9a 'Ü' */
        0x00, /* 00000000 */
        0xc6, /* 11000110 */
        0x00, /* 00000000 */
@@ -2802,7 +2802,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 155 0x9b '\9b' */
+       /* 155 0x9b '¢' */
        0x00, /* 00000000 */
        0x18, /* 00011000 */
        0x18, /* 00011000 */
@@ -2820,7 +2820,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 156 0x9c '\9c' */
+       /* 156 0x9c '£' */
        0x00, /* 00000000 */
        0x38, /* 00111000 */
        0x6c, /* 01101100 */
@@ -2838,7 +2838,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 157 0x9d '\9d' */
+       /* 157 0x9d '¥' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0x66, /* 01100110 */
@@ -2856,7 +2856,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 158 0x9e '\9e' */
+       /* 158 0x9e '' */
        0x00, /* 00000000 */
        0xf8, /* 11111000 */
        0xcc, /* 11001100 */
@@ -2874,7 +2874,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 159 0x9f '\9f' */
+       /* 159 0x9f 'ƒ' */
        0x00, /* 00000000 */
        0x0e, /* 00001110 */
        0x1b, /* 00011011 */
@@ -2892,7 +2892,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 160 0xa0 ' ' */
+       /* 160 0xa0 'á' */
        0x00, /* 00000000 */
        0x18, /* 00011000 */
        0x30, /* 00110000 */
@@ -2910,7 +2910,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 161 0xa1 '¡' */
+       /* 161 0xa1 'í' */
        0x00, /* 00000000 */
        0x0c, /* 00001100 */
        0x18, /* 00011000 */
@@ -2928,7 +2928,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 162 0xa2 '¢' */
+       /* 162 0xa2 'ó' */
        0x00, /* 00000000 */
        0x18, /* 00011000 */
        0x30, /* 00110000 */
@@ -2946,7 +2946,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 163 0xa3 '£' */
+       /* 163 0xa3 'ú' */
        0x00, /* 00000000 */
        0x18, /* 00011000 */
        0x30, /* 00110000 */
@@ -2964,7 +2964,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 164 0xa4 '¤' */
+       /* 164 0xa4 'ñ' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0x76, /* 01110110 */
@@ -2982,7 +2982,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 165 0xa5 '¥' */
+       /* 165 0xa5 'Ñ' */
        0x76, /* 01110110 */
        0xdc, /* 11011100 */
        0x00, /* 00000000 */
@@ -3000,7 +3000,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 166 0xa6 '¦' */
+       /* 166 0xa6 'ª' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0x3c, /* 00111100 */
@@ -3018,7 +3018,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 167 0xa7 '§' */
+       /* 167 0xa7 'º' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0x38, /* 00111000 */
@@ -3036,7 +3036,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 168 0xa8 '¨' */
+       /* 168 0xa8 '¿' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0x30, /* 00110000 */
@@ -3054,7 +3054,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 169 0xa9 '©' */
+       /* 169 0xa9 '' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
@@ -3072,7 +3072,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 170 0xaa 'ª' */
+       /* 170 0xaa '¬' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
@@ -3090,7 +3090,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 171 0xab '«' */
+       /* 171 0xab '½' */
        0x00, /* 00000000 */
        0x60, /* 01100000 */
        0xe0, /* 11100000 */
@@ -3108,7 +3108,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 172 0xac '¬' */
+       /* 172 0xac '¼' */
        0x00, /* 00000000 */
        0x60, /* 01100000 */
        0xe0, /* 11100000 */
@@ -3126,7 +3126,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 173 0xad '­' */
+       /* 173 0xad '¡' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0x18, /* 00011000 */
@@ -3144,7 +3144,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 174 0xae '®' */
+       /* 174 0xae '«' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
@@ -3162,7 +3162,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 175 0xaf '¯' */
+       /* 175 0xaf '»' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
@@ -3180,7 +3180,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 176 0xb0 '°' */
+       /* 176 0xb0 '' */
        0x11, /* 00010001 */
        0x44, /* 01000100 */
        0x11, /* 00010001 */
@@ -3198,7 +3198,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x11, /* 00010001 */
        0x44, /* 01000100 */
 
-       /* 177 0xb1 '±' */
+       /* 177 0xb1 '' */
        0x55, /* 01010101 */
        0xaa, /* 10101010 */
        0x55, /* 01010101 */
@@ -3216,7 +3216,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x55, /* 01010101 */
        0xaa, /* 10101010 */
 
-       /* 178 0xb2 '²' */
+       /* 178 0xb2 '' */
        0xdd, /* 11011101 */
        0x77, /* 01110111 */
        0xdd, /* 11011101 */
@@ -3234,7 +3234,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0xdd, /* 11011101 */
        0x77, /* 01110111 */
 
-       /* 179 0xb3 '³' */
+       /* 179 0xb3 '' */
        0x18, /* 00011000 */
        0x18, /* 00011000 */
        0x18, /* 00011000 */
@@ -3252,7 +3252,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x18, /* 00011000 */
        0x18, /* 00011000 */
 
-       /* 180 0xb4 '´' */
+       /* 180 0xb4 '' */
        0x18, /* 00011000 */
        0x18, /* 00011000 */
        0x18, /* 00011000 */
@@ -3270,7 +3270,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x18, /* 00011000 */
        0x18, /* 00011000 */
 
-       /* 181 0xb5 'µ' */
+       /* 181 0xb5 '' */
        0x18, /* 00011000 */
        0x18, /* 00011000 */
        0x18, /* 00011000 */
@@ -3288,7 +3288,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x18, /* 00011000 */
        0x18, /* 00011000 */
 
-       /* 182 0xb6 '' */
+       /* 182 0xb6 '' */
        0x36, /* 00110110 */
        0x36, /* 00110110 */
        0x36, /* 00110110 */
@@ -3306,7 +3306,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x36, /* 00110110 */
        0x36, /* 00110110 */
 
-       /* 183 0xb7 '·' */
+       /* 183 0xb7 '' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
@@ -3324,7 +3324,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x36, /* 00110110 */
        0x36, /* 00110110 */
 
-       /* 184 0xb8 '¸' */
+       /* 184 0xb8 '' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
@@ -3342,7 +3342,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x18, /* 00011000 */
        0x18, /* 00011000 */
 
-       /* 185 0xb9 '¹' */
+       /* 185 0xb9 '' */
        0x36, /* 00110110 */
        0x36, /* 00110110 */
        0x36, /* 00110110 */
@@ -3360,7 +3360,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x36, /* 00110110 */
        0x36, /* 00110110 */
 
-       /* 186 0xba 'º' */
+       /* 186 0xba '' */
        0x36, /* 00110110 */
        0x36, /* 00110110 */
        0x36, /* 00110110 */
@@ -3378,7 +3378,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x36, /* 00110110 */
        0x36, /* 00110110 */
 
-       /* 187 0xbb '»' */
+       /* 187 0xbb '' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
@@ -3396,7 +3396,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x36, /* 00110110 */
        0x36, /* 00110110 */
 
-       /* 188 0xbc '¼' */
+       /* 188 0xbc '' */
        0x36, /* 00110110 */
        0x36, /* 00110110 */
        0x36, /* 00110110 */
@@ -3414,7 +3414,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 189 0xbd '½' */
+       /* 189 0xbd '' */
        0x36, /* 00110110 */
        0x36, /* 00110110 */
        0x36, /* 00110110 */
@@ -3432,7 +3432,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 190 0xbe '¾' */
+       /* 190 0xbe '' */
        0x18, /* 00011000 */
        0x18, /* 00011000 */
        0x18, /* 00011000 */
@@ -3450,7 +3450,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 191 0xbf '¿' */
+       /* 191 0xbf '' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
@@ -3468,7 +3468,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x18, /* 00011000 */
        0x18, /* 00011000 */
 
-       /* 192 0xc0 'À' */
+       /* 192 0xc0 '' */
        0x18, /* 00011000 */
        0x18, /* 00011000 */
        0x18, /* 00011000 */
@@ -3486,7 +3486,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 193 0xc1 'Á' */
+       /* 193 0xc1 '' */
        0x18, /* 00011000 */
        0x18, /* 00011000 */
        0x18, /* 00011000 */
@@ -3504,7 +3504,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 194 0xc2 'Â' */
+       /* 194 0xc2 '' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
@@ -3522,7 +3522,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x18, /* 00011000 */
        0x18, /* 00011000 */
 
-       /* 195 0xc3 'Ã' */
+       /* 195 0xc3 '' */
        0x18, /* 00011000 */
        0x18, /* 00011000 */
        0x18, /* 00011000 */
@@ -3540,7 +3540,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x18, /* 00011000 */
        0x18, /* 00011000 */
 
-       /* 196 0xc4 'Ä' */
+       /* 196 0xc4 '' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
@@ -3558,7 +3558,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 197 0xc5 'Å' */
+       /* 197 0xc5 '' */
        0x18, /* 00011000 */
        0x18, /* 00011000 */
        0x18, /* 00011000 */
@@ -3576,7 +3576,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x18, /* 00011000 */
        0x18, /* 00011000 */
 
-       /* 198 0xc6 'Æ' */
+       /* 198 0xc6 '' */
        0x18, /* 00011000 */
        0x18, /* 00011000 */
        0x18, /* 00011000 */
@@ -3594,7 +3594,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x18, /* 00011000 */
        0x18, /* 00011000 */
 
-       /* 199 0xc7 'Ç' */
+       /* 199 0xc7 '' */
        0x36, /* 00110110 */
        0x36, /* 00110110 */
        0x36, /* 00110110 */
@@ -3612,7 +3612,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x36, /* 00110110 */
        0x36, /* 00110110 */
 
-       /* 200 0xc8 'È' */
+       /* 200 0xc8 '' */
        0x36, /* 00110110 */
        0x36, /* 00110110 */
        0x36, /* 00110110 */
@@ -3630,7 +3630,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 201 0xc9 'É' */
+       /* 201 0xc9 '' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
@@ -3648,7 +3648,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x36, /* 00110110 */
        0x36, /* 00110110 */
 
-       /* 202 0xca 'Ê' */
+       /* 202 0xca '' */
        0x36, /* 00110110 */
        0x36, /* 00110110 */
        0x36, /* 00110110 */
@@ -3666,7 +3666,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 203 0xcb 'Ë' */
+       /* 203 0xcb '' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
@@ -3684,7 +3684,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x36, /* 00110110 */
        0x36, /* 00110110 */
 
-       /* 204 0xcc 'Ì' */
+       /* 204 0xcc '' */
        0x36, /* 00110110 */
        0x36, /* 00110110 */
        0x36, /* 00110110 */
@@ -3702,7 +3702,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x36, /* 00110110 */
        0x36, /* 00110110 */
 
-       /* 205 0xcd 'Í' */
+       /* 205 0xcd '' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
@@ -3720,7 +3720,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 206 0xce 'Î' */
+       /* 206 0xce '' */
        0x36, /* 00110110 */
        0x36, /* 00110110 */
        0x36, /* 00110110 */
@@ -3738,7 +3738,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x36, /* 00110110 */
        0x36, /* 00110110 */
 
-       /* 207 0xcf 'Ï' */
+       /* 207 0xcf '' */
        0x18, /* 00011000 */
        0x18, /* 00011000 */
        0x18, /* 00011000 */
@@ -3756,7 +3756,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 208 0xd0 'Ð' */
+       /* 208 0xd0 '' */
        0x36, /* 00110110 */
        0x36, /* 00110110 */
        0x36, /* 00110110 */
@@ -3774,7 +3774,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 209 0xd1 'Ñ' */
+       /* 209 0xd1 '' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
@@ -3792,7 +3792,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x18, /* 00011000 */
        0x18, /* 00011000 */
 
-       /* 210 0xd2 'Ò' */
+       /* 210 0xd2 '' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
@@ -3810,7 +3810,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x36, /* 00110110 */
        0x36, /* 00110110 */
 
-       /* 211 0xd3 'Ó' */
+       /* 211 0xd3 '' */
        0x36, /* 00110110 */
        0x36, /* 00110110 */
        0x36, /* 00110110 */
@@ -3828,7 +3828,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 212 0xd4 'Ô' */
+       /* 212 0xd4 '' */
        0x18, /* 00011000 */
        0x18, /* 00011000 */
        0x18, /* 00011000 */
@@ -3846,7 +3846,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 213 0xd5 'Õ' */
+       /* 213 0xd5 '' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
@@ -3864,7 +3864,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x18, /* 00011000 */
        0x18, /* 00011000 */
 
-       /* 214 0xd6 'Ö' */
+       /* 214 0xd6 '' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
@@ -3882,7 +3882,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x36, /* 00110110 */
        0x36, /* 00110110 */
 
-       /* 215 0xd7 '×' */
+       /* 215 0xd7 '' */
        0x36, /* 00110110 */
        0x36, /* 00110110 */
        0x36, /* 00110110 */
@@ -3900,7 +3900,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x36, /* 00110110 */
        0x36, /* 00110110 */
 
-       /* 216 0xd8 'Ø' */
+       /* 216 0xd8 '' */
        0x18, /* 00011000 */
        0x18, /* 00011000 */
        0x18, /* 00011000 */
@@ -3918,7 +3918,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x18, /* 00011000 */
        0x18, /* 00011000 */
 
-       /* 217 0xd9 'Ù' */
+       /* 217 0xd9 '' */
        0x18, /* 00011000 */
        0x18, /* 00011000 */
        0x18, /* 00011000 */
@@ -3936,7 +3936,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 218 0xda 'Ú' */
+       /* 218 0xda '' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
@@ -3954,7 +3954,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x18, /* 00011000 */
        0x18, /* 00011000 */
 
-       /* 219 0xdb 'Û' */
+       /* 219 0xdb '' */
        0xff, /* 11111111 */
        0xff, /* 11111111 */
        0xff, /* 11111111 */
@@ -3972,7 +3972,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0xff, /* 11111111 */
        0xff, /* 11111111 */
 
-       /* 220 0xdc 'Ü' */
+       /* 220 0xdc '' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
@@ -3990,7 +3990,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0xff, /* 11111111 */
        0xff, /* 11111111 */
 
-       /* 221 0xdd 'Ý' */
+       /* 221 0xdd '' */
        0xf0, /* 11110000 */
        0xf0, /* 11110000 */
        0xf0, /* 11110000 */
@@ -4008,7 +4008,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0xf0, /* 11110000 */
        0xf0, /* 11110000 */
 
-       /* 222 0xde 'Þ' */
+       /* 222 0xde '' */
        0x0f, /* 00001111 */
        0x0f, /* 00001111 */
        0x0f, /* 00001111 */
@@ -4026,7 +4026,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x0f, /* 00001111 */
        0x0f, /* 00001111 */
 
-       /* 223 0xdf 'ß' */
+       /* 223 0xdf '' */
        0xff, /* 11111111 */
        0xff, /* 11111111 */
        0xff, /* 11111111 */
@@ -4044,7 +4044,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 224 0xe0 'à' */
+       /* 224 0xe0 'α' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
@@ -4062,7 +4062,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 225 0xe1 'á' */
+       /* 225 0xe1 'ß' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0x78, /* 01111000 */
@@ -4080,7 +4080,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 226 0xe2 'â' */
+       /* 226 0xe2 'Γ' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0xfe, /* 11111110 */
@@ -4098,7 +4098,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 227 0xe3 'ã' */
+       /* 227 0xe3 'π' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
@@ -4116,7 +4116,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 228 0xe4 'ä' */
+       /* 228 0xe4 'Σ' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0xfe, /* 11111110 */
@@ -4134,7 +4134,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 229 0xe5 'å' */
+       /* 229 0xe5 'σ' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
@@ -4152,7 +4152,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 230 0xe6 'æ' */
+       /* 230 0xe6 'µ' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
@@ -4170,7 +4170,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0xc0, /* 11000000 */
        0x00, /* 00000000 */
 
-       /* 231 0xe7 'ç' */
+       /* 231 0xe7 'τ' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
@@ -4188,7 +4188,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 232 0xe8 'è' */
+       /* 232 0xe8 'Φ' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0x7e, /* 01111110 */
@@ -4206,7 +4206,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 233 0xe9 'é' */
+       /* 233 0xe9 'Θ' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0x38, /* 00111000 */
@@ -4224,7 +4224,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 234 0xea 'ê' */
+       /* 234 0xea 'Ω' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0x38, /* 00111000 */
@@ -4242,7 +4242,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 235 0xeb 'ë' */
+       /* 235 0xeb 'δ' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0x1e, /* 00011110 */
@@ -4260,7 +4260,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 236 0xec 'ì' */
+       /* 236 0xec '' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
@@ -4278,7 +4278,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 237 0xed 'í' */
+       /* 237 0xed 'φ' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
@@ -4296,7 +4296,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 238 0xee 'î' */
+       /* 238 0xee 'ε' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0x1c, /* 00011100 */
@@ -4314,7 +4314,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 239 0xef 'ï' */
+       /* 239 0xef '' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
@@ -4332,7 +4332,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 240 0xf0 'ð' */
+       /* 240 0xf0 '' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
@@ -4350,7 +4350,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 241 0xf1 'ñ' */
+       /* 241 0xf1 '±' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
@@ -4368,7 +4368,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 242 0xf2 'ò' */
+       /* 242 0xf2 '' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
@@ -4386,7 +4386,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 243 0xf3 'ó' */
+       /* 243 0xf3 '' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
@@ -4404,7 +4404,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 244 0xf4 'ô' */
+       /* 244 0xf4 '' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0x0e, /* 00001110 */
@@ -4422,7 +4422,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x18, /* 00011000 */
        0x18, /* 00011000 */
 
-       /* 245 0xf5 'õ' */
+       /* 245 0xf5 '' */
        0x18, /* 00011000 */
        0x18, /* 00011000 */
        0x18, /* 00011000 */
@@ -4440,7 +4440,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 246 0xf6 'ö' */
+       /* 246 0xf6 '÷' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
@@ -4458,7 +4458,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 247 0xf7 '÷' */
+       /* 247 0xf7 '' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
@@ -4476,7 +4476,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 248 0xf8 'ø' */
+       /* 248 0xf8 '°' */
        0x00, /* 00000000 */
        0x38, /* 00111000 */
        0x6c, /* 01101100 */
@@ -4494,7 +4494,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 249 0xf9 'ù' */
+       /* 249 0xf9 '·' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
@@ -4512,7 +4512,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 250 0xfa 'ú' */
+       /* 250 0xfa '' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
@@ -4530,7 +4530,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 251 0xfb 'û' */
+       /* 251 0xfb '' */
        0x00, /* 00000000 */
        0x0f, /* 00001111 */
        0x0c, /* 00001100 */
@@ -4548,7 +4548,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 252 0xfc 'ü' */
+       /* 252 0xfc '' */
        0x00, /* 00000000 */
        0x6c, /* 01101100 */
        0x36, /* 00110110 */
@@ -4566,7 +4566,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 253 0xfd 'ý' */
+       /* 253 0xfd '²' */
        0x00, /* 00000000 */
        0x3c, /* 00111100 */
        0x66, /* 01100110 */
@@ -4584,7 +4584,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 254 0xfe 'þ' */
+       /* 254 0xfe '' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
@@ -4602,7 +4602,7 @@ static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 255 0xff 'ÿ' */
+       /* 255 0xff ' ' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
index 751becf..2328ebc 100644 (file)
@@ -1291,7 +1291,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0xfe, /* 11111110 */
        0x00, /* 00000000 */
 
-       /* 128 0x80 '\80' */
+       /* 128 0x80 'Ç' */
        0x7c, /* 01111100 */
        0xc6, /* 11000110 */
        0xc0, /* 11000000 */
@@ -1301,7 +1301,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x0c, /* 00001100 */
        0x78, /* 01111000 */
 
-       /* 129 0x81 '\81' */
+       /* 129 0x81 'ü' */
        0xcc, /* 11001100 */
        0x00, /* 00000000 */
        0xcc, /* 11001100 */
@@ -1311,7 +1311,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x76, /* 01110110 */
        0x00, /* 00000000 */
 
-       /* 130 0x82 '\82' */
+       /* 130 0x82 'é' */
        0x0c, /* 00001100 */
        0x18, /* 00011000 */
        0x7c, /* 01111100 */
@@ -1321,7 +1321,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x7c, /* 01111100 */
        0x00, /* 00000000 */
 
-       /* 131 0x83 '\83' */
+       /* 131 0x83 'â' */
        0x7c, /* 01111100 */
        0x82, /* 10000010 */
        0x78, /* 01111000 */
@@ -1331,7 +1331,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x76, /* 01110110 */
        0x00, /* 00000000 */
 
-       /* 132 0x84 '\84' */
+       /* 132 0x84 'ä' */
        0xc6, /* 11000110 */
        0x00, /* 00000000 */
        0x78, /* 01111000 */
@@ -1341,7 +1341,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x76, /* 01110110 */
        0x00, /* 00000000 */
 
-       /* 133 0x85 '\85' */
+       /* 133 0x85 'à' */
        0x30, /* 00110000 */
        0x18, /* 00011000 */
        0x78, /* 01111000 */
@@ -1351,7 +1351,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x76, /* 01110110 */
        0x00, /* 00000000 */
 
-       /* 134 0x86 '\86' */
+       /* 134 0x86 'å' */
        0x30, /* 00110000 */
        0x30, /* 00110000 */
        0x78, /* 01111000 */
@@ -1361,7 +1361,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x76, /* 01110110 */
        0x00, /* 00000000 */
 
-       /* 135 0x87 '\87' */
+       /* 135 0x87 'ç' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0x7e, /* 01111110 */
@@ -1371,7 +1371,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x0c, /* 00001100 */
        0x38, /* 00111000 */
 
-       /* 136 0x88 '\88' */
+       /* 136 0x88 'ê' */
        0x7c, /* 01111100 */
        0x82, /* 10000010 */
        0x7c, /* 01111100 */
@@ -1381,7 +1381,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x7c, /* 01111100 */
        0x00, /* 00000000 */
 
-       /* 137 0x89 '\89' */
+       /* 137 0x89 'ë' */
        0xc6, /* 11000110 */
        0x00, /* 00000000 */
        0x7c, /* 01111100 */
@@ -1391,7 +1391,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x7c, /* 01111100 */
        0x00, /* 00000000 */
 
-       /* 138 0x8a '\8a' */
+       /* 138 0x8a 'è' */
        0x30, /* 00110000 */
        0x18, /* 00011000 */
        0x7c, /* 01111100 */
@@ -1401,7 +1401,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x7c, /* 01111100 */
        0x00, /* 00000000 */
 
-       /* 139 0x8b '\8b' */
+       /* 139 0x8b 'ï' */
        0x66, /* 01100110 */
        0x00, /* 00000000 */
        0x38, /* 00111000 */
@@ -1411,7 +1411,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x3c, /* 00111100 */
        0x00, /* 00000000 */
 
-       /* 140 0x8c '\8c' */
+       /* 140 0x8c 'î' */
        0x7c, /* 01111100 */
        0x82, /* 10000010 */
        0x38, /* 00111000 */
@@ -1421,7 +1421,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x3c, /* 00111100 */
        0x00, /* 00000000 */
 
-       /* 141 0x8d '\8d' */
+       /* 141 0x8d 'ì' */
        0x30, /* 00110000 */
        0x18, /* 00011000 */
        0x00, /* 00000000 */
@@ -1431,7 +1431,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x3c, /* 00111100 */
        0x00, /* 00000000 */
 
-       /* 142 0x8e '\8e' */
+       /* 142 0x8e 'Ä' */
        0xc6, /* 11000110 */
        0x38, /* 00111000 */
        0x6c, /* 01101100 */
@@ -1441,7 +1441,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0xc6, /* 11000110 */
        0x00, /* 00000000 */
 
-       /* 143 0x8f '\8f' */
+       /* 143 0x8f 'Å' */
        0x38, /* 00111000 */
        0x6c, /* 01101100 */
        0x7c, /* 01111100 */
@@ -1451,7 +1451,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0xc6, /* 11000110 */
        0x00, /* 00000000 */
 
-       /* 144 0x90 '\90' */
+       /* 144 0x90 'É' */
        0x18, /* 00011000 */
        0x30, /* 00110000 */
        0xfe, /* 11111110 */
@@ -1461,7 +1461,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0xfe, /* 11111110 */
        0x00, /* 00000000 */
 
-       /* 145 0x91 '\91' */
+       /* 145 0x91 'æ' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0x7e, /* 01111110 */
@@ -1471,7 +1471,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x7e, /* 01111110 */
        0x00, /* 00000000 */
 
-       /* 146 0x92 '\92' */
+       /* 146 0x92 'Æ' */
        0x3e, /* 00111110 */
        0x6c, /* 01101100 */
        0xcc, /* 11001100 */
@@ -1481,7 +1481,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0xce, /* 11001110 */
        0x00, /* 00000000 */
 
-       /* 147 0x93 '\93' */
+       /* 147 0x93 'ô' */
        0x7c, /* 01111100 */
        0x82, /* 10000010 */
        0x7c, /* 01111100 */
@@ -1491,7 +1491,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x7c, /* 01111100 */
        0x00, /* 00000000 */
 
-       /* 148 0x94 '\94' */
+       /* 148 0x94 'ö' */
        0xc6, /* 11000110 */
        0x00, /* 00000000 */
        0x7c, /* 01111100 */
@@ -1501,7 +1501,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x7c, /* 01111100 */
        0x00, /* 00000000 */
 
-       /* 149 0x95 '\95' */
+       /* 149 0x95 'ò' */
        0x30, /* 00110000 */
        0x18, /* 00011000 */
        0x7c, /* 01111100 */
@@ -1511,7 +1511,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x7c, /* 01111100 */
        0x00, /* 00000000 */
 
-       /* 150 0x96 '\96' */
+       /* 150 0x96 'û' */
        0x78, /* 01111000 */
        0x84, /* 10000100 */
        0x00, /* 00000000 */
@@ -1521,7 +1521,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x76, /* 01110110 */
        0x00, /* 00000000 */
 
-       /* 151 0x97 '\97' */
+       /* 151 0x97 'ù' */
        0x60, /* 01100000 */
        0x30, /* 00110000 */
        0xcc, /* 11001100 */
@@ -1531,7 +1531,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x76, /* 01110110 */
        0x00, /* 00000000 */
 
-       /* 152 0x98 '\98' */
+       /* 152 0x98 'ÿ' */
        0xc6, /* 11000110 */
        0x00, /* 00000000 */
        0xc6, /* 11000110 */
@@ -1541,7 +1541,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x06, /* 00000110 */
        0xfc, /* 11111100 */
 
-       /* 153 0x99 '\99' */
+       /* 153 0x99 'Ö' */
        0xc6, /* 11000110 */
        0x38, /* 00111000 */
        0x6c, /* 01101100 */
@@ -1551,7 +1551,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x38, /* 00111000 */
        0x00, /* 00000000 */
 
-       /* 154 0x9a '\9a' */
+       /* 154 0x9a 'Ü' */
        0xc6, /* 11000110 */
        0x00, /* 00000000 */
        0xc6, /* 11000110 */
@@ -1561,7 +1561,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x7c, /* 01111100 */
        0x00, /* 00000000 */
 
-       /* 155 0x9b '\9b' */
+       /* 155 0x9b '¢' */
        0x18, /* 00011000 */
        0x18, /* 00011000 */
        0x7e, /* 01111110 */
@@ -1571,7 +1571,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x18, /* 00011000 */
        0x18, /* 00011000 */
 
-       /* 156 0x9c '\9c' */
+       /* 156 0x9c '£' */
        0x38, /* 00111000 */
        0x6c, /* 01101100 */
        0x64, /* 01100100 */
@@ -1581,7 +1581,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0xfc, /* 11111100 */
        0x00, /* 00000000 */
 
-       /* 157 0x9d '\9d' */
+       /* 157 0x9d '¥' */
        0x66, /* 01100110 */
        0x66, /* 01100110 */
        0x3c, /* 00111100 */
@@ -1591,7 +1591,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x18, /* 00011000 */
        0x18, /* 00011000 */
 
-       /* 158 0x9e '\9e' */
+       /* 158 0x9e '' */
        0xf8, /* 11111000 */
        0xcc, /* 11001100 */
        0xcc, /* 11001100 */
@@ -1601,7 +1601,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0xc6, /* 11000110 */
        0xc7, /* 11000111 */
 
-       /* 159 0x9f '\9f' */
+       /* 159 0x9f 'ƒ' */
        0x0e, /* 00001110 */
        0x1b, /* 00011011 */
        0x18, /* 00011000 */
@@ -1611,7 +1611,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x70, /* 01110000 */
        0x00, /* 00000000 */
 
-       /* 160 0xa0 ' ' */
+       /* 160 0xa0 'á' */
        0x18, /* 00011000 */
        0x30, /* 00110000 */
        0x78, /* 01111000 */
@@ -1621,7 +1621,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x76, /* 01110110 */
        0x00, /* 00000000 */
 
-       /* 161 0xa1 '¡' */
+       /* 161 0xa1 'í' */
        0x0c, /* 00001100 */
        0x18, /* 00011000 */
        0x00, /* 00000000 */
@@ -1631,7 +1631,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x3c, /* 00111100 */
        0x00, /* 00000000 */
 
-       /* 162 0xa2 '¢' */
+       /* 162 0xa2 'ó' */
        0x0c, /* 00001100 */
        0x18, /* 00011000 */
        0x7c, /* 01111100 */
@@ -1641,7 +1641,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x7c, /* 01111100 */
        0x00, /* 00000000 */
 
-       /* 163 0xa3 '£' */
+       /* 163 0xa3 'ú' */
        0x18, /* 00011000 */
        0x30, /* 00110000 */
        0xcc, /* 11001100 */
@@ -1651,7 +1651,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x76, /* 01110110 */
        0x00, /* 00000000 */
 
-       /* 164 0xa4 '¤' */
+       /* 164 0xa4 'ñ' */
        0x76, /* 01110110 */
        0xdc, /* 11011100 */
        0x00, /* 00000000 */
@@ -1661,7 +1661,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x66, /* 01100110 */
        0x00, /* 00000000 */
 
-       /* 165 0xa5 '¥' */
+       /* 165 0xa5 'Ñ' */
        0x76, /* 01110110 */
        0xdc, /* 11011100 */
        0x00, /* 00000000 */
@@ -1671,7 +1671,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0xce, /* 11001110 */
        0x00, /* 00000000 */
 
-       /* 166 0xa6 '¦' */
+       /* 166 0xa6 'ª' */
        0x3c, /* 00111100 */
        0x6c, /* 01101100 */
        0x6c, /* 01101100 */
@@ -1681,7 +1681,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 167 0xa7 '§' */
+       /* 167 0xa7 'º' */
        0x38, /* 00111000 */
        0x6c, /* 01101100 */
        0x6c, /* 01101100 */
@@ -1691,7 +1691,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 168 0xa8 '¨' */
+       /* 168 0xa8 '¿' */
        0x18, /* 00011000 */
        0x00, /* 00000000 */
        0x18, /* 00011000 */
@@ -1701,7 +1701,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x3e, /* 00111110 */
        0x00, /* 00000000 */
 
-       /* 169 0xa9 '©' */
+       /* 169 0xa9 '' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
@@ -1711,7 +1711,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 170 0xaa 'ª' */
+       /* 170 0xaa '¬' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
@@ -1721,7 +1721,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 171 0xab '«' */
+       /* 171 0xab '½' */
        0x63, /* 01100011 */
        0xe6, /* 11100110 */
        0x6c, /* 01101100 */
@@ -1731,7 +1731,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0xcc, /* 11001100 */
        0x0f, /* 00001111 */
 
-       /* 172 0xac '¬' */
+       /* 172 0xac '¼' */
        0x63, /* 01100011 */
        0xe6, /* 11100110 */
        0x6c, /* 01101100 */
@@ -1741,7 +1741,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0xdf, /* 11011111 */
        0x06, /* 00000110 */
 
-       /* 173 0xad '­' */
+       /* 173 0xad '¡' */
        0x18, /* 00011000 */
        0x00, /* 00000000 */
        0x18, /* 00011000 */
@@ -1751,7 +1751,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x18, /* 00011000 */
        0x00, /* 00000000 */
 
-       /* 174 0xae '®' */
+       /* 174 0xae '«' */
        0x00, /* 00000000 */
        0x33, /* 00110011 */
        0x66, /* 01100110 */
@@ -1761,7 +1761,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 175 0xaf '¯' */
+       /* 175 0xaf '»' */
        0x00, /* 00000000 */
        0xcc, /* 11001100 */
        0x66, /* 01100110 */
@@ -1771,7 +1771,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 176 0xb0 '°' */
+       /* 176 0xb0 '' */
        0x22, /* 00100010 */
        0x88, /* 10001000 */
        0x22, /* 00100010 */
@@ -1781,7 +1781,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x22, /* 00100010 */
        0x88, /* 10001000 */
 
-       /* 177 0xb1 '±' */
+       /* 177 0xb1 '' */
        0x55, /* 01010101 */
        0xaa, /* 10101010 */
        0x55, /* 01010101 */
@@ -1791,7 +1791,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x55, /* 01010101 */
        0xaa, /* 10101010 */
 
-       /* 178 0xb2 '²' */
+       /* 178 0xb2 '' */
        0x77, /* 01110111 */
        0xdd, /* 11011101 */
        0x77, /* 01110111 */
@@ -1801,7 +1801,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x77, /* 01110111 */
        0xdd, /* 11011101 */
 
-       /* 179 0xb3 '³' */
+       /* 179 0xb3 '' */
        0x18, /* 00011000 */
        0x18, /* 00011000 */
        0x18, /* 00011000 */
@@ -1811,7 +1811,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x18, /* 00011000 */
        0x18, /* 00011000 */
 
-       /* 180 0xb4 '´' */
+       /* 180 0xb4 '' */
        0x18, /* 00011000 */
        0x18, /* 00011000 */
        0x18, /* 00011000 */
@@ -1821,7 +1821,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x18, /* 00011000 */
        0x18, /* 00011000 */
 
-       /* 181 0xb5 'µ' */
+       /* 181 0xb5 '' */
        0x18, /* 00011000 */
        0x18, /* 00011000 */
        0xf8, /* 11111000 */
@@ -1831,7 +1831,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x18, /* 00011000 */
        0x18, /* 00011000 */
 
-       /* 182 0xb6 '' */
+       /* 182 0xb6 '' */
        0x36, /* 00110110 */
        0x36, /* 00110110 */
        0x36, /* 00110110 */
@@ -1841,7 +1841,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x36, /* 00110110 */
        0x36, /* 00110110 */
 
-       /* 183 0xb7 '·' */
+       /* 183 0xb7 '' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
@@ -1851,7 +1851,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x36, /* 00110110 */
        0x36, /* 00110110 */
 
-       /* 184 0xb8 '¸' */
+       /* 184 0xb8 '' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0xf8, /* 11111000 */
@@ -1861,7 +1861,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x18, /* 00011000 */
        0x18, /* 00011000 */
 
-       /* 185 0xb9 '¹' */
+       /* 185 0xb9 '' */
        0x36, /* 00110110 */
        0x36, /* 00110110 */
        0xf6, /* 11110110 */
@@ -1871,7 +1871,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x36, /* 00110110 */
        0x36, /* 00110110 */
 
-       /* 186 0xba 'º' */
+       /* 186 0xba '' */
        0x36, /* 00110110 */
        0x36, /* 00110110 */
        0x36, /* 00110110 */
@@ -1881,7 +1881,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x36, /* 00110110 */
        0x36, /* 00110110 */
 
-       /* 187 0xbb '»' */
+       /* 187 0xbb '' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0xfe, /* 11111110 */
@@ -1891,7 +1891,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x36, /* 00110110 */
        0x36, /* 00110110 */
 
-       /* 188 0xbc '¼' */
+       /* 188 0xbc '' */
        0x36, /* 00110110 */
        0x36, /* 00110110 */
        0xf6, /* 11110110 */
@@ -1901,7 +1901,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 189 0xbd '½' */
+       /* 189 0xbd '' */
        0x36, /* 00110110 */
        0x36, /* 00110110 */
        0x36, /* 00110110 */
@@ -1911,7 +1911,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 190 0xbe '¾' */
+       /* 190 0xbe '' */
        0x18, /* 00011000 */
        0x18, /* 00011000 */
        0xf8, /* 11111000 */
@@ -1921,7 +1921,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 191 0xbf '¿' */
+       /* 191 0xbf '' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
@@ -1931,7 +1931,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x18, /* 00011000 */
        0x18, /* 00011000 */
 
-       /* 192 0xc0 'À' */
+       /* 192 0xc0 '' */
        0x18, /* 00011000 */
        0x18, /* 00011000 */
        0x18, /* 00011000 */
@@ -1941,7 +1941,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 193 0xc1 'Á' */
+       /* 193 0xc1 '' */
        0x18, /* 00011000 */
        0x18, /* 00011000 */
        0x18, /* 00011000 */
@@ -1951,7 +1951,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 194 0xc2 'Â' */
+       /* 194 0xc2 '' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
@@ -1961,7 +1961,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x18, /* 00011000 */
        0x18, /* 00011000 */
 
-       /* 195 0xc3 'Ã' */
+       /* 195 0xc3 '' */
        0x18, /* 00011000 */
        0x18, /* 00011000 */
        0x18, /* 00011000 */
@@ -1971,7 +1971,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x18, /* 00011000 */
        0x18, /* 00011000 */
 
-       /* 196 0xc4 'Ä' */
+       /* 196 0xc4 '' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
@@ -1981,7 +1981,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 197 0xc5 'Å' */
+       /* 197 0xc5 '' */
        0x18, /* 00011000 */
        0x18, /* 00011000 */
        0x18, /* 00011000 */
@@ -1991,7 +1991,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x18, /* 00011000 */
        0x18, /* 00011000 */
 
-       /* 198 0xc6 'Æ' */
+       /* 198 0xc6 '' */
        0x18, /* 00011000 */
        0x18, /* 00011000 */
        0x1f, /* 00011111 */
@@ -2001,7 +2001,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x18, /* 00011000 */
        0x18, /* 00011000 */
 
-       /* 199 0xc7 'Ç' */
+       /* 199 0xc7 '' */
        0x36, /* 00110110 */
        0x36, /* 00110110 */
        0x36, /* 00110110 */
@@ -2011,7 +2011,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x36, /* 00110110 */
        0x36, /* 00110110 */
 
-       /* 200 0xc8 'È' */
+       /* 200 0xc8 '' */
        0x36, /* 00110110 */
        0x36, /* 00110110 */
        0x37, /* 00110111 */
@@ -2021,7 +2021,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 201 0xc9 'É' */
+       /* 201 0xc9 '' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0x3f, /* 00111111 */
@@ -2031,7 +2031,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x36, /* 00110110 */
        0x36, /* 00110110 */
 
-       /* 202 0xca 'Ê' */
+       /* 202 0xca '' */
        0x36, /* 00110110 */
        0x36, /* 00110110 */
        0xf7, /* 11110111 */
@@ -2041,7 +2041,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 203 0xcb 'Ë' */
+       /* 203 0xcb '' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0xff, /* 11111111 */
@@ -2051,7 +2051,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x36, /* 00110110 */
        0x36, /* 00110110 */
 
-       /* 204 0xcc 'Ì' */
+       /* 204 0xcc '' */
        0x36, /* 00110110 */
        0x36, /* 00110110 */
        0x37, /* 00110111 */
@@ -2061,7 +2061,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x36, /* 00110110 */
        0x36, /* 00110110 */
 
-       /* 205 0xcd 'Í' */
+       /* 205 0xcd '' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0xff, /* 11111111 */
@@ -2071,7 +2071,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 206 0xce 'Î' */
+       /* 206 0xce '' */
        0x36, /* 00110110 */
        0x36, /* 00110110 */
        0xf7, /* 11110111 */
@@ -2081,7 +2081,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x36, /* 00110110 */
        0x36, /* 00110110 */
 
-       /* 207 0xcf 'Ï' */
+       /* 207 0xcf '' */
        0x18, /* 00011000 */
        0x18, /* 00011000 */
        0xff, /* 11111111 */
@@ -2091,7 +2091,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 208 0xd0 'Ð' */
+       /* 208 0xd0 '' */
        0x36, /* 00110110 */
        0x36, /* 00110110 */
        0x36, /* 00110110 */
@@ -2101,7 +2101,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 209 0xd1 'Ñ' */
+       /* 209 0xd1 '' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0xff, /* 11111111 */
@@ -2111,7 +2111,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x18, /* 00011000 */
        0x18, /* 00011000 */
 
-       /* 210 0xd2 'Ò' */
+       /* 210 0xd2 '' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
@@ -2121,7 +2121,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x36, /* 00110110 */
        0x36, /* 00110110 */
 
-       /* 211 0xd3 'Ó' */
+       /* 211 0xd3 '' */
        0x36, /* 00110110 */
        0x36, /* 00110110 */
        0x36, /* 00110110 */
@@ -2131,7 +2131,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 212 0xd4 'Ô' */
+       /* 212 0xd4 '' */
        0x18, /* 00011000 */
        0x18, /* 00011000 */
        0x1f, /* 00011111 */
@@ -2141,7 +2141,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 213 0xd5 'Õ' */
+       /* 213 0xd5 '' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0x1f, /* 00011111 */
@@ -2151,7 +2151,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x18, /* 00011000 */
        0x18, /* 00011000 */
 
-       /* 214 0xd6 'Ö' */
+       /* 214 0xd6 '' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
@@ -2161,7 +2161,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x36, /* 00110110 */
        0x36, /* 00110110 */
 
-       /* 215 0xd7 '×' */
+       /* 215 0xd7 '' */
        0x36, /* 00110110 */
        0x36, /* 00110110 */
        0x36, /* 00110110 */
@@ -2171,7 +2171,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x36, /* 00110110 */
        0x36, /* 00110110 */
 
-       /* 216 0xd8 'Ø' */
+       /* 216 0xd8 '' */
        0x18, /* 00011000 */
        0x18, /* 00011000 */
        0xff, /* 11111111 */
@@ -2181,7 +2181,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x18, /* 00011000 */
        0x18, /* 00011000 */
 
-       /* 217 0xd9 'Ù' */
+       /* 217 0xd9 '' */
        0x18, /* 00011000 */
        0x18, /* 00011000 */
        0x18, /* 00011000 */
@@ -2191,7 +2191,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 218 0xda 'Ú' */
+       /* 218 0xda '' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
@@ -2201,7 +2201,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x18, /* 00011000 */
        0x18, /* 00011000 */
 
-       /* 219 0xdb 'Û' */
+       /* 219 0xdb '' */
        0xff, /* 11111111 */
        0xff, /* 11111111 */
        0xff, /* 11111111 */
@@ -2211,7 +2211,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0xff, /* 11111111 */
        0xff, /* 11111111 */
 
-       /* 220 0xdc 'Ü' */
+       /* 220 0xdc '' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
@@ -2221,7 +2221,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0xff, /* 11111111 */
        0xff, /* 11111111 */
 
-       /* 221 0xdd 'Ý' */
+       /* 221 0xdd '' */
        0xf0, /* 11110000 */
        0xf0, /* 11110000 */
        0xf0, /* 11110000 */
@@ -2231,7 +2231,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0xf0, /* 11110000 */
        0xf0, /* 11110000 */
 
-       /* 222 0xde 'Þ' */
+       /* 222 0xde '' */
        0x0f, /* 00001111 */
        0x0f, /* 00001111 */
        0x0f, /* 00001111 */
@@ -2241,7 +2241,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x0f, /* 00001111 */
        0x0f, /* 00001111 */
 
-       /* 223 0xdf 'ß' */
+       /* 223 0xdf '' */
        0xff, /* 11111111 */
        0xff, /* 11111111 */
        0xff, /* 11111111 */
@@ -2251,7 +2251,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 224 0xe0 'à' */
+       /* 224 0xe0 'α' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0x76, /* 01110110 */
@@ -2261,7 +2261,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x76, /* 01110110 */
        0x00, /* 00000000 */
 
-       /* 225 0xe1 'á' */
+       /* 225 0xe1 'ß' */
        0x78, /* 01111000 */
        0xcc, /* 11001100 */
        0xcc, /* 11001100 */
@@ -2271,7 +2271,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0xcc, /* 11001100 */
        0x00, /* 00000000 */
 
-       /* 226 0xe2 'â' */
+       /* 226 0xe2 'Γ' */
        0xfe, /* 11111110 */
        0xc6, /* 11000110 */
        0xc0, /* 11000000 */
@@ -2281,7 +2281,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0xc0, /* 11000000 */
        0x00, /* 00000000 */
 
-       /* 227 0xe3 'ã' */
+       /* 227 0xe3 'π' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0xfe, /* 11111110 */
@@ -2291,7 +2291,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x6c, /* 01101100 */
        0x00, /* 00000000 */
 
-       /* 228 0xe4 'ä' */
+       /* 228 0xe4 'Σ' */
        0xfe, /* 11111110 */
        0xc6, /* 11000110 */
        0x60, /* 01100000 */
@@ -2301,7 +2301,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0xfe, /* 11111110 */
        0x00, /* 00000000 */
 
-       /* 229 0xe5 'å' */
+       /* 229 0xe5 'σ' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0x7e, /* 01111110 */
@@ -2311,7 +2311,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x70, /* 01110000 */
        0x00, /* 00000000 */
 
-       /* 230 0xe6 'æ' */
+       /* 230 0xe6 'µ' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0x66, /* 01100110 */
@@ -2321,7 +2321,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x7c, /* 01111100 */
        0xc0, /* 11000000 */
 
-       /* 231 0xe7 'ç' */
+       /* 231 0xe7 'τ' */
        0x00, /* 00000000 */
        0x76, /* 01110110 */
        0xdc, /* 11011100 */
@@ -2331,7 +2331,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x18, /* 00011000 */
        0x00, /* 00000000 */
 
-       /* 232 0xe8 'è' */
+       /* 232 0xe8 'Φ' */
        0x7e, /* 01111110 */
        0x18, /* 00011000 */
        0x3c, /* 00111100 */
@@ -2341,7 +2341,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x18, /* 00011000 */
        0x7e, /* 01111110 */
 
-       /* 233 0xe9 'é' */
+       /* 233 0xe9 'Θ' */
        0x38, /* 00111000 */
        0x6c, /* 01101100 */
        0xc6, /* 11000110 */
@@ -2351,7 +2351,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x38, /* 00111000 */
        0x00, /* 00000000 */
 
-       /* 234 0xea 'ê' */
+       /* 234 0xea 'Ω' */
        0x38, /* 00111000 */
        0x6c, /* 01101100 */
        0xc6, /* 11000110 */
@@ -2361,7 +2361,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0xee, /* 11101110 */
        0x00, /* 00000000 */
 
-       /* 235 0xeb 'ë' */
+       /* 235 0xeb 'δ' */
        0x0e, /* 00001110 */
        0x18, /* 00011000 */
        0x0c, /* 00001100 */
@@ -2371,7 +2371,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x3c, /* 00111100 */
        0x00, /* 00000000 */
 
-       /* 236 0xec 'ì' */
+       /* 236 0xec '' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0x7e, /* 01111110 */
@@ -2381,7 +2381,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 237 0xed 'í' */
+       /* 237 0xed 'φ' */
        0x06, /* 00000110 */
        0x0c, /* 00001100 */
        0x7e, /* 01111110 */
@@ -2391,7 +2391,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x60, /* 01100000 */
        0xc0, /* 11000000 */
 
-       /* 238 0xee 'î' */
+       /* 238 0xee 'ε' */
        0x1e, /* 00011110 */
        0x30, /* 00110000 */
        0x60, /* 01100000 */
@@ -2401,7 +2401,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x1e, /* 00011110 */
        0x00, /* 00000000 */
 
-       /* 239 0xef 'ï' */
+       /* 239 0xef '' */
        0x00, /* 00000000 */
        0x7c, /* 01111100 */
        0xc6, /* 11000110 */
@@ -2411,7 +2411,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0xc6, /* 11000110 */
        0x00, /* 00000000 */
 
-       /* 240 0xf0 'ð' */
+       /* 240 0xf0 '' */
        0x00, /* 00000000 */
        0xfe, /* 11111110 */
        0x00, /* 00000000 */
@@ -2421,7 +2421,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 241 0xf1 'ñ' */
+       /* 241 0xf1 '±' */
        0x18, /* 00011000 */
        0x18, /* 00011000 */
        0x7e, /* 01111110 */
@@ -2431,7 +2431,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x7e, /* 01111110 */
        0x00, /* 00000000 */
 
-       /* 242 0xf2 'ò' */
+       /* 242 0xf2 '' */
        0x30, /* 00110000 */
        0x18, /* 00011000 */
        0x0c, /* 00001100 */
@@ -2441,7 +2441,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x7e, /* 01111110 */
        0x00, /* 00000000 */
 
-       /* 243 0xf3 'ó' */
+       /* 243 0xf3 '' */
        0x0c, /* 00001100 */
        0x18, /* 00011000 */
        0x30, /* 00110000 */
@@ -2451,7 +2451,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x7e, /* 01111110 */
        0x00, /* 00000000 */
 
-       /* 244 0xf4 'ô' */
+       /* 244 0xf4 '' */
        0x0e, /* 00001110 */
        0x1b, /* 00011011 */
        0x1b, /* 00011011 */
@@ -2461,7 +2461,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x18, /* 00011000 */
        0x18, /* 00011000 */
 
-       /* 245 0xf5 'õ' */
+       /* 245 0xf5 '' */
        0x18, /* 00011000 */
        0x18, /* 00011000 */
        0x18, /* 00011000 */
@@ -2471,7 +2471,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0xd8, /* 11011000 */
        0x70, /* 01110000 */
 
-       /* 246 0xf6 'ö' */
+       /* 246 0xf6 '÷' */
        0x00, /* 00000000 */
        0x18, /* 00011000 */
        0x00, /* 00000000 */
@@ -2481,7 +2481,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 247 0xf7 '÷' */
+       /* 247 0xf7 '' */
        0x00, /* 00000000 */
        0x76, /* 01110110 */
        0xdc, /* 11011100 */
@@ -2491,7 +2491,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 248 0xf8 'ø' */
+       /* 248 0xf8 '°' */
        0x38, /* 00111000 */
        0x6c, /* 01101100 */
        0x6c, /* 01101100 */
@@ -2501,7 +2501,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 249 0xf9 'ù' */
+       /* 249 0xf9 '·' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
@@ -2511,7 +2511,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 250 0xfa 'ú' */
+       /* 250 0xfa '' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
@@ -2521,7 +2521,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 251 0xfb 'û' */
+       /* 251 0xfb '' */
        0x0f, /* 00001111 */
        0x0c, /* 00001100 */
        0x0c, /* 00001100 */
@@ -2531,7 +2531,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x3c, /* 00111100 */
        0x1c, /* 00011100 */
 
-       /* 252 0xfc 'ü' */
+       /* 252 0xfc '' */
        0x6c, /* 01101100 */
        0x36, /* 00110110 */
        0x36, /* 00110110 */
@@ -2541,7 +2541,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 253 0xfd 'ý' */
+       /* 253 0xfd '²' */
        0x78, /* 01111000 */
        0x0c, /* 00001100 */
        0x18, /* 00011000 */
@@ -2551,7 +2551,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 254 0xfe 'þ' */
+       /* 254 0xfe '' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0x3c, /* 00111100 */
@@ -2561,7 +2561,7 @@ static const unsigned char fontdata_8x8[FONTDATAMAX] = {
        0x00, /* 00000000 */
        0x00, /* 00000000 */
 
-       /* 255 0xff 'ÿ' */
+       /* 255 0xff ' ' */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
        0x00, /* 00000000 */
index b0514c0..b15d3c3 100644 (file)
@@ -1296,7 +1296,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0xfe, /* 11111110 */
    0x00, /* 00000000 */
 
-   /* 128 0x80 '\80' */
+   /* 128 0x80 'Ç' */
    0x7c, /* 01111100 */
    0xc6, /* 11000110 */
    0xc0, /* 11000000 */
@@ -1306,7 +1306,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x0c, /* 00001100 */
    0x78, /* 01111000 */
 
-   /* 129 0x81 '\81' */
+   /* 129 0x81 'ü' */
    0xcc, /* 11001100 */
    0x00, /* 00000000 */
    0xcc, /* 11001100 */
@@ -1316,7 +1316,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x76, /* 01110110 */
    0x00, /* 00000000 */
 
-   /* 130 0x82 '\82' */
+   /* 130 0x82 'é' */
    0x0c, /* 00001100 */
    0x18, /* 00011000 */
    0x7c, /* 01111100 */
@@ -1326,7 +1326,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x7c, /* 01111100 */
    0x00, /* 00000000 */
 
-   /* 131 0x83 '\83' */
+   /* 131 0x83 'â' */
    0x7c, /* 01111100 */
    0x82, /* 10000010 */
    0x78, /* 01111000 */
@@ -1336,7 +1336,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x76, /* 01110110 */
    0x00, /* 00000000 */
 
-   /* 132 0x84 '\84' */
+   /* 132 0x84 'ä' */
    0xc6, /* 11000110 */
    0x00, /* 00000000 */
    0x78, /* 01111000 */
@@ -1346,7 +1346,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x76, /* 01110110 */
    0x00, /* 00000000 */
 
-   /* 133 0x85 '\85' */
+   /* 133 0x85 'à' */
    0x30, /* 00110000 */
    0x18, /* 00011000 */
    0x78, /* 01111000 */
@@ -1356,7 +1356,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x76, /* 01110110 */
    0x00, /* 00000000 */
 
-   /* 134 0x86 '\86' */
+   /* 134 0x86 'å' */
    0x30, /* 00110000 */
    0x30, /* 00110000 */
    0x78, /* 01111000 */
@@ -1366,7 +1366,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x76, /* 01110110 */
    0x00, /* 00000000 */
 
-   /* 135 0x87 '\87' */
+   /* 135 0x87 'ç' */
    0x00, /* 00000000 */
    0x00, /* 00000000 */
    0x7e, /* 01111110 */
@@ -1376,7 +1376,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x0c, /* 00001100 */
    0x38, /* 00111000 */
 
-   /* 136 0x88 '\88' */
+   /* 136 0x88 'ê' */
    0x7c, /* 01111100 */
    0x82, /* 10000010 */
    0x7c, /* 01111100 */
@@ -1386,7 +1386,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x7c, /* 01111100 */
    0x00, /* 00000000 */
 
-   /* 137 0x89 '\89' */
+   /* 137 0x89 'ë' */
    0xc6, /* 11000110 */
    0x00, /* 00000000 */
    0x7c, /* 01111100 */
@@ -1396,7 +1396,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x7c, /* 01111100 */
    0x00, /* 00000000 */
 
-   /* 138 0x8a '\8a' */
+   /* 138 0x8a 'è' */
    0x30, /* 00110000 */
    0x18, /* 00011000 */
    0x7c, /* 01111100 */
@@ -1406,7 +1406,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x7c, /* 01111100 */
    0x00, /* 00000000 */
 
-   /* 139 0x8b '\8b' */
+   /* 139 0x8b 'ï' */
    0x66, /* 01100110 */
    0x00, /* 00000000 */
    0x38, /* 00111000 */
@@ -1416,7 +1416,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x3c, /* 00111100 */
    0x00, /* 00000000 */
 
-   /* 140 0x8c '\8c' */
+   /* 140 0x8c 'î' */
    0x7c, /* 01111100 */
    0x82, /* 10000010 */
    0x38, /* 00111000 */
@@ -1426,7 +1426,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x3c, /* 00111100 */
    0x00, /* 00000000 */
 
-   /* 141 0x8d '\8d' */
+   /* 141 0x8d 'ì' */
    0x30, /* 00110000 */
    0x18, /* 00011000 */
    0x00, /* 00000000 */
@@ -1436,7 +1436,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x3c, /* 00111100 */
    0x00, /* 00000000 */
 
-   /* 142 0x8e '\8e' */
+   /* 142 0x8e 'Ä' */
    0xc6, /* 11000110 */
    0x38, /* 00111000 */
    0x6c, /* 01101100 */
@@ -1446,7 +1446,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0xc6, /* 11000110 */
    0x00, /* 00000000 */
 
-   /* 143 0x8f '\8f' */
+   /* 143 0x8f 'Å' */
    0x38, /* 00111000 */
    0x6c, /* 01101100 */
    0x7c, /* 01111100 */
@@ -1456,7 +1456,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0xc6, /* 11000110 */
    0x00, /* 00000000 */
 
-   /* 144 0x90 '\90' */
+   /* 144 0x90 'É' */
    0x18, /* 00011000 */
    0x30, /* 00110000 */
    0xfe, /* 11111110 */
@@ -1466,7 +1466,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0xfe, /* 11111110 */
    0x00, /* 00000000 */
 
-   /* 145 0x91 '\91' */
+   /* 145 0x91 'æ' */
    0x00, /* 00000000 */
    0x00, /* 00000000 */
    0x7e, /* 01111110 */
@@ -1476,7 +1476,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x7e, /* 01111110 */
    0x00, /* 00000000 */
 
-   /* 146 0x92 '\92' */
+   /* 146 0x92 'Æ' */
    0x3e, /* 00111110 */
    0x6c, /* 01101100 */
    0xcc, /* 11001100 */
@@ -1486,7 +1486,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0xce, /* 11001110 */
    0x00, /* 00000000 */
 
-   /* 147 0x93 '\93' */
+   /* 147 0x93 'ô' */
    0x7c, /* 01111100 */
    0x82, /* 10000010 */
    0x7c, /* 01111100 */
@@ -1496,7 +1496,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x7c, /* 01111100 */
    0x00, /* 00000000 */
 
-   /* 148 0x94 '\94' */
+   /* 148 0x94 'ö' */
    0xc6, /* 11000110 */
    0x00, /* 00000000 */
    0x7c, /* 01111100 */
@@ -1506,7 +1506,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x7c, /* 01111100 */
    0x00, /* 00000000 */
 
-   /* 149 0x95 '\95' */
+   /* 149 0x95 'ò' */
    0x30, /* 00110000 */
    0x18, /* 00011000 */
    0x7c, /* 01111100 */
@@ -1516,7 +1516,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x7c, /* 01111100 */
    0x00, /* 00000000 */
 
-   /* 150 0x96 '\96' */
+   /* 150 0x96 'û' */
    0x78, /* 01111000 */
    0x84, /* 10000100 */
    0x00, /* 00000000 */
@@ -1526,7 +1526,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x76, /* 01110110 */
    0x00, /* 00000000 */
 
-   /* 151 0x97 '\97' */
+   /* 151 0x97 'ù' */
    0x60, /* 01100000 */
    0x30, /* 00110000 */
    0xcc, /* 11001100 */
@@ -1536,7 +1536,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x76, /* 01110110 */
    0x00, /* 00000000 */
 
-   /* 152 0x98 '\98' */
+   /* 152 0x98 'ÿ' */
    0xc6, /* 11000110 */
    0x00, /* 00000000 */
    0xc6, /* 11000110 */
@@ -1546,7 +1546,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x06, /* 00000110 */
    0xfc, /* 11111100 */
 
-   /* 153 0x99 '\99' */
+   /* 153 0x99 'Ö' */
    0xc6, /* 11000110 */
    0x38, /* 00111000 */
    0x6c, /* 01101100 */
@@ -1556,7 +1556,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x38, /* 00111000 */
    0x00, /* 00000000 */
 
-   /* 154 0x9a '\9a' */
+   /* 154 0x9a 'Ü' */
    0xc6, /* 11000110 */
    0x00, /* 00000000 */
    0xc6, /* 11000110 */
@@ -1566,7 +1566,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x7c, /* 01111100 */
    0x00, /* 00000000 */
 
-   /* 155 0x9b '\9b' */
+   /* 155 0x9b '¢' */
    0x18, /* 00011000 */
    0x18, /* 00011000 */
    0x7e, /* 01111110 */
@@ -1576,7 +1576,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x18, /* 00011000 */
    0x18, /* 00011000 */
 
-   /* 156 0x9c '\9c' */
+   /* 156 0x9c '£' */
    0x38, /* 00111000 */
    0x6c, /* 01101100 */
    0x64, /* 01100100 */
@@ -1586,7 +1586,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0xfc, /* 11111100 */
    0x00, /* 00000000 */
 
-   /* 157 0x9d '\9d' */
+   /* 157 0x9d '¥' */
    0x66, /* 01100110 */
    0x66, /* 01100110 */
    0x3c, /* 00111100 */
@@ -1596,7 +1596,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x18, /* 00011000 */
    0x18, /* 00011000 */
 
-   /* 158 0x9e '\9e' */
+   /* 158 0x9e '' */
    0xf8, /* 11111000 */
    0xcc, /* 11001100 */
    0xcc, /* 11001100 */
@@ -1606,7 +1606,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0xc6, /* 11000110 */
    0xc7, /* 11000111 */
 
-   /* 159 0x9f '\9f' */
+   /* 159 0x9f 'ƒ' */
    0x0e, /* 00001110 */
    0x1b, /* 00011011 */
    0x18, /* 00011000 */
@@ -1616,7 +1616,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x70, /* 01110000 */
    0x00, /* 00000000 */
 
-   /* 160 0xa0 ' ' */
+   /* 160 0xa0 'á' */
    0x18, /* 00011000 */
    0x30, /* 00110000 */
    0x78, /* 01111000 */
@@ -1626,7 +1626,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x76, /* 01110110 */
    0x00, /* 00000000 */
 
-   /* 161 0xa1 '¡' */
+   /* 161 0xa1 'í' */
    0x0c, /* 00001100 */
    0x18, /* 00011000 */
    0x00, /* 00000000 */
@@ -1636,7 +1636,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x3c, /* 00111100 */
    0x00, /* 00000000 */
 
-   /* 162 0xa2 '¢' */
+   /* 162 0xa2 'ó' */
    0x0c, /* 00001100 */
    0x18, /* 00011000 */
    0x7c, /* 01111100 */
@@ -1646,7 +1646,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x7c, /* 01111100 */
    0x00, /* 00000000 */
 
-   /* 163 0xa3 '£' */
+   /* 163 0xa3 'ú' */
    0x18, /* 00011000 */
    0x30, /* 00110000 */
    0xcc, /* 11001100 */
@@ -1656,7 +1656,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x76, /* 01110110 */
    0x00, /* 00000000 */
 
-   /* 164 0xa4 '¤' */
+   /* 164 0xa4 'ñ' */
    0x76, /* 01110110 */
    0xdc, /* 11011100 */
    0x00, /* 00000000 */
@@ -1666,7 +1666,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x66, /* 01100110 */
    0x00, /* 00000000 */
 
-   /* 165 0xa5 '¥' */
+   /* 165 0xa5 'Ñ' */
    0x76, /* 01110110 */
    0xdc, /* 11011100 */
    0x00, /* 00000000 */
@@ -1676,7 +1676,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0xce, /* 11001110 */
    0x00, /* 00000000 */
 
-   /* 166 0xa6 '¦' */
+   /* 166 0xa6 'ª' */
    0x3c, /* 00111100 */
    0x6c, /* 01101100 */
    0x6c, /* 01101100 */
@@ -1686,7 +1686,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x00, /* 00000000 */
    0x00, /* 00000000 */
 
-   /* 167 0xa7 '§' */
+   /* 167 0xa7 'º' */
    0x38, /* 00111000 */
    0x6c, /* 01101100 */
    0x6c, /* 01101100 */
@@ -1696,7 +1696,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x00, /* 00000000 */
    0x00, /* 00000000 */
 
-   /* 168 0xa8 '¨' */
+   /* 168 0xa8 '¿' */
    0x18, /* 00011000 */
    0x00, /* 00000000 */
    0x18, /* 00011000 */
@@ -1706,7 +1706,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x3e, /* 00111110 */
    0x00, /* 00000000 */
 
-   /* 169 0xa9 '©' */
+   /* 169 0xa9 '' */
    0x00, /* 00000000 */
    0x00, /* 00000000 */
    0x00, /* 00000000 */
@@ -1716,7 +1716,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x00, /* 00000000 */
    0x00, /* 00000000 */
 
-   /* 170 0xaa 'ª' */
+   /* 170 0xaa '¬' */
    0x00, /* 00000000 */
    0x00, /* 00000000 */
    0x00, /* 00000000 */
@@ -1726,7 +1726,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x00, /* 00000000 */
    0x00, /* 00000000 */
 
-   /* 171 0xab '«' */
+   /* 171 0xab '½' */
    0x63, /* 01100011 */
    0xe6, /* 11100110 */
    0x6c, /* 01101100 */
@@ -1736,7 +1736,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0xcc, /* 11001100 */
    0x0f, /* 00001111 */
 
-   /* 172 0xac '¬' */
+   /* 172 0xac '¼' */
    0x63, /* 01100011 */
    0xe6, /* 11100110 */
    0x6c, /* 01101100 */
@@ -1746,7 +1746,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0xdf, /* 11011111 */
    0x06, /* 00000110 */
 
-   /* 173 0xad '­' */
+   /* 173 0xad '¡' */
    0x18, /* 00011000 */
    0x00, /* 00000000 */
    0x18, /* 00011000 */
@@ -1756,7 +1756,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x18, /* 00011000 */
    0x00, /* 00000000 */
 
-   /* 174 0xae '®' */
+   /* 174 0xae '«' */
    0x00, /* 00000000 */
    0x33, /* 00110011 */
    0x66, /* 01100110 */
@@ -1766,7 +1766,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x00, /* 00000000 */
    0x00, /* 00000000 */
 
-   /* 175 0xaf '¯' */
+   /* 175 0xaf '»' */
    0x00, /* 00000000 */
    0xcc, /* 11001100 */
    0x66, /* 01100110 */
@@ -1776,7 +1776,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x00, /* 00000000 */
    0x00, /* 00000000 */
 
-   /* 176 0xb0 '°' */
+   /* 176 0xb0 '' */
    0x22, /* 00100010 */
    0x88, /* 10001000 */
    0x22, /* 00100010 */
@@ -1786,7 +1786,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x22, /* 00100010 */
    0x88, /* 10001000 */
 
-   /* 177 0xb1 '±' */
+   /* 177 0xb1 '' */
    0x55, /* 01010101 */
    0xaa, /* 10101010 */
    0x55, /* 01010101 */
@@ -1796,7 +1796,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x55, /* 01010101 */
    0xaa, /* 10101010 */
 
-   /* 178 0xb2 '²' */
+   /* 178 0xb2 '' */
    0x77, /* 01110111 */
    0xdd, /* 11011101 */
    0x77, /* 01110111 */
@@ -1806,7 +1806,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x77, /* 01110111 */
    0xdd, /* 11011101 */
 
-   /* 179 0xb3 '³' */
+   /* 179 0xb3 '' */
    0x18, /* 00011000 */
    0x18, /* 00011000 */
    0x18, /* 00011000 */
@@ -1816,7 +1816,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x18, /* 00011000 */
    0x18, /* 00011000 */
 
-   /* 180 0xb4 '´' */
+   /* 180 0xb4 '' */
    0x18, /* 00011000 */
    0x18, /* 00011000 */
    0x18, /* 00011000 */
@@ -1826,7 +1826,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x18, /* 00011000 */
    0x18, /* 00011000 */
 
-   /* 181 0xb5 'µ' */
+   /* 181 0xb5 '' */
    0x18, /* 00011000 */
    0x18, /* 00011000 */
    0xf8, /* 11111000 */
@@ -1836,7 +1836,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x18, /* 00011000 */
    0x18, /* 00011000 */
 
-   /* 182 0xb6 '' */
+   /* 182 0xb6 '' */
    0x36, /* 00110110 */
    0x36, /* 00110110 */
    0x36, /* 00110110 */
@@ -1846,7 +1846,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x36, /* 00110110 */
    0x36, /* 00110110 */
 
-   /* 183 0xb7 '·' */
+   /* 183 0xb7 '' */
    0x00, /* 00000000 */
    0x00, /* 00000000 */
    0x00, /* 00000000 */
@@ -1856,7 +1856,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x36, /* 00110110 */
    0x36, /* 00110110 */
 
-   /* 184 0xb8 '¸' */
+   /* 184 0xb8 '' */
    0x00, /* 00000000 */
    0x00, /* 00000000 */
    0xf8, /* 11111000 */
@@ -1866,7 +1866,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x18, /* 00011000 */
    0x18, /* 00011000 */
 
-   /* 185 0xb9 '¹' */
+   /* 185 0xb9 '' */
    0x36, /* 00110110 */
    0x36, /* 00110110 */
    0xf6, /* 11110110 */
@@ -1876,7 +1876,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x36, /* 00110110 */
    0x36, /* 00110110 */
 
-   /* 186 0xba 'º' */
+   /* 186 0xba '' */
    0x36, /* 00110110 */
    0x36, /* 00110110 */
    0x36, /* 00110110 */
@@ -1886,7 +1886,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x36, /* 00110110 */
    0x36, /* 00110110 */
 
-   /* 187 0xbb '»' */
+   /* 187 0xbb '' */
    0x00, /* 00000000 */
    0x00, /* 00000000 */
    0xfe, /* 11111110 */
@@ -1896,7 +1896,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x36, /* 00110110 */
    0x36, /* 00110110 */
 
-   /* 188 0xbc '¼' */
+   /* 188 0xbc '' */
    0x36, /* 00110110 */
    0x36, /* 00110110 */
    0xf6, /* 11110110 */
@@ -1906,7 +1906,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x00, /* 00000000 */
    0x00, /* 00000000 */
 
-   /* 189 0xbd '½' */
+   /* 189 0xbd '' */
    0x36, /* 00110110 */
    0x36, /* 00110110 */
    0x36, /* 00110110 */
@@ -1916,7 +1916,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x00, /* 00000000 */
    0x00, /* 00000000 */
 
-   /* 190 0xbe '¾' */
+   /* 190 0xbe '' */
    0x18, /* 00011000 */
    0x18, /* 00011000 */
    0xf8, /* 11111000 */
@@ -1926,7 +1926,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x00, /* 00000000 */
    0x00, /* 00000000 */
 
-   /* 191 0xbf '¿' */
+   /* 191 0xbf '' */
    0x00, /* 00000000 */
    0x00, /* 00000000 */
    0x00, /* 00000000 */
@@ -1936,7 +1936,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x18, /* 00011000 */
    0x18, /* 00011000 */
 
-   /* 192 0xc0 'À' */
+   /* 192 0xc0 '' */
    0x18, /* 00011000 */
    0x18, /* 00011000 */
    0x18, /* 00011000 */
@@ -1946,7 +1946,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x00, /* 00000000 */
    0x00, /* 00000000 */
 
-   /* 193 0xc1 'Á' */
+   /* 193 0xc1 '' */
    0x18, /* 00011000 */
    0x18, /* 00011000 */
    0x18, /* 00011000 */
@@ -1956,7 +1956,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x00, /* 00000000 */
    0x00, /* 00000000 */
 
-   /* 194 0xc2 'Â' */
+   /* 194 0xc2 '' */
    0x00, /* 00000000 */
    0x00, /* 00000000 */
    0x00, /* 00000000 */
@@ -1966,7 +1966,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x18, /* 00011000 */
    0x18, /* 00011000 */
 
-   /* 195 0xc3 'Ã' */
+   /* 195 0xc3 '' */
    0x18, /* 00011000 */
    0x18, /* 00011000 */
    0x18, /* 00011000 */
@@ -1976,7 +1976,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x18, /* 00011000 */
    0x18, /* 00011000 */
 
-   /* 196 0xc4 'Ä' */
+   /* 196 0xc4 '' */
    0x00, /* 00000000 */
    0x00, /* 00000000 */
    0x00, /* 00000000 */
@@ -1986,7 +1986,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x00, /* 00000000 */
    0x00, /* 00000000 */
 
-   /* 197 0xc5 'Å' */
+   /* 197 0xc5 '' */
    0x18, /* 00011000 */
    0x18, /* 00011000 */
    0x18, /* 00011000 */
@@ -1996,7 +1996,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x18, /* 00011000 */
    0x18, /* 00011000 */
 
-   /* 198 0xc6 'Æ' */
+   /* 198 0xc6 '' */
    0x18, /* 00011000 */
    0x18, /* 00011000 */
    0x1f, /* 00011111 */
@@ -2006,7 +2006,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x18, /* 00011000 */
    0x18, /* 00011000 */
 
-   /* 199 0xc7 'Ç' */
+   /* 199 0xc7 '' */
    0x36, /* 00110110 */
    0x36, /* 00110110 */
    0x36, /* 00110110 */
@@ -2016,7 +2016,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x36, /* 00110110 */
    0x36, /* 00110110 */
 
-   /* 200 0xc8 'È' */
+   /* 200 0xc8 '' */
    0x36, /* 00110110 */
    0x36, /* 00110110 */
    0x37, /* 00110111 */
@@ -2026,7 +2026,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x00, /* 00000000 */
    0x00, /* 00000000 */
 
-   /* 201 0xc9 'É' */
+   /* 201 0xc9 '' */
    0x00, /* 00000000 */
    0x00, /* 00000000 */
    0x3f, /* 00111111 */
@@ -2036,7 +2036,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x36, /* 00110110 */
    0x36, /* 00110110 */
 
-   /* 202 0xca 'Ê' */
+   /* 202 0xca '' */
    0x36, /* 00110110 */
    0x36, /* 00110110 */
    0xf7, /* 11110111 */
@@ -2046,7 +2046,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x00, /* 00000000 */
    0x00, /* 00000000 */
 
-   /* 203 0xcb 'Ë' */
+   /* 203 0xcb '' */
    0x00, /* 00000000 */
    0x00, /* 00000000 */
    0xff, /* 11111111 */
@@ -2056,7 +2056,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x36, /* 00110110 */
    0x36, /* 00110110 */
 
-   /* 204 0xcc 'Ì' */
+   /* 204 0xcc '' */
    0x36, /* 00110110 */
    0x36, /* 00110110 */
    0x37, /* 00110111 */
@@ -2066,7 +2066,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x36, /* 00110110 */
    0x36, /* 00110110 */
 
-   /* 205 0xcd 'Í' */
+   /* 205 0xcd '' */
    0x00, /* 00000000 */
    0x00, /* 00000000 */
    0xff, /* 11111111 */
@@ -2076,7 +2076,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x00, /* 00000000 */
    0x00, /* 00000000 */
 
-   /* 206 0xce 'Î' */
+   /* 206 0xce '' */
    0x36, /* 00110110 */
    0x36, /* 00110110 */
    0xf7, /* 11110111 */
@@ -2086,7 +2086,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x36, /* 00110110 */
    0x36, /* 00110110 */
 
-   /* 207 0xcf 'Ï' */
+   /* 207 0xcf '' */
    0x18, /* 00011000 */
    0x18, /* 00011000 */
    0xff, /* 11111111 */
@@ -2096,7 +2096,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x00, /* 00000000 */
    0x00, /* 00000000 */
 
-   /* 208 0xd0 'Ð' */
+   /* 208 0xd0 '' */
    0x36, /* 00110110 */
    0x36, /* 00110110 */
    0x36, /* 00110110 */
@@ -2106,7 +2106,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x00, /* 00000000 */
    0x00, /* 00000000 */
 
-   /* 209 0xd1 'Ñ' */
+   /* 209 0xd1 '' */
    0x00, /* 00000000 */
    0x00, /* 00000000 */
    0xff, /* 11111111 */
@@ -2116,7 +2116,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x18, /* 00011000 */
    0x18, /* 00011000 */
 
-   /* 210 0xd2 'Ò' */
+   /* 210 0xd2 '' */
    0x00, /* 00000000 */
    0x00, /* 00000000 */
    0x00, /* 00000000 */
@@ -2126,7 +2126,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x36, /* 00110110 */
    0x36, /* 00110110 */
 
-   /* 211 0xd3 'Ó' */
+   /* 211 0xd3 '' */
    0x36, /* 00110110 */
    0x36, /* 00110110 */
    0x36, /* 00110110 */
@@ -2136,7 +2136,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x00, /* 00000000 */
    0x00, /* 00000000 */
 
-   /* 212 0xd4 'Ô' */
+   /* 212 0xd4 '' */
    0x18, /* 00011000 */
    0x18, /* 00011000 */
    0x1f, /* 00011111 */
@@ -2146,7 +2146,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x00, /* 00000000 */
    0x00, /* 00000000 */
 
-   /* 213 0xd5 'Õ' */
+   /* 213 0xd5 '' */
    0x00, /* 00000000 */
    0x00, /* 00000000 */
    0x1f, /* 00011111 */
@@ -2156,7 +2156,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x18, /* 00011000 */
    0x18, /* 00011000 */
 
-   /* 214 0xd6 'Ö' */
+   /* 214 0xd6 '' */
    0x00, /* 00000000 */
    0x00, /* 00000000 */
    0x00, /* 00000000 */
@@ -2166,7 +2166,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x36, /* 00110110 */
    0x36, /* 00110110 */
 
-   /* 215 0xd7 '×' */
+   /* 215 0xd7 '' */
    0x36, /* 00110110 */
    0x36, /* 00110110 */
    0x36, /* 00110110 */
@@ -2176,7 +2176,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x36, /* 00110110 */
    0x36, /* 00110110 */
 
-   /* 216 0xd8 'Ø' */
+   /* 216 0xd8 '' */
    0x18, /* 00011000 */
    0x18, /* 00011000 */
    0xff, /* 11111111 */
@@ -2186,7 +2186,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x18, /* 00011000 */
    0x18, /* 00011000 */
 
-   /* 217 0xd9 'Ù' */
+   /* 217 0xd9 '' */
    0x18, /* 00011000 */
    0x18, /* 00011000 */
    0x18, /* 00011000 */
@@ -2196,7 +2196,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x00, /* 00000000 */
    0x00, /* 00000000 */
 
-   /* 218 0xda 'Ú' */
+   /* 218 0xda '' */
    0x00, /* 00000000 */
    0x00, /* 00000000 */
    0x00, /* 00000000 */
@@ -2206,7 +2206,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x18, /* 00011000 */
    0x18, /* 00011000 */
 
-   /* 219 0xdb 'Û' */
+   /* 219 0xdb '' */
    0xff, /* 11111111 */
    0xff, /* 11111111 */
    0xff, /* 11111111 */
@@ -2216,7 +2216,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0xff, /* 11111111 */
    0xff, /* 11111111 */
 
-   /* 220 0xdc 'Ü' */
+   /* 220 0xdc '' */
    0x00, /* 00000000 */
    0x00, /* 00000000 */
    0x00, /* 00000000 */
@@ -2226,7 +2226,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0xff, /* 11111111 */
    0xff, /* 11111111 */
 
-   /* 221 0xdd 'Ý' */
+   /* 221 0xdd '' */
    0xf0, /* 11110000 */
    0xf0, /* 11110000 */
    0xf0, /* 11110000 */
@@ -2236,7 +2236,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0xf0, /* 11110000 */
    0xf0, /* 11110000 */
 
-   /* 222 0xde 'Þ' */
+   /* 222 0xde '' */
    0x0f, /* 00001111 */
    0x0f, /* 00001111 */
    0x0f, /* 00001111 */
@@ -2246,7 +2246,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x0f, /* 00001111 */
    0x0f, /* 00001111 */
 
-   /* 223 0xdf 'ß' */
+   /* 223 0xdf '' */
    0xff, /* 11111111 */
    0xff, /* 11111111 */
    0xff, /* 11111111 */
@@ -2256,7 +2256,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x00, /* 00000000 */
    0x00, /* 00000000 */
 
-   /* 224 0xe0 'à' */
+   /* 224 0xe0 'α' */
    0x00, /* 00000000 */
    0x00, /* 00000000 */
    0x76, /* 01110110 */
@@ -2266,7 +2266,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x76, /* 01110110 */
    0x00, /* 00000000 */
 
-   /* 225 0xe1 'á' */
+   /* 225 0xe1 'ß' */
    0x78, /* 01111000 */
    0xcc, /* 11001100 */
    0xcc, /* 11001100 */
@@ -2276,7 +2276,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0xcc, /* 11001100 */
    0x00, /* 00000000 */
 
-   /* 226 0xe2 'â' */
+   /* 226 0xe2 'Γ' */
    0xfe, /* 11111110 */
    0xc6, /* 11000110 */
    0xc0, /* 11000000 */
@@ -2286,7 +2286,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0xc0, /* 11000000 */
    0x00, /* 00000000 */
 
-   /* 227 0xe3 'ã' */
+   /* 227 0xe3 'π' */
    0x00, /* 00000000 */
    0x00, /* 00000000 */
    0xfe, /* 11111110 */
@@ -2296,7 +2296,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x6c, /* 01101100 */
    0x00, /* 00000000 */
 
-   /* 228 0xe4 'ä' */
+   /* 228 0xe4 'Σ' */
    0xfe, /* 11111110 */
    0xc6, /* 11000110 */
    0x60, /* 01100000 */
@@ -2306,7 +2306,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0xfe, /* 11111110 */
    0x00, /* 00000000 */
 
-   /* 229 0xe5 'å' */
+   /* 229 0xe5 'σ' */
    0x00, /* 00000000 */
    0x00, /* 00000000 */
    0x7e, /* 01111110 */
@@ -2316,7 +2316,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x70, /* 01110000 */
    0x00, /* 00000000 */
 
-   /* 230 0xe6 'æ' */
+   /* 230 0xe6 'µ' */
    0x00, /* 00000000 */
    0x00, /* 00000000 */
    0x66, /* 01100110 */
@@ -2326,7 +2326,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x7c, /* 01111100 */
    0xc0, /* 11000000 */
 
-   /* 231 0xe7 'ç' */
+   /* 231 0xe7 'τ' */
    0x00, /* 00000000 */
    0x76, /* 01110110 */
    0xdc, /* 11011100 */
@@ -2336,7 +2336,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x18, /* 00011000 */
    0x00, /* 00000000 */
 
-   /* 232 0xe8 'è' */
+   /* 232 0xe8 'Φ' */
    0x7e, /* 01111110 */
    0x18, /* 00011000 */
    0x3c, /* 00111100 */
@@ -2346,7 +2346,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x18, /* 00011000 */
    0x7e, /* 01111110 */
 
-   /* 233 0xe9 'é' */
+   /* 233 0xe9 'Θ' */
    0x38, /* 00111000 */
    0x6c, /* 01101100 */
    0xc6, /* 11000110 */
@@ -2356,7 +2356,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x38, /* 00111000 */
    0x00, /* 00000000 */
 
-   /* 234 0xea 'ê' */
+   /* 234 0xea 'Ω' */
    0x38, /* 00111000 */
    0x6c, /* 01101100 */
    0xc6, /* 11000110 */
@@ -2366,7 +2366,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0xee, /* 11101110 */
    0x00, /* 00000000 */
 
-   /* 235 0xeb 'ë' */
+   /* 235 0xeb 'δ' */
    0x0e, /* 00001110 */
    0x18, /* 00011000 */
    0x0c, /* 00001100 */
@@ -2376,7 +2376,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x3c, /* 00111100 */
    0x00, /* 00000000 */
 
-   /* 236 0xec 'ì' */
+   /* 236 0xec '' */
    0x00, /* 00000000 */
    0x00, /* 00000000 */
    0x7e, /* 01111110 */
@@ -2386,7 +2386,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x00, /* 00000000 */
    0x00, /* 00000000 */
 
-   /* 237 0xed 'í' */
+   /* 237 0xed 'φ' */
    0x06, /* 00000110 */
    0x0c, /* 00001100 */
    0x7e, /* 01111110 */
@@ -2396,7 +2396,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x60, /* 01100000 */
    0xc0, /* 11000000 */
 
-   /* 238 0xee 'î' */
+   /* 238 0xee 'ε' */
    0x1e, /* 00011110 */
    0x30, /* 00110000 */
    0x60, /* 01100000 */
@@ -2406,7 +2406,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x1e, /* 00011110 */
    0x00, /* 00000000 */
 
-   /* 239 0xef 'ï' */
+   /* 239 0xef '' */
    0x00, /* 00000000 */
    0x7c, /* 01111100 */
    0xc6, /* 11000110 */
@@ -2416,7 +2416,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0xc6, /* 11000110 */
    0x00, /* 00000000 */
 
-   /* 240 0xf0 'ð' */
+   /* 240 0xf0 '' */
    0x00, /* 00000000 */
    0xfe, /* 11111110 */
    0x00, /* 00000000 */
@@ -2426,7 +2426,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x00, /* 00000000 */
    0x00, /* 00000000 */
 
-   /* 241 0xf1 'ñ' */
+   /* 241 0xf1 '±' */
    0x18, /* 00011000 */
    0x18, /* 00011000 */
    0x7e, /* 01111110 */
@@ -2436,7 +2436,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x7e, /* 01111110 */
    0x00, /* 00000000 */
 
-   /* 242 0xf2 'ò' */
+   /* 242 0xf2 '' */
    0x30, /* 00110000 */
    0x18, /* 00011000 */
    0x0c, /* 00001100 */
@@ -2446,7 +2446,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x7e, /* 01111110 */
    0x00, /* 00000000 */
 
-   /* 243 0xf3 'ó' */
+   /* 243 0xf3 '' */
    0x0c, /* 00001100 */
    0x18, /* 00011000 */
    0x30, /* 00110000 */
@@ -2456,7 +2456,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x7e, /* 01111110 */
    0x00, /* 00000000 */
 
-   /* 244 0xf4 'ô' */
+   /* 244 0xf4 '' */
    0x0e, /* 00001110 */
    0x1b, /* 00011011 */
    0x1b, /* 00011011 */
@@ -2466,7 +2466,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x18, /* 00011000 */
    0x18, /* 00011000 */
 
-   /* 245 0xf5 'õ' */
+   /* 245 0xf5 '' */
    0x18, /* 00011000 */
    0x18, /* 00011000 */
    0x18, /* 00011000 */
@@ -2476,7 +2476,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0xd8, /* 11011000 */
    0x70, /* 01110000 */
 
-   /* 246 0xf6 'ö' */
+   /* 246 0xf6 '÷' */
    0x00, /* 00000000 */
    0x18, /* 00011000 */
    0x00, /* 00000000 */
@@ -2486,7 +2486,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x00, /* 00000000 */
    0x00, /* 00000000 */
 
-   /* 247 0xf7 '÷' */
+   /* 247 0xf7 '' */
    0x00, /* 00000000 */
    0x76, /* 01110110 */
    0xdc, /* 11011100 */
@@ -2496,7 +2496,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x00, /* 00000000 */
    0x00, /* 00000000 */
 
-   /* 248 0xf8 'ø' */
+   /* 248 0xf8 '°' */
    0x38, /* 00111000 */
    0x6c, /* 01101100 */
    0x6c, /* 01101100 */
@@ -2506,7 +2506,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x00, /* 00000000 */
    0x00, /* 00000000 */
 
-   /* 249 0xf9 'ù' */
+   /* 249 0xf9 '·' */
    0x00, /* 00000000 */
    0x00, /* 00000000 */
    0x00, /* 00000000 */
@@ -2516,7 +2516,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x00, /* 00000000 */
    0x00, /* 00000000 */
 
-   /* 250 0xfa 'ú' */
+   /* 250 0xfa '' */
    0x00, /* 00000000 */
    0x00, /* 00000000 */
    0x00, /* 00000000 */
@@ -2526,7 +2526,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x00, /* 00000000 */
    0x00, /* 00000000 */
 
-   /* 251 0xfb 'û' */
+   /* 251 0xfb '' */
    0x0f, /* 00001111 */
    0x0c, /* 00001100 */
    0x0c, /* 00001100 */
@@ -2536,7 +2536,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x3c, /* 00111100 */
    0x1c, /* 00011100 */
 
-   /* 252 0xfc 'ü' */
+   /* 252 0xfc '' */
    0x6c, /* 01101100 */
    0x36, /* 00110110 */
    0x36, /* 00110110 */
@@ -2546,7 +2546,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x00, /* 00000000 */
    0x00, /* 00000000 */
 
-   /* 253 0xfd 'ý' */
+   /* 253 0xfd '²' */
    0x78, /* 01111000 */
    0x0c, /* 00001100 */
    0x18, /* 00011000 */
@@ -2556,7 +2556,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x00, /* 00000000 */
    0x00, /* 00000000 */
 
-   /* 254 0xfe 'þ' */
+   /* 254 0xfe '' */
    0x00, /* 00000000 */
    0x00, /* 00000000 */
    0x3c, /* 00111100 */
@@ -2566,7 +2566,7 @@ static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
    0x00, /* 00000000 */
    0x00, /* 00000000 */
 
-   /* 255 0xff 'ÿ' */
+   /* 255 0xff ' ' */
    0x00, /* 00000000 */
    0x00, /* 00000000 */
    0x00, /* 00000000 */
diff --git a/lib/gen_crc64table.c b/lib/gen_crc64table.c
new file mode 100644 (file)
index 0000000..9011926
--- /dev/null
@@ -0,0 +1,68 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Generate lookup table for the table-driven CRC64 calculation.
+ *
+ * gen_crc64table is executed in kernel build time and generates
+ * lib/crc64table.h. This header is included by lib/crc64.c for
+ * the table-driven CRC64 calculation.
+ *
+ * See lib/crc64.c for more information about which specification
+ * and polynomial arithmetic that gen_crc64table.c follows to
+ * generate the lookup table.
+ *
+ * Copyright 2018 SUSE Linux.
+ *   Author: Coly Li <colyli@suse.de>
+ */
+#include <inttypes.h>
+#include <stdio.h>
+
+#include <linux/swab.h>
+
+#define CRC64_ECMA182_POLY 0x42F0E1EBA9EA3693ULL
+
+static uint64_t crc64_table[256] = {0};
+
+static void generate_crc64_table(void)
+{
+       uint64_t i, j, c, crc;
+
+       for (i = 0; i < 256; i++) {
+               crc = 0;
+               c = i << 56;
+
+               for (j = 0; j < 8; j++) {
+                       if ((crc ^ c) & 0x8000000000000000ULL)
+                               crc = (crc << 1) ^ CRC64_ECMA182_POLY;
+                       else
+                               crc <<= 1;
+                       c <<= 1;
+               }
+
+               crc64_table[i] = crc;
+       }
+}
+
+static void print_crc64_table(void)
+{
+       int i;
+
+       printf("/* this file is generated - do not edit */\n\n");
+       printf("#include <linux/types.h>\n");
+       printf("#include <linux/cache.h>\n\n");
+       printf("static const u64 ____cacheline_aligned crc64table[256] = {\n");
+       for (i = 0; i < 256; i++) {
+               printf("\t0x%016" PRIx64 "ULL", crc64_table[i]);
+               if (i & 0x1)
+                       printf(",\n");
+               else
+                       printf(", ");
+       }
+       printf("};\n");
+}
+
+int main(int argc, char *argv[])
+{
+       generate_crc64_table();
+       print_crc64_table();
+       return 0;
+}
index ed9c169..fab2fd5 100644 (file)
--- a/lib/idr.c
+++ b/lib/idr.c
@@ -317,18 +317,12 @@ EXPORT_SYMBOL(idr_replace);
  * bit per ID, and so is more space efficient than an IDR.  To use an IDA,
  * define it using DEFINE_IDA() (or embed a &struct ida in a data structure,
  * then initialise it using ida_init()).  To allocate a new ID, call
- * ida_simple_get().  To free an ID, call ida_simple_remove().
+ * ida_alloc(), ida_alloc_min(), ida_alloc_max() or ida_alloc_range().
+ * To free an ID, call ida_free().
  *
- * If you have more complex locking requirements, use a loop around
- * ida_pre_get() and ida_get_new() to allocate a new ID.  Then use
- * ida_remove() to free an ID.  You must make sure that ida_get_new() and
- * ida_remove() cannot be called at the same time as each other for the
- * same IDA.
- *
- * You can also use ida_get_new_above() if you need an ID to be allocated
- * above a particular number.  ida_destroy() can be used to dispose of an
- * IDA without needing to free the individual IDs in it.  You can use
- * ida_is_empty() to find out whether the IDA has any IDs currently allocated.
+ * ida_destroy() can be used to dispose of an IDA without needing to
+ * free the individual IDs in it.  You can use ida_is_empty() to find
+ * out whether the IDA has any IDs currently allocated.
  *
  * IDs are currently limited to the range [0-INT_MAX].  If this is an awkward
  * limitation, it should be quite straightforward to raise the maximum.
@@ -369,25 +363,7 @@ EXPORT_SYMBOL(idr_replace);
 
 #define IDA_MAX (0x80000000U / IDA_BITMAP_BITS - 1)
 
-/**
- * ida_get_new_above - allocate new ID above or equal to a start id
- * @ida: ida handle
- * @start: id to start search at
- * @id: pointer to the allocated handle
- *
- * Allocate new ID above or equal to @start.  It should be called
- * with any required locks to ensure that concurrent calls to
- * ida_get_new_above() / ida_get_new() / ida_remove() are not allowed.
- * Consider using ida_simple_get() if you do not have complex locking
- * requirements.
- *
- * If memory is required, it will return %-EAGAIN, you should unlock
- * and go back to the ida_pre_get() call.  If the ida is full, it will
- * return %-ENOSPC.  On success, it will return 0.
- *
- * @id returns a value in the range @start ... %0x7fffffff.
- */
-int ida_get_new_above(struct ida *ida, int start, int *id)
+static int ida_get_new_above(struct ida *ida, int start)
 {
        struct radix_tree_root *root = &ida->ida_rt;
        void __rcu **slot;
@@ -426,8 +402,8 @@ int ida_get_new_above(struct ida *ida, int start, int *id)
                        if (ebit < BITS_PER_LONG) {
                                tmp |= 1UL << ebit;
                                rcu_assign_pointer(*slot, (void *)tmp);
-                               *id = new + ebit - RADIX_TREE_EXCEPTIONAL_SHIFT;
-                               return 0;
+                               return new + ebit -
+                                       RADIX_TREE_EXCEPTIONAL_SHIFT;
                        }
                        bitmap = this_cpu_xchg(ida_bitmap, NULL);
                        if (!bitmap)
@@ -458,8 +434,7 @@ int ida_get_new_above(struct ida *ida, int start, int *id)
                                                RADIX_TREE_EXCEPTIONAL_ENTRY);
                                radix_tree_iter_replace(root, &iter, slot,
                                                bitmap);
-                               *id = new;
-                               return 0;
+                               return new;
                        }
                        bitmap = this_cpu_xchg(ida_bitmap, NULL);
                        if (!bitmap)
@@ -468,20 +443,11 @@ int ida_get_new_above(struct ida *ida, int start, int *id)
                        radix_tree_iter_replace(root, &iter, slot, bitmap);
                }
 
-               *id = new;
-               return 0;
+               return new;
        }
 }
-EXPORT_SYMBOL(ida_get_new_above);
 
-/**
- * ida_remove - Free the given ID
- * @ida: ida handle
- * @id: ID to free
- *
- * This function should not be called at the same time as ida_get_new_above().
- */
-void ida_remove(struct ida *ida, int id)
+static void ida_remove(struct ida *ida, int id)
 {
        unsigned long index = id / IDA_BITMAP_BITS;
        unsigned offset = id % IDA_BITMAP_BITS;
@@ -518,99 +484,90 @@ void ida_remove(struct ida *ida, int id)
        }
        return;
  err:
-       WARN(1, "ida_remove called for id=%d which is not allocated.\n", id);
+       WARN(1, "ida_free called for id=%d which is not allocated.\n", id);
 }
-EXPORT_SYMBOL(ida_remove);
 
 /**
- * ida_destroy - Free the contents of an ida
- * @ida: ida handle
+ * ida_destroy() - Free all IDs.
+ * @ida: IDA handle.
+ *
+ * Calling this function frees all IDs and releases all resources used
+ * by an IDA.  When this call returns, the IDA is empty and can be reused
+ * or freed.  If the IDA is already empty, there is no need to call this
+ * function.
  *
- * Calling this function releases all resources associated with an IDA.  When
- * this call returns, the IDA is empty and can be reused or freed.  The caller
- * should not allow ida_remove() or ida_get_new_above() to be called at the
- * same time.
+ * Context: Any context.
  */
 void ida_destroy(struct ida *ida)
 {
+       unsigned long flags;
        struct radix_tree_iter iter;
        void __rcu **slot;
 
+       xa_lock_irqsave(&ida->ida_rt, flags);
        radix_tree_for_each_slot(slot, &ida->ida_rt, &iter, 0) {
                struct ida_bitmap *bitmap = rcu_dereference_raw(*slot);
                if (!radix_tree_exception(bitmap))
                        kfree(bitmap);
                radix_tree_iter_delete(&ida->ida_rt, &iter, slot);
        }
+       xa_unlock_irqrestore(&ida->ida_rt, flags);
 }
 EXPORT_SYMBOL(ida_destroy);
 
 /**
- * ida_simple_get - get a new id.
- * @ida: the (initialized) ida.
- * @start: the minimum id (inclusive, < 0x8000000)
- * @end: the maximum id (exclusive, < 0x8000000 or 0)
- * @gfp_mask: memory allocation flags
- *
- * Allocates an id in the range start <= id < end, or returns -ENOSPC.
- * On memory allocation failure, returns -ENOMEM.
+ * ida_alloc_range() - Allocate an unused ID.
+ * @ida: IDA handle.
+ * @min: Lowest ID to allocate.
+ * @max: Highest ID to allocate.
+ * @gfp: Memory allocation flags.
  *
- * Compared to ida_get_new_above() this function does its own locking, and
- * should be used unless there are special requirements.
+ * Allocate an ID between @min and @max, inclusive.  The allocated ID will
+ * not exceed %INT_MAX, even if @max is larger.
  *
- * Use ida_simple_remove() to get rid of an id.
+ * Context: Any context.
+ * Return: The allocated ID, or %-ENOMEM if memory could not be allocated,
+ * or %-ENOSPC if there are no free IDs.
  */
-int ida_simple_get(struct ida *ida, unsigned int start, unsigned int end,
-                  gfp_t gfp_mask)
+int ida_alloc_range(struct ida *ida, unsigned int min, unsigned int max,
+                       gfp_t gfp)
 {
-       int ret, id;
-       unsigned int max;
+       int id = 0;
        unsigned long flags;
 
-       BUG_ON((int)start < 0);
-       BUG_ON((int)end < 0);
+       if ((int)min < 0)
+               return -ENOSPC;
 
-       if (end == 0)
-               max = 0x80000000;
-       else {
-               BUG_ON(end < start);
-               max = end - 1;
-       }
+       if ((int)max < 0)
+               max = INT_MAX;
 
 again:
-       if (!ida_pre_get(ida, gfp_mask))
-               return -ENOMEM;
-
        xa_lock_irqsave(&ida->ida_rt, flags);
-       ret = ida_get_new_above(ida, start, &id);
-       if (!ret) {
-               if (id > max) {
-                       ida_remove(ida, id);
-                       ret = -ENOSPC;
-               } else {
-                       ret = id;
-               }
+       id = ida_get_new_above(ida, min);
+       if (id > (int)max) {
+               ida_remove(ida, id);
+               id = -ENOSPC;
        }
        xa_unlock_irqrestore(&ida->ida_rt, flags);
 
-       if (unlikely(ret == -EAGAIN))
+       if (unlikely(id == -EAGAIN)) {
+               if (!ida_pre_get(ida, gfp))
+                       return -ENOMEM;
                goto again;
+       }
 
-       return ret;
+       return id;
 }
-EXPORT_SYMBOL(ida_simple_get);
+EXPORT_SYMBOL(ida_alloc_range);
 
 /**
- * ida_simple_remove - remove an allocated id.
- * @ida: the (initialized) ida.
- * @id: the id returned by ida_simple_get.
- *
- * Use to release an id allocated with ida_simple_get().
+ * ida_free() - Release an allocated ID.
+ * @ida: IDA handle.
+ * @id: Previously allocated ID.
  *
- * Compared to ida_remove() this function does its own locking, and should be
- * used unless there are special requirements.
+ * Context: Any context.
  */
-void ida_simple_remove(struct ida *ida, unsigned int id)
+void ida_free(struct ida *ida, unsigned int id)
 {
        unsigned long flags;
 
@@ -619,4 +576,4 @@ void ida_simple_remove(struct ida *ida, unsigned int id)
        ida_remove(ida, id);
        xa_unlock_irqrestore(&ida->ida_rt, flags);
 }
-EXPORT_SYMBOL(ida_simple_remove);
+EXPORT_SYMBOL(ida_free);
index a9e41ae..bc03ecc 100644 (file)
@@ -120,7 +120,7 @@ bool is_sibling_entry(const struct radix_tree_node *parent, void *node)
 static inline unsigned long
 get_slot_offset(const struct radix_tree_node *parent, void __rcu **slot)
 {
-       return slot - parent->slots;
+       return parent ? slot - parent->slots : 0;
 }
 
 static unsigned int radix_tree_descend(const struct radix_tree_node *parent,
@@ -2106,14 +2106,6 @@ void idr_preload(gfp_t gfp_mask)
 }
 EXPORT_SYMBOL(idr_preload);
 
-/**
- * ida_pre_get - reserve resources for ida allocation
- * @ida: ida handle
- * @gfp: memory allocation flags
- *
- * This function should be called before calling ida_get_new_above().  If it
- * is unable to allocate memory, it will return %0.  On success, it returns %1.
- */
 int ida_pre_get(struct ida *ida, gfp_t gfp)
 {
        /*
@@ -2134,7 +2126,6 @@ int ida_pre_get(struct ida *ida, gfp_t gfp)
 
        return 1;
 }
-EXPORT_SYMBOL(ida_pre_get);
 
 void __rcu **idr_get_free(struct radix_tree_root *root,
                              struct radix_tree_iter *iter, gfp_t gfp,
index 672eecd..30526af 100644 (file)
@@ -173,17 +173,15 @@ static struct bucket_table *bucket_table_alloc(struct rhashtable *ht,
        int i;
 
        size = sizeof(*tbl) + nbuckets * sizeof(tbl->buckets[0]);
-       if (gfp != GFP_KERNEL)
-               tbl = kzalloc(size, gfp | __GFP_NOWARN | __GFP_NORETRY);
-       else
-               tbl = kvzalloc(size, gfp);
+       tbl = kvzalloc(size, gfp);
 
        size = nbuckets;
 
-       if (tbl == NULL && gfp != GFP_KERNEL) {
+       if (tbl == NULL && (gfp & ~__GFP_NOFAIL) != GFP_KERNEL) {
                tbl = nested_bucket_table_alloc(ht, nbuckets, gfp);
                nbuckets = 0;
        }
+
        if (tbl == NULL)
                return NULL;
 
@@ -449,7 +447,7 @@ static int rhashtable_insert_rehash(struct rhashtable *ht,
 
        err = -ENOMEM;
 
-       new_tbl = bucket_table_alloc(ht, size, GFP_ATOMIC);
+       new_tbl = bucket_table_alloc(ht, size, GFP_ATOMIC | __GFP_NOWARN);
        if (new_tbl == NULL)
                goto fail;
 
@@ -1059,9 +1057,16 @@ int rhashtable_init(struct rhashtable *ht,
                }
        }
 
+       /*
+        * This is api initialization and thus we need to guarantee the
+        * initial rhashtable allocation. Upon failure, retry with the
+        * smallest possible size with __GFP_NOFAIL semantics.
+        */
        tbl = bucket_table_alloc(ht, size, GFP_KERNEL);
-       if (tbl == NULL)
-               return -ENOMEM;
+       if (unlikely(tbl == NULL)) {
+               size = max_t(u16, ht->p.min_size, HASH_MIN_SIZE);
+               tbl = bucket_table_alloc(ht, size, GFP_KERNEL | __GFP_NOFAIL);
+       }
 
        atomic_set(&ht->nelems, 0);
 
index b9cdeec..d5a06ad 100644 (file)
@@ -15,7 +15,7 @@ struct foo {
        unsigned int bar;
 };
 
-struct foo *foo;
+static struct foo *foo;
 
 static int __init test_debug_virtual_init(void)
 {
index 3f415d8..626f580 100644 (file)
@@ -18,7 +18,7 @@ static const unsigned char data_b[] = {
 
 static const unsigned char data_a[] = ".2.{....p..$}.4...1.....L...C...";
 
-static const char * const test_data_1_le[] __initconst = {
+static const char * const test_data_1[] __initconst = {
        "be", "32", "db", "7b", "0a", "18", "93", "b2",
        "70", "ba", "c4", "24", "7d", "83", "34", "9b",
        "a6", "9c", "31", "ad", "9c", "0f", "ac", "e9",
@@ -32,16 +32,33 @@ static const char * const test_data_2_le[] __initconst = {
        "d14c", "9919", "b143", "0caf",
 };
 
+static const char * const test_data_2_be[] __initconst = {
+       "be32", "db7b", "0a18", "93b2",
+       "70ba", "c424", "7d83", "349b",
+       "a69c", "31ad", "9c0f", "ace9",
+       "4cd1", "1999", "43b1", "af0c",
+};
+
 static const char * const test_data_4_le[] __initconst = {
        "7bdb32be", "b293180a", "24c4ba70", "9b34837d",
        "ad319ca6", "e9ac0f9c", "9919d14c", "0cafb143",
 };
 
+static const char * const test_data_4_be[] __initconst = {
+       "be32db7b", "0a1893b2", "70bac424", "7d83349b",
+       "a69c31ad", "9c0face9", "4cd11999", "43b1af0c",
+};
+
 static const char * const test_data_8_le[] __initconst = {
        "b293180a7bdb32be", "9b34837d24c4ba70",
        "e9ac0f9cad319ca6", "0cafb1439919d14c",
 };
 
+static const char * const test_data_8_be[] __initconst = {
+       "be32db7b0a1893b2", "70bac4247d83349b",
+       "a69c31ad9c0face9", "4cd1199943b1af0c",
+};
+
 #define FILL_CHAR      '#'
 
 static unsigned total_tests __initdata;
@@ -56,6 +73,7 @@ static void __init test_hexdump_prepare_test(size_t len, int rowsize,
        size_t l = len;
        int gs = groupsize, rs = rowsize;
        unsigned int i;
+       const bool is_be = IS_ENABLED(CONFIG_CPU_BIG_ENDIAN);
 
        if (rs != 16 && rs != 32)
                rs = 16;
@@ -67,13 +85,13 @@ static void __init test_hexdump_prepare_test(size_t len, int rowsize,
                gs = 1;
 
        if (gs == 8)
-               result = test_data_8_le;
+               result = is_be ? test_data_8_be : test_data_8_le;
        else if (gs == 4)
-               result = test_data_4_le;
+               result = is_be ? test_data_4_be : test_data_4_le;
        else if (gs == 2)
-               result = test_data_2_le;
+               result = is_be ? test_data_2_be : test_data_2_le;
        else
-               result = test_data_1_le;
+               result = test_data_1;
 
        /* hex dump */
        p = test;
diff --git a/lib/test_ida.c b/lib/test_ida.c
new file mode 100644 (file)
index 0000000..2d1637d
--- /dev/null
@@ -0,0 +1,177 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * test_ida.c: Test the IDA API
+ * Copyright (c) 2016-2018 Microsoft Corporation
+ * Copyright (c) 2018 Oracle Corporation
+ * Author: Matthew Wilcox <willy@infradead.org>
+ */
+
+#include <linux/idr.h>
+#include <linux/module.h>
+
+static unsigned int tests_run;
+static unsigned int tests_passed;
+
+#ifdef __KERNEL__
+void ida_dump(struct ida *ida) { }
+#endif
+#define IDA_BUG_ON(ida, x) do {                                                \
+       tests_run++;                                                    \
+       if (x) {                                                        \
+               ida_dump(ida);                                          \
+               dump_stack();                                           \
+       } else {                                                        \
+               tests_passed++;                                         \
+       }                                                               \
+} while (0)
+
+/*
+ * Straightforward checks that allocating and freeing IDs work.
+ */
+static void ida_check_alloc(struct ida *ida)
+{
+       int i, id;
+
+       for (i = 0; i < 10000; i++)
+               IDA_BUG_ON(ida, ida_alloc(ida, GFP_KERNEL) != i);
+
+       ida_free(ida, 20);
+       ida_free(ida, 21);
+       for (i = 0; i < 3; i++) {
+               id = ida_alloc(ida, GFP_KERNEL);
+               IDA_BUG_ON(ida, id < 0);
+               if (i == 2)
+                       IDA_BUG_ON(ida, id != 10000);
+       }
+
+       for (i = 0; i < 5000; i++)
+               ida_free(ida, i);
+
+       IDA_BUG_ON(ida, ida_alloc_min(ida, 5000, GFP_KERNEL) != 10001);
+       ida_destroy(ida);
+
+       IDA_BUG_ON(ida, !ida_is_empty(ida));
+}
+
+/* Destroy an IDA with a single entry at @base */
+static void ida_check_destroy_1(struct ida *ida, unsigned int base)
+{
+       IDA_BUG_ON(ida, ida_alloc_min(ida, base, GFP_KERNEL) != base);
+       IDA_BUG_ON(ida, ida_is_empty(ida));
+       ida_destroy(ida);
+       IDA_BUG_ON(ida, !ida_is_empty(ida));
+}
+
+/* Check that ida_destroy and ida_is_empty work */
+static void ida_check_destroy(struct ida *ida)
+{
+       /* Destroy an already-empty IDA */
+       IDA_BUG_ON(ida, !ida_is_empty(ida));
+       ida_destroy(ida);
+       IDA_BUG_ON(ida, !ida_is_empty(ida));
+
+       ida_check_destroy_1(ida, 0);
+       ida_check_destroy_1(ida, 1);
+       ida_check_destroy_1(ida, 1023);
+       ida_check_destroy_1(ida, 1024);
+       ida_check_destroy_1(ida, 12345678);
+}
+
+/*
+ * Check what happens when we fill a leaf and then delete it.  This may
+ * discover mishandling of IDR_FREE.
+ */
+static void ida_check_leaf(struct ida *ida, unsigned int base)
+{
+       unsigned long i;
+
+       for (i = 0; i < IDA_BITMAP_BITS; i++) {
+               IDA_BUG_ON(ida, ida_alloc_min(ida, base, GFP_KERNEL) !=
+                               base + i);
+       }
+
+       ida_destroy(ida);
+       IDA_BUG_ON(ida, !ida_is_empty(ida));
+
+       IDA_BUG_ON(ida, ida_alloc(ida, GFP_KERNEL) != 0);
+       IDA_BUG_ON(ida, ida_is_empty(ida));
+       ida_free(ida, 0);
+       IDA_BUG_ON(ida, !ida_is_empty(ida));
+}
+
+/*
+ * Check allocations up to and slightly above the maximum allowed (2^31-1) ID.
+ * Allocating up to 2^31-1 should succeed, and then allocating the next one
+ * should fail.
+ */
+static void ida_check_max(struct ida *ida)
+{
+       unsigned long i, j;
+
+       for (j = 1; j < 65537; j *= 2) {
+               unsigned long base = (1UL << 31) - j;
+               for (i = 0; i < j; i++) {
+                       IDA_BUG_ON(ida, ida_alloc_min(ida, base, GFP_KERNEL) !=
+                                       base + i);
+               }
+               IDA_BUG_ON(ida, ida_alloc_min(ida, base, GFP_KERNEL) !=
+                               -ENOSPC);
+               ida_destroy(ida);
+               IDA_BUG_ON(ida, !ida_is_empty(ida));
+       }
+}
+
+/*
+ * Check handling of conversions between exceptional entries and full bitmaps.
+ */
+static void ida_check_conv(struct ida *ida)
+{
+       unsigned long i;
+
+       for (i = 0; i < IDA_BITMAP_BITS * 2; i += IDA_BITMAP_BITS) {
+               IDA_BUG_ON(ida, ida_alloc_min(ida, i + 1, GFP_KERNEL) != i + 1);
+               IDA_BUG_ON(ida, ida_alloc_min(ida, i + BITS_PER_LONG,
+                                       GFP_KERNEL) != i + BITS_PER_LONG);
+               ida_free(ida, i + 1);
+               ida_free(ida, i + BITS_PER_LONG);
+               IDA_BUG_ON(ida, !ida_is_empty(ida));
+       }
+
+       for (i = 0; i < IDA_BITMAP_BITS * 2; i++)
+               IDA_BUG_ON(ida, ida_alloc(ida, GFP_KERNEL) != i);
+       for (i = IDA_BITMAP_BITS * 2; i > 0; i--)
+               ida_free(ida, i - 1);
+       IDA_BUG_ON(ida, !ida_is_empty(ida));
+
+       for (i = 0; i < IDA_BITMAP_BITS + BITS_PER_LONG - 4; i++)
+               IDA_BUG_ON(ida, ida_alloc(ida, GFP_KERNEL) != i);
+       for (i = IDA_BITMAP_BITS + BITS_PER_LONG - 4; i > 0; i--)
+               ida_free(ida, i - 1);
+       IDA_BUG_ON(ida, !ida_is_empty(ida));
+}
+
+static int ida_checks(void)
+{
+       DEFINE_IDA(ida);
+
+       IDA_BUG_ON(&ida, !ida_is_empty(&ida));
+       ida_check_alloc(&ida);
+       ida_check_destroy(&ida);
+       ida_check_leaf(&ida, 0);
+       ida_check_leaf(&ida, 1024);
+       ida_check_leaf(&ida, 1024 * 64);
+       ida_check_max(&ida);
+       ida_check_conv(&ida);
+
+       printk("IDA: %u of %u tests passed\n", tests_passed, tests_run);
+       return (tests_run != tests_passed) ? 0 : -EINVAL;
+}
+
+static void ida_exit(void)
+{
+}
+
+module_init(ida_checks);
+module_exit(ida_exit);
+MODULE_AUTHOR("Matthew Wilcox <willy@infradead.org>");
+MODULE_LICENSE("GPL");
index e5e606e..9a7b8b0 100644 (file)
@@ -46,7 +46,8 @@ config PAGE_POISONING
          Fill the pages with poison patterns after free_pages() and verify
          the patterns before alloc_pages. The filling of the memory helps
          reduce the risk of information leaks from freed data. This does
-         have a potential performance impact.
+         have a potential performance impact if enabled with the
+         "page_poison=1" kernel boot option.
 
          Note that "poison" here is not the same thing as the "HWPoison"
          for CONFIG_MEMORY_FAILURE. This is software poisoning only.
@@ -65,7 +66,7 @@ config PAGE_POISONING_NO_SANITY
           say N.
 
 config PAGE_POISONING_ZERO
-       bool "Use zero for poisoning instead of random data"
+       bool "Use zero for poisoning instead of debugging value"
        depends on PAGE_POISONING
        ---help---
           Instead of using the existing poison value, fill the pages with
@@ -75,7 +76,6 @@ config PAGE_POISONING_ZERO
           allocation.
 
           If unsure, say N
-       bool
 
 config DEBUG_PAGE_REF
        bool "Enable tracepoint to track down page reference manipulation"
index 2e5d3df..f5981e9 100644 (file)
@@ -438,10 +438,10 @@ retry:
        if (new_congested) {
                /* !found and storage for new one already allocated, insert */
                congested = new_congested;
-               new_congested = NULL;
                rb_link_node(&congested->rb_node, parent, node);
                rb_insert_color(&congested->rb_node, &bdi->cgwb_congested_tree);
-               goto found;
+               spin_unlock_irqrestore(&cgwb_lock, flags);
+               return congested;
        }
 
        spin_unlock_irqrestore(&cgwb_lock, flags);
@@ -451,13 +451,13 @@ retry:
        if (!new_congested)
                return NULL;
 
-       atomic_set(&new_congested->refcnt, 0);
+       refcount_set(&new_congested->refcnt, 1);
        new_congested->__bdi = bdi;
        new_congested->blkcg_id = blkcg_id;
        goto retry;
 
 found:
-       atomic_inc(&congested->refcnt);
+       refcount_inc(&congested->refcnt);
        spin_unlock_irqrestore(&cgwb_lock, flags);
        kfree(new_congested);
        return congested;
@@ -473,11 +473,8 @@ void wb_congested_put(struct bdi_writeback_congested *congested)
 {
        unsigned long flags;
 
-       local_irq_save(flags);
-       if (!atomic_dec_and_lock(&congested->refcnt, &cgwb_lock)) {
-               local_irq_restore(flags);
+       if (!refcount_dec_and_lock_irqsave(&congested->refcnt, &cgwb_lock, &flags))
                return;
-       }
 
        /* bdi might already have been destroyed leaving @congested unlinked */
        if (congested->__bdi) {
@@ -804,7 +801,7 @@ static int cgwb_bdi_init(struct backing_dev_info *bdi)
        if (!bdi->wb_congested)
                return -ENOMEM;
 
-       atomic_set(&bdi->wb_congested->refcnt, 1);
+       refcount_set(&bdi->wb_congested->refcnt, 1);
 
        err = wb_init(&bdi->wb, bdi, 1, GFP_KERNEL);
        if (err) {
index fc5f980..1abc8b4 100644 (file)
--- a/mm/gup.c
+++ b/mm/gup.c
@@ -497,7 +497,7 @@ static int faultin_page(struct task_struct *tsk, struct vm_area_struct *vma,
                unsigned long address, unsigned int *flags, int *nonblocking)
 {
        unsigned int fault_flags = 0;
-       int ret;
+       vm_fault_t ret;
 
        /* mlock all present pages, but do not fault in new pages */
        if ((*flags & (FOLL_POPULATE | FOLL_MLOCK)) == FOLL_MLOCK)
@@ -818,7 +818,7 @@ int fixup_user_fault(struct task_struct *tsk, struct mm_struct *mm,
                     bool *unlocked)
 {
        struct vm_area_struct *vma;
-       int ret, major = 0;
+       vm_fault_t ret, major = 0;
 
        if (unlocked)
                fault_flags |= FAULT_FLAG_ALLOW_RETRY;
index 76e7a05..c968e49 100644 (file)
--- a/mm/hmm.c
+++ b/mm/hmm.c
@@ -177,16 +177,19 @@ static void hmm_release(struct mmu_notifier *mn, struct mm_struct *mm)
        up_write(&hmm->mirrors_sem);
 }
 
-static void hmm_invalidate_range_start(struct mmu_notifier *mn,
+static int hmm_invalidate_range_start(struct mmu_notifier *mn,
                                       struct mm_struct *mm,
                                       unsigned long start,
-                                      unsigned long end)
+                                      unsigned long end,
+                                      bool blockable)
 {
        struct hmm *hmm = mm->hmm;
 
        VM_BUG_ON(!hmm);
 
        atomic_inc(&hmm->sequence);
+
+       return 0;
 }
 
 static void hmm_invalidate_range_end(struct mmu_notifier *mn,
@@ -965,6 +968,8 @@ static void hmm_devmem_free(struct page *page, void *data)
 {
        struct hmm_devmem *devmem = data;
 
+       page->mapping = NULL;
+
        devmem->ops->free(devmem, page);
 }
 
index 78427af..c3bc7e9 100644 (file)
@@ -541,14 +541,14 @@ unsigned long thp_get_unmapped_area(struct file *filp, unsigned long addr,
 }
 EXPORT_SYMBOL_GPL(thp_get_unmapped_area);
 
-static int __do_huge_pmd_anonymous_page(struct vm_fault *vmf, struct page *page,
-               gfp_t gfp)
+static vm_fault_t __do_huge_pmd_anonymous_page(struct vm_fault *vmf,
+                       struct page *page, gfp_t gfp)
 {
        struct vm_area_struct *vma = vmf->vma;
        struct mem_cgroup *memcg;
        pgtable_t pgtable;
        unsigned long haddr = vmf->address & HPAGE_PMD_MASK;
-       int ret = 0;
+       vm_fault_t ret = 0;
 
        VM_BUG_ON_PAGE(!PageCompound(page), page);
 
@@ -584,15 +584,15 @@ static int __do_huge_pmd_anonymous_page(struct vm_fault *vmf, struct page *page,
 
                /* Deliver the page fault to userland */
                if (userfaultfd_missing(vma)) {
-                       int ret;
+                       vm_fault_t ret2;
 
                        spin_unlock(vmf->ptl);
                        mem_cgroup_cancel_charge(page, memcg, true);
                        put_page(page);
                        pte_free(vma->vm_mm, pgtable);
-                       ret = handle_userfault(vmf, VM_UFFD_MISSING);
-                       VM_BUG_ON(ret & VM_FAULT_FALLBACK);
-                       return ret;
+                       ret2 = handle_userfault(vmf, VM_UFFD_MISSING);
+                       VM_BUG_ON(ret2 & VM_FAULT_FALLBACK);
+                       return ret2;
                }
 
                entry = mk_huge_pmd(page, vma->vm_page_prot);
@@ -663,7 +663,7 @@ static bool set_huge_zero_page(pgtable_t pgtable, struct mm_struct *mm,
        return true;
 }
 
-int do_huge_pmd_anonymous_page(struct vm_fault *vmf)
+vm_fault_t do_huge_pmd_anonymous_page(struct vm_fault *vmf)
 {
        struct vm_area_struct *vma = vmf->vma;
        gfp_t gfp;
@@ -682,7 +682,7 @@ int do_huge_pmd_anonymous_page(struct vm_fault *vmf)
                pgtable_t pgtable;
                struct page *zero_page;
                bool set;
-               int ret;
+               vm_fault_t ret;
                pgtable = pte_alloc_one(vma->vm_mm, haddr);
                if (unlikely(!pgtable))
                        return VM_FAULT_OOM;
@@ -752,7 +752,7 @@ static void insert_pfn_pmd(struct vm_area_struct *vma, unsigned long addr,
        spin_unlock(ptl);
 }
 
-int vmf_insert_pfn_pmd(struct vm_area_struct *vma, unsigned long addr,
+vm_fault_t vmf_insert_pfn_pmd(struct vm_area_struct *vma, unsigned long addr,
                        pmd_t *pmd, pfn_t pfn, bool write)
 {
        pgprot_t pgprot = vma->vm_page_prot;
@@ -812,7 +812,7 @@ static void insert_pfn_pud(struct vm_area_struct *vma, unsigned long addr,
        spin_unlock(ptl);
 }
 
-int vmf_insert_pfn_pud(struct vm_area_struct *vma, unsigned long addr,
+vm_fault_t vmf_insert_pfn_pud(struct vm_area_struct *vma, unsigned long addr,
                        pud_t *pud, pfn_t pfn, bool write)
 {
        pgprot_t pgprot = vma->vm_page_prot;
@@ -1118,15 +1118,16 @@ unlock:
        spin_unlock(vmf->ptl);
 }
 
-static int do_huge_pmd_wp_page_fallback(struct vm_fault *vmf, pmd_t orig_pmd,
-               struct page *page)
+static vm_fault_t do_huge_pmd_wp_page_fallback(struct vm_fault *vmf,
+                       pmd_t orig_pmd, struct page *page)
 {
        struct vm_area_struct *vma = vmf->vma;
        unsigned long haddr = vmf->address & HPAGE_PMD_MASK;
        struct mem_cgroup *memcg;
        pgtable_t pgtable;
        pmd_t _pmd;
-       int ret = 0, i;
+       int i;
+       vm_fault_t ret = 0;
        struct page **pages;
        unsigned long mmun_start;       /* For mmu_notifiers */
        unsigned long mmun_end;         /* For mmu_notifiers */
@@ -1236,7 +1237,7 @@ out_free_pages:
        goto out;
 }
 
-int do_huge_pmd_wp_page(struct vm_fault *vmf, pmd_t orig_pmd)
+vm_fault_t do_huge_pmd_wp_page(struct vm_fault *vmf, pmd_t orig_pmd)
 {
        struct vm_area_struct *vma = vmf->vma;
        struct page *page = NULL, *new_page;
@@ -1245,7 +1246,7 @@ int do_huge_pmd_wp_page(struct vm_fault *vmf, pmd_t orig_pmd)
        unsigned long mmun_start;       /* For mmu_notifiers */
        unsigned long mmun_end;         /* For mmu_notifiers */
        gfp_t huge_gfp;                 /* for allocation and charge */
-       int ret = 0;
+       vm_fault_t ret = 0;
 
        vmf->ptl = pmd_lockptr(vma->vm_mm, vmf->pmd);
        VM_BUG_ON_VMA(!vma->anon_vma, vma);
@@ -1457,7 +1458,7 @@ out:
 }
 
 /* NUMA hinting page fault entry point for trans huge pmds */
-int do_huge_pmd_numa_page(struct vm_fault *vmf, pmd_t pmd)
+vm_fault_t do_huge_pmd_numa_page(struct vm_fault *vmf, pmd_t pmd)
 {
        struct vm_area_struct *vma = vmf->vma;
        struct anon_vma *anon_vma = NULL;
index 47566bb..3c21775 100644 (file)
@@ -1479,22 +1479,20 @@ static int free_pool_huge_page(struct hstate *h, nodemask_t *nodes_allowed,
 /*
  * Dissolve a given free hugepage into free buddy pages. This function does
  * nothing for in-use (including surplus) hugepages. Returns -EBUSY if the
- * number of free hugepages would be reduced below the number of reserved
- * hugepages.
+ * dissolution fails because a give page is not a free hugepage, or because
+ * free hugepages are fully reserved.
  */
 int dissolve_free_huge_page(struct page *page)
 {
-       int rc = 0;
+       int rc = -EBUSY;
 
        spin_lock(&hugetlb_lock);
        if (PageHuge(page) && !page_count(page)) {
                struct page *head = compound_head(page);
                struct hstate *h = page_hstate(head);
                int nid = page_to_nid(head);
-               if (h->free_huge_pages - h->resv_huge_pages == 0) {
-                       rc = -EBUSY;
+               if (h->free_huge_pages - h->resv_huge_pages == 0)
                        goto out;
-               }
                /*
                 * Move PageHWPoison flag from head page to the raw error page,
                 * which makes any subpages rather than the error page reusable.
@@ -1508,6 +1506,7 @@ int dissolve_free_huge_page(struct page *page)
                h->free_huge_pages_node[nid]--;
                h->max_huge_pages--;
                update_and_free_page(h, head);
+               rc = 0;
        }
 out:
        spin_unlock(&hugetlb_lock);
@@ -3502,14 +3501,15 @@ static void unmap_ref_private(struct mm_struct *mm, struct vm_area_struct *vma,
  * cannot race with other handlers or page migration.
  * Keep the pte_same checks anyway to make transition from the mutex easier.
  */
-static int hugetlb_cow(struct mm_struct *mm, struct vm_area_struct *vma,
+static vm_fault_t hugetlb_cow(struct mm_struct *mm, struct vm_area_struct *vma,
                       unsigned long address, pte_t *ptep,
                       struct page *pagecache_page, spinlock_t *ptl)
 {
        pte_t pte;
        struct hstate *h = hstate_vma(vma);
        struct page *old_page, *new_page;
-       int ret = 0, outside_reserve = 0;
+       int outside_reserve = 0;
+       vm_fault_t ret = 0;
        unsigned long mmun_start;       /* For mmu_notifiers */
        unsigned long mmun_end;         /* For mmu_notifiers */
        unsigned long haddr = address & huge_page_mask(h);
@@ -3573,8 +3573,7 @@ retry_avoidcopy:
                        return 0;
                }
 
-               ret = (PTR_ERR(new_page) == -ENOMEM) ?
-                       VM_FAULT_OOM : VM_FAULT_SIGBUS;
+               ret = vmf_error(PTR_ERR(new_page));
                goto out_release_old;
        }
 
@@ -3677,12 +3676,13 @@ int huge_add_to_page_cache(struct page *page, struct address_space *mapping,
        return 0;
 }
 
-static int hugetlb_no_page(struct mm_struct *mm, struct vm_area_struct *vma,
-                          struct address_space *mapping, pgoff_t idx,
-                          unsigned long address, pte_t *ptep, unsigned int flags)
+static vm_fault_t hugetlb_no_page(struct mm_struct *mm,
+                       struct vm_area_struct *vma,
+                       struct address_space *mapping, pgoff_t idx,
+                       unsigned long address, pte_t *ptep, unsigned int flags)
 {
        struct hstate *h = hstate_vma(vma);
-       int ret = VM_FAULT_SIGBUS;
+       vm_fault_t ret = VM_FAULT_SIGBUS;
        int anon_rmap = 0;
        unsigned long size;
        struct page *page;
@@ -3745,11 +3745,7 @@ retry:
 
                page = alloc_huge_page(vma, haddr, 0);
                if (IS_ERR(page)) {
-                       ret = PTR_ERR(page);
-                       if (ret == -ENOMEM)
-                               ret = VM_FAULT_OOM;
-                       else
-                               ret = VM_FAULT_SIGBUS;
+                       ret = vmf_error(PTR_ERR(page));
                        goto out;
                }
                clear_huge_page(page, address, pages_per_huge_page(h));
@@ -3873,12 +3869,12 @@ u32 hugetlb_fault_mutex_hash(struct hstate *h, struct mm_struct *mm,
 }
 #endif
 
-int hugetlb_fault(struct mm_struct *mm, struct vm_area_struct *vma,
+vm_fault_t hugetlb_fault(struct mm_struct *mm, struct vm_area_struct *vma,
                        unsigned long address, unsigned int flags)
 {
        pte_t *ptep, entry;
        spinlock_t *ptl;
-       int ret;
+       vm_fault_t ret;
        u32 hash;
        pgoff_t idx;
        struct page *page = NULL;
@@ -4208,7 +4204,7 @@ long follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma,
                if (absent || is_swap_pte(huge_ptep_get(pte)) ||
                    ((flags & FOLL_WRITE) &&
                      !huge_pte_write(huge_ptep_get(pte)))) {
-                       int ret;
+                       vm_fault_t ret;
                        unsigned int fault_flags = 0;
 
                        if (pte)
index 9e3654d..87256ae 100644 (file)
@@ -38,7 +38,7 @@
 
 void page_writeback_init(void);
 
-int do_swap_page(struct vm_fault *vmf);
+vm_fault_t do_swap_page(struct vm_fault *vmf);
 
 void free_pgtables(struct mmu_gather *tlb, struct vm_area_struct *start_vma,
                unsigned long floor, unsigned long ceiling);
@@ -389,18 +389,6 @@ static inline struct page *mem_map_next(struct page *iter,
        return iter + 1;
 }
 
-/*
- * FLATMEM and DISCONTIGMEM configurations use alloc_bootmem_node,
- * so all functions starting at paging_init should be marked __init
- * in those cases. SPARSEMEM, however, allows for memory hotplug,
- * and alloc_bootmem_node is not used.
- */
-#ifdef CONFIG_SPARSEMEM
-#define __paginginit __meminit
-#else
-#define __paginginit __init
-#endif
-
 /* Memory initialisation debug and verification */
 enum mminit_level {
        MMINIT_WARNING,
index 961cbe9..a31d740 100644 (file)
@@ -880,7 +880,8 @@ static bool __collapse_huge_page_swapin(struct mm_struct *mm,
                                        unsigned long address, pmd_t *pmd,
                                        int referenced)
 {
-       int swapped_in = 0, ret = 0;
+       int swapped_in = 0;
+       vm_fault_t ret = 0;
        struct vm_fault vmf = {
                .vma = vma,
                .address = address,
index 2621be5..5b0894b 100644 (file)
--- a/mm/ksm.c
+++ b/mm/ksm.c
@@ -652,9 +652,9 @@ static void remove_node_from_stable_tree(struct stable_node *stable_node)
         * list_head to stay clear from the rb_parent_color union
         * (aligned and different than any node) and also different
         * from &migrate_nodes. This will verify that future list.h changes
-        * don't break STABLE_NODE_DUP_HEAD.
+        * don't break STABLE_NODE_DUP_HEAD. Only recent gcc can handle it.
         */
-#if GCC_VERSION >= 40903 /* only recent gcc can handle it */
+#if defined(GCC_VERSION) && GCC_VERSION >= 40903
        BUILD_BUG_ON(STABLE_NODE_DUP_HEAD <= &migrate_nodes);
        BUILD_BUG_ON(STABLE_NODE_DUP_HEAD >= &migrate_nodes + 1);
 #endif
@@ -703,7 +703,7 @@ again:
         * We cannot do anything with the page while its refcount is 0.
         * Usually 0 means free, or tail of a higher-order page: in which
         * case this node is no longer referenced, and should be freed;
-        * however, it might mean that the page is under page_freeze_refs().
+        * however, it might mean that the page is under page_ref_freeze().
         * The __remove_mapping() case is easy, again the node is now stale;
         * but if page is swapcache in migrate_page_move_mapping(), it might
         * still be our page, in which case it's essential to keep the node.
@@ -714,7 +714,7 @@ again:
                 * work here too.  We have chosen the !PageSwapCache test to
                 * optimize the common case, when the page is or is about to
                 * be freed: PageSwapCache is cleared (under spin_lock_irq)
-                * in the freeze_refs section of __remove_mapping(); but Anon
+                * in the ref_freeze section of __remove_mapping(); but Anon
                 * page->mapping reset to NULL later, in free_pages_prepare().
                 */
                if (!PageSwapCache(page))
index 4d3c922..972a9ea 100644 (file)
@@ -631,11 +631,13 @@ static int madvise_inject_error(int behavior,
 
 
        for (; start < end; start += PAGE_SIZE << order) {
+               unsigned long pfn;
                int ret;
 
                ret = get_user_pages_fast(start, 1, 0, &page);
                if (ret != 1)
                        return ret;
+               pfn = page_to_pfn(page);
 
                /*
                 * When soft offlining hugepages, after migrating the page
@@ -651,17 +653,25 @@ static int madvise_inject_error(int behavior,
 
                if (behavior == MADV_SOFT_OFFLINE) {
                        pr_info("Soft offlining pfn %#lx at process virtual address %#lx\n",
-                                               page_to_pfn(page), start);
+                                       pfn, start);
 
                        ret = soft_offline_page(page, MF_COUNT_INCREASED);
                        if (ret)
                                return ret;
                        continue;
                }
+
                pr_info("Injecting memory failure for pfn %#lx at process virtual address %#lx\n",
-                                               page_to_pfn(page), start);
+                               pfn, start);
 
-               ret = memory_failure(page_to_pfn(page), MF_COUNT_INCREASED);
+               /*
+                * Drop the page reference taken by get_user_pages_fast(). In
+                * the absence of MF_COUNT_INCREASED the memory_failure()
+                * routine is responsible for pinning the page to prevent it
+                * from being released back to the page allocator.
+                */
+               put_page(page);
+               ret = memory_failure(pfn, 0);
                if (ret)
                        return ret;
        }
index 6a92189..4ead5a4 100644 (file)
@@ -1777,6 +1777,62 @@ cleanup:
 }
 
 /**
+ * mem_cgroup_get_oom_group - get a memory cgroup to clean up after OOM
+ * @victim: task to be killed by the OOM killer
+ * @oom_domain: memcg in case of memcg OOM, NULL in case of system-wide OOM
+ *
+ * Returns a pointer to a memory cgroup, which has to be cleaned up
+ * by killing all belonging OOM-killable tasks.
+ *
+ * Caller has to call mem_cgroup_put() on the returned non-NULL memcg.
+ */
+struct mem_cgroup *mem_cgroup_get_oom_group(struct task_struct *victim,
+                                           struct mem_cgroup *oom_domain)
+{
+       struct mem_cgroup *oom_group = NULL;
+       struct mem_cgroup *memcg;
+
+       if (!cgroup_subsys_on_dfl(memory_cgrp_subsys))
+               return NULL;
+
+       if (!oom_domain)
+               oom_domain = root_mem_cgroup;
+
+       rcu_read_lock();
+
+       memcg = mem_cgroup_from_task(victim);
+       if (memcg == root_mem_cgroup)
+               goto out;
+
+       /*
+        * Traverse the memory cgroup hierarchy from the victim task's
+        * cgroup up to the OOMing cgroup (or root) to find the
+        * highest-level memory cgroup with oom.group set.
+        */
+       for (; memcg; memcg = parent_mem_cgroup(memcg)) {
+               if (memcg->oom_group)
+                       oom_group = memcg;
+
+               if (memcg == oom_domain)
+                       break;
+       }
+
+       if (oom_group)
+               css_get(&oom_group->css);
+out:
+       rcu_read_unlock();
+
+       return oom_group;
+}
+
+void mem_cgroup_print_oom_group(struct mem_cgroup *memcg)
+{
+       pr_info("Tasks in ");
+       pr_cont_cgroup_path(memcg->css.cgroup);
+       pr_cont(" are going to be killed due to memory.oom.group set\n");
+}
+
+/**
  * lock_page_memcg - lock a page->mem_cgroup binding
  * @page: the page
  *
@@ -2899,29 +2955,34 @@ static int mem_cgroup_hierarchy_write(struct cgroup_subsys_state *css,
        return retval;
 }
 
-static void tree_stat(struct mem_cgroup *memcg, unsigned long *stat)
-{
-       struct mem_cgroup *iter;
-       int i;
-
-       memset(stat, 0, sizeof(*stat) * MEMCG_NR_STAT);
-
-       for_each_mem_cgroup_tree(iter, memcg) {
-               for (i = 0; i < MEMCG_NR_STAT; i++)
-                       stat[i] += memcg_page_state(iter, i);
-       }
-}
+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 tree_events(struct mem_cgroup *memcg, unsigned long *events)
+static void accumulate_memcg_tree(struct mem_cgroup *memcg,
+                                 struct accumulated_stats *acc)
 {
-       struct mem_cgroup *iter;
+       struct mem_cgroup *mi;
        int i;
 
-       memset(events, 0, sizeof(*events) * NR_VM_EVENT_ITEMS);
+       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_each_mem_cgroup_tree(iter, memcg) {
-               for (i = 0; i < NR_VM_EVENT_ITEMS; i++)
-                       events[i] += memcg_sum_events(iter, 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));
        }
 }
 
@@ -3332,6 +3393,7 @@ 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);
@@ -3364,32 +3426,27 @@ static int memcg_stat_show(struct seq_file *m, void *v)
                seq_printf(m, "hierarchical_memsw_limit %llu\n",
                           (u64)memsw * PAGE_SIZE);
 
-       for (i = 0; i < ARRAY_SIZE(memcg1_stats); i++) {
-               unsigned long long val = 0;
+       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;
-               for_each_mem_cgroup_tree(mi, memcg)
-                       val += memcg_page_state(mi, memcg1_stats[i]) *
-                       PAGE_SIZE;
-               seq_printf(m, "total_%s %llu\n", memcg1_stat_names[i], val);
+               seq_printf(m, "total_%s %llu\n", memcg1_stat_names[i],
+                          (u64)acc.stat[i] * PAGE_SIZE);
        }
 
-       for (i = 0; i < ARRAY_SIZE(memcg1_events); i++) {
-               unsigned long long val = 0;
-
-               for_each_mem_cgroup_tree(mi, memcg)
-                       val += memcg_sum_events(mi, memcg1_events[i]);
-               seq_printf(m, "total_%s %llu\n", memcg1_event_names[i], val);
-       }
-
-       for (i = 0; i < NR_LRU_LISTS; i++) {
-               unsigned long long val = 0;
+       for (i = 0; i < ARRAY_SIZE(memcg1_events); i++)
+               seq_printf(m, "total_%s %llu\n", memcg1_event_names[i],
+                          (u64)acc.events[i]);
 
-               for_each_mem_cgroup_tree(mi, memcg)
-                       val += mem_cgroup_nr_lru_pages(mi, BIT(i)) * PAGE_SIZE;
-               seq_printf(m, "total_%s %llu\n", mem_cgroup_lru_names[i], val);
-       }
+       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);
 
 #ifdef CONFIG_DEBUG_VM
        {
@@ -5486,8 +5543,7 @@ 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_css(seq_css(m));
-       unsigned long stat[MEMCG_NR_STAT];
-       unsigned long events[NR_VM_EVENT_ITEMS];
+       struct accumulated_stats acc;
        int i;
 
        /*
@@ -5501,70 +5557,97 @@ static int memory_stat_show(struct seq_file *m, void *v)
         * Current memory state:
         */
 
-       tree_stat(memcg, stat);
-       tree_events(memcg, events);
+       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)stat[MEMCG_RSS] * PAGE_SIZE);
+                  (u64)acc.stat[MEMCG_RSS] * PAGE_SIZE);
        seq_printf(m, "file %llu\n",
-                  (u64)stat[MEMCG_CACHE] * PAGE_SIZE);
+                  (u64)acc.stat[MEMCG_CACHE] * PAGE_SIZE);
        seq_printf(m, "kernel_stack %llu\n",
-                  (u64)stat[MEMCG_KERNEL_STACK_KB] * 1024);
+                  (u64)acc.stat[MEMCG_KERNEL_STACK_KB] * 1024);
        seq_printf(m, "slab %llu\n",
-                  (u64)(stat[NR_SLAB_RECLAIMABLE] +
-                        stat[NR_SLAB_UNRECLAIMABLE]) * PAGE_SIZE);
+                  (u64)(acc.stat[NR_SLAB_RECLAIMABLE] +
+                        acc.stat[NR_SLAB_UNRECLAIMABLE]) * PAGE_SIZE);
        seq_printf(m, "sock %llu\n",
-                  (u64)stat[MEMCG_SOCK] * PAGE_SIZE);
+                  (u64)acc.stat[MEMCG_SOCK] * PAGE_SIZE);
 
        seq_printf(m, "shmem %llu\n",
-                  (u64)stat[NR_SHMEM] * PAGE_SIZE);
+                  (u64)acc.stat[NR_SHMEM] * PAGE_SIZE);
        seq_printf(m, "file_mapped %llu\n",
-                  (u64)stat[NR_FILE_MAPPED] * PAGE_SIZE);
+                  (u64)acc.stat[NR_FILE_MAPPED] * PAGE_SIZE);
        seq_printf(m, "file_dirty %llu\n",
-                  (u64)stat[NR_FILE_DIRTY] * PAGE_SIZE);
+                  (u64)acc.stat[NR_FILE_DIRTY] * PAGE_SIZE);
        seq_printf(m, "file_writeback %llu\n",
-                  (u64)stat[NR_WRITEBACK] * PAGE_SIZE);
-
-       for (i = 0; i < NR_LRU_LISTS; i++) {
-               struct mem_cgroup *mi;
-               unsigned long val = 0;
+                  (u64)acc.stat[NR_WRITEBACK] * PAGE_SIZE);
 
-               for_each_mem_cgroup_tree(mi, memcg)
-                       val += mem_cgroup_nr_lru_pages(mi, BIT(i));
-               seq_printf(m, "%s %llu\n",
-                          mem_cgroup_lru_names[i], (u64)val * 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);
 
        seq_printf(m, "slab_reclaimable %llu\n",
-                  (u64)stat[NR_SLAB_RECLAIMABLE] * PAGE_SIZE);
+                  (u64)acc.stat[NR_SLAB_RECLAIMABLE] * PAGE_SIZE);
        seq_printf(m, "slab_unreclaimable %llu\n",
-                  (u64)stat[NR_SLAB_UNRECLAIMABLE] * PAGE_SIZE);
+                  (u64)acc.stat[NR_SLAB_UNRECLAIMABLE] * PAGE_SIZE);
 
        /* Accumulated memory events */
 
-       seq_printf(m, "pgfault %lu\n", events[PGFAULT]);
-       seq_printf(m, "pgmajfault %lu\n", events[PGMAJFAULT]);
+       seq_printf(m, "pgfault %lu\n", acc.events[PGFAULT]);
+       seq_printf(m, "pgmajfault %lu\n", acc.events[PGMAJFAULT]);
 
-       seq_printf(m, "pgrefill %lu\n", events[PGREFILL]);
-       seq_printf(m, "pgscan %lu\n", events[PGSCAN_KSWAPD] +
-                  events[PGSCAN_DIRECT]);
-       seq_printf(m, "pgsteal %lu\n", events[PGSTEAL_KSWAPD] +
-                  events[PGSTEAL_DIRECT]);
-       seq_printf(m, "pgactivate %lu\n", events[PGACTIVATE]);
-       seq_printf(m, "pgdeactivate %lu\n", events[PGDEACTIVATE]);
-       seq_printf(m, "pglazyfree %lu\n", events[PGLAZYFREE]);
-       seq_printf(m, "pglazyfreed %lu\n", events[PGLAZYFREED]);
+       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]);
 
        seq_printf(m, "workingset_refault %lu\n",
-                  stat[WORKINGSET_REFAULT]);
+                  acc.stat[WORKINGSET_REFAULT]);
        seq_printf(m, "workingset_activate %lu\n",
-                  stat[WORKINGSET_ACTIVATE]);
+                  acc.stat[WORKINGSET_ACTIVATE]);
        seq_printf(m, "workingset_nodereclaim %lu\n",
-                  stat[WORKINGSET_NODERECLAIM]);
+                  acc.stat[WORKINGSET_NODERECLAIM]);
+
+       return 0;
+}
+
+static int memory_oom_group_show(struct seq_file *m, void *v)
+{
+       struct mem_cgroup *memcg = mem_cgroup_from_css(seq_css(m));
+
+       seq_printf(m, "%d\n", memcg->oom_group);
 
        return 0;
 }
 
+static ssize_t memory_oom_group_write(struct kernfs_open_file *of,
+                                     char *buf, size_t nbytes, loff_t off)
+{
+       struct mem_cgroup *memcg = mem_cgroup_from_css(of_css(of));
+       int ret, oom_group;
+
+       buf = strstrip(buf);
+       if (!buf)
+               return -EINVAL;
+
+       ret = kstrtoint(buf, 0, &oom_group);
+       if (ret)
+               return ret;
+
+       if (oom_group != 0 && oom_group != 1)
+               return -EINVAL;
+
+       memcg->oom_group = oom_group;
+
+       return nbytes;
+}
+
 static struct cftype memory_files[] = {
        {
                .name = "current",
@@ -5606,6 +5689,12 @@ static struct cftype memory_files[] = {
                .flags = CFTYPE_NOT_ON_ROOT,
                .seq_show = memory_stat_show,
        },
+       {
+               .name = "oom.group",
+               .flags = CFTYPE_NOT_ON_ROOT | CFTYPE_NS_DELEGATABLE,
+               .seq_show = memory_oom_group_show,
+               .write = memory_oom_group_write,
+       },
        { }     /* terminate */
 };
 
index 9d142b9..0cd3de3 100644 (file)
 #include <linux/hugetlb.h>
 #include <linux/memory_hotplug.h>
 #include <linux/mm_inline.h>
+#include <linux/memremap.h>
 #include <linux/kfifo.h>
 #include <linux/ratelimit.h>
+#include <linux/page-isolation.h>
 #include "internal.h"
 #include "ras/ras_event.h"
 
@@ -174,22 +176,51 @@ int hwpoison_filter(struct page *p)
 EXPORT_SYMBOL_GPL(hwpoison_filter);
 
 /*
+ * Kill all processes that have a poisoned page mapped and then isolate
+ * the page.
+ *
+ * General strategy:
+ * Find all processes having the page mapped and kill them.
+ * But we keep a page reference around so that the page is not
+ * actually freed yet.
+ * Then stash the page away
+ *
+ * There's no convenient way to get back to mapped processes
+ * from the VMAs. So do a brute-force search over all
+ * running processes.
+ *
+ * Remember that machine checks are not common (or rather
+ * if they are common you have other problems), so this shouldn't
+ * be a performance issue.
+ *
+ * Also there are some races possible while we get from the
+ * error detection to actually handle it.
+ */
+
+struct to_kill {
+       struct list_head nd;
+       struct task_struct *tsk;
+       unsigned long addr;
+       short size_shift;
+       char addr_valid;
+};
+
+/*
  * Send all the processes who have the page mapped a signal.
  * ``action optional'' if they are not immediately affected by the error
  * ``action required'' if error happened in current execution context
  */
-static int kill_proc(struct task_struct *t, unsigned long addr,
-                       unsigned long pfn, struct page *page, int flags)
+static int kill_proc(struct to_kill *tk, unsigned long pfn, int flags)
 {
-       short addr_lsb;
+       struct task_struct *t = tk->tsk;
+       short addr_lsb = tk->size_shift;
        int ret;
 
        pr_err("Memory failure: %#lx: Killing %s:%d due to hardware memory corruption\n",
                pfn, t->comm, t->pid);
-       addr_lsb = compound_order(compound_head(page)) + PAGE_SHIFT;
 
        if ((flags & MF_ACTION_REQUIRED) && t->mm == current->mm) {
-               ret = force_sig_mceerr(BUS_MCEERR_AR, (void __user *)addr,
+               ret = force_sig_mceerr(BUS_MCEERR_AR, (void __user *)tk->addr,
                                       addr_lsb, current);
        } else {
                /*
@@ -198,7 +229,7 @@ static int kill_proc(struct task_struct *t, unsigned long addr,
                 * This could cause a loop when the user sets SIGBUS
                 * to SIG_IGN, but hopefully no one will do that?
                 */
-               ret = send_sig_mceerr(BUS_MCEERR_AO, (void __user *)addr,
+               ret = send_sig_mceerr(BUS_MCEERR_AO, (void __user *)tk->addr,
                                      addr_lsb, t);  /* synchronous? */
        }
        if (ret < 0)
@@ -234,34 +265,39 @@ void shake_page(struct page *p, int access)
 }
 EXPORT_SYMBOL_GPL(shake_page);
 
-/*
- * Kill all processes that have a poisoned page mapped and then isolate
- * the page.
- *
- * General strategy:
- * Find all processes having the page mapped and kill them.
- * But we keep a page reference around so that the page is not
- * actually freed yet.
- * Then stash the page away
- *
- * There's no convenient way to get back to mapped processes
- * from the VMAs. So do a brute-force search over all
- * running processes.
- *
- * Remember that machine checks are not common (or rather
- * if they are common you have other problems), so this shouldn't
- * be a performance issue.
- *
- * Also there are some races possible while we get from the
- * error detection to actually handle it.
- */
-
-struct to_kill {
-       struct list_head nd;
-       struct task_struct *tsk;
-       unsigned long addr;
-       char addr_valid;
-};
+static unsigned long dev_pagemap_mapping_shift(struct page *page,
+               struct vm_area_struct *vma)
+{
+       unsigned long address = vma_address(page, vma);
+       pgd_t *pgd;
+       p4d_t *p4d;
+       pud_t *pud;
+       pmd_t *pmd;
+       pte_t *pte;
+
+       pgd = pgd_offset(vma->vm_mm, address);
+       if (!pgd_present(*pgd))
+               return 0;
+       p4d = p4d_offset(pgd, address);
+       if (!p4d_present(*p4d))
+               return 0;
+       pud = pud_offset(p4d, address);
+       if (!pud_present(*pud))
+               return 0;
+       if (pud_devmap(*pud))
+               return PUD_SHIFT;
+       pmd = pmd_offset(pud, address);
+       if (!pmd_present(*pmd))
+               return 0;
+       if (pmd_devmap(*pmd))
+               return PMD_SHIFT;
+       pte = pte_offset_map(pmd, address);
+       if (!pte_present(*pte))
+               return 0;
+       if (pte_devmap(*pte))
+               return PAGE_SHIFT;
+       return 0;
+}
 
 /*
  * Failure handling: if we can't find or can't kill a process there's
@@ -292,6 +328,10 @@ static void add_to_kill(struct task_struct *tsk, struct page *p,
        }
        tk->addr = page_address_in_vma(p, vma);
        tk->addr_valid = 1;
+       if (is_zone_device_page(p))
+               tk->size_shift = dev_pagemap_mapping_shift(p, vma);
+       else
+               tk->size_shift = compound_order(compound_head(p)) + PAGE_SHIFT;
 
        /*
         * In theory we don't have to kill when the page was
@@ -299,7 +339,7 @@ static void add_to_kill(struct task_struct *tsk, struct page *p,
         * likely very rare kill anyways just out of paranoia, but use
         * a SIGKILL because the error is not contained anymore.
         */
-       if (tk->addr == -EFAULT) {
+       if (tk->addr == -EFAULT || tk->size_shift == 0) {
                pr_info("Memory failure: Unable to find user space address %lx in %s\n",
                        page_to_pfn(p), tsk->comm);
                tk->addr_valid = 0;
@@ -317,9 +357,8 @@ static void add_to_kill(struct task_struct *tsk, struct page *p,
  * Also when FAIL is set do a force kill because something went
  * wrong earlier.
  */
-static void kill_procs(struct list_head *to_kill, int forcekill,
-                         bool fail, struct page *page, unsigned long pfn,
-                         int flags)
+static void kill_procs(struct list_head *to_kill, int forcekill, bool fail,
+               unsigned long pfn, int flags)
 {
        struct to_kill *tk, *next;
 
@@ -342,8 +381,7 @@ static void kill_procs(struct list_head *to_kill, int forcekill,
                         * check for that, but we need to tell the
                         * process anyways.
                         */
-                       else if (kill_proc(tk->tsk, tk->addr,
-                                             pfn, page, flags) < 0)
+                       else if (kill_proc(tk, pfn, flags) < 0)
                                pr_err("Memory failure: %#lx: Cannot send advisory machine check signal to %s:%d\n",
                                       pfn, tk->tsk->comm, tk->tsk->pid);
                }
@@ -515,6 +553,7 @@ static const char * const action_page_types[] = {
        [MF_MSG_TRUNCATED_LRU]          = "already truncated LRU page",
        [MF_MSG_BUDDY]                  = "free buddy page",
        [MF_MSG_BUDDY_2ND]              = "free buddy page (2nd try)",
+       [MF_MSG_DAX]                    = "dax page",
        [MF_MSG_UNKNOWN]                = "unknown page",
 };
 
@@ -1012,7 +1051,7 @@ static bool hwpoison_user_mappings(struct page *p, unsigned long pfn,
         * any accesses to the poisoned memory.
         */
        forcekill = PageDirty(hpage) || (flags & MF_MUST_KILL);
-       kill_procs(&tokill, forcekill, !unmap_success, p, pfn, flags);
+       kill_procs(&tokill, forcekill, !unmap_success, pfn, flags);
 
        return unmap_success;
 }
@@ -1112,6 +1151,83 @@ out:
        return res;
 }
 
+static int memory_failure_dev_pagemap(unsigned long pfn, int flags,
+               struct dev_pagemap *pgmap)
+{
+       struct page *page = pfn_to_page(pfn);
+       const bool unmap_success = true;
+       unsigned long size = 0;
+       struct to_kill *tk;
+       LIST_HEAD(tokill);
+       int rc = -EBUSY;
+       loff_t start;
+
+       /*
+        * Prevent the inode from being freed while we are interrogating
+        * the address_space, typically this would be handled by
+        * lock_page(), but dax pages do not use the page lock. This
+        * also prevents changes to the mapping of this pfn until
+        * poison signaling is complete.
+        */
+       if (!dax_lock_mapping_entry(page))
+               goto out;
+
+       if (hwpoison_filter(page)) {
+               rc = 0;
+               goto unlock;
+       }
+
+       switch (pgmap->type) {
+       case MEMORY_DEVICE_PRIVATE:
+       case MEMORY_DEVICE_PUBLIC:
+               /*
+                * TODO: Handle HMM pages which may need coordination
+                * with device-side memory.
+                */
+               goto unlock;
+       default:
+               break;
+       }
+
+       /*
+        * Use this flag as an indication that the dax page has been
+        * remapped UC to prevent speculative consumption of poison.
+        */
+       SetPageHWPoison(page);
+
+       /*
+        * Unlike System-RAM there is no possibility to swap in a
+        * different physical page at a given virtual address, so all
+        * userspace consumption of ZONE_DEVICE memory necessitates
+        * SIGBUS (i.e. MF_MUST_KILL)
+        */
+       flags |= MF_ACTION_REQUIRED | MF_MUST_KILL;
+       collect_procs(page, &tokill, flags & MF_ACTION_REQUIRED);
+
+       list_for_each_entry(tk, &tokill, nd)
+               if (tk->size_shift)
+                       size = max(size, 1UL << tk->size_shift);
+       if (size) {
+               /*
+                * Unmap the largest mapping to avoid breaking up
+                * device-dax mappings which are constant size. The
+                * actual size of the mapping being torn down is
+                * communicated in siginfo, see kill_proc()
+                */
+               start = (page->index << PAGE_SHIFT) & ~(size - 1);
+               unmap_mapping_range(page->mapping, start, start + size, 0);
+       }
+       kill_procs(&tokill, flags & MF_MUST_KILL, !unmap_success, pfn, flags);
+       rc = 0;
+unlock:
+       dax_unlock_mapping_entry(page);
+out:
+       /* drop pgmap ref acquired in caller */
+       put_dev_pagemap(pgmap);
+       action_result(pfn, MF_MSG_DAX, rc ? MF_FAILED : MF_RECOVERED);
+       return rc;
+}
+
 /**
  * memory_failure - Handle memory failure of a page.
  * @pfn: Page Number of the corrupted page
@@ -1134,6 +1250,7 @@ int memory_failure(unsigned long pfn, int flags)
        struct page *p;
        struct page *hpage;
        struct page *orig_head;
+       struct dev_pagemap *pgmap;
        int res;
        unsigned long page_flags;
 
@@ -1146,6 +1263,10 @@ int memory_failure(unsigned long pfn, int flags)
                return -ENXIO;
        }
 
+       pgmap = get_dev_pagemap(pfn, NULL);
+       if (pgmap)
+               return memory_failure_dev_pagemap(pfn, flags, pgmap);
+
        p = pfn_to_page(pfn);
        if (PageHuge(p))
                return memory_failure_hugetlb(pfn, flags);
@@ -1167,7 +1288,7 @@ int memory_failure(unsigned long pfn, int flags)
         *    R/W the page; let's pray that the page has been
         *    used and will be freed some time later.
         * In fact it's dangerous to directly bump up page count from 0,
-        * that may make page_freeze_refs()/page_unfreeze_refs() mismatch.
+        * that may make page_ref_freeze()/page_ref_unfreeze() mismatch.
         */
        if (!(flags & MF_COUNT_INCREASED) && !get_hwpoison_page(p)) {
                if (is_free_buddy_page(p)) {
@@ -1598,8 +1719,18 @@ static int soft_offline_huge_page(struct page *page, int flags)
                if (ret > 0)
                        ret = -EIO;
        } else {
-               if (PageHuge(page))
-                       dissolve_free_huge_page(page);
+               /*
+                * We set PG_hwpoison only when the migration source hugepage
+                * was successfully dissolved, because otherwise hwpoisoned
+                * hugepage remains on free hugepage list, then userspace will
+                * find it as SIGBUS by allocation failure. That's not expected
+                * in soft-offlining.
+                */
+               ret = dissolve_free_huge_page(page);
+               if (!ret) {
+                       if (set_hwpoison_free_buddy_page(page))
+                               num_poisoned_pages_inc();
+               }
        }
        return ret;
 }
@@ -1687,6 +1818,7 @@ static int __soft_offline_page(struct page *page, int flags)
 static int soft_offline_in_use_page(struct page *page, int flags)
 {
        int ret;
+       int mt;
        struct page *hpage = compound_head(page);
 
        if (!PageHuge(page) && PageTransHuge(hpage)) {
@@ -1705,23 +1837,37 @@ static int soft_offline_in_use_page(struct page *page, int flags)
                put_hwpoison_page(hpage);
        }
 
+       /*
+        * Setting MIGRATE_ISOLATE here ensures that the page will be linked
+        * to free list immediately (not via pcplist) when released after
+        * successful page migration. Otherwise we can't guarantee that the
+        * page is really free after put_page() returns, so
+        * set_hwpoison_free_buddy_page() highly likely fails.
+        */
+       mt = get_pageblock_migratetype(page);
+       set_pageblock_migratetype(page, MIGRATE_ISOLATE);
        if (PageHuge(page))
                ret = soft_offline_huge_page(page, flags);
        else
                ret = __soft_offline_page(page, flags);
-
+       set_pageblock_migratetype(page, mt);
        return ret;
 }
 
-static void soft_offline_free_page(struct page *page)
+static int soft_offline_free_page(struct page *page)
 {
+       int rc = 0;
        struct page *head = compound_head(page);
 
-       if (!TestSetPageHWPoison(head)) {
-               num_poisoned_pages_inc();
-               if (PageHuge(head))
-                       dissolve_free_huge_page(page);
+       if (PageHuge(head))
+               rc = dissolve_free_huge_page(page);
+       if (!rc) {
+               if (set_hwpoison_free_buddy_page(page))
+                       num_poisoned_pages_inc();
+               else
+                       rc = -EBUSY;
        }
+       return rc;
 }
 
 /**
@@ -1751,6 +1897,14 @@ int soft_offline_page(struct page *page, int flags)
        int ret;
        unsigned long pfn = page_to_pfn(page);
 
+       if (is_zone_device_page(page)) {
+               pr_debug_ratelimited("soft_offline: %#lx page is device page\n",
+                               pfn);
+               if (flags & MF_COUNT_INCREASED)
+                       put_page(page);
+               return -EIO;
+       }
+
        if (PageHWPoison(page)) {
                pr_info("soft offline: %#lx page already poisoned\n", pfn);
                if (flags & MF_COUNT_INCREASED)
@@ -1765,7 +1919,7 @@ int soft_offline_page(struct page *page, int flags)
        if (ret > 0)
                ret = soft_offline_in_use_page(page, flags);
        else if (ret == 0)
-               soft_offline_free_page(page);
+               ret = soft_offline_free_page(page);
 
        return ret;
 }
index 19f47d7..c467102 100644 (file)
@@ -238,23 +238,13 @@ void arch_tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm,
        __tlb_reset_range(tlb);
 }
 
-static void tlb_flush_mmu_tlbonly(struct mmu_gather *tlb)
+static void tlb_flush_mmu_free(struct mmu_gather *tlb)
 {
-       if (!tlb->end)
-               return;
+       struct mmu_gather_batch *batch;
 
-       tlb_flush(tlb);
-       mmu_notifier_invalidate_range(tlb->mm, tlb->start, tlb->end);
 #ifdef CONFIG_HAVE_RCU_TABLE_FREE
        tlb_table_flush(tlb);
 #endif
-       __tlb_reset_range(tlb);
-}
-
-static void tlb_flush_mmu_free(struct mmu_gather *tlb)
-{
-       struct mmu_gather_batch *batch;
-
        for (batch = &tlb->local; batch && batch->nr; batch = batch->next) {
                free_pages_and_swap_cache(batch->pages, batch->nr);
                batch->nr = 0;
@@ -326,20 +316,31 @@ bool __tlb_remove_page_size(struct mmu_gather *tlb, struct page *page, int page_
 
 #ifdef CONFIG_HAVE_RCU_TABLE_FREE
 
-static void tlb_remove_table_smp_sync(void *arg)
+/*
+ * See the comment near struct mmu_table_batch.
+ */
+
+/*
+ * If we want tlb_remove_table() to imply TLB invalidates.
+ */
+static inline void tlb_table_invalidate(struct mmu_gather *tlb)
 {
-       struct mm_struct __maybe_unused *mm = arg;
+#ifdef CONFIG_HAVE_RCU_TABLE_INVALIDATE
        /*
-        * On most architectures this does nothing. Simply delivering the
-        * interrupt is enough to prevent races with software page table
-        * walking like that done in get_user_pages_fast.
-        *
-        * See the comment near struct mmu_table_batch.
+        * Invalidate page-table caches used by hardware walkers. Then we still
+        * need to RCU-sched wait while freeing the pages because software
+        * walkers can still be in-flight.
         */
-       tlb_flush_remove_tables_local(mm);
+       tlb_flush_mmu_tlbonly(tlb);
+#endif
 }
 
-static void tlb_remove_table_one(void *table, struct mmu_gather *tlb)
+static void tlb_remove_table_smp_sync(void *arg)
+{
+       /* Simply deliver the interrupt */
+}
+
+static void tlb_remove_table_one(void *table)
 {
        /*
         * This isn't an RCU grace period and hence the page-tables cannot be
@@ -348,7 +349,7 @@ static void tlb_remove_table_one(void *table, struct mmu_gather *tlb)
         * It is however sufficient for software page-table walkers that rely on
         * IRQ disabling. See the comment near struct mmu_table_batch.
         */
-       smp_call_function(tlb_remove_table_smp_sync, tlb->mm, 1);
+       smp_call_function(tlb_remove_table_smp_sync, NULL, 1);
        __tlb_remove_table(table);
 }
 
@@ -369,9 +370,8 @@ void tlb_table_flush(struct mmu_gather *tlb)
 {
        struct mmu_table_batch **batch = &tlb->batch;
 
-       tlb_flush_remove_tables(tlb->mm);
-
        if (*batch) {
+               tlb_table_invalidate(tlb);
                call_rcu_sched(&(*batch)->rcu, tlb_remove_table_rcu);
                *batch = NULL;
        }
@@ -381,23 +381,16 @@ void tlb_remove_table(struct mmu_gather *tlb, void *table)
 {
        struct mmu_table_batch **batch = &tlb->batch;
 
-       /*
-        * When there's less then two users of this mm there cannot be a
-        * concurrent page-table walk.
-        */
-       if (atomic_read(&tlb->mm->mm_users) < 2) {
-               __tlb_remove_table(table);
-               return;
-       }
-
        if (*batch == NULL) {
                *batch = (struct mmu_table_batch *)__get_free_page(GFP_NOWAIT | __GFP_NOWARN);
                if (*batch == NULL) {
-                       tlb_remove_table_one(table, tlb);
+                       tlb_table_invalidate(tlb);
+                       tlb_remove_table_one(table);
                        return;
                }
                (*batch)->nr = 0;
        }
+
        (*batch)->tables[(*batch)->nr++] = table;
        if ((*batch)->nr == MAX_TABLE_BATCH)
                tlb_table_flush(tlb);
@@ -1029,7 +1022,7 @@ copy_one_pte(struct mm_struct *dst_mm, struct mm_struct *src_mm,
         * If it's a COW mapping, write protect it both
         * in the parent and the child
         */
-       if (is_cow_mapping(vm_flags)) {
+       if (is_cow_mapping(vm_flags) && pte_write(pte)) {
                ptep_set_wrprotect(src_mm, addr, src_pte);
                pte = pte_wrprotect(pte);
        }
@@ -2384,9 +2377,9 @@ static gfp_t __get_fault_gfp_mask(struct vm_area_struct *vma)
  *
  * We do this without the lock held, so that it can sleep if it needs to.
  */
-static int do_page_mkwrite(struct vm_fault *vmf)
+static vm_fault_t do_page_mkwrite(struct vm_fault *vmf)
 {
-       int ret;
+       vm_fault_t ret;
        struct page *page = vmf->page;
        unsigned int old_flags = vmf->flags;
 
@@ -2490,7 +2483,7 @@ static inline void wp_page_reuse(struct vm_fault *vmf)
  *   held to the old page, as well as updating the rmap.
  * - In any case, unlock the PTL and drop the reference we took to the old page.
  */
-static int wp_page_copy(struct vm_fault *vmf)
+static vm_fault_t wp_page_copy(struct vm_fault *vmf)
 {
        struct vm_area_struct *vma = vmf->vma;
        struct mm_struct *mm = vma->vm_mm;
@@ -2638,7 +2631,7 @@ oom:
  * The function expects the page to be locked or other protection against
  * concurrent faults / writeback (such as DAX radix tree locks).
  */
-int finish_mkwrite_fault(struct vm_fault *vmf)
+vm_fault_t finish_mkwrite_fault(struct vm_fault *vmf)
 {
        WARN_ON_ONCE(!(vmf->vma->vm_flags & VM_SHARED));
        vmf->pte = pte_offset_map_lock(vmf->vma->vm_mm, vmf->pmd, vmf->address,
@@ -2659,12 +2652,12 @@ int finish_mkwrite_fault(struct vm_fault *vmf)
  * Handle write page faults for VM_MIXEDMAP or VM_PFNMAP for a VM_SHARED
  * mapping
  */
-static int wp_pfn_shared(struct vm_fault *vmf)
+static vm_fault_t wp_pfn_shared(struct vm_fault *vmf)
 {
        struct vm_area_struct *vma = vmf->vma;
 
        if (vma->vm_ops && vma->vm_ops->pfn_mkwrite) {
-               int ret;
+               vm_fault_t ret;
 
                pte_unmap_unlock(vmf->pte, vmf->ptl);
                vmf->flags |= FAULT_FLAG_MKWRITE;
@@ -2677,7 +2670,7 @@ static int wp_pfn_shared(struct vm_fault *vmf)
        return VM_FAULT_WRITE;
 }
 
-static int wp_page_shared(struct vm_fault *vmf)
+static vm_fault_t wp_page_shared(struct vm_fault *vmf)
        __releases(vmf->ptl)
 {
        struct vm_area_struct *vma = vmf->vma;
@@ -2685,7 +2678,7 @@ static int wp_page_shared(struct vm_fault *vmf)
        get_page(vmf->page);
 
        if (vma->vm_ops && vma->vm_ops->page_mkwrite) {
-               int tmp;
+               vm_fault_t tmp;
 
                pte_unmap_unlock(vmf->pte, vmf->ptl);
                tmp = do_page_mkwrite(vmf);
@@ -2728,7 +2721,7 @@ static int wp_page_shared(struct vm_fault *vmf)
  * but allow concurrent faults), with pte both mapped and locked.
  * We return with mmap_sem still held, but pte unmapped and unlocked.
  */
-static int do_wp_page(struct vm_fault *vmf)
+static vm_fault_t do_wp_page(struct vm_fault *vmf)
        __releases(vmf->ptl)
 {
        struct vm_area_struct *vma = vmf->vma;
@@ -2904,7 +2897,7 @@ EXPORT_SYMBOL(unmap_mapping_range);
  * We return with the mmap_sem locked or unlocked in the same cases
  * as does filemap_fault().
  */
-int do_swap_page(struct vm_fault *vmf)
+vm_fault_t do_swap_page(struct vm_fault *vmf)
 {
        struct vm_area_struct *vma = vmf->vma;
        struct page *page = NULL, *swapcache;
@@ -2913,7 +2906,7 @@ int do_swap_page(struct vm_fault *vmf)
        pte_t pte;
        int locked;
        int exclusive = 0;
-       int ret = 0;
+       vm_fault_t ret = 0;
 
        if (!pte_unmap_same(vma->vm_mm, vmf->pmd, vmf->pte, vmf->orig_pte))
                goto out;
@@ -3124,12 +3117,12 @@ out_release:
  * but allow concurrent faults), and pte mapped but not yet locked.
  * We return with mmap_sem still held, but pte unmapped and unlocked.
  */
-static int do_anonymous_page(struct vm_fault *vmf)
+static vm_fault_t do_anonymous_page(struct vm_fault *vmf)
 {
        struct vm_area_struct *vma = vmf->vma;
        struct mem_cgroup *memcg;
        struct page *page;
-       int ret = 0;
+       vm_fault_t ret = 0;
        pte_t entry;
 
        /* File mapping without ->vm_ops ? */
@@ -3239,10 +3232,10 @@ oom:
  * released depending on flags and vma->vm_ops->fault() return value.
  * See filemap_fault() and __lock_page_retry().
  */
-static int __do_fault(struct vm_fault *vmf)
+static vm_fault_t __do_fault(struct vm_fault *vmf)
 {
        struct vm_area_struct *vma = vmf->vma;
-       int ret;
+       vm_fault_t ret;
 
        ret = vma->vm_ops->fault(vmf);
        if (unlikely(ret & (VM_FAULT_ERROR | VM_FAULT_NOPAGE | VM_FAULT_RETRY |
@@ -3276,7 +3269,7 @@ static int pmd_devmap_trans_unstable(pmd_t *pmd)
        return pmd_devmap(*pmd) || pmd_trans_unstable(pmd);
 }
 
-static int pte_alloc_one_map(struct vm_fault *vmf)
+static vm_fault_t pte_alloc_one_map(struct vm_fault *vmf)
 {
        struct vm_area_struct *vma = vmf->vma;
 
@@ -3352,13 +3345,14 @@ static void deposit_prealloc_pte(struct vm_fault *vmf)
        vmf->prealloc_pte = NULL;
 }
 
-static int do_set_pmd(struct vm_fault *vmf, struct page *page)
+static vm_fault_t do_set_pmd(struct vm_fault *vmf, struct page *page)
 {
        struct vm_area_struct *vma = vmf->vma;
        bool write = vmf->flags & FAULT_FLAG_WRITE;
        unsigned long haddr = vmf->address & HPAGE_PMD_MASK;
        pmd_t entry;
-       int i, ret;
+       int i;
+       vm_fault_t ret;
 
        if (!transhuge_vma_suitable(vma, haddr))
                return VM_FAULT_FALLBACK;
@@ -3408,7 +3402,7 @@ out:
        return ret;
 }
 #else
-static int do_set_pmd(struct vm_fault *vmf, struct page *page)
+static vm_fault_t do_set_pmd(struct vm_fault *vmf, struct page *page)
 {
        BUILD_BUG();
        return 0;
@@ -3429,13 +3423,13 @@ static int do_set_pmd(struct vm_fault *vmf, struct page *page)
  * Target users are page handler itself and implementations of
  * vm_ops->map_pages.
  */
-int alloc_set_pte(struct vm_fault *vmf, struct mem_cgroup *memcg,
+vm_fault_t alloc_set_pte(struct vm_fault *vmf, struct mem_cgroup *memcg,
                struct page *page)
 {
        struct vm_area_struct *vma = vmf->vma;
        bool write = vmf->flags & FAULT_FLAG_WRITE;
        pte_t entry;
-       int ret;
+       vm_fault_t ret;
 
        if (pmd_none(*vmf->pmd) && PageTransCompound(page) &&
                        IS_ENABLED(CONFIG_TRANSPARENT_HUGE_PAGECACHE)) {
@@ -3494,10 +3488,10 @@ int alloc_set_pte(struct vm_fault *vmf, struct mem_cgroup *memcg,
  * The function expects the page to be locked and on success it consumes a
  * reference of a page being mapped (for the PTE which maps it).
  */
-int finish_fault(struct vm_fault *vmf)
+vm_fault_t finish_fault(struct vm_fault *vmf)
 {
        struct page *page;
-       int ret = 0;
+       vm_fault_t ret = 0;
 
        /* Did we COW the page? */
        if ((vmf->flags & FAULT_FLAG_WRITE) &&
@@ -3583,12 +3577,13 @@ late_initcall(fault_around_debugfs);
  * (and therefore to page order).  This way it's easier to guarantee
  * that we don't cross page table boundaries.
  */
-static int do_fault_around(struct vm_fault *vmf)
+static vm_fault_t do_fault_around(struct vm_fault *vmf)
 {
        unsigned long address = vmf->address, nr_pages, mask;
        pgoff_t start_pgoff = vmf->pgoff;
        pgoff_t end_pgoff;
-       int off, ret = 0;
+       int off;
+       vm_fault_t ret = 0;
 
        nr_pages = READ_ONCE(fault_around_bytes) >> PAGE_SHIFT;
        mask = ~(nr_pages * PAGE_SIZE - 1) & PAGE_MASK;
@@ -3638,10 +3633,10 @@ out:
        return ret;
 }
 
-static int do_read_fault(struct vm_fault *vmf)
+static vm_fault_t do_read_fault(struct vm_fault *vmf)
 {
        struct vm_area_struct *vma = vmf->vma;
-       int ret = 0;
+       vm_fault_t ret = 0;
 
        /*
         * Let's call ->map_pages() first and use ->fault() as fallback
@@ -3665,10 +3660,10 @@ static int do_read_fault(struct vm_fault *vmf)
        return ret;
 }
 
-static int do_cow_fault(struct vm_fault *vmf)
+static vm_fault_t do_cow_fault(struct vm_fault *vmf)
 {
        struct vm_area_struct *vma = vmf->vma;
-       int ret;
+       vm_fault_t ret;
 
        if (unlikely(anon_vma_prepare(vma)))
                return VM_FAULT_OOM;
@@ -3704,10 +3699,10 @@ uncharge_out:
        return ret;
 }
 
-static int do_shared_fault(struct vm_fault *vmf)
+static vm_fault_t do_shared_fault(struct vm_fault *vmf)
 {
        struct vm_area_struct *vma = vmf->vma;
-       int ret, tmp;
+       vm_fault_t ret, tmp;
 
        ret = __do_fault(vmf);
        if (unlikely(ret & (VM_FAULT_ERROR | VM_FAULT_NOPAGE | VM_FAULT_RETRY)))
@@ -3745,10 +3740,10 @@ static int do_shared_fault(struct vm_fault *vmf)
  * The mmap_sem may have been released depending on flags and our
  * return value.  See filemap_fault() and __lock_page_or_retry().
  */
-static int do_fault(struct vm_fault *vmf)
+static vm_fault_t do_fault(struct vm_fault *vmf)
 {
        struct vm_area_struct *vma = vmf->vma;
-       int ret;
+       vm_fault_t ret;
 
        /* The VMA was not fully populated on mmap() or missing VM_DONTEXPAND */
        if (!vma->vm_ops->fault)
@@ -3783,7 +3778,7 @@ static int numa_migrate_prep(struct page *page, struct vm_area_struct *vma,
        return mpol_misplaced(page, vma, addr);
 }
 
-static int do_numa_page(struct vm_fault *vmf)
+static vm_fault_t do_numa_page(struct vm_fault *vmf)
 {
        struct vm_area_struct *vma = vmf->vma;
        struct page *page = NULL;
@@ -3873,7 +3868,7 @@ out:
        return 0;
 }
 
-static inline int create_huge_pmd(struct vm_fault *vmf)
+static inline vm_fault_t create_huge_pmd(struct vm_fault *vmf)
 {
        if (vma_is_anonymous(vmf->vma))
                return do_huge_pmd_anonymous_page(vmf);
@@ -3883,7 +3878,7 @@ static inline int create_huge_pmd(struct vm_fault *vmf)
 }
 
 /* `inline' is required to avoid gcc 4.1.2 build error */
-static inline int wp_huge_pmd(struct vm_fault *vmf, pmd_t orig_pmd)
+static inline vm_fault_t wp_huge_pmd(struct vm_fault *vmf, pmd_t orig_pmd)
 {
        if (vma_is_anonymous(vmf->vma))
                return do_huge_pmd_wp_page(vmf, orig_pmd);
@@ -3902,7 +3897,7 @@ static inline bool vma_is_accessible(struct vm_area_struct *vma)
        return vma->vm_flags & (VM_READ | VM_EXEC | VM_WRITE);
 }
 
-static int create_huge_pud(struct vm_fault *vmf)
+static vm_fault_t create_huge_pud(struct vm_fault *vmf)
 {
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
        /* No support for anonymous transparent PUD pages yet */
@@ -3914,7 +3909,7 @@ static int create_huge_pud(struct vm_fault *vmf)
        return VM_FAULT_FALLBACK;
 }
 
-static int wp_huge_pud(struct vm_fault *vmf, pud_t orig_pud)
+static vm_fault_t wp_huge_pud(struct vm_fault *vmf, pud_t orig_pud)
 {
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
        /* No support for anonymous transparent PUD pages yet */
@@ -3941,7 +3936,7 @@ static int wp_huge_pud(struct vm_fault *vmf, pud_t orig_pud)
  * The mmap_sem may have been released depending on flags and our return value.
  * See filemap_fault() and __lock_page_or_retry().
  */
-static int handle_pte_fault(struct vm_fault *vmf)
+static vm_fault_t handle_pte_fault(struct vm_fault *vmf)
 {
        pte_t entry;
 
@@ -4029,8 +4024,8 @@ unlock:
  * The mmap_sem may have been released depending on flags and our
  * return value.  See filemap_fault() and __lock_page_or_retry().
  */
-static int __handle_mm_fault(struct vm_area_struct *vma, unsigned long address,
-               unsigned int flags)
+static vm_fault_t __handle_mm_fault(struct vm_area_struct *vma,
+               unsigned long address, unsigned int flags)
 {
        struct vm_fault vmf = {
                .vma = vma,
@@ -4043,7 +4038,7 @@ static int __handle_mm_fault(struct vm_area_struct *vma, unsigned long address,
        struct mm_struct *mm = vma->vm_mm;
        pgd_t *pgd;
        p4d_t *p4d;
-       int ret;
+       vm_fault_t ret;
 
        pgd = pgd_offset(mm, address);
        p4d = p4d_alloc(mm, pgd, address);
@@ -4118,10 +4113,10 @@ static int __handle_mm_fault(struct vm_area_struct *vma, unsigned long address,
  * The mmap_sem may have been released depending on flags and our
  * return value.  See filemap_fault() and __lock_page_or_retry().
  */
-int handle_mm_fault(struct vm_area_struct *vma, unsigned long address,
+vm_fault_t handle_mm_fault(struct vm_area_struct *vma, unsigned long address,
                unsigned int flags)
 {
-       int ret;
+       vm_fault_t ret;
 
        __set_current_state(TASK_RUNNING);
 
index 4eb6e82..9eea6e8 100644 (file)
@@ -982,8 +982,6 @@ static void reset_node_present_pages(pg_data_t *pgdat)
 static pg_data_t __ref *hotadd_new_pgdat(int nid, u64 start)
 {
        struct pglist_data *pgdat;
-       unsigned long zones_size[MAX_NR_ZONES] = {0};
-       unsigned long zholes_size[MAX_NR_ZONES] = {0};
        unsigned long start_pfn = PFN_DOWN(start);
 
        pgdat = NODE_DATA(nid);
@@ -1006,8 +1004,11 @@ static pg_data_t __ref *hotadd_new_pgdat(int nid, u64 start)
 
        /* we can use NODE_DATA(nid) from here */
 
+       pgdat->node_id = nid;
+       pgdat->node_start_pfn = start_pfn;
+
        /* init node's zones as empty zones, we don't have any present pages.*/
-       free_area_init_node(nid, zones_size, start_pfn, zholes_size);
+       free_area_init_core_hotplug(nid);
        pgdat->per_cpu_nodestats = alloc_percpu(struct per_cpu_nodestat);
 
        /*
@@ -1017,18 +1018,11 @@ static pg_data_t __ref *hotadd_new_pgdat(int nid, u64 start)
        build_all_zonelists(pgdat);
 
        /*
-        * zone->managed_pages is set to an approximate value in
-        * free_area_init_core(), which will cause
-        * /sys/device/system/node/nodeX/meminfo has wrong data.
-        * So reset it to 0 before any memory is onlined.
-        */
-       reset_node_managed_pages(pgdat);
-
-       /*
         * When memory is hot-added, all the memory is in offline state. So
         * clear all zones' present_pages because they will be updated in
         * online_pages() and offline_pages().
         */
+       reset_node_managed_pages(pgdat);
        reset_node_present_pages(pgdat);
 
        return pgdat;
index 01f1a14..da858f7 100644 (file)
@@ -1784,7 +1784,7 @@ unsigned int mempolicy_slab_node(void)
                zonelist = &NODE_DATA(node)->node_zonelists[ZONELIST_FALLBACK];
                z = first_zones_zonelist(zonelist, highest_zoneidx,
                                                        &policy->v.nodes);
-               return z->zone ? z->zone->node : node;
+               return z->zone ? zone_to_nid(z->zone) : node;
        }
 
        default:
@@ -2326,7 +2326,7 @@ int mpol_misplaced(struct page *page, struct vm_area_struct *vma, unsigned long
                                node_zonelist(numa_node_id(), GFP_HIGHUSER),
                                gfp_zone(GFP_HIGHUSER),
                                &pol->v.nodes);
-               polnid = z->zone->node;
+               polnid = zone_to_nid(z->zone);
                break;
 
        default:
@@ -2504,7 +2504,6 @@ void mpol_shared_policy_init(struct shared_policy *sp, struct mempolicy *mpol)
                        goto put_new;
 
                /* Create pseudo-vma that contains just the policy */
-               memset(&pvma, 0, sizeof(struct vm_area_struct));
                vma_init(&pvma, NULL);
                pvma.vm_end = TASK_SIZE;        /* policy covers entire file */
                mpol_set_shared_policy(sp, &pvma, new); /* adds ref */
index 44f5fa9..0ef8cc8 100644 (file)
@@ -213,6 +213,7 @@ EXPORT_SYMBOL(mempool_init_node);
 
 /**
  * mempool_init - initialize a memory pool
+ * @pool:      pointer to the memory pool that should be initialized
  * @min_nr:    the minimum number of elements guaranteed to be
  *             allocated for this pool.
  * @alloc_fn:  user-defined element-allocation function.
index 4a83268..d6a2e89 100644 (file)
@@ -1131,7 +1131,8 @@ out:
  * gcc 4.7 and 4.8 on arm get an ICEs when inlining unmap_and_move().  Work
  * around it.
  */
-#if (GCC_VERSION >= 40700 && GCC_VERSION < 40900) && defined(CONFIG_ARM)
+#if defined(CONFIG_ARM) && \
+       defined(GCC_VERSION) && GCC_VERSION < 40900 && GCC_VERSION >= 40700
 #define ICE_noinline noinline
 #else
 #define ICE_noinline
@@ -1211,7 +1212,7 @@ out:
                         * intentionally. Although it's rather weird,
                         * it's how HWPoison flag works at the moment.
                         */
-                       if (!test_set_page_hwpoison(page))
+                       if (set_hwpoison_free_buddy_page(page))
                                num_poisoned_pages_inc();
                }
        } else {
@@ -1330,8 +1331,6 @@ put_anon:
 out:
        if (rc != -EAGAIN)
                putback_active_hugepage(hpage);
-       if (reason == MR_MEMORY_FAILURE && !test_set_page_hwpoison(hpage))
-               num_poisoned_pages_inc();
 
        /*
         * If migration was not successful and there's a freeing callback, use
index 5b72266..6838a53 100644 (file)
@@ -53,13 +53,8 @@ void __init mminit_verify_zonelist(void)
                                zone->name);
 
                        /* Iterate the zonelist */
-                       for_each_zone_zonelist(zone, z, zonelist, zoneid) {
-#ifdef CONFIG_NUMA
-                               pr_cont("%d:%s ", zone->node, zone->name);
-#else
-                               pr_cont("0:%s ", zone->name);
-#endif /* CONFIG_NUMA */
-                       }
+                       for_each_zone_zonelist(zone, z, zonelist, zoneid)
+                               pr_cont("%d:%s ", zone_to_nid(zone), zone->name);
                        pr_cont("\n");
                }
        }
index 8d6449e..5f2b2b1 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -3063,9 +3063,7 @@ void exit_mmap(struct mm_struct *mm)
                 * which clears VM_LOCKED, otherwise the oom reaper cannot
                 * reliably test it.
                 */
-               mutex_lock(&oom_lock);
-               __oom_reap_task_mm(mm);
-               mutex_unlock(&oom_lock);
+               (void)__oom_reap_task_mm(mm);
 
                set_bit(MMF_OOM_SKIP, &mm->flags);
                down_write(&mm->mmap_sem);
index eff6b88..82bb1a9 100644 (file)
@@ -174,18 +174,29 @@ void __mmu_notifier_change_pte(struct mm_struct *mm, unsigned long address,
        srcu_read_unlock(&srcu, id);
 }
 
-void __mmu_notifier_invalidate_range_start(struct mm_struct *mm,
-                                 unsigned long start, unsigned long end)
+int __mmu_notifier_invalidate_range_start(struct mm_struct *mm,
+                                 unsigned long start, unsigned long end,
+                                 bool blockable)
 {
        struct mmu_notifier *mn;
+       int ret = 0;
        int id;
 
        id = srcu_read_lock(&srcu);
        hlist_for_each_entry_rcu(mn, &mm->mmu_notifier_mm->list, hlist) {
-               if (mn->ops->invalidate_range_start)
-                       mn->ops->invalidate_range_start(mn, mm, start, end);
+               if (mn->ops->invalidate_range_start) {
+                       int _ret = mn->ops->invalidate_range_start(mn, mm, start, end, blockable);
+                       if (_ret) {
+                               pr_info("%pS callback failed with %d in %sblockable context.\n",
+                                               mn->ops->invalidate_range_start, _ret,
+                                               !blockable ? "non-" : "");
+                               ret = _ret;
+                       }
+               }
        }
        srcu_read_unlock(&srcu, id);
+
+       return ret;
 }
 EXPORT_SYMBOL_GPL(__mmu_notifier_invalidate_range_start);
 
index 412f434..b5b25e4 100644 (file)
@@ -400,7 +400,8 @@ static void dump_tasks(struct mem_cgroup *memcg, const nodemask_t *nodemask)
        struct task_struct *p;
        struct task_struct *task;
 
-       pr_info("[ pid ]   uid  tgid total_vm      rss pgtables_bytes swapents oom_score_adj name\n");
+       pr_info("Tasks state (memory values in pages):\n");
+       pr_info("[  pid  ]   uid  tgid total_vm      rss pgtables_bytes swapents oom_score_adj name\n");
        rcu_read_lock();
        for_each_process(p) {
                if (oom_unkillable_task(p, memcg, nodemask))
@@ -416,7 +417,7 @@ static void dump_tasks(struct mem_cgroup *memcg, const nodemask_t *nodemask)
                        continue;
                }
 
-               pr_info("[%5d] %5d %5d %8lu %8lu %8ld %8lu         %5hd %s\n",
+               pr_info("[%7d] %5d %5d %8lu %8lu %8ld %8lu         %5hd %s\n",
                        task->pid, from_kuid(&init_user_ns, task_uid(task)),
                        task->tgid, task->mm->total_vm, get_mm_rss(task->mm),
                        mm_pgtables_bytes(task->mm),
@@ -487,9 +488,10 @@ static DECLARE_WAIT_QUEUE_HEAD(oom_reaper_wait);
 static struct task_struct *oom_reaper_list;
 static DEFINE_SPINLOCK(oom_reaper_lock);
 
-void __oom_reap_task_mm(struct mm_struct *mm)
+bool __oom_reap_task_mm(struct mm_struct *mm)
 {
        struct vm_area_struct *vma;
+       bool ret = true;
 
        /*
         * Tell all users of get_user/copy_from_user etc... that the content
@@ -519,50 +521,32 @@ void __oom_reap_task_mm(struct mm_struct *mm)
                        struct mmu_gather tlb;
 
                        tlb_gather_mmu(&tlb, mm, start, end);
-                       mmu_notifier_invalidate_range_start(mm, start, end);
+                       if (mmu_notifier_invalidate_range_start_nonblock(mm, start, end)) {
+                               ret = false;
+                               continue;
+                       }
                        unmap_page_range(&tlb, vma, start, end, NULL);
                        mmu_notifier_invalidate_range_end(mm, start, end);
                        tlb_finish_mmu(&tlb, start, end);
                }
        }
+
+       return ret;
 }
 
+/*
+ * Reaps the address space of the give task.
+ *
+ * Returns true on success and false if none or part of the address space
+ * has been reclaimed and the caller should retry later.
+ */
 static bool oom_reap_task_mm(struct task_struct *tsk, struct mm_struct *mm)
 {
        bool ret = true;
 
-       /*
-        * We have to make sure to not race with the victim exit path
-        * and cause premature new oom victim selection:
-        * oom_reap_task_mm             exit_mm
-        *   mmget_not_zero
-        *                                mmput
-        *                                  atomic_dec_and_test
-        *                                exit_oom_victim
-        *                              [...]
-        *                              out_of_memory
-        *                                select_bad_process
-        *                                  # no TIF_MEMDIE task selects new victim
-        *  unmap_page_range # frees some memory
-        */
-       mutex_lock(&oom_lock);
-
        if (!down_read_trylock(&mm->mmap_sem)) {
-               ret = false;
                trace_skip_task_reaping(tsk->pid);
-               goto unlock_oom;
-       }
-
-       /*
-        * If the mm has invalidate_{start,end}() notifiers that could block,
-        * sleep to give the oom victim some more time.
-        * TODO: we really want to get rid of this ugly hack and make sure that
-        * notifiers cannot block for unbounded amount of time
-        */
-       if (mm_has_blockable_invalidate_notifiers(mm)) {
-               up_read(&mm->mmap_sem);
-               schedule_timeout_idle(HZ);
-               goto unlock_oom;
+               return false;
        }
 
        /*
@@ -572,25 +556,27 @@ static bool oom_reap_task_mm(struct task_struct *tsk, struct mm_struct *mm)
         * down_write();up_write() cycle in exit_mmap().
         */
        if (test_bit(MMF_OOM_SKIP, &mm->flags)) {
-               up_read(&mm->mmap_sem);
                trace_skip_task_reaping(tsk->pid);
-               goto unlock_oom;
+               goto out_unlock;
        }
 
        trace_start_task_reaping(tsk->pid);
 
-       __oom_reap_task_mm(mm);
+       /* failed to reap part of the address space. Try again later */
+       ret = __oom_reap_task_mm(mm);
+       if (!ret)
+               goto out_finish;
 
        pr_info("oom_reaper: reaped process %d (%s), now anon-rss:%lukB, file-rss:%lukB, shmem-rss:%lukB\n",
                        task_pid_nr(tsk), tsk->comm,
                        K(get_mm_counter(mm, MM_ANONPAGES)),
                        K(get_mm_counter(mm, MM_FILEPAGES)),
                        K(get_mm_counter(mm, MM_SHMEMPAGES)));
+out_finish:
+       trace_finish_task_reaping(tsk->pid);
+out_unlock:
        up_read(&mm->mmap_sem);
 
-       trace_finish_task_reaping(tsk->pid);
-unlock_oom:
-       mutex_unlock(&oom_lock);
        return ret;
 }
 
@@ -843,68 +829,12 @@ static bool task_will_free_mem(struct task_struct *task)
        return ret;
 }
 
-static void oom_kill_process(struct oom_control *oc, const char *message)
+static void __oom_kill_process(struct task_struct *victim)
 {
-       struct task_struct *p = oc->chosen;
-       unsigned int points = oc->chosen_points;
-       struct task_struct *victim = p;
-       struct task_struct *child;
-       struct task_struct *t;
+       struct task_struct *p;
        struct mm_struct *mm;
-       unsigned int victim_points = 0;
-       static DEFINE_RATELIMIT_STATE(oom_rs, DEFAULT_RATELIMIT_INTERVAL,
-                                             DEFAULT_RATELIMIT_BURST);
        bool can_oom_reap = true;
 
-       /*
-        * If the task is already exiting, don't alarm the sysadmin or kill
-        * its children or threads, just give it access to memory reserves
-        * so it can die quickly
-        */
-       task_lock(p);
-       if (task_will_free_mem(p)) {
-               mark_oom_victim(p);
-               wake_oom_reaper(p);
-               task_unlock(p);
-               put_task_struct(p);
-               return;
-       }
-       task_unlock(p);
-
-       if (__ratelimit(&oom_rs))
-               dump_header(oc, p);
-
-       pr_err("%s: Kill process %d (%s) score %u or sacrifice child\n",
-               message, task_pid_nr(p), p->comm, points);
-
-       /*
-        * If any of p's children has a different mm and is eligible for kill,
-        * the one with the highest oom_badness() score is sacrificed for its
-        * parent.  This attempts to lose the minimal amount of work done while
-        * still freeing memory.
-        */
-       read_lock(&tasklist_lock);
-       for_each_thread(p, t) {
-               list_for_each_entry(child, &t->children, sibling) {
-                       unsigned int child_points;
-
-                       if (process_shares_mm(child, p->mm))
-                               continue;
-                       /*
-                        * oom_badness() returns 0 if the thread is unkillable
-                        */
-                       child_points = oom_badness(child,
-                               oc->memcg, oc->nodemask, oc->totalpages);
-                       if (child_points > victim_points) {
-                               put_task_struct(victim);
-                               victim = child;
-                               victim_points = child_points;
-                               get_task_struct(victim);
-                       }
-               }
-       }
-       read_unlock(&tasklist_lock);
-
        p = find_lock_task_mm(victim);
        if (!p) {
                put_task_struct(victim);
@@ -928,7 +858,7 @@ static void oom_kill_process(struct oom_control *oc, const char *message)
         * in order to prevent the OOM victim from depleting the memory
         * reserves from the user space under its control.
         */
-       do_send_sig_info(SIGKILL, SEND_SIG_FORCED, victim, true);
+       do_send_sig_info(SIGKILL, SEND_SIG_FORCED, victim, PIDTYPE_TGID);
        mark_oom_victim(victim);
        pr_err("Killed process %d (%s) total-vm:%lukB, anon-rss:%lukB, file-rss:%lukB, shmem-rss:%lukB\n",
                task_pid_nr(victim), victim->comm, K(victim->mm->total_vm),
@@ -966,7 +896,7 @@ static void oom_kill_process(struct oom_control *oc, const char *message)
                 */
                if (unlikely(p->flags & PF_KTHREAD))
                        continue;
-               do_send_sig_info(SIGKILL, SEND_SIG_FORCED, p, true);
+               do_send_sig_info(SIGKILL, SEND_SIG_FORCED, p, PIDTYPE_TGID);
        }
        rcu_read_unlock();
 
@@ -979,6 +909,99 @@ static void oom_kill_process(struct oom_control *oc, const char *message)
 #undef K
 
 /*
+ * Kill provided task unless it's secured by setting
+ * oom_score_adj to OOM_SCORE_ADJ_MIN.
+ */
+static int oom_kill_memcg_member(struct task_struct *task, void *unused)
+{
+       if (task->signal->oom_score_adj != OOM_SCORE_ADJ_MIN) {
+               get_task_struct(task);
+               __oom_kill_process(task);
+       }
+       return 0;
+}
+
+static void oom_kill_process(struct oom_control *oc, const char *message)
+{
+       struct task_struct *p = oc->chosen;
+       unsigned int points = oc->chosen_points;
+       struct task_struct *victim = p;
+       struct task_struct *child;
+       struct task_struct *t;
+       struct mem_cgroup *oom_group;
+       unsigned int victim_points = 0;
+       static DEFINE_RATELIMIT_STATE(oom_rs, DEFAULT_RATELIMIT_INTERVAL,
+                                             DEFAULT_RATELIMIT_BURST);
+
+       /*
+        * If the task is already exiting, don't alarm the sysadmin or kill
+        * its children or threads, just give it access to memory reserves
+        * so it can die quickly
+        */
+       task_lock(p);
+       if (task_will_free_mem(p)) {
+               mark_oom_victim(p);
+               wake_oom_reaper(p);
+               task_unlock(p);
+               put_task_struct(p);
+               return;
+       }
+       task_unlock(p);
+
+       if (__ratelimit(&oom_rs))
+               dump_header(oc, p);
+
+       pr_err("%s: Kill process %d (%s) score %u or sacrifice child\n",
+               message, task_pid_nr(p), p->comm, points);
+
+       /*
+        * If any of p's children has a different mm and is eligible for kill,
+        * the one with the highest oom_badness() score is sacrificed for its
+        * parent.  This attempts to lose the minimal amount of work done while
+        * still freeing memory.
+        */
+       read_lock(&tasklist_lock);
+       for_each_thread(p, t) {
+               list_for_each_entry(child, &t->children, sibling) {
+                       unsigned int child_points;
+
+                       if (process_shares_mm(child, p->mm))
+                               continue;
+                       /*
+                        * oom_badness() returns 0 if the thread is unkillable
+                        */
+                       child_points = oom_badness(child,
+                               oc->memcg, oc->nodemask, oc->totalpages);
+                       if (child_points > victim_points) {
+                               put_task_struct(victim);
+                               victim = child;
+                               victim_points = child_points;
+                               get_task_struct(victim);
+                       }
+               }
+       }
+       read_unlock(&tasklist_lock);
+
+       /*
+        * Do we need to kill the entire memory cgroup?
+        * Or even one of the ancestor memory cgroups?
+        * Check this out before killing the victim task.
+        */
+       oom_group = mem_cgroup_get_oom_group(victim, oc->memcg);
+
+       __oom_kill_process(victim);
+
+       /*
+        * If necessary, kill all tasks in the selected memory cgroup.
+        */
+       if (oom_group) {
+               mem_cgroup_print_oom_group(oom_group);
+               mem_cgroup_scan_tasks(oom_group, oom_kill_memcg_member, NULL);
+               mem_cgroup_put(oom_group);
+       }
+}
+
+/*
  * Determines whether the kernel must panic because of the panic_on_oom sysctl.
  */
 static void check_panic_on_oom(struct oom_control *oc,
index 15ea511..e75865d 100644 (file)
@@ -2909,10 +2909,10 @@ static inline void zone_statistics(struct zone *preferred_zone, struct zone *z)
        if (!static_branch_likely(&vm_numa_stat_key))
                return;
 
-       if (z->node != numa_node_id())
+       if (zone_to_nid(z) != numa_node_id())
                local_stat = NUMA_OTHER;
 
-       if (z->node == preferred_zone->node)
+       if (zone_to_nid(z) == zone_to_nid(preferred_zone))
                __inc_numa_state(z, NUMA_HIT);
        else {
                __inc_numa_state(z, NUMA_MISS);
@@ -5278,7 +5278,7 @@ int local_memory_node(int node)
        z = first_zones_zonelist(node_zonelist(node, GFP_KERNEL),
                                   gfp_zone(GFP_KERNEL),
                                   NULL);
-       return z->zone->node;
+       return zone_to_nid(z->zone);
 }
 #endif
 
@@ -6120,7 +6120,7 @@ static unsigned long __init usemap_size(unsigned long zone_start_pfn, unsigned l
        return usemapsize / 8;
 }
 
-static void __init setup_usemap(struct pglist_data *pgdat,
+static void __ref setup_usemap(struct pglist_data *pgdat,
                                struct zone *zone,
                                unsigned long zone_start_pfn,
                                unsigned long zonesize)
@@ -6140,7 +6140,7 @@ static inline void setup_usemap(struct pglist_data *pgdat, struct zone *zone,
 #ifdef CONFIG_HUGETLB_PAGE_SIZE_VARIABLE
 
 /* Initialise the number of pages represented by NR_PAGEBLOCK_BITS */
-void __paginginit set_pageblock_order(void)
+void __init set_pageblock_order(void)
 {
        unsigned int order;
 
@@ -6168,14 +6168,14 @@ void __paginginit set_pageblock_order(void)
  * include/linux/pageblock-flags.h for the values of pageblock_order based on
  * the kernel config
  */
-void __paginginit set_pageblock_order(void)
+void __init set_pageblock_order(void)
 {
 }
 
 #endif /* CONFIG_HUGETLB_PAGE_SIZE_VARIABLE */
 
-static unsigned long __paginginit calc_memmap_size(unsigned long spanned_pages,
-                                                  unsigned long present_pages)
+static unsigned long __init calc_memmap_size(unsigned long spanned_pages,
+                                               unsigned long present_pages)
 {
        unsigned long pages = spanned_pages;
 
@@ -6194,39 +6194,99 @@ static unsigned long __paginginit calc_memmap_size(unsigned long spanned_pages,
        return PAGE_ALIGN(pages * sizeof(struct page)) >> PAGE_SHIFT;
 }
 
-/*
- * Set up the zone data structures:
- *   - mark all pages reserved
- *   - mark all memory queues empty
- *   - clear the memory bitmaps
- *
- * NOTE: pgdat should get zeroed by caller.
- */
-static void __paginginit free_area_init_core(struct pglist_data *pgdat)
-{
-       enum zone_type j;
-       int nid = pgdat->node_id;
-
-       pgdat_resize_init(pgdat);
 #ifdef CONFIG_NUMA_BALANCING
+static void pgdat_init_numabalancing(struct pglist_data *pgdat)
+{
        spin_lock_init(&pgdat->numabalancing_migrate_lock);
        pgdat->numabalancing_migrate_nr_pages = 0;
        pgdat->numabalancing_migrate_next_window = jiffies;
+}
+#else
+static void pgdat_init_numabalancing(struct pglist_data *pgdat) {}
 #endif
+
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
+static void pgdat_init_split_queue(struct pglist_data *pgdat)
+{
        spin_lock_init(&pgdat->split_queue_lock);
        INIT_LIST_HEAD(&pgdat->split_queue);
        pgdat->split_queue_len = 0;
+}
+#else
+static void pgdat_init_split_queue(struct pglist_data *pgdat) {}
 #endif
-       init_waitqueue_head(&pgdat->kswapd_wait);
-       init_waitqueue_head(&pgdat->pfmemalloc_wait);
+
 #ifdef CONFIG_COMPACTION
+static void pgdat_init_kcompactd(struct pglist_data *pgdat)
+{
        init_waitqueue_head(&pgdat->kcompactd_wait);
+}
+#else
+static void pgdat_init_kcompactd(struct pglist_data *pgdat) {}
 #endif
+
+static void __meminit pgdat_init_internals(struct pglist_data *pgdat)
+{
+       pgdat_resize_init(pgdat);
+
+       pgdat_init_numabalancing(pgdat);
+       pgdat_init_split_queue(pgdat);
+       pgdat_init_kcompactd(pgdat);
+
+       init_waitqueue_head(&pgdat->kswapd_wait);
+       init_waitqueue_head(&pgdat->pfmemalloc_wait);
+
        pgdat_page_ext_init(pgdat);
        spin_lock_init(&pgdat->lru_lock);
        lruvec_init(node_lruvec(pgdat));
+}
+
+static void __meminit zone_init_internals(struct zone *zone, enum zone_type idx, int nid,
+                                                       unsigned long remaining_pages)
+{
+       zone->managed_pages = remaining_pages;
+       zone_set_nid(zone, nid);
+       zone->name = zone_names[idx];
+       zone->zone_pgdat = NODE_DATA(nid);
+       spin_lock_init(&zone->lock);
+       zone_seqlock_init(zone);
+       zone_pcp_init(zone);
+}
+
+/*
+ * Set up the zone data structures
+ * - init pgdat internals
+ * - init all zones belonging to this node
+ *
+ * NOTE: this function is only called during memory hotplug
+ */
+#ifdef CONFIG_MEMORY_HOTPLUG
+void __ref free_area_init_core_hotplug(int nid)
+{
+       enum zone_type z;
+       pg_data_t *pgdat = NODE_DATA(nid);
+
+       pgdat_init_internals(pgdat);
+       for (z = 0; z < MAX_NR_ZONES; z++)
+               zone_init_internals(&pgdat->node_zones[z], z, nid, 0);
+}
+#endif
+
+/*
+ * Set up the zone data structures:
+ *   - mark all pages reserved
+ *   - mark all memory queues empty
+ *   - clear the memory bitmaps
+ *
+ * NOTE: pgdat should get zeroed by caller.
+ * NOTE: this function is only called during early init.
+ */
+static void __init free_area_init_core(struct pglist_data *pgdat)
+{
+       enum zone_type j;
+       int nid = pgdat->node_id;
 
+       pgdat_init_internals(pgdat);
        pgdat->per_cpu_nodestats = &boot_nodestats;
 
        for (j = 0; j < MAX_NR_ZONES; j++) {
@@ -6274,15 +6334,7 @@ static void __paginginit free_area_init_core(struct pglist_data *pgdat)
                 * when the bootmem allocator frees pages into the buddy system.
                 * And all highmem pages will be managed by the buddy system.
                 */
-               zone->managed_pages = freesize;
-#ifdef CONFIG_NUMA
-               zone->node = nid;
-#endif
-               zone->name = zone_names[j];
-               zone->zone_pgdat = pgdat;
-               spin_lock_init(&zone->lock);
-               zone_seqlock_init(zone);
-               zone_pcp_init(zone);
+               zone_init_internals(zone, j, nid, freesize);
 
                if (!size)
                        continue;
@@ -6342,8 +6394,24 @@ static void __ref alloc_node_mem_map(struct pglist_data *pgdat)
 static void __ref alloc_node_mem_map(struct pglist_data *pgdat) { }
 #endif /* CONFIG_FLAT_NODE_MEM_MAP */
 
-void __paginginit free_area_init_node(int nid, unsigned long *zones_size,
-               unsigned long node_start_pfn, unsigned long *zholes_size)
+#ifdef CONFIG_DEFERRED_STRUCT_PAGE_INIT
+static inline void pgdat_set_deferred_range(pg_data_t *pgdat)
+{
+       /*
+        * We start only with one section of pages, more pages are added as
+        * needed until the rest of deferred pages are initialized.
+        */
+       pgdat->static_init_pgcnt = min_t(unsigned long, PAGES_PER_SECTION,
+                                               pgdat->node_spanned_pages);
+       pgdat->first_deferred_pfn = ULONG_MAX;
+}
+#else
+static inline void pgdat_set_deferred_range(pg_data_t *pgdat) {}
+#endif
+
+void __init free_area_init_node(int nid, unsigned long *zones_size,
+                                  unsigned long node_start_pfn,
+                                  unsigned long *zholes_size)
 {
        pg_data_t *pgdat = NODE_DATA(nid);
        unsigned long start_pfn = 0;
@@ -6367,16 +6435,8 @@ void __paginginit free_area_init_node(int nid, unsigned long *zones_size,
                                  zones_size, zholes_size);
 
        alloc_node_mem_map(pgdat);
+       pgdat_set_deferred_range(pgdat);
 
-#ifdef CONFIG_DEFERRED_STRUCT_PAGE_INIT
-       /*
-        * We start only with one section of pages, more pages are added as
-        * needed until the rest of deferred pages are initialized.
-        */
-       pgdat->static_init_pgcnt = min_t(unsigned long, PAGES_PER_SECTION,
-                                        pgdat->node_spanned_pages);
-       pgdat->first_deferred_pfn = ULONG_MAX;
-#endif
        free_area_init_core(pgdat);
 }
 
@@ -6388,7 +6448,7 @@ void __paginginit free_area_init_node(int nid, unsigned long *zones_size,
  * may be accessed (for example page_to_pfn() on some configuration accesses
  * flags). We must explicitly zero those struct pages.
  */
-void __paginginit zero_resv_unavail(void)
+void __init zero_resv_unavail(void)
 {
        phys_addr_t start, end;
        unsigned long pfn;
@@ -8036,3 +8096,33 @@ bool is_free_buddy_page(struct page *page)
 
        return order < MAX_ORDER;
 }
+
+#ifdef CONFIG_MEMORY_FAILURE
+/*
+ * Set PG_hwpoison flag if a given page is confirmed to be a free page.  This
+ * test is performed under the zone lock to prevent a race against page
+ * allocation.
+ */
+bool set_hwpoison_free_buddy_page(struct page *page)
+{
+       struct zone *zone = page_zone(page);
+       unsigned long pfn = page_to_pfn(page);
+       unsigned long flags;
+       unsigned int order;
+       bool hwpoisoned = false;
+
+       spin_lock_irqsave(&zone->lock, flags);
+       for (order = 0; order < MAX_ORDER; order++) {
+               struct page *page_head = page - (pfn & ((1 << order) - 1));
+
+               if (PageBuddy(page_head) && page_order(page_head) >= order) {
+                       if (!TestSetPageHWPoison(page))
+                               hwpoisoned = true;
+                       break;
+               }
+       }
+       spin_unlock_irqrestore(&zone->lock, flags);
+
+       return hwpoisoned;
+}
+#endif
index 0b64809..a749d4d 100644 (file)
@@ -170,6 +170,14 @@ static LIST_HEAD(pcpu_map_extend_chunks);
 int pcpu_nr_empty_pop_pages;
 
 /*
+ * The number of populated pages in use by the allocator, protected by
+ * pcpu_lock.  This number is kept per a unit per chunk (i.e. when a page gets
+ * allocated/deallocated, it is allocated/deallocated in all units of a chunk
+ * and increments/decrements this count by 1).
+ */
+static unsigned long pcpu_nr_populated;
+
+/*
  * Balance work is used to populate or destroy chunks asynchronously.  We
  * try to keep the number of populated free pages between
  * PCPU_EMPTY_POP_PAGES_LOW and HIGH for atomic allocations and at most one
@@ -1232,6 +1240,7 @@ static void pcpu_chunk_populated(struct pcpu_chunk *chunk, int page_start,
 
        bitmap_set(chunk->populated, page_start, nr);
        chunk->nr_populated += nr;
+       pcpu_nr_populated += nr;
 
        if (!for_alloc) {
                chunk->nr_empty_pop_pages += nr;
@@ -1260,6 +1269,7 @@ static void pcpu_chunk_depopulated(struct pcpu_chunk *chunk,
        chunk->nr_populated -= nr;
        chunk->nr_empty_pop_pages -= nr;
        pcpu_nr_empty_pop_pages -= nr;
+       pcpu_nr_populated -= nr;
 }
 
 /*
@@ -2176,6 +2186,9 @@ int __init pcpu_setup_first_chunk(const struct pcpu_alloc_info *ai,
        pcpu_nr_empty_pop_pages = pcpu_first_chunk->nr_empty_pop_pages;
        pcpu_chunk_relocate(pcpu_first_chunk, -1);
 
+       /* include all regions of the first chunk */
+       pcpu_nr_populated += PFN_DOWN(size_sum);
+
        pcpu_stats_chunk_alloc();
        trace_percpu_create_chunk(base_addr);
 
@@ -2746,6 +2759,22 @@ void __init setup_per_cpu_areas(void)
 #endif /* CONFIG_SMP */
 
 /*
+ * pcpu_nr_pages - calculate total number of populated backing pages
+ *
+ * This reflects the number of pages populated to back chunks.  Metadata is
+ * excluded in the number exposed in meminfo as the number of backing pages
+ * scales with the number of cpus and can quickly outweigh the memory used for
+ * metadata.  It also keeps this calculation nice and simple.
+ *
+ * RETURNS:
+ * Total number of populated backing pages in use by the allocator.
+ */
+unsigned long pcpu_nr_pages(void)
+{
+       return pcpu_nr_populated * pcpu_nr_units;
+}
+
+/*
  * Percpu allocator is initialized early during boot when neither slab or
  * workqueue is available.  Plug async management until everything is up
  * and running.
index c48c790..0376c12 100644 (file)
@@ -124,7 +124,7 @@ static int shmem_replace_page(struct page **pagep, gfp_t gfp,
 static int shmem_getpage_gfp(struct inode *inode, pgoff_t index,
                struct page **pagep, enum sgp_type sgp,
                gfp_t gfp, struct vm_area_struct *vma,
-               struct vm_fault *vmf, int *fault_type);
+               struct vm_fault *vmf, vm_fault_t *fault_type);
 
 int shmem_getpage(struct inode *inode, pgoff_t index,
                struct page **pagep, enum sgp_type sgp)
@@ -1421,7 +1421,6 @@ static void shmem_pseudo_vma_init(struct vm_area_struct *vma,
                struct shmem_inode_info *info, pgoff_t index)
 {
        /* Create a pseudo vma that just contains the policy */
-       memset(vma, 0, sizeof(*vma));
        vma_init(vma, NULL);
        /* Bias interleave by inode number to distribute better across nodes */
        vma->vm_pgoff = index + info->vfs_inode.i_ino;
@@ -1621,7 +1620,8 @@ static int shmem_replace_page(struct page **pagep, gfp_t gfp,
  */
 static int shmem_getpage_gfp(struct inode *inode, pgoff_t index,
        struct page **pagep, enum sgp_type sgp, gfp_t gfp,
-       struct vm_area_struct *vma, struct vm_fault *vmf, int *fault_type)
+       struct vm_area_struct *vma, struct vm_fault *vmf,
+                       vm_fault_t *fault_type)
 {
        struct address_space *mapping = inode->i_mapping;
        struct shmem_inode_info *info = SHMEM_I(inode);
index 008ccb2..63a7b45 100644 (file)
@@ -269,8 +269,8 @@ static int refill_swap_slots_cache(struct swap_slots_cache *cache)
 
        cache->cur = 0;
        if (swap_slot_cache_active)
-               cache->nr = get_swap_pages(SWAP_SLOTS_CACHE_SIZE, false,
-                                          cache->slots);
+               cache->nr = get_swap_pages(SWAP_SLOTS_CACHE_SIZE,
+                                          cache->slots, 1);
 
        return cache->nr;
 }
@@ -316,7 +316,7 @@ swp_entry_t get_swap_page(struct page *page)
 
        if (PageTransHuge(page)) {
                if (IS_ENABLED(CONFIG_THP_SWAP))
-                       get_swap_pages(1, true, &entry);
+                       get_swap_pages(1, &entry, HPAGE_PMD_NR);
                goto out;
        }
 
@@ -350,7 +350,7 @@ repeat:
                        goto out;
        }
 
-       get_swap_pages(1, false, &entry);
+       get_swap_pages(1, &entry, 1);
 out:
        if (mem_cgroup_try_charge_swap(page, entry)) {
                put_swap_page(page, entry);
index 8837b22..d954b71 100644 (file)
@@ -204,8 +204,16 @@ static void discard_swap_cluster(struct swap_info_struct *si,
 
 #ifdef CONFIG_THP_SWAP
 #define SWAPFILE_CLUSTER       HPAGE_PMD_NR
+
+#define swap_entry_size(size)  (size)
 #else
 #define SWAPFILE_CLUSTER       256
+
+/*
+ * Define swap_entry_size() as constant to let compiler to optimize
+ * out some code if !CONFIG_THP_SWAP
+ */
+#define swap_entry_size(size)  1
 #endif
 #define LATENCY_LIMIT          256
 
@@ -269,7 +277,9 @@ static inline void cluster_set_null(struct swap_cluster_info *info)
 
 static inline bool cluster_is_huge(struct swap_cluster_info *info)
 {
-       return info->flags & CLUSTER_FLAG_HUGE;
+       if (IS_ENABLED(CONFIG_THP_SWAP))
+               return info->flags & CLUSTER_FLAG_HUGE;
+       return false;
 }
 
 static inline void cluster_clear_huge(struct swap_cluster_info *info)
@@ -296,13 +306,18 @@ static inline void unlock_cluster(struct swap_cluster_info *ci)
                spin_unlock(&ci->lock);
 }
 
+/*
+ * Determine the locking method in use for this device.  Return
+ * swap_cluster_info if SSD-style cluster-based locking is in place.
+ */
 static inline struct swap_cluster_info *lock_cluster_or_swap_info(
-       struct swap_info_struct *si,
-       unsigned long offset)
+               struct swap_info_struct *si, unsigned long offset)
 {
        struct swap_cluster_info *ci;
 
+       /* Try to use fine-grained SSD-style locking if available: */
        ci = lock_cluster(si, offset);
+       /* Otherwise, fall back to traditional, coarse locking: */
        if (!ci)
                spin_lock(&si->lock);
 
@@ -863,7 +878,6 @@ no_page:
        return n_ret;
 }
 
-#ifdef CONFIG_THP_SWAP
 static int swap_alloc_cluster(struct swap_info_struct *si, swp_entry_t *slot)
 {
        unsigned long idx;
@@ -871,6 +885,15 @@ static int swap_alloc_cluster(struct swap_info_struct *si, swp_entry_t *slot)
        unsigned long offset, i;
        unsigned char *map;
 
+       /*
+        * Should not even be attempting cluster allocations when huge
+        * page swap is disabled.  Warn and fail the allocation.
+        */
+       if (!IS_ENABLED(CONFIG_THP_SWAP)) {
+               VM_WARN_ON_ONCE(1);
+               return 0;
+       }
+
        if (cluster_list_empty(&si->free_clusters))
                return 0;
 
@@ -901,13 +924,6 @@ static void swap_free_cluster(struct swap_info_struct *si, unsigned long idx)
        unlock_cluster(ci);
        swap_range_free(si, offset, SWAPFILE_CLUSTER);
 }
-#else
-static int swap_alloc_cluster(struct swap_info_struct *si, swp_entry_t *slot)
-{
-       VM_WARN_ON_ONCE(1);
-       return 0;
-}
-#endif /* CONFIG_THP_SWAP */
 
 static unsigned long scan_swap_map(struct swap_info_struct *si,
                                   unsigned char usage)
@@ -924,18 +940,18 @@ static unsigned long scan_swap_map(struct swap_info_struct *si,
 
 }
 
-int get_swap_pages(int n_goal, bool cluster, swp_entry_t swp_entries[])
+int get_swap_pages(int n_goal, swp_entry_t swp_entries[], int entry_size)
 {
-       unsigned long nr_pages = cluster ? SWAPFILE_CLUSTER : 1;
+       unsigned long size = swap_entry_size(entry_size);
        struct swap_info_struct *si, *next;
        long avail_pgs;
        int n_ret = 0;
        int node;
 
        /* Only single cluster request supported */
-       WARN_ON_ONCE(n_goal > 1 && cluster);
+       WARN_ON_ONCE(n_goal > 1 && size == SWAPFILE_CLUSTER);
 
-       avail_pgs = atomic_long_read(&nr_swap_pages) / nr_pages;
+       avail_pgs = atomic_long_read(&nr_swap_pages) / size;
        if (avail_pgs <= 0)
                goto noswap;
 
@@ -945,7 +961,7 @@ int get_swap_pages(int n_goal, bool cluster, swp_entry_t swp_entries[])
        if (n_goal > avail_pgs)
                n_goal = avail_pgs;
 
-       atomic_long_sub(n_goal * nr_pages, &nr_swap_pages);
+       atomic_long_sub(n_goal * size, &nr_swap_pages);
 
        spin_lock(&swap_avail_lock);
 
@@ -972,14 +988,14 @@ start_over:
                        spin_unlock(&si->lock);
                        goto nextsi;
                }
-               if (cluster) {
+               if (size == SWAPFILE_CLUSTER) {
                        if (!(si->flags & SWP_FILE))
                                n_ret = swap_alloc_cluster(si, swp_entries);
                } else
                        n_ret = scan_swap_map_slots(si, SWAP_HAS_CACHE,
                                                    n_goal, swp_entries);
                spin_unlock(&si->lock);
-               if (n_ret || cluster)
+               if (n_ret || size == SWAPFILE_CLUSTER)
                        goto check_out;
                pr_debug("scan_swap_map of si %d failed to find offset\n",
                        si->type);
@@ -1005,7 +1021,7 @@ nextsi:
 
 check_out:
        if (n_ret < n_goal)
-               atomic_long_add((long)(n_goal - n_ret) * nr_pages,
+               atomic_long_add((long)(n_goal - n_ret) * size,
                                &nr_swap_pages);
 noswap:
        return n_ret;
@@ -1107,16 +1123,13 @@ static struct swap_info_struct *swap_info_get_cont(swp_entry_t entry,
        return p;
 }
 
-static unsigned char __swap_entry_free(struct swap_info_struct *p,
-                                      swp_entry_t entry, unsigned char usage)
+static unsigned char __swap_entry_free_locked(struct swap_info_struct *p,
+                                             unsigned long offset,
+                                             unsigned char usage)
 {
-       struct swap_cluster_info *ci;
-       unsigned long offset = swp_offset(entry);
        unsigned char count;
        unsigned char has_cache;
 
-       ci = lock_cluster_or_swap_info(p, offset);
-
        count = p->swap_map[offset];
 
        has_cache = count & SWAP_HAS_CACHE;
@@ -1144,6 +1157,17 @@ static unsigned char __swap_entry_free(struct swap_info_struct *p,
        usage = count | has_cache;
        p->swap_map[offset] = usage ? : SWAP_HAS_CACHE;
 
+       return usage;
+}
+
+static unsigned char __swap_entry_free(struct swap_info_struct *p,
+                                      swp_entry_t entry, unsigned char usage)
+{
+       struct swap_cluster_info *ci;
+       unsigned long offset = swp_offset(entry);
+
+       ci = lock_cluster_or_swap_info(p, offset);
+       usage = __swap_entry_free_locked(p, offset, usage);
        unlock_cluster_or_swap_info(p, ci);
 
        return usage;
@@ -1184,19 +1208,7 @@ void swap_free(swp_entry_t entry)
 /*
  * Called after dropping swapcache to decrease refcnt to swap entries.
  */
-static void swapcache_free(swp_entry_t entry)
-{
-       struct swap_info_struct *p;
-
-       p = _swap_info_get(entry);
-       if (p) {
-               if (!__swap_entry_free(p, entry, SWAP_HAS_CACHE))
-                       free_swap_slot(entry);
-       }
-}
-
-#ifdef CONFIG_THP_SWAP
-static void swapcache_free_cluster(swp_entry_t entry)
+void put_swap_page(struct page *page, swp_entry_t entry)
 {
        unsigned long offset = swp_offset(entry);
        unsigned long idx = offset / SWAPFILE_CLUSTER;
@@ -1205,42 +1217,48 @@ static void swapcache_free_cluster(swp_entry_t entry)
        unsigned char *map;
        unsigned int i, free_entries = 0;
        unsigned char val;
+       int size = swap_entry_size(hpage_nr_pages(page));
 
        si = _swap_info_get(entry);
        if (!si)
                return;
 
-       ci = lock_cluster(si, offset);
-       VM_BUG_ON(!cluster_is_huge(ci));
-       map = si->swap_map + offset;
-       for (i = 0; i < SWAPFILE_CLUSTER; i++) {
-               val = map[i];
-               VM_BUG_ON(!(val & SWAP_HAS_CACHE));
-               if (val == SWAP_HAS_CACHE)
-                       free_entries++;
-       }
-       if (!free_entries) {
-               for (i = 0; i < SWAPFILE_CLUSTER; i++)
-                       map[i] &= ~SWAP_HAS_CACHE;
+       ci = lock_cluster_or_swap_info(si, offset);
+       if (size == SWAPFILE_CLUSTER) {
+               VM_BUG_ON(!cluster_is_huge(ci));
+               map = si->swap_map + offset;
+               for (i = 0; i < SWAPFILE_CLUSTER; i++) {
+                       val = map[i];
+                       VM_BUG_ON(!(val & SWAP_HAS_CACHE));
+                       if (val == SWAP_HAS_CACHE)
+                               free_entries++;
+               }
+               cluster_clear_huge(ci);
+               if (free_entries == SWAPFILE_CLUSTER) {
+                       unlock_cluster_or_swap_info(si, ci);
+                       spin_lock(&si->lock);
+                       ci = lock_cluster(si, offset);
+                       memset(map, 0, SWAPFILE_CLUSTER);
+                       unlock_cluster(ci);
+                       mem_cgroup_uncharge_swap(entry, SWAPFILE_CLUSTER);
+                       swap_free_cluster(si, idx);
+                       spin_unlock(&si->lock);
+                       return;
+               }
        }
-       cluster_clear_huge(ci);
-       unlock_cluster(ci);
-       if (free_entries == SWAPFILE_CLUSTER) {
-               spin_lock(&si->lock);
-               ci = lock_cluster(si, offset);
-               memset(map, 0, SWAPFILE_CLUSTER);
-               unlock_cluster(ci);
-               mem_cgroup_uncharge_swap(entry, SWAPFILE_CLUSTER);
-               swap_free_cluster(si, idx);
-               spin_unlock(&si->lock);
-       } else if (free_entries) {
-               for (i = 0; i < SWAPFILE_CLUSTER; i++, entry.val++) {
-                       if (!__swap_entry_free(si, entry, SWAP_HAS_CACHE))
-                               free_swap_slot(entry);
+       for (i = 0; i < size; i++, entry.val++) {
+               if (!__swap_entry_free_locked(si, offset + i, SWAP_HAS_CACHE)) {
+                       unlock_cluster_or_swap_info(si, ci);
+                       free_swap_slot(entry);
+                       if (i == size - 1)
+                               return;
+                       lock_cluster_or_swap_info(si, offset);
                }
        }
+       unlock_cluster_or_swap_info(si, ci);
 }
 
+#ifdef CONFIG_THP_SWAP
 int split_swap_cluster(swp_entry_t entry)
 {
        struct swap_info_struct *si;
@@ -1255,19 +1273,7 @@ int split_swap_cluster(swp_entry_t entry)
        unlock_cluster(ci);
        return 0;
 }
-#else
-static inline void swapcache_free_cluster(swp_entry_t entry)
-{
-}
-#endif /* CONFIG_THP_SWAP */
-
-void put_swap_page(struct page *page, swp_entry_t entry)
-{
-       if (!PageTransHuge(page))
-               swapcache_free(entry);
-       else
-               swapcache_free_cluster(entry);
-}
+#endif
 
 static int swp_entry_cmp(const void *ent1, const void *ent2)
 {
@@ -1409,7 +1415,6 @@ out:
        return count;
 }
 
-#ifdef CONFIG_THP_SWAP
 static bool swap_page_trans_huge_swapped(struct swap_info_struct *si,
                                         swp_entry_t entry)
 {
@@ -1422,12 +1427,12 @@ static bool swap_page_trans_huge_swapped(struct swap_info_struct *si,
 
        ci = lock_cluster_or_swap_info(si, offset);
        if (!ci || !cluster_is_huge(ci)) {
-               if (map[roffset] != SWAP_HAS_CACHE)
+               if (swap_count(map[roffset]))
                        ret = true;
                goto unlock_out;
        }
        for (i = 0; i < SWAPFILE_CLUSTER; i++) {
-               if (map[offset + i] != SWAP_HAS_CACHE) {
+               if (swap_count(map[offset + i])) {
                        ret = true;
                        break;
                }
@@ -1442,7 +1447,7 @@ static bool page_swapped(struct page *page)
        swp_entry_t entry;
        struct swap_info_struct *si;
 
-       if (likely(!PageTransCompound(page)))
+       if (!IS_ENABLED(CONFIG_THP_SWAP) || likely(!PageTransCompound(page)))
                return page_swapcount(page) != 0;
 
        page = compound_head(page);
@@ -1466,10 +1471,8 @@ static int page_trans_huge_map_swapcount(struct page *page, int *total_mapcount,
        /* hugetlbfs shouldn't call it */
        VM_BUG_ON_PAGE(PageHuge(page), page);
 
-       if (likely(!PageTransCompound(page))) {
-               mapcount = atomic_read(&page->_mapcount) + 1;
-               if (total_mapcount)
-                       *total_mapcount = mapcount;
+       if (!IS_ENABLED(CONFIG_THP_SWAP) || likely(!PageTransCompound(page))) {
+               mapcount = page_trans_huge_mapcount(page, total_mapcount);
                if (PageSwapCache(page))
                        swapcount = page_swapcount(page);
                if (total_swapcount)
@@ -1516,26 +1519,6 @@ static int page_trans_huge_map_swapcount(struct page *page, int *total_mapcount,
 
        return map_swapcount;
 }
-#else
-#define swap_page_trans_huge_swapped(si, entry)        swap_swapcount(si, entry)
-#define page_swapped(page)                     (page_swapcount(page) != 0)
-
-static int page_trans_huge_map_swapcount(struct page *page, int *total_mapcount,
-                                        int *total_swapcount)
-{
-       int mapcount, swapcount = 0;
-
-       /* hugetlbfs shouldn't call it */
-       VM_BUG_ON_PAGE(PageHuge(page), page);
-
-       mapcount = page_trans_huge_mapcount(page, total_mapcount);
-       if (PageSwapCache(page))
-               swapcount = page_swapcount(page);
-       if (total_swapcount)
-               *total_swapcount = swapcount;
-       return mapcount + swapcount;
-}
-#endif
 
 /*
  * We can write to an anon page without COW if there are no other references
index 3351659..d2890a4 100644 (file)
--- a/mm/util.c
+++ b/mm/util.c
@@ -196,7 +196,7 @@ void *vmemdup_user(const void __user *src, size_t len)
 }
 EXPORT_SYMBOL(vmemdup_user);
 
-/*
+/**
  * strndup_user - duplicate an existing string from user space
  * @s: The string to duplicate
  * @n: Maximum number of bytes to copy, including the trailing NUL.
@@ -434,6 +434,13 @@ void *kvmalloc_node(size_t size, gfp_t flags, int node)
 }
 EXPORT_SYMBOL(kvmalloc_node);
 
+/**
+ * kvfree - free memory allocated with kvmalloc
+ * @addr: pointer returned by kvmalloc
+ *
+ * If the memory is allocated from vmalloc area it is freed with vfree().
+ * Otherwise kfree() is used.
+ */
 void kvfree(const void *addr)
 {
        if (is_vmalloc_addr(addr))
index 4375b1e..7e7d255 100644 (file)
@@ -408,7 +408,8 @@ void register_shrinker_prepared(struct shrinker *shrinker)
        down_write(&shrinker_rwsem);
        list_add_tail(&shrinker->list, &shrinker_list);
 #ifdef CONFIG_MEMCG_KMEM
-       idr_replace(&shrinker_idr, shrinker, shrinker->id);
+       if (shrinker->flags & SHRINKER_MEMCG_AWARE)
+               idr_replace(&shrinker_idr, shrinker, shrinker->id);
 #endif
        up_write(&shrinker_rwsem);
 }
@@ -902,7 +903,7 @@ static int __remove_mapping(struct address_space *mapping, struct page *page,
                refcount = 2;
        if (!page_ref_freeze(page, refcount))
                goto cannot_free;
-       /* note: atomic_cmpxchg in page_freeze_refs provides the smp_rmb */
+       /* note: atomic_cmpxchg in page_ref_freeze provides the smp_rmb */
        if (unlikely(PageDirty(page))) {
                page_ref_unfreeze(page, refcount);
                goto cannot_free;
index f8cceb9..cd2d5b9 100644 (file)
@@ -41,4 +41,3 @@ config CEPH_LIB_USE_DNS_RESOLVER
          Documentation/networking/dns_resolver.txt
 
          If unsure, say N.
-
index 12bf497..db09def 100644 (file)
@@ -15,4 +15,3 @@ libceph-y := ceph_common.o messenger.o msgpool.o buffer.o pagelist.o \
        auth_x.o \
        ceph_fs.o ceph_strings.o ceph_hash.o \
        pagevec.o snapshot.o string_table.o
-
index dbde2b3..fbeee06 100644 (file)
@@ -315,6 +315,22 @@ int ceph_auth_update_authorizer(struct ceph_auth_client *ac,
 }
 EXPORT_SYMBOL(ceph_auth_update_authorizer);
 
+int ceph_auth_add_authorizer_challenge(struct ceph_auth_client *ac,
+                                      struct ceph_authorizer *a,
+                                      void *challenge_buf,
+                                      int challenge_buf_len)
+{
+       int ret = 0;
+
+       mutex_lock(&ac->mutex);
+       if (ac->ops && ac->ops->add_authorizer_challenge)
+               ret = ac->ops->add_authorizer_challenge(ac, a, challenge_buf,
+                                                       challenge_buf_len);
+       mutex_unlock(&ac->mutex);
+       return ret;
+}
+EXPORT_SYMBOL(ceph_auth_add_authorizer_challenge);
+
 int ceph_auth_verify_authorizer_reply(struct ceph_auth_client *ac,
                                      struct ceph_authorizer *a)
 {
index 41d2a0c..edb7042 100644 (file)
@@ -142,4 +142,3 @@ int ceph_auth_none_init(struct ceph_auth_client *ac)
        ac->ops = &ceph_auth_none_ops;
        return 0;
 }
-
index 860ed98..4158f06 100644 (file)
@@ -26,4 +26,3 @@ struct ceph_auth_none_info {
 int ceph_auth_none_init(struct ceph_auth_client *ac);
 
 #endif
-
index 2f4a1ba..b527323 100644 (file)
@@ -9,6 +9,7 @@
 
 #include <linux/ceph/decode.h>
 #include <linux/ceph/auth.h>
+#include <linux/ceph/ceph_features.h>
 #include <linux/ceph/libceph.h>
 #include <linux/ceph/messenger.h>
 
@@ -70,25 +71,40 @@ static int ceph_x_encrypt(struct ceph_crypto_key *secret, void *buf,
        return sizeof(u32) + ciphertext_len;
 }
 
+static int __ceph_x_decrypt(struct ceph_crypto_key *secret, void *p,
+                           int ciphertext_len)
+{
+       struct ceph_x_encrypt_header *hdr = p;
+       int plaintext_len;
+       int ret;
+
+       ret = ceph_crypt(secret, false, p, ciphertext_len, ciphertext_len,
+                        &plaintext_len);
+       if (ret)
+               return ret;
+
+       if (le64_to_cpu(hdr->magic) != CEPHX_ENC_MAGIC) {
+               pr_err("%s bad magic\n", __func__);
+               return -EINVAL;
+       }
+
+       return plaintext_len - sizeof(*hdr);
+}
+
 static int ceph_x_decrypt(struct ceph_crypto_key *secret, void **p, void *end)
 {
-       struct ceph_x_encrypt_header *hdr = *p + sizeof(u32);
-       int ciphertext_len, plaintext_len;
+       int ciphertext_len;
        int ret;
 
        ceph_decode_32_safe(p, end, ciphertext_len, e_inval);
        ceph_decode_need(p, end, ciphertext_len, e_inval);
 
-       ret = ceph_crypt(secret, false, *p, end - *p, ciphertext_len,
-                        &plaintext_len);
-       if (ret)
+       ret = __ceph_x_decrypt(secret, *p, ciphertext_len);
+       if (ret < 0)
                return ret;
 
-       if (hdr->struct_v != 1 || le64_to_cpu(hdr->magic) != CEPHX_ENC_MAGIC)
-               return -EPERM;
-
        *p += ciphertext_len;
-       return plaintext_len - sizeof(struct ceph_x_encrypt_header);
+       return ret;
 
 e_inval:
        return -EINVAL;
@@ -149,12 +165,12 @@ static int process_one_ticket(struct ceph_auth_client *ac,
        void *dp, *dend;
        int dlen;
        char is_enc;
-       struct timespec validity;
+       struct timespec64 validity;
        void *tp, *tpend;
        void **ptp;
        struct ceph_crypto_key new_session_key = { 0 };
        struct ceph_buffer *new_ticket_blob;
-       unsigned long new_expires, new_renew_after;
+       time64_t new_expires, new_renew_after;
        u64 new_secret_id;
        int ret;
 
@@ -189,11 +205,11 @@ static int process_one_ticket(struct ceph_auth_client *ac,
        if (ret)
                goto out;
 
-       ceph_decode_timespec(&validity, dp);
+       ceph_decode_timespec64(&validity, dp);
        dp += sizeof(struct ceph_timespec);
-       new_expires = get_seconds() + validity.tv_sec;
+       new_expires = ktime_get_real_seconds() + validity.tv_sec;
        new_renew_after = new_expires - (validity.tv_sec / 4);
-       dout(" expires=%lu renew_after=%lu\n", new_expires,
+       dout(" expires=%llu renew_after=%llu\n", new_expires,
             new_renew_after);
 
        /* ticket blob for service */
@@ -275,6 +291,51 @@ bad:
        return -EINVAL;
 }
 
+/*
+ * Encode and encrypt the second part (ceph_x_authorize_b) of the
+ * authorizer.  The first part (ceph_x_authorize_a) should already be
+ * encoded.
+ */
+static int encrypt_authorizer(struct ceph_x_authorizer *au,
+                             u64 *server_challenge)
+{
+       struct ceph_x_authorize_a *msg_a;
+       struct ceph_x_authorize_b *msg_b;
+       void *p, *end;
+       int ret;
+
+       msg_a = au->buf->vec.iov_base;
+       WARN_ON(msg_a->ticket_blob.secret_id != cpu_to_le64(au->secret_id));
+       p = (void *)(msg_a + 1) + le32_to_cpu(msg_a->ticket_blob.blob_len);
+       end = au->buf->vec.iov_base + au->buf->vec.iov_len;
+
+       msg_b = p + ceph_x_encrypt_offset();
+       msg_b->struct_v = 2;
+       msg_b->nonce = cpu_to_le64(au->nonce);
+       if (server_challenge) {
+               msg_b->have_challenge = 1;
+               msg_b->server_challenge_plus_one =
+                   cpu_to_le64(*server_challenge + 1);
+       } else {
+               msg_b->have_challenge = 0;
+               msg_b->server_challenge_plus_one = 0;
+       }
+
+       ret = ceph_x_encrypt(&au->session_key, p, end - p, sizeof(*msg_b));
+       if (ret < 0)
+               return ret;
+
+       p += ret;
+       if (server_challenge) {
+               WARN_ON(p != end);
+       } else {
+               WARN_ON(p > end);
+               au->buf->vec.iov_len = p - au->buf->vec.iov_base;
+       }
+
+       return 0;
+}
+
 static void ceph_x_authorizer_cleanup(struct ceph_x_authorizer *au)
 {
        ceph_crypto_key_destroy(&au->session_key);
@@ -291,7 +352,6 @@ static int ceph_x_build_authorizer(struct ceph_auth_client *ac,
        int maxlen;
        struct ceph_x_authorize_a *msg_a;
        struct ceph_x_authorize_b *msg_b;
-       void *p, *end;
        int ret;
        int ticket_blob_len =
                (th->ticket_blob ? th->ticket_blob->vec.iov_len : 0);
@@ -335,21 +395,13 @@ static int ceph_x_build_authorizer(struct ceph_auth_client *ac,
        dout(" th %p secret_id %lld %lld\n", th, th->secret_id,
             le64_to_cpu(msg_a->ticket_blob.secret_id));
 
-       p = msg_a + 1;
-       p += ticket_blob_len;
-       end = au->buf->vec.iov_base + au->buf->vec.iov_len;
-
-       msg_b = p + ceph_x_encrypt_offset();
-       msg_b->struct_v = 1;
        get_random_bytes(&au->nonce, sizeof(au->nonce));
-       msg_b->nonce = cpu_to_le64(au->nonce);
-       ret = ceph_x_encrypt(&au->session_key, p, end - p, sizeof(*msg_b));
-       if (ret < 0)
+       ret = encrypt_authorizer(au, NULL);
+       if (ret) {
+               pr_err("failed to encrypt authorizer: %d", ret);
                goto out_au;
+       }
 
-       p += ret;
-       WARN_ON(p > end);
-       au->buf->vec.iov_len = p - au->buf->vec.iov_base;
        dout(" built authorizer nonce %llx len %d\n", au->nonce,
             (int)au->buf->vec.iov_len);
        return 0;
@@ -385,13 +437,13 @@ static bool need_key(struct ceph_x_ticket_handler *th)
        if (!th->have_key)
                return true;
 
-       return get_seconds() >= th->renew_after;
+       return ktime_get_real_seconds() >= th->renew_after;
 }
 
 static bool have_key(struct ceph_x_ticket_handler *th)
 {
        if (th->have_key) {
-               if (get_seconds() >= th->expires)
+               if (ktime_get_real_seconds() >= th->expires)
                        th->have_key = false;
        }
 
@@ -626,6 +678,54 @@ static int ceph_x_update_authorizer(
        return 0;
 }
 
+static int decrypt_authorize_challenge(struct ceph_x_authorizer *au,
+                                      void *challenge_buf,
+                                      int challenge_buf_len,
+                                      u64 *server_challenge)
+{
+       struct ceph_x_authorize_challenge *ch =
+           challenge_buf + sizeof(struct ceph_x_encrypt_header);
+       int ret;
+
+       /* no leading len */
+       ret = __ceph_x_decrypt(&au->session_key, challenge_buf,
+                              challenge_buf_len);
+       if (ret < 0)
+               return ret;
+       if (ret < sizeof(*ch)) {
+               pr_err("bad size %d for ceph_x_authorize_challenge\n", ret);
+               return -EINVAL;
+       }
+
+       *server_challenge = le64_to_cpu(ch->server_challenge);
+       return 0;
+}
+
+static int ceph_x_add_authorizer_challenge(struct ceph_auth_client *ac,
+                                          struct ceph_authorizer *a,
+                                          void *challenge_buf,
+                                          int challenge_buf_len)
+{
+       struct ceph_x_authorizer *au = (void *)a;
+       u64 server_challenge;
+       int ret;
+
+       ret = decrypt_authorize_challenge(au, challenge_buf, challenge_buf_len,
+                                         &server_challenge);
+       if (ret) {
+               pr_err("failed to decrypt authorize challenge: %d", ret);
+               return ret;
+       }
+
+       ret = encrypt_authorizer(au, &server_challenge);
+       if (ret) {
+               pr_err("failed to encrypt authorizer w/ challenge: %d", ret);
+               return ret;
+       }
+
+       return 0;
+}
+
 static int ceph_x_verify_authorizer_reply(struct ceph_auth_client *ac,
                                          struct ceph_authorizer *a)
 {
@@ -637,8 +737,10 @@ static int ceph_x_verify_authorizer_reply(struct ceph_auth_client *ac,
        ret = ceph_x_decrypt(&au->session_key, &p, p + CEPHX_AU_ENC_BUF_LEN);
        if (ret < 0)
                return ret;
-       if (ret != sizeof(*reply))
-               return -EPERM;
+       if (ret < sizeof(*reply)) {
+               pr_err("bad size %d for ceph_x_authorize_reply\n", ret);
+               return -EINVAL;
+       }
 
        if (au->nonce + 1 != le64_to_cpu(reply->nonce_plus_one))
                ret = -EPERM;
@@ -704,26 +806,64 @@ static int calc_signature(struct ceph_x_authorizer *au, struct ceph_msg *msg,
                          __le64 *psig)
 {
        void *enc_buf = au->enc_buf;
-       struct {
-               __le32 len;
-               __le32 header_crc;
-               __le32 front_crc;
-               __le32 middle_crc;
-               __le32 data_crc;
-       } __packed *sigblock = enc_buf + ceph_x_encrypt_offset();
        int ret;
 
-       sigblock->len = cpu_to_le32(4*sizeof(u32));
-       sigblock->header_crc = msg->hdr.crc;
-       sigblock->front_crc = msg->footer.front_crc;
-       sigblock->middle_crc = msg->footer.middle_crc;
-       sigblock->data_crc =  msg->footer.data_crc;
-       ret = ceph_x_encrypt(&au->session_key, enc_buf, CEPHX_AU_ENC_BUF_LEN,
-                            sizeof(*sigblock));
-       if (ret < 0)
-               return ret;
+       if (!CEPH_HAVE_FEATURE(msg->con->peer_features, CEPHX_V2)) {
+               struct {
+                       __le32 len;
+                       __le32 header_crc;
+                       __le32 front_crc;
+                       __le32 middle_crc;
+                       __le32 data_crc;
+               } __packed *sigblock = enc_buf + ceph_x_encrypt_offset();
+
+               sigblock->len = cpu_to_le32(4*sizeof(u32));
+               sigblock->header_crc = msg->hdr.crc;
+               sigblock->front_crc = msg->footer.front_crc;
+               sigblock->middle_crc = msg->footer.middle_crc;
+               sigblock->data_crc =  msg->footer.data_crc;
+
+               ret = ceph_x_encrypt(&au->session_key, enc_buf,
+                                    CEPHX_AU_ENC_BUF_LEN, sizeof(*sigblock));
+               if (ret < 0)
+                       return ret;
+
+               *psig = *(__le64 *)(enc_buf + sizeof(u32));
+       } else {
+               struct {
+                       __le32 header_crc;
+                       __le32 front_crc;
+                       __le32 front_len;
+                       __le32 middle_crc;
+                       __le32 middle_len;
+                       __le32 data_crc;
+                       __le32 data_len;
+                       __le32 seq_lower_word;
+               } __packed *sigblock = enc_buf;
+               struct {
+                       __le64 a, b, c, d;
+               } __packed *penc = enc_buf;
+               int ciphertext_len;
+
+               sigblock->header_crc = msg->hdr.crc;
+               sigblock->front_crc = msg->footer.front_crc;
+               sigblock->front_len = msg->hdr.front_len;
+               sigblock->middle_crc = msg->footer.middle_crc;
+               sigblock->middle_len = msg->hdr.middle_len;
+               sigblock->data_crc =  msg->footer.data_crc;
+               sigblock->data_len = msg->hdr.data_len;
+               sigblock->seq_lower_word = *(__le32 *)&msg->hdr.seq;
+
+               /* no leading len, no ceph_x_encrypt_header */
+               ret = ceph_crypt(&au->session_key, true, enc_buf,
+                                CEPHX_AU_ENC_BUF_LEN, sizeof(*sigblock),
+                                &ciphertext_len);
+               if (ret)
+                       return ret;
+
+               *psig = penc->a ^ penc->b ^ penc->c ^ penc->d;
+       }
 
-       *psig = *(__le64 *)(enc_buf + sizeof(u32));
        return 0;
 }
 
@@ -778,6 +918,7 @@ static const struct ceph_auth_client_ops ceph_x_ops = {
        .handle_reply = ceph_x_handle_reply,
        .create_authorizer = ceph_x_create_authorizer,
        .update_authorizer = ceph_x_update_authorizer,
+       .add_authorizer_challenge = ceph_x_add_authorizer_challenge,
        .verify_authorizer_reply = ceph_x_verify_authorizer_reply,
        .invalidate_authorizer = ceph_x_invalidate_authorizer,
        .reset =  ceph_x_reset,
@@ -823,5 +964,3 @@ out_nomem:
 out:
        return ret;
 }
-
-
index 454cb54..c03735f 100644 (file)
@@ -22,7 +22,7 @@ struct ceph_x_ticket_handler {
        u64 secret_id;
        struct ceph_buffer *ticket_blob;
 
-       unsigned long renew_after, expires;
+       time64_t renew_after, expires;
 };
 
 #define CEPHX_AU_ENC_BUF_LEN   128  /* big enough for encrypted blob */
@@ -52,4 +52,3 @@ struct ceph_x_info {
 int ceph_x_init(struct ceph_auth_client *ac);
 
 #endif
-
index 32c13d7..24b0b74 100644 (file)
@@ -70,6 +70,13 @@ struct ceph_x_authorize_a {
 struct ceph_x_authorize_b {
        __u8 struct_v;
        __le64 nonce;
+       __u8 have_challenge;
+       __le64 server_challenge_plus_one;
+} __attribute__ ((packed));
+
+struct ceph_x_authorize_challenge {
+       __u8 struct_v;
+       __le64 server_challenge;
 } __attribute__ ((packed));
 
 struct ceph_x_authorize_reply {
index 584fdbe..87afb9e 100644 (file)
@@ -304,7 +304,7 @@ static int get_secret(struct ceph_crypto_key *dst, const char *name) {
        struct ceph_crypto_key *ckey;
 
        ukey = request_key(&key_type_ceph, name, NULL);
-       if (!ukey || IS_ERR(ukey)) {
+       if (IS_ERR(ukey)) {
                /* request_key errors don't map nicely to mount(2)
                   errors; don't even try, but still printk */
                key_err = PTR_ERR(ukey);
@@ -379,7 +379,7 @@ ceph_parse_options(char *options, const char *dev_name,
 
        /* parse mount options */
        while ((c = strsep(&options, ",")) != NULL) {
-               int token, intval, ret;
+               int token, intval;
                if (!*c)
                        continue;
                err = -EINVAL;
@@ -394,11 +394,10 @@ ceph_parse_options(char *options, const char *dev_name,
                        continue;
                }
                if (token < Opt_last_int) {
-                       ret = match_int(&argstr[0], &intval);
-                       if (ret < 0) {
-                               pr_err("bad mount option arg (not int) "
-                                      "at '%s'\n", c);
-                               continue;
+                       err = match_int(&argstr[0], &intval);
+                       if (err < 0) {
+                               pr_err("bad option arg (not int) at '%s'\n", c);
+                               goto out;
                        }
                        dout("got int token %d val %d\n", token, intval);
                } else if (token > Opt_last_int && token < Opt_last_string) {
index 8d2032b..2105a6e 100644 (file)
@@ -32,7 +32,7 @@ int ceph_cls_lock(struct ceph_osd_client *osdc,
        int desc_len = strlen(desc);
        void *p, *end;
        struct page *lock_op_page;
-       struct timespec mtime;
+       struct timespec64 mtime;
        int ret;
 
        lock_op_buf_size = name_len + sizeof(__le32) +
@@ -63,7 +63,7 @@ int ceph_cls_lock(struct ceph_osd_client *osdc,
        ceph_encode_string(&p, end, desc, desc_len);
        /* only support infinite duration */
        memset(&mtime, 0, sizeof(mtime));
-       ceph_encode_timespec(p, &mtime);
+       ceph_encode_timespec64(p, &mtime);
        p += sizeof(struct ceph_timespec);
        ceph_encode_8(&p, flags);
 
index 417df67..3f323ed 100644 (file)
@@ -514,7 +514,7 @@ static int crush_choose_firstn(const struct crush_map *map,
                                                in, work->work[-1-in->id],
                                                x, r,
                                                (choose_args ?
-                                                &choose_args[-1-in->id] : 0),
+                                                &choose_args[-1-in->id] : NULL),
                                                outpos);
                                if (item >= map->max_devices) {
                                        dprintk("   bad item %d\n", item);
@@ -725,7 +725,7 @@ static void crush_choose_indep(const struct crush_map *map,
                                        in, work->work[-1-in->id],
                                        x, r,
                                        (choose_args ?
-                                        &choose_args[-1-in->id] : 0),
+                                        &choose_args[-1-in->id] : NULL),
                                        outpos);
                                if (item >= map->max_devices) {
                                        dprintk("   bad item %d\n", item);
index c6413c3..0a18719 100644 (file)
@@ -1417,11 +1417,11 @@ static void prepare_write_keepalive(struct ceph_connection *con)
        dout("prepare_write_keepalive %p\n", con);
        con_out_kvec_reset(con);
        if (con->peer_features & CEPH_FEATURE_MSGR_KEEPALIVE2) {
-               struct timespec now;
+               struct timespec64 now;
 
-               ktime_get_real_ts(&now);
+               ktime_get_real_ts64(&now);
                con_out_kvec_add(con, sizeof(tag_keepalive2), &tag_keepalive2);
-               ceph_encode_timespec(&con->out_temp_keepalive2, &now);
+               ceph_encode_timespec64(&con->out_temp_keepalive2, &now);
                con_out_kvec_add(con, sizeof(con->out_temp_keepalive2),
                                 &con->out_temp_keepalive2);
        } else {
@@ -1434,24 +1434,26 @@ static void prepare_write_keepalive(struct ceph_connection *con)
  * Connection negotiation.
  */
 
-static struct ceph_auth_handshake *get_connect_authorizer(struct ceph_connection *con,
-                                               int *auth_proto)
+static int get_connect_authorizer(struct ceph_connection *con)
 {
        struct ceph_auth_handshake *auth;
+       int auth_proto;
 
        if (!con->ops->get_authorizer) {
+               con->auth = NULL;
                con->out_connect.authorizer_protocol = CEPH_AUTH_UNKNOWN;
                con->out_connect.authorizer_len = 0;
-               return NULL;
+               return 0;
        }
 
-       auth = con->ops->get_authorizer(con, auth_proto, con->auth_retry);
+       auth = con->ops->get_authorizer(con, &auth_proto, con->auth_retry);
        if (IS_ERR(auth))
-               return auth;
+               return PTR_ERR(auth);
 
-       con->auth_reply_buf = auth->authorizer_reply_buf;
-       con->auth_reply_buf_len = auth->authorizer_reply_buf_len;
-       return auth;
+       con->auth = auth;
+       con->out_connect.authorizer_protocol = cpu_to_le32(auth_proto);
+       con->out_connect.authorizer_len = cpu_to_le32(auth->authorizer_buf_len);
+       return 0;
 }
 
 /*
@@ -1467,12 +1469,22 @@ static void prepare_write_banner(struct ceph_connection *con)
        con_flag_set(con, CON_FLAG_WRITE_PENDING);
 }
 
+static void __prepare_write_connect(struct ceph_connection *con)
+{
+       con_out_kvec_add(con, sizeof(con->out_connect), &con->out_connect);
+       if (con->auth)
+               con_out_kvec_add(con, con->auth->authorizer_buf_len,
+                                con->auth->authorizer_buf);
+
+       con->out_more = 0;
+       con_flag_set(con, CON_FLAG_WRITE_PENDING);
+}
+
 static int prepare_write_connect(struct ceph_connection *con)
 {
        unsigned int global_seq = get_global_seq(con->msgr, 0);
        int proto;
-       int auth_proto;
-       struct ceph_auth_handshake *auth;
+       int ret;
 
        switch (con->peer_name.type) {
        case CEPH_ENTITY_TYPE_MON:
@@ -1499,24 +1511,11 @@ static int prepare_write_connect(struct ceph_connection *con)
        con->out_connect.protocol_version = cpu_to_le32(proto);
        con->out_connect.flags = 0;
 
-       auth_proto = CEPH_AUTH_UNKNOWN;
-       auth = get_connect_authorizer(con, &auth_proto);
-       if (IS_ERR(auth))
-               return PTR_ERR(auth);
-
-       con->out_connect.authorizer_protocol = cpu_to_le32(auth_proto);
-       con->out_connect.authorizer_len = auth ?
-               cpu_to_le32(auth->authorizer_buf_len) : 0;
-
-       con_out_kvec_add(con, sizeof (con->out_connect),
-                                       &con->out_connect);
-       if (auth && auth->authorizer_buf_len)
-               con_out_kvec_add(con, auth->authorizer_buf_len,
-                                       auth->authorizer_buf);
-
-       con->out_more = 0;
-       con_flag_set(con, CON_FLAG_WRITE_PENDING);
+       ret = get_connect_authorizer(con);
+       if (ret)
+               return ret;
 
+       __prepare_write_connect(con);
        return 0;
 }
 
@@ -1781,11 +1780,21 @@ static int read_partial_connect(struct ceph_connection *con)
        if (ret <= 0)
                goto out;
 
-       size = le32_to_cpu(con->in_reply.authorizer_len);
-       end += size;
-       ret = read_partial(con, end, size, con->auth_reply_buf);
-       if (ret <= 0)
-               goto out;
+       if (con->auth) {
+               size = le32_to_cpu(con->in_reply.authorizer_len);
+               if (size > con->auth->authorizer_reply_buf_len) {
+                       pr_err("authorizer reply too big: %d > %zu\n", size,
+                              con->auth->authorizer_reply_buf_len);
+                       ret = -EINVAL;
+                       goto out;
+               }
+
+               end += size;
+               ret = read_partial(con, end, size,
+                                  con->auth->authorizer_reply_buf);
+               if (ret <= 0)
+                       goto out;
+       }
 
        dout("read_partial_connect %p tag %d, con_seq = %u, g_seq = %u\n",
             con, (int)con->in_reply.tag,
@@ -1793,7 +1802,6 @@ static int read_partial_connect(struct ceph_connection *con)
             le32_to_cpu(con->in_reply.global_seq));
 out:
        return ret;
-
 }
 
 /*
@@ -2076,12 +2084,27 @@ static int process_connect(struct ceph_connection *con)
 
        dout("process_connect on %p tag %d\n", con, (int)con->in_tag);
 
-       if (con->auth_reply_buf) {
+       if (con->auth) {
                /*
                 * Any connection that defines ->get_authorizer()
-                * should also define ->verify_authorizer_reply().
+                * should also define ->add_authorizer_challenge() and
+                * ->verify_authorizer_reply().
+                *
                 * See get_connect_authorizer().
                 */
+               if (con->in_reply.tag == CEPH_MSGR_TAG_CHALLENGE_AUTHORIZER) {
+                       ret = con->ops->add_authorizer_challenge(
+                                   con, con->auth->authorizer_reply_buf,
+                                   le32_to_cpu(con->in_reply.authorizer_len));
+                       if (ret < 0)
+                               return ret;
+
+                       con_out_kvec_reset(con);
+                       __prepare_write_connect(con);
+                       prepare_read_connect(con);
+                       return 0;
+               }
+
                ret = con->ops->verify_authorizer_reply(con);
                if (ret < 0) {
                        con->error_msg = "bad authorize reply";
@@ -2555,7 +2578,7 @@ static int read_keepalive_ack(struct ceph_connection *con)
        int ret = read_partial(con, size, size, &ceph_ts);
        if (ret <= 0)
                return ret;
-       ceph_decode_timespec(&con->last_keepalive_ack, &ceph_ts);
+       ceph_decode_timespec64(&con->last_keepalive_ack, &ceph_ts);
        prepare_read_tag(con);
        return 1;
 }
@@ -3223,12 +3246,12 @@ bool ceph_con_keepalive_expired(struct ceph_connection *con,
 {
        if (interval > 0 &&
            (con->peer_features & CEPH_FEATURE_MSGR_KEEPALIVE2)) {
-               struct timespec now;
-               struct timespec ts;
-               ktime_get_real_ts(&now);
-               jiffies_to_timespec(interval, &ts);
-               ts = timespec_add(con->last_keepalive_ack, ts);
-               return timespec_compare(&now, &ts) >= 0;
+               struct timespec64 now;
+               struct timespec64 ts;
+               ktime_get_real_ts64(&now);
+               jiffies_to_timespec64(interval, &ts);
+               ts = timespec64_add(con->last_keepalive_ack, ts);
+               return timespec64_compare(&now, &ts) >= 0;
        }
        return false;
 }
index d7a7a23..18deb3d 100644 (file)
@@ -1249,7 +1249,7 @@ static void dispatch(struct ceph_connection *con, struct ceph_msg *msg)
                if (monc->client->extra_mon_dispatch &&
                    monc->client->extra_mon_dispatch(monc->client, msg) == 0)
                        break;
-                       
+
                pr_err("received unknown message type %d %s\n", type,
                       ceph_msg_type_name(type));
        }
index a00c74f..60934bd 100644 (file)
@@ -1978,7 +1978,7 @@ static void encode_request_partial(struct ceph_osd_request *req,
        p += sizeof(struct ceph_blkin_trace_info);
 
        ceph_encode_32(&p, 0); /* client_inc, always 0 */
-       ceph_encode_timespec(p, &req->r_mtime);
+       ceph_encode_timespec64(p, &req->r_mtime);
        p += sizeof(struct ceph_timespec);
 
        encode_oloc(&p, end, &req->r_t.target_oloc);
@@ -4512,7 +4512,7 @@ ceph_osdc_watch(struct ceph_osd_client *osdc,
        ceph_oid_copy(&lreq->t.base_oid, oid);
        ceph_oloc_copy(&lreq->t.base_oloc, oloc);
        lreq->t.flags = CEPH_OSD_FLAG_WRITE;
-       ktime_get_real_ts(&lreq->mtime);
+       ktime_get_real_ts64(&lreq->mtime);
 
        lreq->reg_req = alloc_linger_request(lreq);
        if (!lreq->reg_req) {
@@ -4570,7 +4570,7 @@ int ceph_osdc_unwatch(struct ceph_osd_client *osdc,
        ceph_oid_copy(&req->r_base_oid, &lreq->t.base_oid);
        ceph_oloc_copy(&req->r_base_oloc, &lreq->t.base_oloc);
        req->r_flags = CEPH_OSD_FLAG_WRITE;
-       ktime_get_real_ts(&req->r_mtime);
+       ktime_get_real_ts64(&req->r_mtime);
        osd_req_op_watch_init(req, 0, lreq->linger_id,
                              CEPH_OSD_WATCH_OP_UNWATCH);
 
@@ -4591,7 +4591,7 @@ EXPORT_SYMBOL(ceph_osdc_unwatch);
 
 static int osd_req_op_notify_ack_init(struct ceph_osd_request *req, int which,
                                      u64 notify_id, u64 cookie, void *payload,
-                                     size_t payload_len)
+                                     u32 payload_len)
 {
        struct ceph_osd_req_op *op;
        struct ceph_pagelist *pl;
@@ -4628,7 +4628,7 @@ int ceph_osdc_notify_ack(struct ceph_osd_client *osdc,
                         u64 notify_id,
                         u64 cookie,
                         void *payload,
-                        size_t payload_len)
+                        u32 payload_len)
 {
        struct ceph_osd_request *req;
        int ret;
@@ -4661,7 +4661,7 @@ EXPORT_SYMBOL(ceph_osdc_notify_ack);
 
 static int osd_req_op_notify_init(struct ceph_osd_request *req, int which,
                                  u64 cookie, u32 prot_ver, u32 timeout,
-                                 void *payload, size_t payload_len)
+                                 void *payload, u32 payload_len)
 {
        struct ceph_osd_req_op *op;
        struct ceph_pagelist *pl;
@@ -4701,7 +4701,7 @@ int ceph_osdc_notify(struct ceph_osd_client *osdc,
                     struct ceph_object_id *oid,
                     struct ceph_object_locator *oloc,
                     void *payload,
-                    size_t payload_len,
+                    u32 payload_len,
                     u32 timeout,
                     struct page ***preply_pages,
                     size_t *preply_len)
@@ -5136,7 +5136,7 @@ int ceph_osdc_writepages(struct ceph_osd_client *osdc, struct ceph_vino vino,
                         struct ceph_snap_context *snapc,
                         u64 off, u64 len,
                         u32 truncate_seq, u64 truncate_size,
-                        struct timespec *mtime,
+                        struct timespec64 *mtime,
                         struct page **pages, int num_pages)
 {
        struct ceph_osd_request *req;
@@ -5393,6 +5393,16 @@ static struct ceph_auth_handshake *get_authorizer(struct ceph_connection *con,
        return auth;
 }
 
+static int add_authorizer_challenge(struct ceph_connection *con,
+                                   void *challenge_buf, int challenge_buf_len)
+{
+       struct ceph_osd *o = con->private;
+       struct ceph_osd_client *osdc = o->o_osdc;
+       struct ceph_auth_client *ac = osdc->client->monc.auth;
+
+       return ceph_auth_add_authorizer_challenge(ac, o->o_auth.authorizer,
+                                           challenge_buf, challenge_buf_len);
+}
 
 static int verify_authorizer_reply(struct ceph_connection *con)
 {
@@ -5442,6 +5452,7 @@ static const struct ceph_connection_operations osd_con_ops = {
        .put = put_osd_con,
        .dispatch = dispatch,
        .get_authorizer = get_authorizer,
+       .add_authorizer_challenge = add_authorizer_challenge,
        .verify_authorizer_reply = verify_authorizer_reply,
        .invalidate_authorizer = invalidate_authorizer,
        .alloc_msg = alloc_msg,
index e560d39..d3736f5 100644 (file)
@@ -197,4 +197,3 @@ void ceph_zero_page_vector_range(int off, int len, struct page **pages)
        }
 }
 EXPORT_SYMBOL(ceph_zero_page_vector_range);
-
index 738871a..670c84b 100644 (file)
@@ -1001,22 +1001,18 @@ static int register_pernet_operations(struct list_head *list,
        int error;
 
        if (ops->id) {
-again:
-               error = ida_get_new_above(&net_generic_ids, MIN_PERNET_OPS_ID, ops->id);
-               if (error < 0) {
-                       if (error == -EAGAIN) {
-                               ida_pre_get(&net_generic_ids, GFP_KERNEL);
-                               goto again;
-                       }
+               error = ida_alloc_min(&net_generic_ids, MIN_PERNET_OPS_ID,
+                               GFP_KERNEL);
+               if (error < 0)
                        return error;
-               }
+               *ops->id = error;
                max_gen_ptrs = max(max_gen_ptrs, *ops->id + 1);
        }
        error = __register_pernet_operations(list, ops);
        if (error) {
                rcu_barrier();
                if (ops->id)
-                       ida_remove(&net_generic_ids, *ops->id);
+                       ida_free(&net_generic_ids, *ops->id);
        }
 
        return error;
@@ -1027,7 +1023,7 @@ static void unregister_pernet_operations(struct pernet_operations *ops)
        __unregister_pernet_operations(ops);
        rcu_barrier();
        if (ops->id)
-               ida_remove(&net_generic_ids, *ops->id);
+               ida_free(&net_generic_ids, *ops->id);
 }
 
 /**
index 05dc1b7..cad48d0 100644 (file)
@@ -296,10 +296,10 @@ config IP_VS_MH_TAB_INDEX
          stored in a hash table. This table is assigned by a preference
          list of the positions to each destination until all slots in
          the table are filled. The index determines the prime for size of
-         the table as 251, 509, 1021, 2039, 4093, 8191, 16381, 32749,
-         65521 or 131071. When using weights to allow destinations to
-         receive more connections, the table is assigned an amount
-         proportional to the weights specified. The table needs to be large
+         the table as 251, 509, 1021, 2039, 4093, 8191, 16381, 32749,
+         65521 or 131071. When using weights to allow destinations to
+         receive more connections, the table is assigned an amount
+         proportional to the weights specified. The table needs to be large
          enough to effectively fit all the destinations multiplied by their
          respective weights.
 
index 0f795b1..94d9d34 100644 (file)
@@ -5,10 +5,10 @@
  *
  */
 
-/* The mh algorithm is to assign a preference list of all the lookup
+/* The mh algorithm is to assign a preference list of all the lookup
  * table positions to each destination and populate the table with
  * the most-preferred position of destinations. Then it is to select
- * destination with the hash key of source IP address through looking
+ * destination with the hash key of source IP address through looking
  * up a the lookup table.
  *
  * The algorithm is detailed in:
index 9bb5274..e519ef2 100644 (file)
@@ -145,17 +145,21 @@ out:
 
 static int smc_ib_fill_mac(struct smc_ib_device *smcibdev, u8 ibport)
 {
-       struct ib_gid_attr gattr;
-       union ib_gid gid;
-       int rc;
+       const struct ib_gid_attr *attr;
+       int rc = 0;
 
-       rc = ib_query_gid(smcibdev->ibdev, ibport, 0, &gid, &gattr);
-       if (rc || !gattr.ndev)
+       attr = rdma_get_gid_attr(smcibdev->ibdev, ibport, 0);
+       if (IS_ERR(attr))
                return -ENODEV;
 
-       memcpy(smcibdev->mac[ibport - 1], gattr.ndev->dev_addr, ETH_ALEN);
-       dev_put(gattr.ndev);
-       return 0;
+       if (attr->ndev)
+               memcpy(smcibdev->mac[ibport - 1], attr->ndev->dev_addr,
+                      ETH_ALEN);
+       else
+               rc = -ENODEV;
+
+       rdma_put_gid_attr(attr);
+       return rc;
 }
 
 /* Create an identifier unique for this instance of SMC-R.
@@ -180,29 +184,27 @@ bool smc_ib_port_active(struct smc_ib_device *smcibdev, u8 ibport)
 int smc_ib_determine_gid(struct smc_ib_device *smcibdev, u8 ibport,
                         unsigned short vlan_id, u8 gid[], u8 *sgid_index)
 {
-       struct ib_gid_attr gattr;
-       union ib_gid _gid;
+       const struct ib_gid_attr *attr;
        int i;
 
        for (i = 0; i < smcibdev->pattr[ibport - 1].gid_tbl_len; i++) {
-               memset(&_gid, 0, SMC_GID_SIZE);
-               memset(&gattr, 0, sizeof(gattr));
-               if (ib_query_gid(smcibdev->ibdev, ibport, i, &_gid, &gattr))
+               attr = rdma_get_gid_attr(smcibdev->ibdev, ibport, i);
+               if (IS_ERR(attr))
                        continue;
-               if (!gattr.ndev)
-                       continue;
-               if (((!vlan_id && !is_vlan_dev(gattr.ndev)) ||
-                    (vlan_id && is_vlan_dev(gattr.ndev) &&
-                     vlan_dev_vlan_id(gattr.ndev) == vlan_id)) &&
-                   gattr.gid_type == IB_GID_TYPE_IB) {
+
+               if (attr->ndev &&
+                   ((!vlan_id && !is_vlan_dev(attr->ndev)) ||
+                    (vlan_id && is_vlan_dev(attr->ndev) &&
+                     vlan_dev_vlan_id(attr->ndev) == vlan_id)) &&
+                   attr->gid_type == IB_GID_TYPE_ROCE) {
                        if (gid)
-                               memcpy(gid, &_gid, SMC_GID_SIZE);
+                               memcpy(gid, &attr->gid, SMC_GID_SIZE);
                        if (sgid_index)
-                               *sgid_index = i;
-                       dev_put(gattr.ndev);
+                               *sgid_index = attr->index;
+                       rdma_put_gid_attr(attr);
                        return 0;
                }
-               dev_put(gattr.ndev);
+               rdma_put_gid_attr(attr);
        }
        return -ENODEV;
 }
index d2623b9..305ecea 100644 (file)
@@ -50,7 +50,7 @@ static int param_set_hashtbl_sz(const char *val, const struct kernel_param *kp)
        if (!val)
                goto out_inval;
        ret = kstrtoul(val, 0, &num);
-       if (ret == -EINVAL)
+       if (ret)
                goto out_inval;
        nbits = fls(num - 1);
        if (nbits > MAX_HASHTABLE_BITS || nbits < 2)
@@ -253,7 +253,7 @@ rpcauth_list_flavors(rpc_authflavor_t *array, int size)
 EXPORT_SYMBOL_GPL(rpcauth_list_flavors);
 
 struct rpc_auth *
-rpcauth_create(struct rpc_auth_create_args *args, struct rpc_clnt *clnt)
+rpcauth_create(const struct rpc_auth_create_args *args, struct rpc_clnt *clnt)
 {
        struct rpc_auth         *auth;
        const struct rpc_authops *ops;
index 0fc397f..21c0aa0 100644 (file)
@@ -284,7 +284,12 @@ err:
        return p;
 }
 
-#define UPCALL_BUF_LEN 128
+/* XXX: Need some documentation about why UPCALL_BUF_LEN is so small.
+ *     Is user space expecting no more than UPCALL_BUF_LEN bytes?
+ *     Note that there are now _two_ NI_MAXHOST sized data items
+ *     being passed in this string.
+ */
+#define UPCALL_BUF_LEN 256
 
 struct gss_upcall_msg {
        refcount_t count;
@@ -456,18 +461,44 @@ static int gss_encode_v1_msg(struct gss_upcall_msg *gss_msg,
        buflen -= len;
        p += len;
        gss_msg->msg.len = len;
+
+       /*
+        * target= is a full service principal that names the remote
+        * identity that we are authenticating to.
+        */
        if (target_name) {
                len = scnprintf(p, buflen, "target=%s ", target_name);
                buflen -= len;
                p += len;
                gss_msg->msg.len += len;
        }
-       if (service_name != NULL) {
-               len = scnprintf(p, buflen, "service=%s ", service_name);
+
+       /*
+        * gssd uses service= and srchost= to select a matching key from
+        * the system's keytab to use as the source principal.
+        *
+        * service= is the service name part of the source principal,
+        * or "*" (meaning choose any).
+        *
+        * srchost= is the hostname part of the source principal. When
+        * not provided, gssd uses the local hostname.
+        */
+       if (service_name) {
+               char *c = strchr(service_name, '@');
+
+               if (!c)
+                       len = scnprintf(p, buflen, "service=%s ",
+                                       service_name);
+               else
+                       len = scnprintf(p, buflen,
+                                       "service=%.*s srchost=%s ",
+                                       (int)(c - service_name),
+                                       service_name, c + 1);
                buflen -= len;
                p += len;
                gss_msg->msg.len += len;
        }
+
        if (mech->gm_upcall_enctypes) {
                len = scnprintf(p, buflen, "enctypes=%s ",
                                mech->gm_upcall_enctypes);
@@ -985,7 +1016,7 @@ static void gss_pipe_free(struct gss_pipe *p)
  * parameters based on the input flavor (which must be a pseudoflavor)
  */
 static struct gss_auth *
-gss_create_new(struct rpc_auth_create_args *args, struct rpc_clnt *clnt)
+gss_create_new(const struct rpc_auth_create_args *args, struct rpc_clnt *clnt)
 {
        rpc_authflavor_t flavor = args->pseudoflavor;
        struct gss_auth *gss_auth;
@@ -1132,7 +1163,7 @@ gss_destroy(struct rpc_auth *auth)
  * (which is guaranteed to last as long as any of its descendants).
  */
 static struct gss_auth *
-gss_auth_find_or_add_hashed(struct rpc_auth_create_args *args,
+gss_auth_find_or_add_hashed(const struct rpc_auth_create_args *args,
                struct rpc_clnt *clnt,
                struct gss_auth *new)
 {
@@ -1169,7 +1200,8 @@ out:
 }
 
 static struct gss_auth *
-gss_create_hashed(struct rpc_auth_create_args *args, struct rpc_clnt *clnt)
+gss_create_hashed(const struct rpc_auth_create_args *args,
+                 struct rpc_clnt *clnt)
 {
        struct gss_auth *gss_auth;
        struct gss_auth *new;
@@ -1188,7 +1220,7 @@ out:
 }
 
 static struct rpc_auth *
-gss_create(struct rpc_auth_create_args *args, struct rpc_clnt *clnt)
+gss_create(const struct rpc_auth_create_args *args, struct rpc_clnt *clnt)
 {
        struct gss_auth *gss_auth;
        struct rpc_xprt_switch *xps = rcu_access_pointer(clnt->cl_xpi.xpi_xpswitch);
@@ -1571,7 +1603,7 @@ static int gss_cred_is_negative_entry(struct rpc_cred *cred)
        if (test_bit(RPCAUTH_CRED_NEGATIVE, &cred->cr_flags)) {
                unsigned long now = jiffies;
                unsigned long begin, expire;
-               struct gss_cred *gss_cred; 
+               struct gss_cred *gss_cred;
 
                gss_cred = container_of(cred, struct gss_cred, gc_base);
                begin = gss_cred->gc_upcall_timestamp;
index 254defe..fe97f31 100644 (file)
@@ -231,4 +231,3 @@ g_verify_token_header(struct xdr_netobj *mech, int *body_size,
 }
 
 EXPORT_SYMBOL_GPL(g_verify_token_header);
-
index 8654494..0220e1c 100644 (file)
@@ -169,7 +169,7 @@ make_checksum_hmac_md5(struct krb5_ctx *kctx, char *header, int hdrlen,
        struct scatterlist              sg[1];
        int err = -1;
        u8 *checksumdata;
-       u8 rc4salt[4];
+       u8 *rc4salt;
        struct crypto_ahash *md5;
        struct crypto_ahash *hmac_md5;
        struct ahash_request *req;
@@ -183,14 +183,18 @@ make_checksum_hmac_md5(struct krb5_ctx *kctx, char *header, int hdrlen,
                return GSS_S_FAILURE;
        }
 
+       rc4salt = kmalloc_array(4, sizeof(*rc4salt), GFP_NOFS);
+       if (!rc4salt)
+               return GSS_S_FAILURE;
+
        if (arcfour_hmac_md5_usage_to_salt(usage, rc4salt)) {
                dprintk("%s: invalid usage value %u\n", __func__, usage);
-               return GSS_S_FAILURE;
+               goto out_free_rc4salt;
        }
 
        checksumdata = kmalloc(GSS_KRB5_MAX_CKSUM_LEN, GFP_NOFS);
        if (!checksumdata)
-               return GSS_S_FAILURE;
+               goto out_free_rc4salt;
 
        md5 = crypto_alloc_ahash("md5", 0, CRYPTO_ALG_ASYNC);
        if (IS_ERR(md5))
@@ -258,6 +262,8 @@ out_free_md5:
        crypto_free_ahash(md5);
 out_free_cksum:
        kfree(checksumdata);
+out_free_rc4salt:
+       kfree(rc4salt);
        return err ? GSS_S_FAILURE : 0;
 }
 
@@ -373,7 +379,6 @@ make_checksum_v2(struct krb5_ctx *kctx, char *header, int hdrlen,
        struct scatterlist sg[1];
        int err = -1;
        u8 *checksumdata;
-       unsigned int checksumlen;
 
        if (kctx->gk5e->keyed_cksum == 0) {
                dprintk("%s: expected keyed hash for %s\n",
@@ -393,7 +398,6 @@ make_checksum_v2(struct krb5_ctx *kctx, char *header, int hdrlen,
        tfm = crypto_alloc_ahash(kctx->gk5e->cksum_name, 0, CRYPTO_ALG_ASYNC);
        if (IS_ERR(tfm))
                goto out_free_cksum;
-       checksumlen = crypto_ahash_digestsize(tfm);
 
        req = ahash_request_alloc(tfm, GFP_NOFS);
        if (!req)
@@ -1077,4 +1081,3 @@ out_err:
        dprintk("%s: returning %d\n", __func__, err);
        return err;
 }
-
index 8701331..f7fe2d2 100644 (file)
@@ -324,4 +324,3 @@ u32 gss_krb5_aes_make_key(const struct gss_krb5_enctype *gk5e,
 err_out:
        return ret;
 }
-
index 94a2b3f..eaad9bc 100644 (file)
@@ -229,4 +229,3 @@ gss_get_mic_kerberos(struct gss_ctx *gss_ctx, struct xdr_buf *text,
                return gss_get_mic_v2(ctx, text, token);
        }
 }
-
index b601a73..ef2b25b 100644 (file)
@@ -225,4 +225,3 @@ gss_verify_mic_kerberos(struct gss_ctx *gss_ctx,
                return gss_verify_mic_v2(ctx, message_buffer, read_token);
        }
 }
-
index a737c2d..39a2e67 100644 (file)
@@ -440,7 +440,6 @@ static u32
 gss_wrap_kerberos_v2(struct krb5_ctx *kctx, u32 offset,
                     struct xdr_buf *buf, struct page **pages)
 {
-       int             blocksize;
        u8              *ptr, *plainhdr;
        s32             now;
        u8              flags = 0x00;
@@ -473,7 +472,6 @@ gss_wrap_kerberos_v2(struct krb5_ctx *kctx, u32 offset,
        *ptr++ = 0xff;
        be16ptr = (__be16 *)ptr;
 
-       blocksize = crypto_skcipher_blocksize(kctx->acceptor_enc);
        *be16ptr++ = 0;
        /* "inner" token header always uses 0 for RRC */
        *be16ptr++ = 0;
@@ -623,4 +621,3 @@ gss_unwrap_kerberos(struct gss_ctx *gctx, int offset, struct xdr_buf *buf)
                return gss_unwrap_kerberos_v2(kctx, offset, buf);
        }
 }
-
index 1c7c49d..73dcda0 100644 (file)
@@ -234,6 +234,35 @@ static int gssp_alloc_receive_pages(struct gssx_arg_accept_sec_context *arg)
        return 0;
 }
 
+static char *gssp_stringify(struct xdr_netobj *netobj)
+{
+       return kstrndup(netobj->data, netobj->len, GFP_KERNEL);
+}
+
+static void gssp_hostbased_service(char **principal)
+{
+       char *c;
+
+       if (!*principal)
+               return;
+
+       /* terminate and remove realm part */
+       c = strchr(*principal, '@');
+       if (c) {
+               *c = '\0';
+
+               /* change service-hostname delimiter */
+               c = strchr(*principal, '/');
+               if (c)
+                       *c = '@';
+       }
+       if (!c) {
+               /* not a service principal */
+               kfree(*principal);
+               *principal = NULL;
+       }
+}
+
 /*
  * Public functions
  */
@@ -262,6 +291,7 @@ int gssp_accept_sec_context_upcall(struct net *net,
                 */
                .exported_context_token.len = GSSX_max_output_handle_sz,
                .mech.len = GSS_OID_MAX_LEN,
+               .targ_name.display_name.len = GSSX_max_princ_sz,
                .src_name.display_name.len = GSSX_max_princ_sz
        };
        struct gssx_res_accept_sec_context res = {
@@ -275,6 +305,7 @@ int gssp_accept_sec_context_upcall(struct net *net,
                .rpc_cred = NULL, /* FIXME ? */
        };
        struct xdr_netobj client_name = { 0 , NULL };
+       struct xdr_netobj target_name = { 0, NULL };
        int ret;
 
        if (data->in_handle.len != 0)
@@ -285,8 +316,6 @@ int gssp_accept_sec_context_upcall(struct net *net,
        if (ret)
                return ret;
 
-       /* use nfs/ for targ_name ? */
-
        ret = gssp_call(net, &msg);
 
        gssp_free_receive_pages(&arg);
@@ -304,6 +333,7 @@ int gssp_accept_sec_context_upcall(struct net *net,
                        kfree(rctxh.mech.data);
                }
                client_name = rctxh.src_name.display_name;
+               target_name = rctxh.targ_name.display_name;
        }
 
        if (res.options.count == 1) {
@@ -325,32 +355,22 @@ int gssp_accept_sec_context_upcall(struct net *net,
        }
 
        /* convert to GSS_NT_HOSTBASED_SERVICE form and set into creds */
-       if (data->found_creds && client_name.data != NULL) {
-               char *c;
-
-               data->creds.cr_raw_principal = kstrndup(client_name.data,
-                                               client_name.len, GFP_KERNEL);
-
-               data->creds.cr_principal = kstrndup(client_name.data,
-                                               client_name.len, GFP_KERNEL);
-               if (data->creds.cr_principal) {
-                       /* terminate and remove realm part */
-                       c = strchr(data->creds.cr_principal, '@');
-                       if (c) {
-                               *c = '\0';
-
-                               /* change service-hostname delimiter */
-                               c = strchr(data->creds.cr_principal, '/');
-                               if (c) *c = '@';
-                       }
-                       if (!c) {
-                               /* not a service principal */
-                               kfree(data->creds.cr_principal);
-                               data->creds.cr_principal = NULL;
-                       }
+       if (data->found_creds) {
+               if (client_name.data) {
+                       data->creds.cr_raw_principal =
+                                       gssp_stringify(&client_name);
+                       data->creds.cr_principal =
+                                       gssp_stringify(&client_name);
+                       gssp_hostbased_service(&data->creds.cr_principal);
+               }
+               if (target_name.data) {
+                       data->creds.cr_targ_princ =
+                                       gssp_stringify(&target_name);
+                       gssp_hostbased_service(&data->creds.cr_targ_princ);
                }
        }
        kfree(client_name.data);
+       kfree(target_name.data);
 
        return ret;
 }
index 5089dbb..860f2a1 100644 (file)
@@ -1389,7 +1389,7 @@ static void destroy_use_gss_proxy_proc_entry(struct net *net)
        struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
 
        if (sn->use_gssp_proc) {
-               remove_proc_entry("use-gss-proxy", sn->proc_net_rpc); 
+               remove_proc_entry("use-gss-proxy", sn->proc_net_rpc);
                clear_gssp_clnt(sn);
        }
 }
index 75d72e1..4b48228 100644 (file)
@@ -19,7 +19,7 @@ static struct rpc_auth null_auth;
 static struct rpc_cred null_cred;
 
 static struct rpc_auth *
-nul_create(struct rpc_auth_create_args *args, struct rpc_clnt *clnt)
+nul_create(const struct rpc_auth_create_args *args, struct rpc_clnt *clnt)
 {
        atomic_inc(&null_auth.au_count);
        return &null_auth;
index dafd6b8..185e56d 100644 (file)
@@ -30,7 +30,7 @@ static struct rpc_auth                unix_auth;
 static const struct rpc_credops        unix_credops;
 
 static struct rpc_auth *
-unx_create(struct rpc_auth_create_args *args, struct rpc_clnt *clnt)
+unx_create(const struct rpc_auth_create_args *args, struct rpc_clnt *clnt)
 {
        dprintk("RPC:       creating UNIX authenticator for client %p\n",
                        clnt);
index c2c68a1..3c15a99 100644 (file)
@@ -362,4 +362,3 @@ void xprt_complete_bc_request(struct rpc_rqst *req, uint32_t copied)
        wake_up(&bc_serv->sv_cb_waitq);
        spin_unlock(&bc_serv->sv_cb_lock);
 }
-
index d839c33..8ea2f5f 100644 (file)
@@ -892,7 +892,7 @@ rpc_free_client(struct rpc_clnt *clnt)
 /*
  * Free an RPC client
  */
-static struct rpc_clnt * 
+static struct rpc_clnt *
 rpc_free_auth(struct rpc_clnt *clnt)
 {
        if (clnt->cl_auth == NULL)
@@ -965,10 +965,20 @@ out:
 }
 EXPORT_SYMBOL_GPL(rpc_bind_new_program);
 
+void rpc_task_release_transport(struct rpc_task *task)
+{
+       struct rpc_xprt *xprt = task->tk_xprt;
+
+       if (xprt) {
+               task->tk_xprt = NULL;
+               xprt_put(xprt);
+       }
+}
+EXPORT_SYMBOL_GPL(rpc_task_release_transport);
+
 void rpc_task_release_client(struct rpc_task *task)
 {
        struct rpc_clnt *clnt = task->tk_client;
-       struct rpc_xprt *xprt = task->tk_xprt;
 
        if (clnt != NULL) {
                /* Remove from client task list */
@@ -979,12 +989,14 @@ void rpc_task_release_client(struct rpc_task *task)
 
                rpc_release_client(clnt);
        }
+       rpc_task_release_transport(task);
+}
 
-       if (xprt != NULL) {
-               task->tk_xprt = NULL;
-
-               xprt_put(xprt);
-       }
+static
+void rpc_task_set_transport(struct rpc_task *task, struct rpc_clnt *clnt)
+{
+       if (!task->tk_xprt)
+               task->tk_xprt = xprt_iter_get_next(&clnt->cl_xpi);
 }
 
 static
@@ -992,8 +1004,7 @@ void rpc_task_set_client(struct rpc_task *task, struct rpc_clnt *clnt)
 {
 
        if (clnt != NULL) {
-               if (task->tk_xprt == NULL)
-                       task->tk_xprt = xprt_iter_get_next(&clnt->cl_xpi);
+               rpc_task_set_transport(task, clnt);
                task->tk_client = clnt;
                atomic_inc(&clnt->cl_count);
                if (clnt->cl_softrtry)
@@ -1512,6 +1523,7 @@ call_start(struct rpc_task *task)
                clnt->cl_program->version[clnt->cl_vers]->counts[idx]++;
        clnt->cl_stats->rpccnt++;
        task->tk_action = call_reserve;
+       rpc_task_set_transport(task, clnt);
 }
 
 /*
index c526f8f..c7872bc 100644 (file)
@@ -213,7 +213,7 @@ static void rpcb_set_local(struct net *net, struct rpc_clnt *clnt,
        sn->rpcb_local_clnt = clnt;
        sn->rpcb_local_clnt4 = clnt4;
        sn->rpcb_is_af_local = is_af_local ? 1 : 0;
-       smp_wmb(); 
+       smp_wmb();
        sn->rpcb_users = 1;
        dprintk("RPC:       created new rpcb local clients (rpcb_local_clnt: "
                "%p, rpcb_local_clnt4: %p) for net %x%s\n",
index f68aa46..71166b3 100644 (file)
@@ -208,13 +208,39 @@ static void _print_name(struct seq_file *seq, unsigned int op,
                seq_printf(seq, "\t%12u: ", op);
 }
 
-void rpc_print_iostats(struct seq_file *seq, struct rpc_clnt *clnt)
+static void _add_rpc_iostats(struct rpc_iostats *a, struct rpc_iostats *b)
+{
+       a->om_ops += b->om_ops;
+       a->om_ntrans += b->om_ntrans;
+       a->om_timeouts += b->om_timeouts;
+       a->om_bytes_sent += b->om_bytes_sent;
+       a->om_bytes_recv += b->om_bytes_recv;
+       a->om_queue = ktime_add(a->om_queue, b->om_queue);
+       a->om_rtt = ktime_add(a->om_rtt, b->om_rtt);
+       a->om_execute = ktime_add(a->om_execute, b->om_execute);
+}
+
+static void _print_rpc_iostats(struct seq_file *seq, struct rpc_iostats *stats,
+                              int op, const struct rpc_procinfo *procs)
+{
+       _print_name(seq, op, procs);
+       seq_printf(seq, "%lu %lu %lu %Lu %Lu %Lu %Lu %Lu\n",
+                  stats->om_ops,
+                  stats->om_ntrans,
+                  stats->om_timeouts,
+                  stats->om_bytes_sent,
+                  stats->om_bytes_recv,
+                  ktime_to_ms(stats->om_queue),
+                  ktime_to_ms(stats->om_rtt),
+                  ktime_to_ms(stats->om_execute));
+}
+
+void rpc_clnt_show_stats(struct seq_file *seq, struct rpc_clnt *clnt)
 {
-       struct rpc_iostats *stats = clnt->cl_metrics;
        struct rpc_xprt *xprt;
        unsigned int op, maxproc = clnt->cl_maxproc;
 
-       if (!stats)
+       if (!clnt->cl_metrics)
                return;
 
        seq_printf(seq, "\tRPC iostats version: %s  ", RPC_IOSTATS_VERS);
@@ -229,20 +255,18 @@ void rpc_print_iostats(struct seq_file *seq, struct rpc_clnt *clnt)
 
        seq_printf(seq, "\tper-op statistics\n");
        for (op = 0; op < maxproc; op++) {
-               struct rpc_iostats *metrics = &stats[op];
-               _print_name(seq, op, clnt->cl_procinfo);
-               seq_printf(seq, "%lu %lu %lu %Lu %Lu %Lu %Lu %Lu\n",
-                               metrics->om_ops,
-                               metrics->om_ntrans,
-                               metrics->om_timeouts,
-                               metrics->om_bytes_sent,
-                               metrics->om_bytes_recv,
-                               ktime_to_ms(metrics->om_queue),
-                               ktime_to_ms(metrics->om_rtt),
-                               ktime_to_ms(metrics->om_execute));
+               struct rpc_iostats stats = {};
+               struct rpc_clnt *next = clnt;
+               do {
+                       _add_rpc_iostats(&stats, &next->cl_metrics[op]);
+                       if (next == next->cl_parent)
+                               break;
+                       next = next->cl_parent;
+               } while (next);
+               _print_rpc_iostats(seq, &stats, op, clnt->cl_procinfo);
        }
 }
-EXPORT_SYMBOL_GPL(rpc_print_iostats);
+EXPORT_SYMBOL_GPL(rpc_clnt_show_stats);
 
 /*
  * Register/unregister RPC proc files
@@ -310,4 +334,3 @@ void rpc_proc_exit(struct net *net)
        dprintk("RPC:       unregistering /proc/net/rpc\n");
        remove_proc_entry("rpc", net->proc_net);
 }
-
index 09a0315..c9bacb3 100644 (file)
@@ -57,4 +57,3 @@ int svc_send_common(struct socket *sock, struct xdr_buf *xdr,
 int rpc_clients_notifier_register(void);
 void rpc_clients_notifier_unregister(void);
 #endif /* _NET_SUNRPC_SUNRPC_H */
-
index 30a4226..d13e05f 100644 (file)
@@ -1537,16 +1537,16 @@ EXPORT_SYMBOL_GPL(svc_max_payload);
 /**
  * svc_fill_write_vector - Construct data argument for VFS write call
  * @rqstp: svc_rqst to operate on
+ * @pages: list of pages containing data payload
  * @first: buffer containing first section of write payload
  * @total: total number of bytes of write payload
  *
- * Returns the number of elements populated in the data argument array.
+ * Fills in rqstp::rq_vec, and returns the number of elements.
  */
-unsigned int svc_fill_write_vector(struct svc_rqst *rqstp, struct kvec *first,
-                                  size_t total)
+unsigned int svc_fill_write_vector(struct svc_rqst *rqstp, struct page **pages,
+                                  struct kvec *first, size_t total)
 {
        struct kvec *vec = rqstp->rq_vec;
-       struct page **pages;
        unsigned int i;
 
        /* Some types of transport can present the write payload
@@ -1560,14 +1560,11 @@ unsigned int svc_fill_write_vector(struct svc_rqst *rqstp, struct kvec *first,
                ++i;
        }
 
-       WARN_ON_ONCE(rqstp->rq_arg.page_base != 0);
-       pages = rqstp->rq_arg.pages;
        while (total) {
                vec[i].iov_base = page_address(*pages);
                vec[i].iov_len = min_t(size_t, total, PAGE_SIZE);
                total -= vec[i].iov_len;
                ++i;
-
                ++pages;
        }
 
@@ -1580,65 +1577,48 @@ EXPORT_SYMBOL_GPL(svc_fill_write_vector);
  * svc_fill_symlink_pathname - Construct pathname argument for VFS symlink call
  * @rqstp: svc_rqst to operate on
  * @first: buffer containing first section of pathname
+ * @p: buffer containing remaining section of pathname
  * @total: total length of the pathname argument
  *
- * Returns pointer to a NUL-terminated string, or an ERR_PTR. The buffer is
- * released automatically when @rqstp is recycled.
+ * The VFS symlink API demands a NUL-terminated pathname in mapped memory.
+ * Returns pointer to a NUL-terminated string, or an ERR_PTR. Caller must free
+ * the returned string.
  */
 char *svc_fill_symlink_pathname(struct svc_rqst *rqstp, struct kvec *first,
-                               size_t total)
+                               void *p, size_t total)
 {
-       struct xdr_buf *arg = &rqstp->rq_arg;
-       struct page **pages;
-       char *result;
-
-       /* VFS API demands a NUL-terminated pathname. This function
-        * uses a page from @rqstp as the pathname buffer, to enable
-        * direct placement. Thus the total buffer size is PAGE_SIZE.
-        * Space in this buffer for NUL-termination requires that we
-        * cap the size of the returned symlink pathname just a
-        * little early.
-        */
-       if (total > PAGE_SIZE - 1)
-               return ERR_PTR(-ENAMETOOLONG);
+       size_t len, remaining;
+       char *result, *dst;
 
-       /* Some types of transport can present the pathname entirely
-        * in rq_arg.pages. If not, then copy the pathname into one
-        * page.
-        */
-       pages = arg->pages;
-       WARN_ON_ONCE(arg->page_base != 0);
-       if (first->iov_base == 0) {
-               result = page_address(*pages);
-               result[total] = '\0';
-       } else {
-               size_t len, remaining;
-               char *dst;
+       result = kmalloc(total + 1, GFP_KERNEL);
+       if (!result)
+               return ERR_PTR(-ESERVERFAULT);
 
-               result = page_address(*(rqstp->rq_next_page++));
-               dst = result;
-               remaining = total;
+       dst = result;
+       remaining = total;
 
-               len = min_t(size_t, total, first->iov_len);
+       len = min_t(size_t, total, first->iov_len);
+       if (len) {
                memcpy(dst, first->iov_base, len);
                dst += len;
                remaining -= len;
+       }
 
-               /* No more than one page left */
-               if (remaining) {
-                       len = min_t(size_t, remaining, PAGE_SIZE);
-                       memcpy(dst, page_address(*pages), len);
-                       dst += len;
-               }
-
-               *dst = '\0';
+       if (remaining) {
+               len = min_t(size_t, remaining, PAGE_SIZE);
+               memcpy(dst, p, len);
+               dst += len;
        }
 
-       /* Sanity check: we don't allow the pathname argument to
+       *dst = '\0';
+
+       /* Sanity check: Linux doesn't allow the pathname argument to
         * contain a NUL byte.
         */
-       if (strlen(result) != total)
+       if (strlen(result) != total) {
+               kfree(result);
                return ERR_PTR(-EINVAL);
+       }
        return result;
 }
 EXPORT_SYMBOL_GPL(svc_fill_symlink_pathname);
index 3fabf9f..a8db2e3 100644 (file)
@@ -880,7 +880,7 @@ static void xprt_wait_on_pinned_rqst(struct rpc_rqst *req)
 __must_hold(&req->rq_xprt->recv_lock)
 {
        struct rpc_task *task = req->rq_task;
-       
+
        if (task && test_bit(RPC_TASK_MSG_RECV, &task->tk_runstate)) {
                spin_unlock(&req->rq_xprt->recv_lock);
                set_bit(RPC_TASK_MSG_RECV_WAIT, &task->tk_runstate);
index 357ba90..134bef6 100644 (file)
@@ -94,7 +94,6 @@ static int read_reset_stat(struct ctl_table *table, int write,
                atomic_set(stat, 0);
        else {
                char str_buf[32];
-               char *data;
                int len = snprintf(str_buf, 32, "%d\n", atomic_read(stat));
                if (len >= 32)
                        return -EFAULT;
@@ -103,7 +102,6 @@ static int read_reset_stat(struct ctl_table *table, int write,
                        *lenp = 0;
                        return 0;
                }
-               data = &str_buf[*ppos];
                len -= *ppos;
                if (len > *lenp)
                        len = *lenp;
index 2ef75e8..b24d5b8 100644 (file)
@@ -365,9 +365,6 @@ static void svc_rdma_build_arg_xdr(struct svc_rqst *rqstp,
        arg->page_base = 0;
        arg->buflen = ctxt->rc_byte_len;
        arg->len = ctxt->rc_byte_len;
-
-       rqstp->rq_respages = &rqstp->rq_pages[0];
-       rqstp->rq_next_page = rqstp->rq_respages + 1;
 }
 
 /* This accommodates the largest possible Write chunk,
@@ -729,6 +726,12 @@ int svc_rdma_recvfrom(struct svc_rqst *rqstp)
 
        svc_rdma_build_arg_xdr(rqstp, ctxt);
 
+       /* Prevent svc_xprt_release from releasing pages in rq_pages
+        * if we return 0 or an error.
+        */
+       rqstp->rq_respages = rqstp->rq_pages;
+       rqstp->rq_next_page = rqstp->rq_respages;
+
        p = (__be32 *)rqstp->rq_arg.head[0].iov_base;
        ret = svc_rdma_xdr_decode_req(&rqstp->rq_arg);
        if (ret < 0)
index 04cb336..dc19517 100644 (file)
@@ -680,6 +680,7 @@ static int svc_rdma_build_read_chunk(struct svc_rqst *rqstp,
                                     struct svc_rdma_read_info *info,
                                     __be32 *p)
 {
+       unsigned int i;
        int ret;
 
        ret = -EINVAL;
@@ -702,6 +703,12 @@ static int svc_rdma_build_read_chunk(struct svc_rqst *rqstp,
                info->ri_chunklen += rs_length;
        }
 
+       /* Pages under I/O have been copied to head->rc_pages.
+        * Prevent their premature release by svc_xprt_release() .
+        */
+       for (i = 0; i < info->ri_readctxt->rc_page_count; i++)
+               rqstp->rq_pages[i] = NULL;
+
        return ret;
 }
 
@@ -817,7 +824,6 @@ int svc_rdma_recv_read_chunk(struct svcxprt_rdma *rdma, struct svc_rqst *rqstp,
                             struct svc_rdma_recv_ctxt *head, __be32 *p)
 {
        struct svc_rdma_read_info *info;
-       struct page **page;
        int ret;
 
        /* The request (with page list) is constructed in
@@ -844,27 +850,15 @@ int svc_rdma_recv_read_chunk(struct svcxprt_rdma *rdma, struct svc_rqst *rqstp,
                ret = svc_rdma_build_normal_read_chunk(rqstp, info, p);
        else
                ret = svc_rdma_build_pz_read_chunk(rqstp, info, p);
-
-       /* Mark the start of the pages that can be used for the reply */
-       if (info->ri_pageoff > 0)
-               info->ri_pageno++;
-       rqstp->rq_respages = &rqstp->rq_pages[info->ri_pageno];
-       rqstp->rq_next_page = rqstp->rq_respages + 1;
-
        if (ret < 0)
-               goto out;
+               goto out_err;
 
        ret = svc_rdma_post_chunk_ctxt(&info->ri_cc);
-
-out:
-       /* Read sink pages have been moved from rqstp->rq_pages to
-        * head->rc_arg.pages. Force svc_recv to refill those slots
-        * in rq_pages.
-        */
-       for (page = rqstp->rq_pages; page < rqstp->rq_respages; page++)
-               *page = NULL;
-
        if (ret < 0)
-               svc_rdma_read_info_free(info);
+               goto out_err;
+       return 0;
+
+out_err:
+       svc_rdma_read_info_free(info);
        return ret;
 }
index ffef0c5..8602a5f 100644 (file)
@@ -656,7 +656,9 @@ static void svc_rdma_save_io_pages(struct svc_rqst *rqstp,
                ctxt->sc_pages[i] = rqstp->rq_respages[i];
                rqstp->rq_respages[i] = NULL;
        }
-       rqstp->rq_next_page = rqstp->rq_respages + 1;
+
+       /* Prevent svc_xprt_release from releasing pages in rq_pages */
+       rqstp->rq_next_page = rqstp->rq_respages;
 }
 
 /* Prepare the portion of the RPC Reply that will be transmitted
index 547b2cd..2848caf 100644 (file)
@@ -296,7 +296,6 @@ static int rdma_listen_handler(struct rdma_cm_id *cma_id,
                               struct rdma_cm_event *event)
 {
        struct sockaddr *sap = (struct sockaddr *)&cma_id->route.addr.src_addr;
-       int ret = 0;
 
        trace_svcrdma_cm_event(event, sap);
 
@@ -315,7 +314,7 @@ static int rdma_listen_handler(struct rdma_cm_id *cma_id,
                break;
        }
 
-       return ret;
+       return 0;
 }
 
 static int rdma_cma_handler(struct rdma_cm_id *cma_id,
index 5efeba0..956a5ea 100644 (file)
@@ -280,7 +280,6 @@ rpcrdma_conn_upcall(struct rdma_cm_id *id, struct rdma_cm_event *event)
                ++xprt->rx_xprt.connect_cookie;
                connstate = -ECONNABORTED;
 connected:
-               xprt->rx_buf.rb_credits = 1;
                ep->rep_connected = connstate;
                rpcrdma_conn_func(ep);
                wake_up_all(&ep->rep_connect_wait);
@@ -755,6 +754,7 @@ retry:
        }
 
        ep->rep_connected = 0;
+       rpcrdma_post_recvs(r_xprt, true);
 
        rc = rdma_connect(ia->ri_id, &ep->rep_remote_cma);
        if (rc) {
@@ -773,8 +773,6 @@ retry:
 
        dprintk("RPC:       %s: connected\n", __func__);
 
-       rpcrdma_post_recvs(r_xprt, true);
-
 out:
        if (rc)
                ep->rep_connected = rc;
@@ -1171,6 +1169,7 @@ rpcrdma_buffer_create(struct rpcrdma_xprt *r_xprt)
                list_add(&req->rl_list, &buf->rb_send_bufs);
        }
 
+       buf->rb_credits = 1;
        buf->rb_posted_receives = 0;
        INIT_LIST_HEAD(&buf->rb_recv_bufs);
 
index 9e1c502..6b7539c 100644 (file)
@@ -3375,4 +3375,3 @@ module_param_named(tcp_max_slot_table_entries, xprt_max_tcp_slot_table_entries,
                   max_slot_table_size, 0644);
 module_param_named(udp_slot_table_entries, xprt_udp_slot_table_entries,
                   slot_table_size, 0644);
-
index 7c98f60..c75413d 100644 (file)
@@ -163,8 +163,8 @@ cc-ldoption = $(call try-run,\
        $(CC) $(1) $(KBUILD_CPPFLAGS) $(CC_OPTION_CFLAGS) -nostdlib -x c /dev/null -o "$$TMP",$(1),$(2))
 
 # ld-option
-# Usage: LDFLAGS += $(call ld-option, -X, -Y)
-ld-option = $(call try-run, $(LD) $(LDFLAGS) $(1) -v,$(1),$(2),$(3))
+# Usage: KBUILD_LDFLAGS += $(call ld-option, -X, -Y)
+ld-option = $(call try-run, $(LD) $(KBUILD_LDFLAGS) $(1) -v,$(1),$(2),$(3))
 
 # ar-option
 # Usage: KBUILD_ARFLAGS := $(call ar-option,D)
index 1adaac4..1c48572 100644 (file)
@@ -190,7 +190,7 @@ cmd_modversions_c =                                                         \
                $(call cmd_gensymtypes_c,$(KBUILD_SYMTYPES),$(@:.o=.symtypes))  \
                    > $(@D)/.tmp_$(@F:.o=.ver);                                 \
                                                                                \
-               $(LD) $(LDFLAGS) -r -o $@ $(@D)/.tmp_$(@F)                      \
+               $(LD) $(KBUILD_LDFLAGS) -r -o $@ $(@D)/.tmp_$(@F)               \
                        -T $(@D)/.tmp_$(@F:.o=.ver);                            \
                rm -f $(@D)/.tmp_$(@F) $(@D)/.tmp_$(@F:.o=.ver);                \
        else                                                                    \
@@ -199,11 +199,8 @@ cmd_modversions_c =                                                                \
 endif
 
 ifdef CONFIG_FTRACE_MCOUNT_RECORD
-# gcc 5 supports generating the mcount tables directly
-ifneq ($(call cc-option,-mrecord-mcount,y),y)
-KBUILD_CFLAGS += -mrecord-mcount
-else
-# else do it all manually
+ifndef CC_USING_RECORD_MCOUNT
+# compiler will not generate __mcount_loc use recordmcount or recordmcount.pl
 ifdef BUILD_C_RECORDMCOUNT
 ifeq ("$(origin RECORDMCOUNT_WARN)", "command line")
   RECORDMCOUNT_FLAGS = -w
@@ -223,7 +220,7 @@ sub_cmd_record_mcount = set -e ; perl $(srctree)/scripts/recordmcount.pl "$(ARCH
        "$(if $(CONFIG_CPU_BIG_ENDIAN),big,little)" \
        "$(if $(CONFIG_64BIT),64,32)" \
        "$(OBJDUMP)" "$(OBJCOPY)" "$(CC) $(KBUILD_CFLAGS)" \
-       "$(LD)" "$(NM)" "$(RM)" "$(MV)" \
+       "$(LD) $(KBUILD_LDFLAGS)" "$(NM)" "$(RM)" "$(MV)" \
        "$(if $(part-of-module),1,0)" "$(@)";
 recordmcount_source := $(srctree)/scripts/recordmcount.pl
 endif # BUILD_C_RECORDMCOUNT
@@ -232,7 +229,7 @@ cmd_record_mcount =                                         \
             "$(CC_FLAGS_FTRACE)" ]; then                       \
                $(sub_cmd_record_mcount)                        \
        fi;
-endif # -record-mcount
+endif # CC_USING_RECORD_MCOUNT
 endif # CONFIG_FTRACE_MCOUNT_RECORD
 
 ifdef CONFIG_STACK_VALIDATION
@@ -397,7 +394,7 @@ cmd_modversions_S =                                                         \
                $(call cmd_gensymtypes_S,$(KBUILD_SYMTYPES),$(@:.o=.symtypes))  \
                    > $(@D)/.tmp_$(@F:.o=.ver);                                 \
                                                                                \
-               $(LD) $(LDFLAGS) -r -o $@ $(@D)/.tmp_$(@F)                      \
+               $(LD) $(KBUILD_LDFLAGS) -r -o $@ $(@D)/.tmp_$(@F)               \
                        -T $(@D)/.tmp_$(@F:.o=.ver);                            \
                rm -f $(@D)/.tmp_$(@F) $(@D)/.tmp_$(@F:.o=.ver);                \
        else                                                                    \
index df0fff2..61e5966 100644 (file)
@@ -162,7 +162,7 @@ a_flags        = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(LINUXINCLUDE)     \
 cpp_flags      = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(LINUXINCLUDE)     \
                 $(__cpp_flags)
 
-ld_flags       = $(LDFLAGS) $(ldflags-y) $(LDFLAGS_$(@F))
+ld_flags       = $(KBUILD_LDFLAGS) $(ldflags-y) $(LDFLAGS_$(@F))
 
 DTC_INCLUDE    := $(srctree)/scripts/dtc/include-prefixes
 
index dd92dbb..7d4af0d 100644 (file)
@@ -120,7 +120,7 @@ ARCH_POSTLINK := $(wildcard $(srctree)/arch/$(SRCARCH)/Makefile.postlink)
 # Step 6), final link of the modules with optional arch pass after final link
 quiet_cmd_ld_ko_o = LD [M]  $@
       cmd_ld_ko_o =                                                     \
-       $(LD) -r $(LDFLAGS)                                             \
+       $(LD) -r $(KBUILD_LDFLAGS)                                      \
                  $(KBUILD_LDFLAGS_MODULE) $(LDFLAGS_MODULE)             \
                  -o $@ $(filter-out FORCE,$^) ;                         \
        $(if $(ARCH_POSTLINK), $(MAKE) -f $(ARCH_POSTLINK) $@, true)
index 447857f..5219280 100755 (executable)
@@ -13,6 +13,7 @@ use POSIX;
 use File::Basename;
 use Cwd 'abs_path';
 use Term::ANSIColor qw(:constants);
+use Encode qw(decode encode);
 
 my $P = $0;
 my $D = dirname(abs_path($P));
@@ -240,11 +241,11 @@ $check_orig = $check;
 
 my $exit = 0;
 
+my $perl_version_ok = 1;
 if ($^V && $^V lt $minimum_perl_version) {
+       $perl_version_ok = 0;
        printf "$P: requires at least perl version %vd\n", $minimum_perl_version;
-       if (!$ignore_perl_version) {
-               exit(1);
-       }
+       exit(1) if (!$ignore_perl_version);
 }
 
 #if no filenames are given, push '-' to read patch from stdin
@@ -346,9 +347,10 @@ our $Sparse        = qr{
                        __force|
                        __iomem|
                        __must_check|
-                       __init_refok|
                        __kprobes|
                        __ref|
+                       __refconst|
+                       __refdata|
                        __rcu|
                        __private
                }x;
@@ -847,6 +849,17 @@ sub is_maintained_obsolete {
        return $status =~ /obsolete/i;
 }
 
+sub is_SPDX_License_valid {
+       my ($license) = @_;
+
+       return 1 if (!$tree || which("python") eq "" || !(-e "$root/scripts/spdxcheck.py") || !(-e "$root/.git"));
+
+       my $root_path = abs_path($root);
+       my $status = `cd "$root_path"; echo "$license" | python scripts/spdxcheck.py -`;
+       return 0 if ($status ne "");
+       return 1;
+}
+
 my $camelcase_seeded = 0;
 sub seed_camelcase_includes {
        return if ($camelcase_seeded);
@@ -1026,11 +1039,11 @@ if (!$quiet) {
        hash_show_words(\%use_type, "Used");
        hash_show_words(\%ignore_type, "Ignored");
 
-       if ($^V lt 5.10.0) {
+       if (!$perl_version_ok) {
                print << "EOM"
 
 NOTE: perl $^V is not modern enough to detect all possible issues.
-      An upgrade to at least perl v5.10.0 is suggested.
+      An upgrade to at least perl $minimum_perl_version is suggested.
 EOM
        }
        if ($exit) {
@@ -2235,10 +2248,14 @@ sub process {
 
        our $clean = 1;
        my $signoff = 0;
+       my $author = '';
+       my $authorsignoff = 0;
        my $is_patch = 0;
+       my $is_binding_patch = -1;
        my $in_header_lines = $file ? 0 : 1;
        my $in_commit_log = 0;          #Scanning lines before patch
        my $has_commit_log = 0;         #Encountered lines before patch
+       my $commit_log_lines = 0;       #Number of commit log lines
        my $commit_log_possible_stack_dump = 0;
        my $commit_log_long_line = 0;
        my $commit_log_has_diff = 0;
@@ -2485,6 +2502,19 @@ sub process {
                                $check = $check_orig;
                        }
                        $checklicenseline = 1;
+
+                       if ($realfile !~ /^MAINTAINERS/) {
+                               my $last_binding_patch = $is_binding_patch;
+
+                               $is_binding_patch = () = $realfile =~ m@^(?:Documentation/devicetree/|include/dt-bindings/)@;
+
+                               if (($last_binding_patch != -1) &&
+                                   ($last_binding_patch ^ $is_binding_patch)) {
+                                       WARN("DT_SPLIT_BINDING_PATCH",
+                                            "DT binding docs and includes should be a separate patch. See: Documentation/devicetree/bindings/submitting-patches.txt\n");
+                               }
+                       }
+
                        next;
                }
 
@@ -2496,6 +2526,18 @@ sub process {
 
                $cnt_lines++ if ($realcnt != 0);
 
+# Verify the existence of a commit log if appropriate
+# 2 is used because a $signature is counted in $commit_log_lines
+               if ($in_commit_log) {
+                       if ($line !~ /^\s*$/) {
+                               $commit_log_lines++;    #could be a $signature
+                       }
+               } elsif ($has_commit_log && $commit_log_lines < 2) {
+                       WARN("COMMIT_MESSAGE",
+                            "Missing commit description - Add an appropriate one\n");
+                       $commit_log_lines = 2;  #warn only once
+               }
+
 # Check if the commit log has what seems like a diff which can confuse patch
                if ($in_commit_log && !$commit_log_has_diff &&
                    (($line =~ m@^\s+diff\b.*a/[\w/]+@ &&
@@ -2517,10 +2559,24 @@ sub process {
                        }
                }
 
+# Check the patch for a From:
+               if (decode("MIME-Header", $line) =~ /^From:\s*(.*)/) {
+                       $author = $1;
+                       $author = encode("utf8", $author) if ($line =~ /=\?utf-8\?/i);
+                       $author =~ s/"//g;
+               }
+
 # Check the patch for a signoff:
                if ($line =~ /^\s*signed-off-by:/i) {
                        $signoff++;
                        $in_commit_log = 0;
+                       if ($author ne '') {
+                               my $l = $line;
+                               $l =~ s/"//g;
+                               if ($l =~ /^\s*signed-off-by:\s*\Q$author\E/i) {
+                                   $authorsignoff = 1;
+                               }
+                       }
                }
 
 # Check if MAINTAINERS is being updated.  If so, there's probably no need to
@@ -2960,8 +3016,14 @@ sub process {
 
                                if ($comment !~ /^$/ &&
                                    $rawline !~ /^\+\Q$comment\E SPDX-License-Identifier: /) {
-                                       WARN("SPDX_LICENSE_TAG",
-                                            "Missing or malformed SPDX-License-Identifier tag in line $checklicenseline\n" . $herecurr);
+                                        WARN("SPDX_LICENSE_TAG",
+                                             "Missing or malformed SPDX-License-Identifier tag in line $checklicenseline\n" . $herecurr);
+                               } elsif ($rawline =~ /(SPDX-License-Identifier: .*)/) {
+                                        my $spdx_license = $1;
+                                        if (!is_SPDX_License_valid($spdx_license)) {
+                                                 WARN("SPDX_LICENSE_TAG",
+                                                      "'$spdx_license' is not supported in LICENSES/...\n" . $herecurr);
+                                        }
                                }
                        }
                }
@@ -3079,7 +3141,7 @@ sub process {
                }
 
 # check indentation starts on a tab stop
-               if ($^V && $^V ge 5.10.0 &&
+               if ($perl_version_ok &&
                    $sline =~ /^\+\t+( +)(?:$c90_Keywords\b|\{\s*$|\}\s*(?:else\b|while\b|\s*$)|$Declare\s*$Ident\s*[;=])/) {
                        my $indent = length($1);
                        if ($indent % 8) {
@@ -3092,7 +3154,7 @@ sub process {
                }
 
 # check multi-line statement indentation matches previous line
-               if ($^V && $^V ge 5.10.0 &&
+               if ($perl_version_ok &&
                    $prevline =~ /^\+([ \t]*)((?:$c90_Keywords(?:\s+if)\s*)|(?:$Declare\s*)?(?:$Ident|\(\s*\*\s*$Ident\s*\))\s*|(?:\*\s*)*$Lval\s*=\s*$Ident\s*)\(.*(\&\&|\|\||,)\s*$/) {
                        $prevline =~ /^\+(\t*)(.*)$/;
                        my $oldindent = $1;
@@ -3781,6 +3843,26 @@ sub process {
                             "type '$tmp' should be specified in [[un]signed] [short|int|long|long long] order\n" . $herecurr);
                }
 
+# check for unnecessary <signed> int declarations of short/long/long long
+               while ($sline =~ m{\b($TypeMisordered(\s*\*)*|$C90_int_types)\b}g) {
+                       my $type = trim($1);
+                       next if ($type !~ /\bint\b/);
+                       next if ($type !~ /\b(?:short|long\s+long|long)\b/);
+                       my $new_type = $type;
+                       $new_type =~ s/\b\s*int\s*\b/ /;
+                       $new_type =~ s/\b\s*(?:un)?signed\b\s*/ /;
+                       $new_type =~ s/^const\s+//;
+                       $new_type = "unsigned $new_type" if ($type =~ /\bunsigned\b/);
+                       $new_type = "const $new_type" if ($type =~ /^const\b/);
+                       $new_type =~ s/\s+/ /g;
+                       $new_type = trim($new_type);
+                       if (WARN("UNNECESSARY_INT",
+                                "Prefer '$new_type' over '$type' as the int is unnecessary\n" . $herecurr) &&
+                           $fix) {
+                               $fixed[$fixlinenr] =~ s/\b\Q$type\E\b/$new_type/;
+                       }
+               }
+
 # check for static const char * arrays.
                if ($line =~ /\bstatic\s+const\s+char\s*\*\s*(\w+)\s*\[\s*\]\s*=\s*/) {
                        WARN("STATIC_CONST_CHAR_ARRAY",
@@ -3967,7 +4049,7 @@ sub process {
 
 # function brace can't be on same line, except for #defines of do while,
 # or if closed on same line
-               if ($^V && $^V ge 5.10.0 &&
+               if ($perl_version_ok &&
                    $sline =~ /$Type\s*$Ident\s*$balanced_parens\s*\{/ &&
                    $sline !~ /\#\s*define\b.*do\s*\{/ &&
                    $sline !~ /}/) {
@@ -4483,11 +4565,11 @@ sub process {
 
 #need space before brace following if, while, etc
                if (($line =~ /\(.*\)\{/ && $line !~ /\($Type\)\{/) ||
-                   $line =~ /do\{/) {
+                   $line =~ /\b(?:else|do)\{/) {
                        if (ERROR("SPACING",
                                  "space required before the open brace '{'\n" . $herecurr) &&
                            $fix) {
-                               $fixed[$fixlinenr] =~ s/^(\+.*(?:do|\)))\{/$1 {/;
+                               $fixed[$fixlinenr] =~ s/^(\+.*(?:do|else|\)))\{/$1 {/;
                        }
                }
 
@@ -4578,7 +4660,7 @@ sub process {
 # check for unnecessary parentheses around comparisons in if uses
 # when !drivers/staging or command-line uses --strict
                if (($realfile !~ m@^(?:drivers/staging/)@ || $check_orig) &&
-                   $^V && $^V ge 5.10.0 && defined($stat) &&
+                   $perl_version_ok && defined($stat) &&
                    $stat =~ /(^.\s*if\s*($balanced_parens))/) {
                        my $if_stat = $1;
                        my $test = substr($2, 1, -1);
@@ -4615,7 +4697,7 @@ sub process {
 # return is not a function
                if (defined($stat) && $stat =~ /^.\s*return(\s*)\(/s) {
                        my $spacing = $1;
-                       if ($^V && $^V ge 5.10.0 &&
+                       if ($perl_version_ok &&
                            $stat =~ /^.\s*return\s*($balanced_parens)\s*;\s*$/) {
                                my $value = $1;
                                $value = deparenthesize($value);
@@ -4642,7 +4724,7 @@ sub process {
                }
 
 # if statements using unnecessary parentheses - ie: if ((foo == bar))
-               if ($^V && $^V ge 5.10.0 &&
+               if ($perl_version_ok &&
                    $line =~ /\bif\s*((?:\(\s*){2,})/) {
                        my $openparens = $1;
                        my $count = $openparens =~ tr@\(@\(@;
@@ -4659,7 +4741,7 @@ sub process {
 #      avoid cases like "foo + BAR < baz"
 #      only fix matches surrounded by parentheses to avoid incorrect
 #      conversions like "FOO < baz() + 5" being "misfixed" to "baz() > FOO + 5"
-               if ($^V && $^V ge 5.10.0 &&
+               if ($perl_version_ok &&
                    $line =~ /^\+(.*)\b($Constant|[A-Z_][A-Z0-9_]*)\s*($Compare)\s*($LvalOrFunc)/) {
                        my $lead = $1;
                        my $const = $2;
@@ -4949,6 +5031,7 @@ sub process {
                        if (defined $define_args && $define_args ne "") {
                                $define_args = substr($define_args, 1, length($define_args) - 2);
                                $define_args =~ s/\s*//g;
+                               $define_args =~ s/\\\+?//g;
                                @def_args = split(",", $define_args);
                        }
 
@@ -5084,7 +5167,7 @@ sub process {
 # do {} while (0) macro tests:
 # single-statement macros do not need to be enclosed in do while (0) loop,
 # macro should not end with a semicolon
-               if ($^V && $^V ge 5.10.0 &&
+               if ($perl_version_ok &&
                    $realfile !~ m@/vmlinux.lds.h$@ &&
                    $line =~ /^.\s*\#\s*define\s+$Ident(\()?/) {
                        my $ln = $linenr;
@@ -5330,15 +5413,28 @@ sub process {
                }
 
 # concatenated string without spaces between elements
-               if ($line =~ /$String[A-Z_]/ || $line =~ /[A-Za-z0-9_]$String/) {
-                       CHK("CONCATENATED_STRING",
-                           "Concatenated strings should use spaces between elements\n" . $herecurr);
+               if ($line =~ /$String[A-Za-z0-9_]/ || $line =~ /[A-Za-z0-9_]$String/) {
+                       if (CHK("CONCATENATED_STRING",
+                               "Concatenated strings should use spaces between elements\n" . $herecurr) &&
+                           $fix) {
+                               while ($line =~ /($String)/g) {
+                                       my $extracted_string = substr($rawline, $-[0], $+[0] - $-[0]);
+                                       $fixed[$fixlinenr] =~ s/\Q$extracted_string\E([A-Za-z0-9_])/$extracted_string $1/;
+                                       $fixed[$fixlinenr] =~ s/([A-Za-z0-9_])\Q$extracted_string\E/$1 $extracted_string/;
+                               }
+                       }
                }
 
 # uncoalesced string fragments
                if ($line =~ /$String\s*"/) {
-                       WARN("STRING_FRAGMENTS",
-                            "Consecutive strings are generally better as a single string\n" . $herecurr);
+                       if (WARN("STRING_FRAGMENTS",
+                                "Consecutive strings are generally better as a single string\n" . $herecurr) &&
+                           $fix) {
+                               while ($line =~ /($String)(?=\s*")/g) {
+                                       my $extracted_string = substr($rawline, $-[0], $+[0] - $-[0]);
+                                       $fixed[$fixlinenr] =~ s/\Q$extracted_string\E\s*"/substr($extracted_string, 0, -1)/e;
+                               }
+                       }
                }
 
 # check for non-standard and hex prefixed decimal printf formats
@@ -5374,9 +5470,14 @@ sub process {
 
 # warn about #if 0
                if ($line =~ /^.\s*\#\s*if\s+0\b/) {
-                       CHK("REDUNDANT_CODE",
-                           "if this code is redundant consider removing it\n" .
-                               $herecurr);
+                       WARN("IF_0",
+                            "Consider removing the code enclosed by this #if 0 and its #endif\n" . $herecurr);
+               }
+
+# warn about #if 1
+               if ($line =~ /^.\s*\#\s*if\s+1\b/) {
+                       WARN("IF_1",
+                            "Consider removing the #if 1 and its #endif\n" . $herecurr);
                }
 
 # check for needless "if (<foo>) fn(<foo>)" uses
@@ -5447,7 +5548,7 @@ sub process {
                }
 
 # check for mask then right shift without a parentheses
-               if ($^V && $^V ge 5.10.0 &&
+               if ($perl_version_ok &&
                    $line =~ /$LvalOrFunc\s*\&\s*($LvalOrFunc)\s*>>/ &&
                    $4 !~ /^\&/) { # $LvalOrFunc may be &foo, ignore if so
                        WARN("MASK_THEN_SHIFT",
@@ -5455,7 +5556,7 @@ sub process {
                }
 
 # check for pointer comparisons to NULL
-               if ($^V && $^V ge 5.10.0) {
+               if ($perl_version_ok) {
                        while ($line =~ /\b$LvalOrFunc\s*(==|\!=)\s*NULL\b/g) {
                                my $val = $1;
                                my $equal = "!";
@@ -5727,7 +5828,7 @@ sub process {
                }
 
 # Check for __attribute__ weak, or __weak declarations (may have link issues)
-               if ($^V && $^V ge 5.10.0 &&
+               if ($perl_version_ok &&
                    $line =~ /(?:$Declare|$DeclareMisordered)\s*$Ident\s*$balanced_parens\s*(?:$Attribute)?\s*;/ &&
                    ($line =~ /\b__attribute__\s*\(\s*\(.*\bweak\b/ ||
                     $line =~ /\b__weak\b/)) {
@@ -5809,7 +5910,7 @@ sub process {
                }
 
 # check for vsprintf extension %p<foo> misuses
-               if ($^V && $^V ge 5.10.0 &&
+               if ($perl_version_ok &&
                    defined $stat &&
                    $stat =~ /^\+(?![^\{]*\{\s*).*\b(\w+)\s*\(.*$String\s*,/s &&
                    $1 !~ /^_*volatile_*$/) {
@@ -5856,7 +5957,7 @@ sub process {
                }
 
 # Check for misused memsets
-               if ($^V && $^V ge 5.10.0 &&
+               if ($perl_version_ok &&
                    defined $stat &&
                    $stat =~ /^\+(?:.*?)\bmemset\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*$FuncArg\s*\)/) {
 
@@ -5874,7 +5975,7 @@ sub process {
                }
 
 # Check for memcpy(foo, bar, ETH_ALEN) that could be ether_addr_copy(foo, bar)
-#              if ($^V && $^V ge 5.10.0 &&
+#              if ($perl_version_ok &&
 #                  defined $stat &&
 #                  $stat =~ /^\+(?:.*?)\bmemcpy\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/) {
 #                      if (WARN("PREFER_ETHER_ADDR_COPY",
@@ -5885,7 +5986,7 @@ sub process {
 #              }
 
 # Check for memcmp(foo, bar, ETH_ALEN) that could be ether_addr_equal*(foo, bar)
-#              if ($^V && $^V ge 5.10.0 &&
+#              if ($perl_version_ok &&
 #                  defined $stat &&
 #                  $stat =~ /^\+(?:.*?)\bmemcmp\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/) {
 #                      WARN("PREFER_ETHER_ADDR_EQUAL",
@@ -5894,7 +5995,7 @@ sub process {
 
 # check for memset(foo, 0x0, ETH_ALEN) that could be eth_zero_addr
 # check for memset(foo, 0xFF, ETH_ALEN) that could be eth_broadcast_addr
-#              if ($^V && $^V ge 5.10.0 &&
+#              if ($perl_version_ok &&
 #                  defined $stat &&
 #                  $stat =~ /^\+(?:.*?)\bmemset\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/) {
 #
@@ -5916,7 +6017,7 @@ sub process {
 #              }
 
 # typecasts on min/max could be min_t/max_t
-               if ($^V && $^V ge 5.10.0 &&
+               if ($perl_version_ok &&
                    defined $stat &&
                    $stat =~ /^\+(?:.*?)\b(min|max)\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\)/) {
                        if (defined $2 || defined $7) {
@@ -5940,7 +6041,7 @@ sub process {
                }
 
 # check usleep_range arguments
-               if ($^V && $^V ge 5.10.0 &&
+               if ($perl_version_ok &&
                    defined $stat &&
                    $stat =~ /^\+(?:.*?)\busleep_range\s*\(\s*($FuncArg)\s*,\s*($FuncArg)\s*\)/) {
                        my $min = $1;
@@ -5956,7 +6057,7 @@ sub process {
                }
 
 # check for naked sscanf
-               if ($^V && $^V ge 5.10.0 &&
+               if ($perl_version_ok &&
                    defined $stat &&
                    $line =~ /\bsscanf\b/ &&
                    ($stat !~ /$Ident\s*=\s*sscanf\s*$balanced_parens/ &&
@@ -5970,7 +6071,7 @@ sub process {
                }
 
 # check for simple sscanf that should be kstrto<foo>
-               if ($^V && $^V ge 5.10.0 &&
+               if ($perl_version_ok &&
                    defined $stat &&
                    $line =~ /\bsscanf\b/) {
                        my $lc = $stat =~ tr@\n@@;
@@ -6042,7 +6143,7 @@ sub process {
                }
 
 # check for function definitions
-               if ($^V && $^V ge 5.10.0 &&
+               if ($perl_version_ok &&
                    defined $stat &&
                    $stat =~ /^.\s*(?:$Storage\s+)?$Type\s*($Ident)\s*$balanced_parens\s*{/s) {
                        $context_function = $1;
@@ -6082,14 +6183,14 @@ sub process {
 
 # alloc style
 # p = alloc(sizeof(struct foo), ...) should be p = alloc(sizeof(*p), ...)
-               if ($^V && $^V ge 5.10.0 &&
+               if ($perl_version_ok &&
                    $line =~ /\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*([kv][mz]alloc(?:_node)?)\s*\(\s*(sizeof\s*\(\s*struct\s+$Lval\s*\))/) {
                        CHK("ALLOC_SIZEOF_STRUCT",
                            "Prefer $3(sizeof(*$1)...) over $3($4...)\n" . $herecurr);
                }
 
 # check for k[mz]alloc with multiplies that could be kmalloc_array/kcalloc
-               if ($^V && $^V ge 5.10.0 &&
+               if ($perl_version_ok &&
                    defined $stat &&
                    $stat =~ /^\+\s*($Lval)\s*\=\s*(?:$balanced_parens)?\s*(k[mz]alloc)\s*\(\s*($FuncArg)\s*\*\s*($FuncArg)\s*,/) {
                        my $oldfunc = $3;
@@ -6118,8 +6219,9 @@ sub process {
                }
 
 # check for krealloc arg reuse
-               if ($^V && $^V ge 5.10.0 &&
-                   $line =~ /\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*krealloc\s*\(\s*\1\s*,/) {
+               if ($perl_version_ok &&
+                   $line =~ /\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*krealloc\s*\(\s*($Lval)\s*,/ &&
+                   $1 eq $3) {
                        WARN("KREALLOC_ARG_REUSE",
                             "Reusing the krealloc arg is almost always a bug\n" . $herecurr);
                }
@@ -6187,7 +6289,7 @@ sub process {
                }
 
 # check for switch/default statements without a break;
-               if ($^V && $^V ge 5.10.0 &&
+               if ($perl_version_ok &&
                    defined $stat &&
                    $stat =~ /^\+[$;\s]*(?:case[$;\s]+\w+[$;\s]*:[$;\s]*|)*[$;\s]*\bdefault[$;\s]*:[$;\s]*;/g) {
                        my $cnt = statement_rawlines($stat);
@@ -6251,6 +6353,13 @@ sub process {
                             "Avoid using bool as bitfield.  Prefer bool bitfields as unsigned int or u<8|16|32>\n" . $herecurr);
                }
 
+# check for bool use in .h files
+               if ($realfile =~ /\.h$/ &&
+                   $sline =~ /^.\s+bool\s*$Ident\s*(?::\s*d+\s*)?;/) {
+                       CHK("BOOL_MEMBER",
+                           "Avoid using bool structure members because of possible alignment issues - see: https://lkml.org/lkml/2017/11/21/384\n" . $herecurr);
+               }
+
 # check for semaphores initialized locked
                if ($line =~ /^.\s*sema_init.+,\W?0\W?\)/) {
                        WARN("CONSIDER_COMPLETION",
@@ -6297,7 +6406,7 @@ sub process {
                }
 
 # likely/unlikely comparisons similar to "(likely(foo) > 0)"
-               if ($^V && $^V ge 5.10.0 &&
+               if ($perl_version_ok &&
                    $line =~ /\b((?:un)?likely)\s*\(\s*$FuncArg\s*\)\s*$Compare/) {
                        WARN("LIKELY_MISUSE",
                             "Using $1 should generally have parentheses around the comparison\n" . $herecurr);
@@ -6340,7 +6449,7 @@ sub process {
 # check for DEVICE_ATTR uses that could be DEVICE_ATTR_<FOO>
 # and whether or not function naming is typical and if
 # DEVICE_ATTR permissions uses are unusual too
-               if ($^V && $^V ge 5.10.0 &&
+               if ($perl_version_ok &&
                    defined $stat &&
                    $stat =~ /\bDEVICE_ATTR\s*\(\s*(\w+)\s*,\s*\(?\s*(\s*(?:${multi_mode_perms_string_search}|0[0-7]{3,3})\s*)\s*\)?\s*,\s*(\w+)\s*,\s*(\w+)\s*\)/) {
                        my $var = $1;
@@ -6400,7 +6509,7 @@ sub process {
 #   specific definition of not visible in sysfs.
 # o Ignore proc_create*(...) uses with a decimal 0 permission as that means
 #   use the default permissions
-               if ($^V && $^V ge 5.10.0 &&
+               if ($perl_version_ok &&
                    defined $stat &&
                    $line =~ /$mode_perms_search/) {
                        foreach my $entry (@mode_permission_funcs) {
@@ -6486,9 +6595,14 @@ sub process {
                ERROR("NOT_UNIFIED_DIFF",
                      "Does not appear to be a unified-diff format patch\n");
        }
-       if ($is_patch && $has_commit_log && $chk_signoff && $signoff == 0) {
-               ERROR("MISSING_SIGN_OFF",
-                     "Missing Signed-off-by: line(s)\n");
+       if ($is_patch && $has_commit_log && $chk_signoff) {
+               if ($signoff == 0) {
+                       ERROR("MISSING_SIGN_OFF",
+                             "Missing Signed-off-by: line(s)\n");
+               } elsif (!$authorsignoff) {
+                       WARN("NO_AUTHOR_SIGN_OFF",
+                            "Missing Signed-off-by: line by nominal patch author '$author'\n");
+               }
        }
 
        print report_dump();
index dbf0a31..e65fbc3 100755 (executable)
@@ -12,7 +12,7 @@
 
 compiler="$*"
 
-if !( $compiler --version | grep -q clang) ; then
+if ! ( $compiler --version | grep -q clang) ; then
        echo 0
        exit 1
 fi
index 92b2091..d819275 100644 (file)
@@ -35,8 +35,7 @@ statement S;
 
 * x = (T)\(kmalloc(E1, ...)\|vmalloc(E1)\|dma_alloc_coherent(...,E1,...)\|
   kmalloc_node(E1, ...)\|kmem_cache_alloc(...)\|kmem_alloc(E1, ...)\|
-  devm_kmalloc(...,E1,...)\|kvmalloc(E1, ...)\|pci_alloc_consistent(...,E1,...)\|
-  kvmalloc_node(E1,...)\);
+  devm_kmalloc(...,E1,...)\|kvmalloc(E1, ...)\|kvmalloc_node(E1,...)\);
   if ((x==NULL) || ...) S
 * memset((T2)x,0,E1);
 
@@ -124,15 +123,6 @@ statement S;
 - x = (T)kvmalloc(E1,E2);
 + x = (T)kvzalloc(E1,E2);
 |
-- x = pci_alloc_consistent(E2,E1,E3);
-+ x = pci_zalloc_consistent(E2,E1,E3);
-|
-- x = (T *)pci_alloc_consistent(E2,E1,E3);
-+ x = pci_zalloc_consistent(E2,E1,E3);
-|
-- x = (T)pci_alloc_consistent(E2,E1,E3);
-+ x = (T)pci_zalloc_consistent(E2,E1,E3);
-|
 - x = kvmalloc_node(E1,E2,E3);
 + x = kvzalloc_node(E1,E2,E3);
 |
@@ -389,35 +379,6 @@ msg="WARNING: kvzalloc should be used for %s, instead of kvmalloc/memset" % (x)
 coccilib.report.print_report(p[0], msg)
 
 //-----------------------------------------------------------------
-@r8 depends on org || report@
-type T, T2;
-expression x;
-expression E1,E2,E3;
-statement S;
-position p;
-@@
-
- x = (T)pci_alloc_consistent@p(E2,E1,E3);
- if ((x==NULL) || ...) S
- memset((T2)x,0,E1);
-
-@script:python depends on org@
-p << r8.p;
-x << r8.x;
-@@
-
-msg="%s" % (x)
-msg_safe=msg.replace("[","@(").replace("]",")")
-coccilib.org.print_todo(p[0], msg_safe)
-
-@script:python depends on report@
-p << r8.p;
-x << r8.x;
-@@
-
-msg="WARNING: pci_zalloc_consistent should be used for %s, instead of pci_alloc_consistent/memset" % (x)
-coccilib.report.print_report(p[0], msg)
-//-----------------------------------------------------------------
 @r9 depends on org || report@
 type T, T2;
 expression x;
index 9cac65b..1c943e0 100644 (file)
@@ -9,21 +9,11 @@ dtc-objs      := dtc.o flattree.o fstree.o data.o livetree.o treesource.o \
 dtc-objs       += dtc-lexer.lex.o dtc-parser.tab.o
 
 # Source files need to get at the userspace version of libfdt_env.h to compile
+HOST_EXTRACFLAGS := -I$(src)/libfdt
 
-HOSTCFLAGS_DTC := -I$(src) -I$(src)/libfdt
-
-HOSTCFLAGS_checks.o := $(HOSTCFLAGS_DTC)
-HOSTCFLAGS_data.o := $(HOSTCFLAGS_DTC)
-HOSTCFLAGS_dtc.o := $(HOSTCFLAGS_DTC)
-HOSTCFLAGS_flattree.o := $(HOSTCFLAGS_DTC)
-HOSTCFLAGS_fstree.o := $(HOSTCFLAGS_DTC)
-HOSTCFLAGS_livetree.o := $(HOSTCFLAGS_DTC)
-HOSTCFLAGS_srcpos.o := $(HOSTCFLAGS_DTC)
-HOSTCFLAGS_treesource.o := $(HOSTCFLAGS_DTC)
-HOSTCFLAGS_util.o := $(HOSTCFLAGS_DTC)
-
-HOSTCFLAGS_dtc-lexer.lex.o := $(HOSTCFLAGS_DTC)
-HOSTCFLAGS_dtc-parser.tab.o := $(HOSTCFLAGS_DTC)
+# Generated files need one more search path to include headers in source tree
+HOSTCFLAGS_dtc-lexer.lex.o := -I$(src)
+HOSTCFLAGS_dtc-parser.tab.o := -I$(src)
 
 # dependencies on generated files need to be listed explicitly
 $(obj)/dtc-lexer.lex.o: $(obj)/dtc-parser.tab.h
index 7430a7c..cb0c889 100644 (file)
@@ -2,7 +2,7 @@ preferred-plugin-hostcc := $(if-success,[ $(gcc-version) -ge 40800 ],$(HOSTCXX),
 
 config PLUGIN_HOSTCC
        string
-       default "$(shell,$(srctree)/scripts/gcc-plugin.sh "$(preferred-plugin-hostcc)" "$(HOSTCXX)" "$(CC)")"
+       default "$(shell,$(srctree)/scripts/gcc-plugin.sh "$(preferred-plugin-hostcc)" "$(HOSTCXX)" "$(CC)")" if CC_IS_GCC
        help
          Host compiler used to build GCC plugins.  This can be $(HOSTCXX),
          $(HOSTCC), or a null string if GCC plugin is unsupported.
index c87fa73..c1c088e 100755 (executable)
@@ -48,6 +48,7 @@ my $output_roles = 0;
 my $output_rolestats = 1;
 my $output_section_maxlen = 50;
 my $scm = 0;
+my $tree = 1;
 my $web = 0;
 my $subsystem = 0;
 my $status = 0;
@@ -61,7 +62,7 @@ my $self_test = undef;
 my $version = 0;
 my $help = 0;
 my $find_maintainer_files = 0;
-
+my $maintainer_path;
 my $vcs_used = 0;
 
 my $exit = 0;
@@ -255,6 +256,7 @@ if (!GetOptions(
                'subsystem!' => \$subsystem,
                'status!' => \$status,
                'scm!' => \$scm,
+               'tree!' => \$tree,
                'web!' => \$web,
                'letters=s' => \$letters,
                'pattern-depth=i' => \$pattern_depth,
@@ -263,6 +265,7 @@ if (!GetOptions(
                'fe|file-emails!' => \$file_emails,
                'f|file' => \$from_filename,
                'find-maintainer-files' => \$find_maintainer_files,
+               'mpath|maintainer-path=s' => \$maintainer_path,
                'self-test:s' => \$self_test,
                'v|version' => \$version,
                'h|help|usage' => \$help,
@@ -319,7 +322,7 @@ if ($email &&
     die "$P: Please select at least 1 email option\n";
 }
 
-if (!top_of_kernel_tree($lk_path)) {
+if ($tree && !top_of_kernel_tree($lk_path)) {
     die "$P: The current directory does not appear to be "
        . "a linux kernel source tree.\n";
 }
@@ -384,26 +387,36 @@ sub find_ignore_git {
 read_all_maintainer_files();
 
 sub read_all_maintainer_files {
-    if (-d "${lk_path}MAINTAINERS") {
-        opendir(DIR, "${lk_path}MAINTAINERS") or die $!;
-        my @files = readdir(DIR);
-        closedir(DIR);
-        foreach my $file (@files) {
-            push(@mfiles, "${lk_path}MAINTAINERS/$file") if ($file !~ /^\./);
-        }
-    }
-
-    if ($find_maintainer_files) {
-        find( { wanted => \&find_is_maintainer_file,
-                preprocess => \&find_ignore_git,
-                no_chdir => 1,
-        }, "${lk_path}");
+    my $path = "${lk_path}MAINTAINERS";
+    if (defined $maintainer_path) {
+       $path = $maintainer_path;
+       # Perl Cookbook tilde expansion if necessary
+       $path =~ s@^~([^/]*)@ $1 ? (getpwnam($1))[7] : ( $ENV{HOME} || $ENV{LOGDIR} || (getpwuid($<))[7])@ex;
+    }
+
+    if (-d $path) {
+       $path .= '/' if ($path !~ m@/$@);
+       if ($find_maintainer_files) {
+           find( { wanted => \&find_is_maintainer_file,
+                   preprocess => \&find_ignore_git,
+                   no_chdir => 1,
+               }, "$path");
+       } else {
+           opendir(DIR, "$path") or die $!;
+           my @files = readdir(DIR);
+           closedir(DIR);
+           foreach my $file (@files) {
+               push(@mfiles, "$path$file") if ($file !~ /^\./);
+           }
+       }
+    } elsif (-f "$path") {
+       push(@mfiles, "$path");
     } else {
-        push(@mfiles, "${lk_path}MAINTAINERS") if -f "${lk_path}MAINTAINERS";
+       die "$P: MAINTAINER file not found '$path'\n";
     }
-
+    die "$P: No MAINTAINER files found in '$path'\n" if (scalar(@mfiles) == 0);
     foreach my $file (@mfiles) {
-        read_maintainer_file("$file");
+       read_maintainer_file("$file");
     }
 }
 
@@ -1031,13 +1044,14 @@ Other options:
   --sections => print all of the subsystem sections with pattern matches
   --letters => print all matching 'letter' types from all matching sections
   --mailmap => use .mailmap file (default: $email_use_mailmap)
+  --no-tree => run without a kernel tree
   --self-test => show potential issues with MAINTAINERS file content
   --version => show version
   --help => show this help information
 
 Default options:
-  [--email --nogit --git-fallback --m --r --n --l --multiline --pattern-depth=0
-   --remove-duplicates --rolestats]
+  [--email --tree --nogit --git-fallback --m --r --n --l --multiline
+   --pattern-depth=0 --remove-duplicates --rolestats]
 
 Notes:
   Using "-f directory" may give unexpected results:
index 8d87910..4a7bd21 100644 (file)
@@ -3,7 +3,8 @@
 # Kernel configuration targets
 # These targets are used from top-level makefile
 
-PHONY += xconfig gconfig menuconfig config localmodconfig localyesconfig
+PHONY += xconfig gconfig menuconfig config localmodconfig localyesconfig \
+       build_menuconfig build_nconfig build_gconfig build_xconfig
 
 ifdef KBUILD_KCONFIG
 Kconfig := $(KBUILD_KCONFIG)
@@ -33,6 +34,14 @@ config: $(obj)/conf
 nconfig: $(obj)/nconf
        $< $(silent) $(Kconfig)
 
+build_menuconfig: $(obj)/mconf
+
+build_nconfig: $(obj)/nconf
+
+build_gconfig: $(obj)/gconf
+
+build_xconfig: $(obj)/qconf
+
 localyesconfig localmodconfig: $(obj)/conf
        $(Q)perl $(srctree)/$(src)/streamline_config.pl --$@ $(srctree) $(Kconfig) > .tmp.config
        $(Q)if [ -f .config ]; then                                     \
@@ -169,7 +178,7 @@ HOSTLDLIBS_nconf    = $(shell . $(obj)/.nconf-cfg && echo $$libs)
 HOSTCFLAGS_nconf.o     = $(shell . $(obj)/.nconf-cfg && echo $$cflags)
 HOSTCFLAGS_nconf.gui.o = $(shell . $(obj)/.nconf-cfg && echo $$cflags)
 
-$(obj)/nconf.o: $(obj)/.nconf-cfg
+$(obj)/nconf.o $(obj)/nconf.gui.o: $(obj)/.nconf-cfg
 
 # mconf: Used for the menuconfig target based on lxdialog
 hostprogs-y    += mconf
@@ -180,7 +189,8 @@ HOSTLDLIBS_mconf = $(shell . $(obj)/.mconf-cfg && echo $$libs)
 $(foreach f, mconf.o $(lxdialog), \
   $(eval HOSTCFLAGS_$f = $$(shell . $(obj)/.mconf-cfg && echo $$$$cflags)))
 
-$(addprefix $(obj)/, mconf.o $(lxdialog)): $(obj)/.mconf-cfg
+$(obj)/mconf.o: $(obj)/.mconf-cfg
+$(addprefix $(obj)/lxdialog/, $(lxdialog)): $(obj)/.mconf-cfg
 
 # qconf: Used for the xconfig target based on Qt
 hostprogs-y    += qconf
index b35cc93..7b2b372 100644 (file)
@@ -508,6 +508,11 @@ int main(int ac, char **av)
                input_mode = (enum input_mode)opt;
                switch (opt) {
                case syncconfig:
+                       /*
+                        * syncconfig is invoked during the build stage.
+                        * Suppress distracting "configuration written to ..."
+                        */
+                       conf_set_message_callback(NULL);
                        sync_kconfig = 1;
                        break;
                case defconfig:
index 4ec8b1f..703b9b8 100644 (file)
@@ -1011,7 +1011,7 @@ static struct dep_stack {
        struct dep_stack *prev, *next;
        struct symbol *sym;
        struct property *prop;
-       struct expr *expr;
+       struct expr **expr;
 } *check_top;
 
 static void dep_stack_insert(struct dep_stack *stack, struct symbol *sym)
@@ -1076,31 +1076,42 @@ static void sym_check_print_recursive(struct symbol *last_sym)
                        fprintf(stderr, "%s:%d:error: recursive dependency detected!\n",
                                prop->file->name, prop->lineno);
 
-               if (stack->expr) {
-                       fprintf(stderr, "%s:%d:\tsymbol %s %s value contains %s\n",
-                               prop->file->name, prop->lineno,
+               if (sym_is_choice(sym)) {
+                       fprintf(stderr, "%s:%d:\tchoice %s contains symbol %s\n",
+                               menu->file->name, menu->lineno,
                                sym->name ? sym->name : "<choice>",
-                               prop_get_type_name(prop->type),
                                next_sym->name ? next_sym->name : "<choice>");
-               } else if (stack->prop) {
+               } else if (sym_is_choice_value(sym)) {
+                       fprintf(stderr, "%s:%d:\tsymbol %s is part of choice %s\n",
+                               menu->file->name, menu->lineno,
+                               sym->name ? sym->name : "<choice>",
+                               next_sym->name ? next_sym->name : "<choice>");
+               } else if (stack->expr == &sym->dir_dep.expr) {
                        fprintf(stderr, "%s:%d:\tsymbol %s depends on %s\n",
                                prop->file->name, prop->lineno,
                                sym->name ? sym->name : "<choice>",
                                next_sym->name ? next_sym->name : "<choice>");
-               } else if (sym_is_choice(sym)) {
-                       fprintf(stderr, "%s:%d:\tchoice %s contains symbol %s\n",
-                               menu->file->name, menu->lineno,
+               } else if (stack->expr == &sym->rev_dep.expr) {
+                       fprintf(stderr, "%s:%d:\tsymbol %s is selected by %s\n",
+                               prop->file->name, prop->lineno,
                                sym->name ? sym->name : "<choice>",
                                next_sym->name ? next_sym->name : "<choice>");
-               } else if (sym_is_choice_value(sym)) {
-                       fprintf(stderr, "%s:%d:\tsymbol %s is part of choice %s\n",
-                               menu->file->name, menu->lineno,
+               } else if (stack->expr == &sym->implied.expr) {
+                       fprintf(stderr, "%s:%d:\tsymbol %s is implied by %s\n",
+                               prop->file->name, prop->lineno,
+                               sym->name ? sym->name : "<choice>",
+                               next_sym->name ? next_sym->name : "<choice>");
+               } else if (stack->expr) {
+                       fprintf(stderr, "%s:%d:\tsymbol %s %s value contains %s\n",
+                               prop->file->name, prop->lineno,
                                sym->name ? sym->name : "<choice>",
+                               prop_get_type_name(prop->type),
                                next_sym->name ? next_sym->name : "<choice>");
                } else {
-                       fprintf(stderr, "%s:%d:\tsymbol %s is selected by %s\n",
+                       fprintf(stderr, "%s:%d:\tsymbol %s %s is visible depending on %s\n",
                                prop->file->name, prop->lineno,
                                sym->name ? sym->name : "<choice>",
+                               prop_get_type_name(prop->type),
                                next_sym->name ? next_sym->name : "<choice>");
                }
        }
@@ -1157,12 +1168,26 @@ static struct symbol *sym_check_sym_deps(struct symbol *sym)
 
        dep_stack_insert(&stack, sym);
 
+       stack.expr = &sym->dir_dep.expr;
+       sym2 = sym_check_expr_deps(sym->dir_dep.expr);
+       if (sym2)
+               goto out;
+
+       stack.expr = &sym->rev_dep.expr;
        sym2 = sym_check_expr_deps(sym->rev_dep.expr);
        if (sym2)
                goto out;
 
+       stack.expr = &sym->implied.expr;
+       sym2 = sym_check_expr_deps(sym->implied.expr);
+       if (sym2)
+               goto out;
+
+       stack.expr = NULL;
+
        for (prop = sym->prop; prop; prop = prop->next) {
-               if (prop->type == P_CHOICE || prop->type == P_SELECT)
+               if (prop->type == P_CHOICE || prop->type == P_SELECT ||
+                   prop->type == P_IMPLY)
                        continue;
                stack.prop = prop;
                sym2 = sym_check_expr_deps(prop->visible.expr);
@@ -1170,7 +1195,7 @@ static struct symbol *sym_check_sym_deps(struct symbol *sym)
                        break;
                if (prop->type != P_DEFAULT || sym_is_choice(sym))
                        continue;
-               stack.expr = prop->expr;
+               stack.expr = &prop->expr;
                sym2 = sym_check_expr_deps(prop->expr);
                if (sym2)
                        break;
@@ -1248,9 +1273,6 @@ struct symbol *sym_check_deps(struct symbol *sym)
                sym->flags &= ~SYMBOL_CHECK;
        }
 
-       if (sym2 && sym2 == sym)
-               sym2 = NULL;
-
        return sym2;
 }
 
@@ -1,3 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0
+
 # depends on itself
 
 config A
@@ -31,7 +33,6 @@ config D2
        bool
 
 # depends on and imply
-# This is not recursive dependency
 
 config E1
        bool "E1"
diff --git a/scripts/kconfig/tests/err_recursive_dep/__init__.py b/scripts/kconfig/tests/err_recursive_dep/__init__.py
new file mode 100644 (file)
index 0000000..5f3821b
--- /dev/null
@@ -0,0 +1,10 @@
+# SPDX-License-Identifier: GPL-2.0
+"""
+Detect recursive dependency error.
+
+Recursive dependency should be treated as an error.
+"""
+
+def test(conf):
+    assert conf.oldaskconfig() == 1
+    assert conf.stderr_contains('expected_stderr')
diff --git a/scripts/kconfig/tests/err_recursive_dep/expected_stderr b/scripts/kconfig/tests/err_recursive_dep/expected_stderr
new file mode 100644 (file)
index 0000000..84679b1
--- /dev/null
@@ -0,0 +1,38 @@
+Kconfig:11:error: recursive dependency detected!
+Kconfig:11:    symbol B is selected by B
+For a resolution refer to Documentation/kbuild/kconfig-language.txt
+subsection "Kconfig recursive dependency limitations"
+
+Kconfig:5:error: recursive dependency detected!
+Kconfig:5:     symbol A depends on A
+For a resolution refer to Documentation/kbuild/kconfig-language.txt
+subsection "Kconfig recursive dependency limitations"
+
+Kconfig:17:error: recursive dependency detected!
+Kconfig:17:    symbol C1 depends on C2
+Kconfig:21:    symbol C2 depends on C1
+For a resolution refer to Documentation/kbuild/kconfig-language.txt
+subsection "Kconfig recursive dependency limitations"
+
+Kconfig:32:error: recursive dependency detected!
+Kconfig:32:    symbol D2 is selected by D1
+Kconfig:27:    symbol D1 depends on D2
+For a resolution refer to Documentation/kbuild/kconfig-language.txt
+subsection "Kconfig recursive dependency limitations"
+
+Kconfig:37:error: recursive dependency detected!
+Kconfig:37:    symbol E1 depends on E2
+Kconfig:42:    symbol E2 is implied by E1
+For a resolution refer to Documentation/kbuild/kconfig-language.txt
+subsection "Kconfig recursive dependency limitations"
+
+Kconfig:60:error: recursive dependency detected!
+Kconfig:60:    symbol G depends on G
+For a resolution refer to Documentation/kbuild/kconfig-language.txt
+subsection "Kconfig recursive dependency limitations"
+
+Kconfig:51:error: recursive dependency detected!
+Kconfig:51:    symbol F2 depends on F1
+Kconfig:49:    symbol F1 default value contains F2
+For a resolution refer to Documentation/kbuild/kconfig-language.txt
+subsection "Kconfig recursive dependency limitations"
diff --git a/scripts/kconfig/tests/warn_recursive_dep/__init__.py b/scripts/kconfig/tests/warn_recursive_dep/__init__.py
deleted file mode 100644 (file)
index adb2195..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-"""
-Warn recursive inclusion.
-
-Recursive dependency should be warned.
-"""
-
-def test(conf):
-    assert conf.oldaskconfig() == 0
-    assert conf.stderr_contains('expected_stderr')
diff --git a/scripts/kconfig/tests/warn_recursive_dep/expected_stderr b/scripts/kconfig/tests/warn_recursive_dep/expected_stderr
deleted file mode 100644 (file)
index 3de807d..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-Kconfig:9:error: recursive dependency detected!
-Kconfig:9:     symbol B is selected by B
-For a resolution refer to Documentation/kbuild/kconfig-language.txt
-subsection "Kconfig recursive dependency limitations"
-
-Kconfig:3:error: recursive dependency detected!
-Kconfig:3:     symbol A depends on A
-For a resolution refer to Documentation/kbuild/kconfig-language.txt
-subsection "Kconfig recursive dependency limitations"
-
-Kconfig:15:error: recursive dependency detected!
-Kconfig:15:    symbol C1 depends on C2
-Kconfig:19:    symbol C2 depends on C1
-For a resolution refer to Documentation/kbuild/kconfig-language.txt
-subsection "Kconfig recursive dependency limitations"
-
-Kconfig:30:error: recursive dependency detected!
-Kconfig:30:    symbol D2 is selected by D1
-Kconfig:25:    symbol D1 depends on D2
-For a resolution refer to Documentation/kbuild/kconfig-language.txt
-subsection "Kconfig recursive dependency limitations"
-
-Kconfig:59:error: recursive dependency detected!
-Kconfig:59:    symbol G depends on G
-For a resolution refer to Documentation/kbuild/kconfig-language.txt
-subsection "Kconfig recursive dependency limitations"
-
-Kconfig:50:error: recursive dependency detected!
-Kconfig:50:    symbol F2 depends on F1
-Kconfig:48:    symbol F1 default value contains F2
index 4bf811c..c8cf453 100755 (executable)
@@ -75,7 +75,7 @@ modpost_link()
                ${KBUILD_VMLINUX_LIBS}                          \
                --end-group"
 
-       ${LD} ${LDFLAGS} -r -o ${1} ${objects}
+       ${LD} ${KBUILD_LDFLAGS} -r -o ${1} ${objects}
 }
 
 # Link of vmlinux
@@ -95,7 +95,7 @@ vmlinux_link()
                        --end-group                             \
                        ${1}"
 
-               ${LD} ${LDFLAGS} ${LDFLAGS_vmlinux} -o ${2}     \
+               ${LD} ${KBUILD_LDFLAGS} ${LDFLAGS_vmlinux} -o ${2}      \
                        -T ${lds} ${objects}
        else
                objects="-Wl,--whole-archive                    \
index dc6d714..0d998c5 100644 (file)
@@ -672,7 +672,7 @@ static void handle_modversions(struct module *mod, struct elf_info *info,
                        if (ELF_ST_TYPE(sym->st_info) == STT_SPARC_REGISTER)
                                break;
                        if (symname[0] == '.') {
-                               char *munged = strdup(symname);
+                               char *munged = NOFAIL(strdup(symname));
                                munged[0] = '_';
                                munged[1] = toupper(munged[1]);
                                symname = munged;
@@ -1318,7 +1318,7 @@ static Elf_Sym *find_elf_symbol2(struct elf_info *elf, Elf_Addr addr,
 static char *sec2annotation(const char *s)
 {
        if (match(s, init_exit_sections)) {
-               char *p = malloc(20);
+               char *p = NOFAIL(malloc(20));
                char *r = p;
 
                *p++ = '_';
@@ -1338,7 +1338,7 @@ static char *sec2annotation(const char *s)
                        strcat(p, " ");
                return r;
        } else {
-               return strdup("");
+               return NOFAIL(strdup(""));
        }
 }
 
@@ -2036,7 +2036,7 @@ void buf_write(struct buffer *buf, const char *s, int len)
 {
        if (buf->size - buf->pos < len) {
                buf->size += len + SZ;
-               buf->p = realloc(buf->p, buf->size);
+               buf->p = NOFAIL(realloc(buf->p, buf->size));
        }
        strncpy(buf->p + buf->pos, s, len);
        buf->pos += len;
index 9a058cf..517d0c3 100644 (file)
@@ -10,6 +10,8 @@
 abandonning||abandoning
 abigious||ambiguous
 abitrate||arbitrate
+abord||abort
+aboslute||absolute
 abov||above
 abreviated||abbreviated
 absense||absence
@@ -25,6 +27,7 @@ accessable||accessible
 accesss||access
 accidentaly||accidentally
 accidentually||accidentally
+acclerated||accelerated
 accoding||according
 accomodate||accommodate
 accomodates||accommodates
@@ -58,12 +61,15 @@ addres||address
 adddress||address
 addreses||addresses
 addresss||address
+addrress||address
 aditional||additional
 aditionally||additionally
 aditionaly||additionally
 adminstrative||administrative
 adress||address
 adresses||addresses
+adrresses||addresses
+advertisment||advertisement
 adviced||advised
 afecting||affecting
 againt||against
@@ -100,6 +106,7 @@ alue||value
 ambigious||ambiguous
 amoung||among
 amout||amount
+amplifer||amplifier
 an union||a union
 an user||a user
 an userspace||a userspace
@@ -145,11 +152,15 @@ assistent||assistant
 assocation||association
 associcated||associated
 assotiated||associated
+asssert||assert
 assum||assume
 assumtpion||assumption
 asuming||assuming
 asycronous||asynchronous
 asynchnous||asynchronous
+asynchromous||asynchronous
+asymetric||asymmetric
+asymmeric||asymmetric
 atomatically||automatically
 atomicly||atomically
 atempt||attempt
@@ -172,6 +183,7 @@ avaible||available
 availabe||available
 availabled||available
 availablity||availability
+availaible||available
 availale||available
 availavility||availability
 availble||available
@@ -206,8 +218,11 @@ borad||board
 boundry||boundary
 brievely||briefly
 broadcat||broadcast
+bufufer||buffer
 cacluated||calculated
+caculate||calculate
 caculation||calculation
+cadidate||candidate
 calender||calendar
 calescing||coalescing
 calle||called
@@ -221,12 +236,14 @@ capabilty||capability
 capabitilies||capabilities
 capatibilities||capabilities
 capapbilities||capabilities
+caputure||capture
 carefuly||carefully
 cariage||carriage
 catagory||category
 cehck||check
 challange||challenge
 challanges||challenges
+chache||cache
 chanell||channel
 changable||changeable
 chanined||chained
@@ -240,6 +257,7 @@ charaters||characters
 charcter||character
 chcek||check
 chck||check
+checksumed||checksummed
 checksuming||checksumming
 childern||children
 childs||children
@@ -292,8 +310,10 @@ comunication||communication
 conbination||combination
 conditionaly||conditionally
 conected||connected
+conector||connector
 connecetd||connected
 configuartion||configuration
+configuation||configuration
 configuratoin||configuration
 configuraton||configuration
 configuretion||configuration
@@ -315,6 +335,7 @@ continous||continuous
 continously||continuously
 continueing||continuing
 contraints||constraints
+contruct||construct
 contol||control
 contoller||controller
 controled||controlled
@@ -343,6 +364,7 @@ dafault||default
 deafult||default
 deamon||daemon
 decompres||decompress
+decsribed||described
 decription||description
 dectected||detected
 defailt||default
@@ -379,6 +401,7 @@ desctiptor||descriptor
 desriptor||descriptor
 desriptors||descriptors
 destionation||destination
+destoried||destroyed
 destory||destroy
 destoryed||destroyed
 destorys||destroys
@@ -400,22 +423,30 @@ didnt||didn't
 diferent||different
 differrence||difference
 diffrent||different
+differenciate||differentiate
 diffrentiate||differentiate
 difinition||definition
 dimesions||dimensions
 diplay||display
+directon||direction
 direectly||directly
+diregard||disregard
 disassocation||disassociation
 disapear||disappear
 disapeared||disappeared
 disappared||disappeared
+disbale||disable
+disbaled||disabled
 disble||disable
 disbled||disabled
 disconnet||disconnect
 discontinous||discontinuous
+disharge||discharge
 dispertion||dispersion
 dissapears||disappears
 distiction||distinction
+divisable||divisible
+divsiors||divisors
 docuentation||documentation
 documantation||documentation
 documentaion||documentation
@@ -427,6 +458,7 @@ downlad||download
 downlads||downloads
 druing||during
 dynmaic||dynamic
+eanable||enable
 easilly||easily
 ecspecially||especially
 edditable||editable
@@ -484,9 +516,12 @@ exprimental||experimental
 extened||extended
 extensability||extensibility
 extention||extension
+extenstion||extension
 extracter||extractor
+faield||failed
 falied||failed
 faild||failed
+failer||failure
 faill||fail
 failied||failed
 faillure||failure
@@ -520,6 +555,7 @@ forseeable||foreseeable
 forse||force
 fortan||fortran
 forwardig||forwarding
+frambuffer||framebuffer
 framming||framing
 framwork||framework
 frequncy||frequency
@@ -527,6 +563,7 @@ frome||from
 fucntion||function
 fuction||function
 fuctions||functions
+funcation||function
 funcion||function
 functionallity||functionality
 functionaly||functionally
@@ -540,6 +577,7 @@ futrue||future
 gaurenteed||guaranteed
 generiously||generously
 genereate||generate
+genereted||generated
 genric||generic
 globel||global
 grabing||grabbing
@@ -553,6 +591,7 @@ guarentee||guarantee
 halfs||halves
 hander||handler
 handfull||handful
+hanlde||handle
 hanled||handled
 happend||happened
 harware||hardware
@@ -561,6 +600,7 @@ helpfull||helpful
 hybernate||hibernate
 hierachy||hierarchy
 hierarchie||hierarchy
+homogenous||homogeneous
 howver||however
 hsould||should
 hypervior||hypervisor
@@ -568,6 +608,8 @@ hypter||hyper
 identidier||identifier
 iligal||illegal
 illigal||illegal
+illgal||illegal
+iomaped||iomapped
 imblance||imbalance
 immeadiately||immediately
 immedaite||immediate
@@ -618,12 +660,15 @@ initation||initiation
 initators||initiators
 initialiazation||initialization
 initializiation||initialization
+initialze||initialize
 initialzed||initialized
 initilization||initialization
 initilize||initialize
 inofficial||unofficial
+inrerface||interface
 insititute||institute
 instal||install
+instanciate||instantiate
 instanciated||instantiated
 inteface||interface
 integreated||integrated
@@ -657,6 +702,7 @@ intregral||integral
 intrrupt||interrupt
 intterrupt||interrupt
 intuative||intuitive
+inavlid||invalid
 invaid||invalid
 invald||invalid
 invalde||invalid
@@ -683,6 +729,7 @@ langauge||language
 langugage||language
 lauch||launch
 layed||laid
+legnth||length
 leightweight||lightweight
 lengh||length
 lenght||length
@@ -696,6 +743,7 @@ licenceing||licencing
 loggging||logging
 loggin||login
 logile||logfile
+loobpack||loopback
 loosing||losing
 losted||lost
 machinary||machinery
@@ -703,6 +751,7 @@ maintainance||maintenance
 maintainence||maintenance
 maintan||maintain
 makeing||making
+mailformed||malformed
 malplaced||misplaced
 malplace||misplace
 managable||manageable
@@ -710,6 +759,7 @@ managment||management
 mangement||management
 manoeuvering||maneuvering
 mappping||mapping
+matchs||matches
 mathimatical||mathematical
 mathimatic||mathematic
 mathimatics||mathematics
@@ -725,6 +775,7 @@ messsage||message
 messsages||messages
 micropone||microphone
 microprocesspr||microprocessor
+migrateable||migratable
 milliseonds||milliseconds
 minium||minimum
 minimam||minimum
@@ -741,6 +792,7 @@ missmatch||mismatch
 miximum||maximum
 mmnemonic||mnemonic
 mnay||many
+modfiy||modify
 modulues||modules
 momery||memory
 memomry||memory
@@ -777,6 +829,7 @@ notifed||notified
 numebr||number
 numner||number
 obtaion||obtain
+obusing||abusing
 occassionally||occasionally
 occationally||occasionally
 occurance||occurrence
@@ -787,6 +840,7 @@ occure||occurred
 occured||occurred
 occuring||occurring
 offet||offset
+offloded||offloaded
 omited||omitted
 omiting||omitting
 omitt||omit
@@ -829,6 +883,7 @@ parametes||parameters
 parametised||parametrised
 paramter||parameter
 paramters||parameters
+parmaters||parameters
 particuarly||particularly
 particularily||particularly
 partiton||partition
@@ -837,6 +892,7 @@ passin||passing
 pathes||paths
 pecularities||peculiarities
 peformance||performance
+peforming||performing
 peice||piece
 pendantic||pedantic
 peprocessor||preprocessor
@@ -846,6 +902,7 @@ peroid||period
 persistance||persistence
 persistant||persistent
 plalform||platform
+platfoem||platform
 platfrom||platform
 plattform||platform
 pleaes||please
@@ -858,6 +915,7 @@ posible||possible
 positon||position
 possibilites||possibilities
 powerfull||powerful
+preamle||preamble
 preample||preamble
 preapre||prepare
 preceeded||preceded
@@ -870,6 +928,7 @@ prefered||preferred
 prefferably||preferably
 premption||preemption
 prepaired||prepared
+preperation||preparation
 pressre||pressure
 primative||primitive
 princliple||principle
@@ -935,6 +994,7 @@ recommanded||recommended
 recyle||recycle
 redircet||redirect
 redirectrion||redirection
+redundacy||redundancy
 reename||rename
 refcounf||refcount
 refence||reference
@@ -945,6 +1005,7 @@ refernces||references
 refernnce||reference
 refrence||reference
 registerd||registered
+registeration||registration
 registeresd||registered
 registerred||registered
 registes||registers
@@ -973,7 +1034,9 @@ requirment||requirement
 requred||required
 requried||required
 requst||request
+reregisteration||reregistration
 reseting||resetting
+reseverd||reserved
 resizeable||resizable
 resouce||resource
 resouces||resources
@@ -982,6 +1045,7 @@ responce||response
 ressizes||resizes
 ressource||resource
 ressources||resources
+restesting||retesting
 retransmited||retransmitted
 retreived||retrieved
 retreive||retrieve
@@ -1006,6 +1070,7 @@ sacrifying||sacrificing
 safly||safely
 safty||safety
 savable||saveable
+scaleing||scaling
 scaned||scanned
 scaning||scanning
 scarch||search
@@ -1014,6 +1079,8 @@ searchs||searches
 secquence||sequence
 secund||second
 segement||segment
+semaphone||semaphore
+senario||scenario
 senarios||scenarios
 sentivite||sensitive
 separatly||separately
@@ -1025,9 +1092,13 @@ seperate||separate
 seperatly||separately
 seperator||separator
 sepperate||separate
+seqeunce||sequence
+seqeuncer||sequencer
+seqeuencer||sequencer
 sequece||sequence
 sequencial||sequential
 serveral||several
+servive||service
 setts||sets
 settting||setting
 shotdown||shutdown
@@ -1073,6 +1144,7 @@ standartization||standardization
 standart||standard
 staticly||statically
 stoped||stopped
+stoping||stopping
 stoppped||stopped
 straming||streaming
 struc||struct
@@ -1085,6 +1157,7 @@ subdirectoires||subdirectories
 suble||subtle
 substract||subtract
 submition||submission
+suceed||succeed
 succesfully||successfully
 succesful||successful
 successed||succeeded
@@ -1108,6 +1181,7 @@ surpressed||suppressed
 surpresses||suppresses
 susbsystem||subsystem
 suspeneded||suspended
+suspsend||suspend
 suspicously||suspiciously
 swaping||swapping
 switchs||switches
@@ -1122,6 +1196,7 @@ swtich||switch
 symetric||symmetric
 synax||syntax
 synchonized||synchronized
+synchronuously||synchronously
 syncronize||synchronize
 syncronized||synchronized
 syncronizing||synchronizing
@@ -1130,11 +1205,14 @@ syste||system
 sytem||system
 sythesis||synthesis
 taht||that
+tansmit||transmit
 targetted||targeted
 targetting||targeting
+taskelt||tasklet
 teh||the
 temorary||temporary
 temproarily||temporarily
+thead||thread
 therfore||therefore
 thier||their
 threds||threads
@@ -1143,11 +1221,14 @@ thresold||threshold
 throught||through
 troughput||throughput
 thses||these
+tiggers||triggers
 tiggered||triggered
 tipically||typically
+timeing||timing
 timout||timeout
 tmis||this
 torerable||tolerable
+traking||tracking
 tramsmitted||transmitted
 tramsmit||transmit
 tranasction||transaction
@@ -1162,6 +1243,7 @@ transormed||transformed
 trasfer||transfer
 trasmission||transmission
 treshold||threshold
+trigerred||triggered
 trigerring||triggering
 trun||turn
 tunning||tuning
@@ -1169,6 +1251,8 @@ ture||true
 tyep||type
 udpate||update
 uesd||used
+uknown||unknown
+usupported||unsupported
 uncommited||uncommitted
 unconditionaly||unconditionally
 underun||underrun
@@ -1181,11 +1265,14 @@ unexpeted||unexpected
 unexpexted||unexpected
 unfortunatelly||unfortunately
 unifiy||unify
+uniterrupted||uninterrupted
 unintialized||uninitialized
 unkmown||unknown
 unknonw||unknown
 unknow||unknown
 unkown||unknown
+unamed||unnamed
+uneeded||unneeded
 unneded||unneeded
 unneccecary||unnecessary
 unneccesary||unnecessary
@@ -1210,6 +1297,7 @@ usefull||useful
 usege||usage
 usera||users
 usualy||usually
+usupported||unsupported
 utilites||utilities
 utillities||utilities
 utilties||utilities
@@ -1233,7 +1321,9 @@ virtaul||virtual
 virtiual||virtual
 visiters||visitors
 vitual||virtual
+vunerable||vulnerable
 wakeus||wakeups
+wathdog||watchdog
 wating||waiting
 wiat||wait
 wether||whether
index 949dd8a..e09fe4d 100644 (file)
@@ -603,7 +603,7 @@ static const struct file_operations aa_fs_ns_revision_fops = {
 static void profile_query_cb(struct aa_profile *profile, struct aa_perms *perms,
                             const char *match_str, size_t match_len)
 {
-       struct aa_perms tmp;
+       struct aa_perms tmp = { };
        struct aa_dfa *dfa;
        unsigned int state = 0;
 
@@ -613,7 +613,6 @@ static void profile_query_cb(struct aa_profile *profile, struct aa_perms *perms,
                dfa = profile->file.dfa;
                state = aa_dfa_match_len(dfa, profile->file.start,
                                         match_str + 1, match_len - 1);
-               tmp = nullperms;
                if (state) {
                        struct path_cond cond = { };
 
@@ -627,8 +626,6 @@ static void profile_query_cb(struct aa_profile *profile, struct aa_perms *perms,
                                         match_str, match_len);
                if (state)
                        aa_compute_perms(dfa, state, &tmp);
-               else
-                       tmp = nullperms;
        }
        aa_apply_modes_to_perms(profile, &tmp);
        aa_perms_accum_raw(perms, &tmp);
index 098d546..08c88de 100644 (file)
@@ -1036,7 +1036,7 @@ static struct aa_label *build_change_hat(struct aa_profile *profile,
 audit:
        aa_audit_file(profile, &nullperms, OP_CHANGE_HAT, AA_MAY_CHANGEHAT,
                      name, hat ? hat->base.hname : NULL,
-                     hat ? &hat->label : NULL, GLOBAL_ROOT_UID, NULL,
+                     hat ? &hat->label : NULL, GLOBAL_ROOT_UID, info,
                      error);
        if (!hat || (error && error != -ENOENT))
                return ERR_PTR(error);
index 224b2fe..4285943 100644 (file)
@@ -47,7 +47,8 @@ static void audit_file_mask(struct audit_buffer *ab, u32 mask)
 {
        char str[10];
 
-       aa_perm_mask_to_str(str, aa_file_perm_chrs, map_mask_to_chr_mask(mask));
+       aa_perm_mask_to_str(str, sizeof(str), aa_file_perm_chrs,
+                           map_mask_to_chr_mask(mask));
        audit_log_string(ab, str);
 }
 
index 38aa624..b94ec11 100644 (file)
@@ -137,7 +137,8 @@ extern struct aa_perms allperms;
        xcheck(fn_for_each((L1), (P), (FN1)), fn_for_each((L2), (P), (FN2)))
 
 
-void aa_perm_mask_to_str(char *str, const char *chrs, u32 mask);
+void aa_perm_mask_to_str(char *str, size_t str_size, const char *chrs,
+                        u32 mask);
 void aa_audit_perm_names(struct audit_buffer *ab, const char * const *names,
                         u32 mask);
 void aa_audit_perm_mask(struct audit_buffer *ab, u32 mask, const char *chrs,
index a7b3f68..974affe 100644 (file)
@@ -198,15 +198,24 @@ const char *aa_file_perm_names[] = {
 /**
  * aa_perm_mask_to_str - convert a perm mask to its short string
  * @str: character buffer to store string in (at least 10 characters)
+ * @str_size: size of the @str buffer
+ * @chrs: NUL-terminated character buffer of permission characters
  * @mask: permission mask to convert
  */
-void aa_perm_mask_to_str(char *str, const char *chrs, u32 mask)
+void aa_perm_mask_to_str(char *str, size_t str_size, const char *chrs, u32 mask)
 {
        unsigned int i, perm = 1;
+       size_t num_chrs = strlen(chrs);
+
+       for (i = 0; i < num_chrs; perm <<= 1, i++) {
+               if (mask & perm) {
+                       /* Ensure that one byte is left for NUL-termination */
+                       if (WARN_ON_ONCE(str_size <= 1))
+                               break;
 
-       for (i = 0; i < 32; perm <<= 1, i++) {
-               if (mask & perm)
                        *str++ = chrs[i];
+                       str_size--;
+               }
        }
        *str = '\0';
 }
@@ -236,7 +245,7 @@ void aa_audit_perm_mask(struct audit_buffer *ab, u32 mask, const char *chrs,
 
        audit_log_format(ab, "\"");
        if ((mask & chrsmask) && chrs) {
-               aa_perm_mask_to_str(str, chrs, mask & chrsmask);
+               aa_perm_mask_to_str(str, sizeof(str), chrs, mask & chrsmask);
                mask &= ~chrsmask;
                audit_log_format(ab, "%s", str);
                if (mask & namesmask)
index b0f9dc3..1a7cec5 100644 (file)
@@ -255,7 +255,7 @@ static struct aa_ns *__aa_create_ns(struct aa_ns *parent, const char *name,
 
        ns = alloc_ns(parent->base.hname, name);
        if (!ns)
-               return NULL;
+               return ERR_PTR(-ENOMEM);
        ns->level = parent->level + 1;
        mutex_lock_nested(&ns->lock, ns->level);
        error = __aafs_ns_mkdir(ns, ns_subns_dir(parent), name, dir);
index 0e566a0..21cb384 100644 (file)
@@ -389,32 +389,6 @@ static int unpack_strdup(struct aa_ext *e, char **string, const char *name)
        return res;
 }
 
-#define DFA_VALID_PERM_MASK            0xffffffff
-#define DFA_VALID_PERM2_MASK           0xffffffff
-
-/**
- * verify_accept - verify the accept tables of a dfa
- * @dfa: dfa to verify accept tables of (NOT NULL)
- * @flags: flags governing dfa
- *
- * Returns: 1 if valid accept tables else 0 if error
- */
-static bool verify_accept(struct aa_dfa *dfa, int flags)
-{
-       int i;
-
-       /* verify accept permissions */
-       for (i = 0; i < dfa->tables[YYTD_ID_ACCEPT]->td_lolen; i++) {
-               int mode = ACCEPT_TABLE(dfa)[i];
-
-               if (mode & ~DFA_VALID_PERM_MASK)
-                       return 0;
-
-               if (ACCEPT_TABLE2(dfa)[i] & ~DFA_VALID_PERM2_MASK)
-                       return 0;
-       }
-       return 1;
-}
 
 /**
  * unpack_dfa - unpack a file rule dfa
@@ -445,15 +419,9 @@ static struct aa_dfa *unpack_dfa(struct aa_ext *e)
                if (IS_ERR(dfa))
                        return dfa;
 
-               if (!verify_accept(dfa, flags))
-                       goto fail;
        }
 
        return dfa;
-
-fail:
-       aa_put_dfa(dfa);
-       return ERR_PTR(-EPROTO);
 }
 
 /**
index f4c33ab..2e489d6 100644 (file)
@@ -388,7 +388,7 @@ int cap_inode_getsecurity(struct inode *inode, const char *name, void **buffer,
        if (strcmp(name, "capability") != 0)
                return -EOPNOTSUPP;
 
-       dentry = d_find_alias(inode);
+       dentry = d_find_any_alias(inode);
        if (!dentry)
                return -EINVAL;
 
index 47cfff0..736e78d 100644 (file)
@@ -48,14 +48,17 @@ static __initdata char chosen_lsm[SECURITY_NAME_MAX + 1] =
 static void __init do_security_initcalls(void)
 {
        int ret;
-       initcall_t *call;
-       call = __security_initcall_start;
+       initcall_t call;
+       initcall_entry_t *ce;
+
+       ce = __security_initcall_start;
        trace_initcall_level("security");
-       while (call < __security_initcall_end) {
-               trace_initcall_start((*call));
-               ret = (*call) ();
-               trace_initcall_finish((*call), ret);
-               call++;
+       while (ce < __security_initcall_end) {
+               call = initcall_from_entry(ce);
+               trace_initcall_start(call);
+               ret = call();
+               trace_initcall_finish(call, ret);
+               ce++;
        }
 }
 
index 7a0dfca..9f0c480 100644 (file)
@@ -529,7 +529,7 @@ static int ac97_bus_remove(struct device *dev)
        int ret;
 
        ret = pm_runtime_get_sync(dev);
-       if (ret)
+       if (ret < 0)
                return ret;
 
        ret = adrv->remove(adev);
@@ -537,6 +537,8 @@ static int ac97_bus_remove(struct device *dev)
        if (ret == 0)
                ac97_put_disable_clk(adev);
 
+       pm_runtime_disable(dev);
+
        return ret;
 }
 
index 61544e0..8bab44f 100644 (file)
 
 #include "ac97_core.h"
 
+static void compat_ac97_release(struct device *dev)
+{
+       kfree(to_ac97_t(dev));
+}
+
 static void compat_ac97_reset(struct snd_ac97 *ac97)
 {
        struct ac97_codec_device *adev = to_ac97_device(ac97->private_data);
@@ -65,21 +70,31 @@ static struct snd_ac97_bus compat_soc_ac97_bus = {
 struct snd_ac97 *snd_ac97_compat_alloc(struct ac97_codec_device *adev)
 {
        struct snd_ac97 *ac97;
+       int ret;
 
        ac97 = kzalloc(sizeof(struct snd_ac97), GFP_KERNEL);
        if (ac97 == NULL)
                return ERR_PTR(-ENOMEM);
 
-       ac97->dev = adev->dev;
        ac97->private_data = adev;
        ac97->bus = &compat_soc_ac97_bus;
+
+       ac97->dev.parent = &adev->dev;
+       ac97->dev.release = compat_ac97_release;
+       dev_set_name(&ac97->dev, "%s-compat", dev_name(&adev->dev));
+       ret = device_register(&ac97->dev);
+       if (ret) {
+               put_device(&ac97->dev);
+               return ERR_PTR(ret);
+       }
+
        return ac97;
 }
 EXPORT_SYMBOL_GPL(snd_ac97_compat_alloc);
 
 void snd_ac97_compat_release(struct snd_ac97 *ac97)
 {
-       kfree(ac97);
+       device_unregister(&ac97->dev);
 }
 EXPORT_SYMBOL_GPL(snd_ac97_compat_release);
 
index a2f1c6b..cb988ef 100644 (file)
@@ -149,8 +149,9 @@ static void snd_vmidi_output_work(struct work_struct *work)
        /* discard the outputs in dispatch mode unless subscribed */
        if (vmidi->seq_mode == SNDRV_VIRMIDI_SEQ_DISPATCH &&
            !(vmidi->rdev->flags & SNDRV_VIRMIDI_SUBSCRIBE)) {
-               while (!snd_rawmidi_transmit_empty(substream))
-                       snd_rawmidi_transmit_ack(substream, 1);
+               char buf[32];
+               while (snd_rawmidi_transmit(substream, buf, sizeof(buf)) > 0)
+                       ; /* ignored */
                return;
        }
 
index b20974e..1d117f0 100644 (file)
@@ -5494,6 +5494,7 @@ enum {
        ALC255_FIXUP_DUMMY_LINEOUT_VERB,
        ALC255_FIXUP_DELL_HEADSET_MIC,
        ALC295_FIXUP_HP_X360,
+       ALC221_FIXUP_HP_HEADSET_MIC,
 };
 
 static const struct hda_fixup alc269_fixups[] = {
@@ -6351,7 +6352,16 @@ static const struct hda_fixup alc269_fixups[] = {
                .v.func = alc295_fixup_hp_top_speakers,
                .chained = true,
                .chain_id = ALC269_FIXUP_HP_MUTE_LED_MIC3
-       }
+       },
+       [ALC221_FIXUP_HP_HEADSET_MIC] = {
+               .type = HDA_FIXUP_PINS,
+               .v.pins = (const struct hda_pintbl[]) {
+                       { 0x19, 0x0181313f},
+                       { }
+               },
+               .chained = true,
+               .chain_id = ALC269_FIXUP_HEADSET_MIC
+       },
 };
 
 static const struct snd_pci_quirk alc269_fixup_tbl[] = {
@@ -6777,6 +6787,12 @@ static const struct hda_model_fixup alc269_fixup_models[] = {
        {0x21, 0x03211020}
 
 static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = {
+       SND_HDA_PIN_QUIRK(0x10ec0221, 0x103c, "HP Workstation", ALC221_FIXUP_HP_HEADSET_MIC,
+               {0x14, 0x01014020},
+               {0x17, 0x90170110},
+               {0x18, 0x02a11030},
+               {0x19, 0x0181303F},
+               {0x21, 0x0221102f}),
        SND_HDA_PIN_QUIRK(0x10ec0255, 0x1025, "Acer", ALC255_FIXUP_ACER_MIC_NO_PRESENCE,
                {0x12, 0x90a601c0},
                {0x14, 0x90171120},
index 8734040..3631457 100644 (file)
@@ -153,7 +153,7 @@ struct sst_block_allocator {
 };
 
 /*
- * Runtime Module Instance - A module object can be instanciated multiple
+ * Runtime Module Instance - A module object can be instantiated multiple
  * times within the DSP FW.
  */
 struct sst_module_runtime {
@@ -193,7 +193,7 @@ enum sst_module_state {
  *
  * Each Firmware file can consist of 1..N modules. A module can span multiple
  * ADSP memory blocks. The simplest FW will be a file with 1 module. A module
- * can be instanciated multiple times in the DSP.
+ * can be instantiated multiple times in the DSP.
  */
 struct sst_module {
        struct sst_dsp *dsp;
index 64aaa3f..89a048c 100644 (file)
 #define X86_FEATURE_STIBP              ( 7*32+27) /* Single Thread Indirect Branch Predictors */
 #define X86_FEATURE_ZEN                        ( 7*32+28) /* "" CPU is AMD family 0x17 (Zen) */
 #define X86_FEATURE_L1TF_PTEINV                ( 7*32+29) /* "" L1TF workaround PTE inversion */
+#define X86_FEATURE_IBRS_ENHANCED      ( 7*32+30) /* Enhanced IBRS */
 
 /* Virtualization flags: Linux defined, word 8 */
 #define X86_FEATURE_TPR_SHADOW         ( 8*32+ 0) /* Intel TPR Shadow */
 
 #define X86_FEATURE_VMMCALL            ( 8*32+15) /* Prefer VMMCALL to VMCALL */
 #define X86_FEATURE_XENPV              ( 8*32+16) /* "" Xen paravirtual guest */
-
+#define X86_FEATURE_EPT_AD             ( 8*32+17) /* Intel Extended Page Table access-dirty bit */
 
 /* Intel-defined CPU features, CPUID level 0x00000007:0 (EBX), word 9 */
 #define X86_FEATURE_FSGSBASE           ( 9*32+ 0) /* RDFSBASE, WRFSBASE, RDGSBASE, WRGSBASE instructions*/
index 298ef14..3b24dc0 100644 (file)
@@ -256,7 +256,7 @@ ENTRY(__memcpy_mcsafe)
 
        /* Copy successful. Return zero */
 .L_done_memcpy_trap:
-       xorq %rax, %rax
+       xorl %eax, %eax
        ret
 ENDPROC(__memcpy_mcsafe)
 EXPORT_SYMBOL_GPL(__memcpy_mcsafe)
index 63440cc..e63662d 100644 (file)
@@ -97,6 +97,23 @@ static inline int test_and_set_bit(int nr, unsigned long *addr)
 }
 
 /**
+ * test_and_clear_bit - Clear a bit and return its old value
+ * @nr: Bit to clear
+ * @addr: Address to count from
+ */
+static inline int test_and_clear_bit(int nr, unsigned long *addr)
+{
+       unsigned long mask = BIT_MASK(nr);
+       unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
+       unsigned long old;
+
+       old = *p;
+       *p = old & ~mask;
+
+       return (old & mask) != 0;
+}
+
+/**
  * bitmap_alloc - Allocate bitmap
  * @nbits: Number of bits
  */
index 9b0ca3a..9dafb8c 100644 (file)
@@ -129,12 +129,12 @@ $(OUTPUT)liblockdep.a: $(LIB_IN)
 tags:  force
        $(RM) tags
        find . -name '*.[ch]' | xargs ctags --extra=+f --c-kinds=+px \
-       --regex-c++='/_PE\(([^,)]*).*/PEVENT_ERRNO__\1/'
+       --regex-c++='/_PE\(([^,)]*).*/TEP_ERRNO__\1/'
 
 TAGS:  force
        $(RM) TAGS
        find . -name '*.[ch]' | xargs etags \
-       --regex='/_PE(\([^,)]*\).*/PEVENT_ERRNO__\1/'
+       --regex='/_PE(\([^,)]*\).*/TEP_ERRNO__\1/'
 
 define do_install
        $(print_install)                                \
index 46cd5f8..0b4e833 100644 (file)
@@ -233,12 +233,12 @@ endef
 tags:  force
        $(RM) tags
        find . -name '*.[ch]' | xargs ctags --extra=+f --c-kinds=+px \
-       --regex-c++='/_PE\(([^,)]*).*/PEVENT_ERRNO__\1/'
+       --regex-c++='/_PE\(([^,)]*).*/TEP_ERRNO__\1/'
 
 TAGS:  force
        $(RM) TAGS
        find . -name '*.[ch]' | xargs etags \
-       --regex='/_PE(\([^,)]*\).*/PEVENT_ERRNO__\1/'
+       --regex='/_PE(\([^,)]*\).*/TEP_ERRNO__\1/'
 
 define do_install_mkdir
        if [ ! -d '$(DESTDIR_SQ)$1' ]; then             \
index e5f2acb..ce1e202 100644 (file)
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: LGPL-2.1
 /*
  * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
  *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License (not later!)
- *
- * 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not,  see <http://www.gnu.org/licenses>
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  *
  *  The parts for function graph printing was taken and modified from the
  *  Linux Kernel that were written by
@@ -73,12 +59,12 @@ static void init_input_buf(const char *buf, unsigned long long size)
        input_buf_ptr = 0;
 }
 
-const char *pevent_get_input_buf(void)
+const char *tep_get_input_buf(void)
 {
        return input_buf;
 }
 
-unsigned long long pevent_get_input_buf_ptr(void)
+unsigned long long tep_get_input_buf_ptr(void)
 {
        return input_buf_ptr;
 }
@@ -88,21 +74,21 @@ struct event_handler {
        int                             id;
        const char                      *sys_name;
        const char                      *event_name;
-       pevent_event_handler_func       func;
+       tep_event_handler_func          func;
        void                            *context;
 };
 
-struct pevent_func_params {
-       struct pevent_func_params       *next;
-       enum pevent_func_arg_type       type;
+struct func_params {
+       struct func_params      *next;
+       enum tep_func_arg_type  type;
 };
 
-struct pevent_function_handler {
-       struct pevent_function_handler  *next;
-       enum pevent_func_arg_type       ret_type;
+struct tep_function_handler {
+       struct tep_function_handler     *next;
+       enum tep_func_arg_type          ret_type;
        char                            *name;
-       pevent_func_handler             func;
-       struct pevent_func_params       *params;
+       tep_func_handler                func;
+       struct func_params              *params;
        int                             nr_args;
 };
 
@@ -110,17 +96,17 @@ static unsigned long long
 process_defined_func(struct trace_seq *s, void *data, int size,
                     struct event_format *event, struct print_arg *arg);
 
-static void free_func_handle(struct pevent_function_handler *func);
+static void free_func_handle(struct tep_function_handler *func);
 
 /**
- * pevent_buffer_init - init buffer for parsing
+ * tep_buffer_init - init buffer for parsing
  * @buf: buffer to parse
  * @size: the size of the buffer
  *
- * For use with pevent_read_token(), this initializes the internal
- * buffer that pevent_read_token() will parse.
+ * For use with tep_read_token(), this initializes the internal
+ * buffer that tep_read_token() will parse.
  */
-void pevent_buffer_init(const char *buf, unsigned long long size)
+void tep_buffer_init(const char *buf, unsigned long long size)
 {
        init_input_buf(buf, size);
 }
@@ -160,7 +146,7 @@ struct cmdline_list {
        int                     pid;
 };
 
-static int cmdline_init(struct pevent *pevent)
+static int cmdline_init(struct tep_handle *pevent)
 {
        struct cmdline_list *cmdlist = pevent->cmdlist;
        struct cmdline_list *item;
@@ -189,7 +175,7 @@ static int cmdline_init(struct pevent *pevent)
        return 0;
 }
 
-static const char *find_cmdline(struct pevent *pevent, int pid)
+static const char *find_cmdline(struct tep_handle *pevent, int pid)
 {
        const struct cmdline *comm;
        struct cmdline key;
@@ -211,14 +197,14 @@ static const char *find_cmdline(struct pevent *pevent, int pid)
 }
 
 /**
- * pevent_pid_is_registered - return if a pid has a cmdline registered
+ * tep_pid_is_registered - return if a pid has a cmdline registered
  * @pevent: handle for the pevent
  * @pid: The pid to check if it has a cmdline registered with.
  *
  * Returns 1 if the pid has a cmdline mapped to it
  * 0 otherwise.
  */
-int pevent_pid_is_registered(struct pevent *pevent, int pid)
+int tep_pid_is_registered(struct tep_handle *pevent, int pid)
 {
        const struct cmdline *comm;
        struct cmdline key;
@@ -244,7 +230,7 @@ int pevent_pid_is_registered(struct pevent *pevent, int pid)
  * we must add this pid. This is much slower than when cmdlines
  * are added before the array is initialized.
  */
-static int add_new_comm(struct pevent *pevent, const char *comm, int pid)
+static int add_new_comm(struct tep_handle *pevent, const char *comm, int pid)
 {
        struct cmdline *cmdlines = pevent->cmdlines;
        const struct cmdline *cmdline;
@@ -288,7 +274,7 @@ static int add_new_comm(struct pevent *pevent, const char *comm, int pid)
 }
 
 /**
- * pevent_register_comm - register a pid / comm mapping
+ * tep_register_comm - register a pid / comm mapping
  * @pevent: handle for the pevent
  * @comm: the command line to register
  * @pid: the pid to map the command line to
@@ -296,7 +282,7 @@ static int add_new_comm(struct pevent *pevent, const char *comm, int pid)
  * This adds a mapping to search for command line names with
  * a given pid. The comm is duplicated.
  */
-int pevent_register_comm(struct pevent *pevent, const char *comm, int pid)
+int tep_register_comm(struct tep_handle *pevent, const char *comm, int pid)
 {
        struct cmdline_list *item;
 
@@ -324,7 +310,7 @@ int pevent_register_comm(struct pevent *pevent, const char *comm, int pid)
        return 0;
 }
 
-int pevent_register_trace_clock(struct pevent *pevent, const char *trace_clock)
+int tep_register_trace_clock(struct tep_handle *pevent, const char *trace_clock)
 {
        pevent->trace_clock = strdup(trace_clock);
        if (!pevent->trace_clock) {
@@ -381,7 +367,7 @@ static int func_bcmp(const void *a, const void *b)
        return 1;
 }
 
-static int func_map_init(struct pevent *pevent)
+static int func_map_init(struct tep_handle *pevent)
 {
        struct func_list *funclist;
        struct func_list *item;
@@ -421,7 +407,7 @@ static int func_map_init(struct pevent *pevent)
 }
 
 static struct func_map *
-__find_func(struct pevent *pevent, unsigned long long addr)
+__find_func(struct tep_handle *pevent, unsigned long long addr)
 {
        struct func_map *func;
        struct func_map key;
@@ -438,13 +424,13 @@ __find_func(struct pevent *pevent, unsigned long long addr)
 }
 
 struct func_resolver {
-       pevent_func_resolver_t *func;
-       void                   *priv;
-       struct func_map        map;
+       tep_func_resolver_t     *func;
+       void                    *priv;
+       struct func_map         map;
 };
 
 /**
- * pevent_set_function_resolver - set an alternative function resolver
+ * tep_set_function_resolver - set an alternative function resolver
  * @pevent: handle for the pevent
  * @resolver: function to be used
  * @priv: resolver function private state.
@@ -453,8 +439,8 @@ struct func_resolver {
  * keep using it instead of duplicating all the entries inside
  * pevent->funclist.
  */
-int pevent_set_function_resolver(struct pevent *pevent,
-                                pevent_func_resolver_t *func, void *priv)
+int tep_set_function_resolver(struct tep_handle *pevent,
+                             tep_func_resolver_t *func, void *priv)
 {
        struct func_resolver *resolver = malloc(sizeof(*resolver));
 
@@ -471,20 +457,20 @@ int pevent_set_function_resolver(struct pevent *pevent,
 }
 
 /**
- * pevent_reset_function_resolver - reset alternative function resolver
+ * tep_reset_function_resolver - reset alternative function resolver
  * @pevent: handle for the pevent
  *
  * Stop using whatever alternative resolver was set, use the default
  * one instead.
  */
-void pevent_reset_function_resolver(struct pevent *pevent)
+void tep_reset_function_resolver(struct tep_handle *pevent)
 {
        free(pevent->func_resolver);
        pevent->func_resolver = NULL;
 }
 
 static struct func_map *
-find_func(struct pevent *pevent, unsigned long long addr)
+find_func(struct tep_handle *pevent, unsigned long long addr)
 {
        struct func_map *map;
 
@@ -503,7 +489,7 @@ find_func(struct pevent *pevent, unsigned long long addr)
 }
 
 /**
- * pevent_find_function - find a function by a given address
+ * tep_find_function - find a function by a given address
  * @pevent: handle for the pevent
  * @addr: the address to find the function with
  *
@@ -511,7 +497,7 @@ find_func(struct pevent *pevent, unsigned long long addr)
  * address. Note, the address does not have to be exact, it
  * will select the function that would contain the address.
  */
-const char *pevent_find_function(struct pevent *pevent, unsigned long long addr)
+const char *tep_find_function(struct tep_handle *pevent, unsigned long long addr)
 {
        struct func_map *map;
 
@@ -523,16 +509,16 @@ const char *pevent_find_function(struct pevent *pevent, unsigned long long addr)
 }
 
 /**
- * pevent_find_function_address - find a function address by a given address
+ * tep_find_function_address - find a function address by a given address
  * @pevent: handle for the pevent
  * @addr: the address to find the function with
  *
  * Returns the address the function starts at. This can be used in
- * conjunction with pevent_find_function to print both the function
+ * conjunction with tep_find_function to print both the function
  * name and the function offset.
  */
 unsigned long long
-pevent_find_function_address(struct pevent *pevent, unsigned long long addr)
+tep_find_function_address(struct tep_handle *pevent, unsigned long long addr)
 {
        struct func_map *map;
 
@@ -544,7 +530,7 @@ pevent_find_function_address(struct pevent *pevent, unsigned long long addr)
 }
 
 /**
- * pevent_register_function - register a function with a given address
+ * tep_register_function - register a function with a given address
  * @pevent: handle for the pevent
  * @function: the function name to register
  * @addr: the address the function starts at
@@ -553,8 +539,8 @@ pevent_find_function_address(struct pevent *pevent, unsigned long long addr)
  * This registers a function name with an address and module.
  * The @func passed in is duplicated.
  */
-int pevent_register_function(struct pevent *pevent, char *func,
-                            unsigned long long addr, char *mod)
+int tep_register_function(struct tep_handle *pevent, char *func,
+                         unsigned long long addr, char *mod)
 {
        struct func_list *item = malloc(sizeof(*item));
 
@@ -589,12 +575,12 @@ out_free:
 }
 
 /**
- * pevent_print_funcs - print out the stored functions
+ * tep_print_funcs - print out the stored functions
  * @pevent: handle for the pevent
  *
  * This prints out the stored functions.
  */
-void pevent_print_funcs(struct pevent *pevent)
+void tep_print_funcs(struct tep_handle *pevent)
 {
        int i;
 
@@ -636,7 +622,7 @@ static int printk_cmp(const void *a, const void *b)
        return 0;
 }
 
-static int printk_map_init(struct pevent *pevent)
+static int printk_map_init(struct tep_handle *pevent)
 {
        struct printk_list *printklist;
        struct printk_list *item;
@@ -668,7 +654,7 @@ static int printk_map_init(struct pevent *pevent)
 }
 
 static struct printk_map *
-find_printk(struct pevent *pevent, unsigned long long addr)
+find_printk(struct tep_handle *pevent, unsigned long long addr)
 {
        struct printk_map *printk;
        struct printk_map key;
@@ -685,7 +671,7 @@ find_printk(struct pevent *pevent, unsigned long long addr)
 }
 
 /**
- * pevent_register_print_string - register a string by its address
+ * tep_register_print_string - register a string by its address
  * @pevent: handle for the pevent
  * @fmt: the string format to register
  * @addr: the address the string was located at
@@ -693,8 +679,8 @@ find_printk(struct pevent *pevent, unsigned long long addr)
  * This registers a string by the address it was stored in the kernel.
  * The @fmt passed in is duplicated.
  */
-int pevent_register_print_string(struct pevent *pevent, const char *fmt,
-                                unsigned long long addr)
+int tep_register_print_string(struct tep_handle *pevent, const char *fmt,
+                             unsigned long long addr)
 {
        struct printk_list *item = malloc(sizeof(*item));
        char *p;
@@ -732,12 +718,12 @@ out_free:
 }
 
 /**
- * pevent_print_printk - print out the stored strings
+ * tep_print_printk - print out the stored strings
  * @pevent: handle for the pevent
  *
  * This prints the string formats that were stored.
  */
-void pevent_print_printk(struct pevent *pevent)
+void tep_print_printk(struct tep_handle *pevent)
 {
        int i;
 
@@ -756,7 +742,7 @@ static struct event_format *alloc_event(void)
        return calloc(1, sizeof(struct event_format));
 }
 
-static int add_event(struct pevent *pevent, struct event_format *event)
+static int add_event(struct tep_handle *pevent, struct event_format *event)
 {
        int i;
        struct event_format **events = realloc(pevent->events, sizeof(event) *
@@ -913,11 +899,11 @@ static int __peek_char(void)
 }
 
 /**
- * pevent_peek_char - peek at the next character that will be read
+ * tep_peek_char - peek at the next character that will be read
  *
  * Returns the next character read, or -1 if end of buffer.
  */
-int pevent_peek_char(void)
+int tep_peek_char(void)
 {
        return __peek_char();
 }
@@ -1157,24 +1143,24 @@ static enum event_type read_token(char **tok)
 }
 
 /**
- * pevent_read_token - access to utilites to use the pevent parser
+ * tep_read_token - access to utilites to use the pevent parser
  * @tok: The token to return
  *
  * This will parse tokens from the string given by
- * pevent_init_data().
+ * tep_init_data().
  *
  * Returns the token type.
  */
-enum event_type pevent_read_token(char **tok)
+enum event_type tep_read_token(char **tok)
 {
        return read_token(tok);
 }
 
 /**
- * pevent_free_token - free a token returned by pevent_read_token
+ * tep_free_token - free a token returned by tep_read_token
  * @token: the token to free
  */
-void pevent_free_token(char *token)
+void tep_free_token(char *token)
 {
        free_token(token);
 }
@@ -2101,11 +2087,11 @@ process_entry(struct event_format *event __maybe_unused, struct print_arg *arg,
        arg->field.name = field;
 
        if (is_flag_field) {
-               arg->field.field = pevent_find_any_field(event, arg->field.name);
+               arg->field.field = tep_find_any_field(event, arg->field.name);
                arg->field.field->flags |= FIELD_IS_FLAG;
                is_flag_field = 0;
        } else if (is_symbolic_field) {
-               arg->field.field = pevent_find_any_field(event, arg->field.name);
+               arg->field.field = tep_find_any_field(event, arg->field.name);
                arg->field.field->flags |= FIELD_IS_SYMBOLIC;
                is_symbolic_field = 0;
        }
@@ -2714,7 +2700,7 @@ process_dynamic_array(struct event_format *event, struct print_arg *arg, char **
 
        /* Find the field */
 
-       field = pevent_find_field(event, token);
+       field = tep_find_field(event, token);
        if (!field)
                goto out_free;
 
@@ -2771,7 +2757,7 @@ process_dynamic_array_len(struct event_format *event, struct print_arg *arg,
        arg->type = PRINT_DYNAMIC_ARRAY_LEN;
 
        /* Find the field */
-       field = pevent_find_field(event, token);
+       field = tep_find_field(event, token);
        if (!field)
                goto out_free;
 
@@ -2914,10 +2900,10 @@ process_bitmask(struct event_format *event __maybe_unused, struct print_arg *arg
        return EVENT_ERROR;
 }
 
-static struct pevent_function_handler *
-find_func_handler(struct pevent *pevent, char *func_name)
+static struct tep_function_handler *
+find_func_handler(struct tep_handle *pevent, char *func_name)
 {
-       struct pevent_function_handler *func;
+       struct tep_function_handler *func;
 
        if (!pevent)
                return NULL;
@@ -2930,10 +2916,10 @@ find_func_handler(struct pevent *pevent, char *func_name)
        return func;
 }
 
-static void remove_func_handler(struct pevent *pevent, char *func_name)
+static void remove_func_handler(struct tep_handle *pevent, char *func_name)
 {
-       struct pevent_function_handler *func;
-       struct pevent_function_handler **next;
+       struct tep_function_handler *func;
+       struct tep_function_handler **next;
 
        next = &pevent->func_handlers;
        while ((func = *next)) {
@@ -2947,7 +2933,7 @@ static void remove_func_handler(struct pevent *pevent, char *func_name)
 }
 
 static enum event_type
-process_func_handler(struct event_format *event, struct pevent_function_handler *func,
+process_func_handler(struct event_format *event, struct tep_function_handler *func,
                     struct print_arg *arg, char **tok)
 {
        struct print_arg **next_arg;
@@ -3008,7 +2994,7 @@ static enum event_type
 process_function(struct event_format *event, struct print_arg *arg,
                 char *token, char **tok)
 {
-       struct pevent_function_handler *func;
+       struct tep_function_handler *func;
 
        if (strcmp(token, "__print_flags") == 0) {
                free_token(token);
@@ -3265,7 +3251,7 @@ static int event_read_print(struct event_format *event)
 }
 
 /**
- * pevent_find_common_field - return a common field by event
+ * tep_find_common_field - return a common field by event
  * @event: handle for the event
  * @name: the name of the common field to return
  *
@@ -3273,7 +3259,7 @@ static int event_read_print(struct event_format *event)
  * This only searchs the common fields and not all field.
  */
 struct format_field *
-pevent_find_common_field(struct event_format *event, const char *name)
+tep_find_common_field(struct event_format *event, const char *name)
 {
        struct format_field *format;
 
@@ -3287,7 +3273,7 @@ pevent_find_common_field(struct event_format *event, const char *name)
 }
 
 /**
- * pevent_find_field - find a non-common field
+ * tep_find_field - find a non-common field
  * @event: handle for the event
  * @name: the name of the non-common field
  *
@@ -3295,7 +3281,7 @@ pevent_find_common_field(struct event_format *event, const char *name)
  * This does not search common fields.
  */
 struct format_field *
-pevent_find_field(struct event_format *event, const char *name)
+tep_find_field(struct event_format *event, const char *name)
 {
        struct format_field *format;
 
@@ -3309,7 +3295,7 @@ pevent_find_field(struct event_format *event, const char *name)
 }
 
 /**
- * pevent_find_any_field - find any field by name
+ * tep_find_any_field - find any field by name
  * @event: handle for the event
  * @name: the name of the field
  *
@@ -3318,18 +3304,18 @@ pevent_find_field(struct event_format *event, const char *name)
  * the non-common ones if a common one was not found.
  */
 struct format_field *
-pevent_find_any_field(struct event_format *event, const char *name)
+tep_find_any_field(struct event_format *event, const char *name)
 {
        struct format_field *format;
 
-       format = pevent_find_common_field(event, name);
+       format = tep_find_common_field(event, name);
        if (format)
                return format;
-       return pevent_find_field(event, name);
+       return tep_find_field(event, name);
 }
 
 /**
- * pevent_read_number - read a number from data
+ * tep_read_number - read a number from data
  * @pevent: handle for the pevent
  * @ptr: the raw data
  * @size: the size of the data that holds the number
@@ -3337,8 +3323,8 @@ pevent_find_any_field(struct event_format *event, const char *name)
  * Returns the number (converted to host) from the
  * raw data.
  */
-unsigned long long pevent_read_number(struct pevent *pevent,
-                                     const void *ptr, int size)
+unsigned long long tep_read_number(struct tep_handle *pevent,
+                                  const void *ptr, int size)
 {
        switch (size) {
        case 1:
@@ -3356,7 +3342,7 @@ unsigned long long pevent_read_number(struct pevent *pevent,
 }
 
 /**
- * pevent_read_number_field - read a number from data
+ * tep_read_number_field - read a number from data
  * @field: a handle to the field
  * @data: the raw data to read
  * @value: the value to place the number in
@@ -3366,8 +3352,8 @@ unsigned long long pevent_read_number(struct pevent *pevent,
  *
  * Returns 0 on success, -1 otherwise.
  */
-int pevent_read_number_field(struct format_field *field, const void *data,
-                            unsigned long long *value)
+int tep_read_number_field(struct format_field *field, const void *data,
+                         unsigned long long *value)
 {
        if (!field)
                return -1;
@@ -3376,15 +3362,15 @@ int pevent_read_number_field(struct format_field *field, const void *data,
        case 2:
        case 4:
        case 8:
-               *value = pevent_read_number(field->event->pevent,
-                                           data + field->offset, field->size);
+               *value = tep_read_number(field->event->pevent,
+                                        data + field->offset, field->size);
                return 0;
        default:
                return -1;
        }
 }
 
-static int get_common_info(struct pevent *pevent,
+static int get_common_info(struct tep_handle *pevent,
                           const char *type, int *offset, int *size)
 {
        struct event_format *event;
@@ -3400,7 +3386,7 @@ static int get_common_info(struct pevent *pevent,
        }
 
        event = pevent->events[0];
-       field = pevent_find_common_field(event, type);
+       field = tep_find_common_field(event, type);
        if (!field)
                return -1;
 
@@ -3410,7 +3396,7 @@ static int get_common_info(struct pevent *pevent,
        return 0;
 }
 
-static int __parse_common(struct pevent *pevent, void *data,
+static int __parse_common(struct tep_handle *pevent, void *data,
                          int *size, int *offset, const char *name)
 {
        int ret;
@@ -3420,45 +3406,45 @@ static int __parse_common(struct pevent *pevent, void *data,
                if (ret < 0)
                        return ret;
        }
-       return pevent_read_number(pevent, data + *offset, *size);
+       return tep_read_number(pevent, data + *offset, *size);
 }
 
-static int trace_parse_common_type(struct pevent *pevent, void *data)
+static int trace_parse_common_type(struct tep_handle *pevent, void *data)
 {
        return __parse_common(pevent, data,
                              &pevent->type_size, &pevent->type_offset,
                              "common_type");
 }
 
-static int parse_common_pid(struct pevent *pevent, void *data)
+static int parse_common_pid(struct tep_handle *pevent, void *data)
 {
        return __parse_common(pevent, data,
                              &pevent->pid_size, &pevent->pid_offset,
                              "common_pid");
 }
 
-static int parse_common_pc(struct pevent *pevent, void *data)
+static int parse_common_pc(struct tep_handle *pevent, void *data)
 {
        return __parse_common(pevent, data,
                              &pevent->pc_size, &pevent->pc_offset,
                              "common_preempt_count");
 }
 
-static int parse_common_flags(struct pevent *pevent, void *data)
+static int parse_common_flags(struct tep_handle *pevent, void *data)
 {
        return __parse_common(pevent, data,
                              &pevent->flags_size, &pevent->flags_offset,
                              "common_flags");
 }
 
-static int parse_common_lock_depth(struct pevent *pevent, void *data)
+static int parse_common_lock_depth(struct tep_handle *pevent, void *data)
 {
        return __parse_common(pevent, data,
                              &pevent->ld_size, &pevent->ld_offset,
                              "common_lock_depth");
 }
 
-static int parse_common_migrate_disable(struct pevent *pevent, void *data)
+static int parse_common_migrate_disable(struct tep_handle *pevent, void *data)
 {
        return __parse_common(pevent, data,
                              &pevent->ld_size, &pevent->ld_offset,
@@ -3468,13 +3454,13 @@ static int parse_common_migrate_disable(struct pevent *pevent, void *data)
 static int events_id_cmp(const void *a, const void *b);
 
 /**
- * pevent_find_event - find an event by given id
+ * tep_find_event - find an event by given id
  * @pevent: a handle to the pevent
  * @id: the id of the event
  *
  * Returns an event that has a given @id.
  */
-struct event_format *pevent_find_event(struct pevent *pevent, int id)
+struct event_format *tep_find_event(struct tep_handle *pevent, int id)
 {
        struct event_format **eventptr;
        struct event_format key;
@@ -3498,7 +3484,7 @@ struct event_format *pevent_find_event(struct pevent *pevent, int id)
 }
 
 /**
- * pevent_find_event_by_name - find an event by given name
+ * tep_find_event_by_name - find an event by given name
  * @pevent: a handle to the pevent
  * @sys: the system name to search for
  * @name: the name of the event to search for
@@ -3507,8 +3493,8 @@ struct event_format *pevent_find_event(struct pevent *pevent, int id)
  * @sys. If @sys is NULL the first event with @name is returned.
  */
 struct event_format *
-pevent_find_event_by_name(struct pevent *pevent,
-                         const char *sys, const char *name)
+tep_find_event_by_name(struct tep_handle *pevent,
+                      const char *sys, const char *name)
 {
        struct event_format *event;
        int i;
@@ -3537,7 +3523,7 @@ pevent_find_event_by_name(struct pevent *pevent,
 static unsigned long long
 eval_num_arg(void *data, int size, struct event_format *event, struct print_arg *arg)
 {
-       struct pevent *pevent = event->pevent;
+       struct tep_handle *pevent = event->pevent;
        unsigned long long val = 0;
        unsigned long long left, right;
        struct print_arg *typearg = NULL;
@@ -3553,14 +3539,14 @@ eval_num_arg(void *data, int size, struct event_format *event, struct print_arg
                return strtoull(arg->atom.atom, NULL, 0);
        case PRINT_FIELD:
                if (!arg->field.field) {
-                       arg->field.field = pevent_find_any_field(event, arg->field.name);
+                       arg->field.field = tep_find_any_field(event, arg->field.name);
                        if (!arg->field.field)
                                goto out_warning_field;
                        
                }
                /* must be a number */
-               val = pevent_read_number(pevent, data + arg->field.field->offset,
-                               arg->field.field->size);
+               val = tep_read_number(pevent, data + arg->field.field->offset,
+                                     arg->field.field->size);
                break;
        case PRINT_FLAGS:
        case PRINT_SYMBOL:
@@ -3603,7 +3589,7 @@ eval_num_arg(void *data, int size, struct event_format *event, struct print_arg
 
                        switch (larg->type) {
                        case PRINT_DYNAMIC_ARRAY:
-                               offset = pevent_read_number(pevent,
+                               offset = tep_read_number(pevent,
                                                   data + larg->dynarray.field->offset,
                                                   larg->dynarray.field->size);
                                if (larg->dynarray.field->elementsize)
@@ -3619,7 +3605,7 @@ eval_num_arg(void *data, int size, struct event_format *event, struct print_arg
                        case PRINT_FIELD:
                                if (!larg->field.field) {
                                        larg->field.field =
-                                               pevent_find_any_field(event, larg->field.name);
+                                               tep_find_any_field(event, larg->field.name);
                                        if (!larg->field.field) {
                                                arg = larg;
                                                goto out_warning_field;
@@ -3632,8 +3618,8 @@ eval_num_arg(void *data, int size, struct event_format *event, struct print_arg
                        default:
                                goto default_op; /* oops, all bets off */
                        }
-                       val = pevent_read_number(pevent,
-                                                data + offset, field_size);
+                       val = tep_read_number(pevent,
+                                             data + offset, field_size);
                        if (typearg)
                                val = eval_type(val, typearg, 1);
                        break;
@@ -3733,9 +3719,9 @@ eval_num_arg(void *data, int size, struct event_format *event, struct print_arg
                }
                break;
        case PRINT_DYNAMIC_ARRAY_LEN:
-               offset = pevent_read_number(pevent,
-                                           data + arg->dynarray.field->offset,
-                                           arg->dynarray.field->size);
+               offset = tep_read_number(pevent,
+                                        data + arg->dynarray.field->offset,
+                                        arg->dynarray.field->size);
                /*
                 * The total allocated length of the dynamic array is
                 * stored in the top half of the field, and the offset
@@ -3745,9 +3731,9 @@ eval_num_arg(void *data, int size, struct event_format *event, struct print_arg
                break;
        case PRINT_DYNAMIC_ARRAY:
                /* Without [], we pass the address to the dynamic data */
-               offset = pevent_read_number(pevent,
-                                           data + arg->dynarray.field->offset,
-                                           arg->dynarray.field->size);
+               offset = tep_read_number(pevent,
+                                        data + arg->dynarray.field->offset,
+                                        arg->dynarray.field->size);
                /*
                 * The total allocated length of the dynamic array is
                 * stored in the top half of the field, and the offset
@@ -3820,7 +3806,7 @@ static void print_str_to_seq(struct trace_seq *s, const char *format,
                trace_seq_printf(s, format, str);
 }
 
-static void print_bitmask_to_seq(struct pevent *pevent,
+static void print_bitmask_to_seq(struct tep_handle *pevent,
                                 struct trace_seq *s, const char *format,
                                 int len_arg, const void *data, int size)
 {
@@ -3878,7 +3864,7 @@ static void print_str_arg(struct trace_seq *s, void *data, int size,
                          struct event_format *event, const char *format,
                          int len_arg, struct print_arg *arg)
 {
-       struct pevent *pevent = event->pevent;
+       struct tep_handle *pevent = event->pevent;
        struct print_flag_sym *flag;
        struct format_field *field;
        struct printk_map *printk;
@@ -3899,7 +3885,7 @@ static void print_str_arg(struct trace_seq *s, void *data, int size,
        case PRINT_FIELD:
                field = arg->field.field;
                if (!field) {
-                       field = pevent_find_any_field(event, arg->field.name);
+                       field = tep_find_any_field(event, arg->field.name);
                        if (!field) {
                                str = arg->field.name;
                                goto out_warning_field;
@@ -3992,7 +3978,7 @@ static void print_str_arg(struct trace_seq *s, void *data, int size,
        case PRINT_HEX_STR:
                if (arg->hex.field->type == PRINT_DYNAMIC_ARRAY) {
                        unsigned long offset;
-                       offset = pevent_read_number(pevent,
+                       offset = tep_read_number(pevent,
                                data + arg->hex.field->dynarray.field->offset,
                                arg->hex.field->dynarray.field->size);
                        hex = data + (offset & 0xffff);
@@ -4000,7 +3986,7 @@ static void print_str_arg(struct trace_seq *s, void *data, int size,
                        field = arg->hex.field->field.field;
                        if (!field) {
                                str = arg->hex.field->field.name;
-                               field = pevent_find_any_field(event, str);
+                               field = tep_find_any_field(event, str);
                                if (!field)
                                        goto out_warning_field;
                                arg->hex.field->field.field = field;
@@ -4023,15 +4009,15 @@ static void print_str_arg(struct trace_seq *s, void *data, int size,
                        unsigned long offset;
                        struct format_field *field =
                                arg->int_array.field->dynarray.field;
-                       offset = pevent_read_number(pevent,
-                                                   data + field->offset,
-                                                   field->size);
+                       offset = tep_read_number(pevent,
+                                                data + field->offset,
+                                                field->size);
                        num = data + (offset & 0xffff);
                } else {
                        field = arg->int_array.field->field.field;
                        if (!field) {
                                str = arg->int_array.field->field.name;
-                               field = pevent_find_any_field(event, str);
+                               field = tep_find_any_field(event, str);
                                if (!field)
                                        goto out_warning_field;
                                arg->int_array.field->field.field = field;
@@ -4071,7 +4057,7 @@ static void print_str_arg(struct trace_seq *s, void *data, int size,
                if (arg->string.offset == -1) {
                        struct format_field *f;
 
-                       f = pevent_find_any_field(event, arg->string.string);
+                       f = tep_find_any_field(event, arg->string.string);
                        arg->string.offset = f->offset;
                }
                str_offset = data2host4(pevent, data + arg->string.offset);
@@ -4089,7 +4075,7 @@ static void print_str_arg(struct trace_seq *s, void *data, int size,
                if (arg->bitmask.offset == -1) {
                        struct format_field *f;
 
-                       f = pevent_find_any_field(event, arg->bitmask.bitmask);
+                       f = tep_find_any_field(event, arg->bitmask.bitmask);
                        arg->bitmask.offset = f->offset;
                }
                bitmask_offset = data2host4(pevent, data + arg->bitmask.offset);
@@ -4132,8 +4118,8 @@ static unsigned long long
 process_defined_func(struct trace_seq *s, void *data, int size,
                     struct event_format *event, struct print_arg *arg)
 {
-       struct pevent_function_handler *func_handle = arg->func.func;
-       struct pevent_func_params *param;
+       struct tep_function_handler *func_handle = arg->func.func;
+       struct func_params *param;
        unsigned long long *args;
        unsigned long long ret;
        struct print_arg *farg;
@@ -4159,12 +4145,12 @@ process_defined_func(struct trace_seq *s, void *data, int size,
 
        for (i = 0; i < func_handle->nr_args; i++) {
                switch (param->type) {
-               case PEVENT_FUNC_ARG_INT:
-               case PEVENT_FUNC_ARG_LONG:
-               case PEVENT_FUNC_ARG_PTR:
+               case TEP_FUNC_ARG_INT:
+               case TEP_FUNC_ARG_LONG:
+               case TEP_FUNC_ARG_PTR:
                        args[i] = eval_num_arg(data, size, event, farg);
                        break;
-               case PEVENT_FUNC_ARG_STRING:
+               case TEP_FUNC_ARG_STRING:
                        trace_seq_init(&str);
                        print_str_arg(&str, data, size, event, "%s", -1, farg);
                        trace_seq_terminate(&str);
@@ -4227,7 +4213,7 @@ static void free_args(struct print_arg *args)
 
 static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struct event_format *event)
 {
-       struct pevent *pevent = event->pevent;
+       struct tep_handle *pevent = event->pevent;
        struct format_field *field, *ip_field;
        struct print_arg *args, *arg, **next;
        unsigned long long ip, val;
@@ -4239,12 +4225,12 @@ static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struc
        ip_field = pevent->bprint_ip_field;
 
        if (!field) {
-               field = pevent_find_field(event, "buf");
+               field = tep_find_field(event, "buf");
                if (!field) {
                        do_warning_event(event, "can't find buffer field for binary printk");
                        return NULL;
                }
-               ip_field = pevent_find_field(event, "ip");
+               ip_field = tep_find_field(event, "ip");
                if (!ip_field) {
                        do_warning_event(event, "can't find ip field for binary printk");
                        return NULL;
@@ -4253,7 +4239,7 @@ static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struc
                pevent->bprint_ip_field = ip_field;
        }
 
-       ip = pevent_read_number(pevent, data + ip_field->offset, ip_field->size);
+       ip = tep_read_number(pevent, data + ip_field->offset, ip_field->size);
 
        /*
         * The first arg is the IP pointer.
@@ -4347,7 +4333,7 @@ static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struc
                                /* the pointers are always 4 bytes aligned */
                                bptr = (void *)(((unsigned long)bptr + 3) &
                                                ~3);
-                               val = pevent_read_number(pevent, bptr, vsize);
+                               val = tep_read_number(pevent, bptr, vsize);
                                bptr += vsize;
                                arg = alloc_arg();
                                if (!arg) {
@@ -4404,7 +4390,7 @@ static char *
 get_bprint_format(void *data, int size __maybe_unused,
                  struct event_format *event)
 {
-       struct pevent *pevent = event->pevent;
+       struct tep_handle *pevent = event->pevent;
        unsigned long long addr;
        struct format_field *field;
        struct printk_map *printk;
@@ -4413,7 +4399,7 @@ get_bprint_format(void *data, int size __maybe_unused,
        field = pevent->bprint_fmt_field;
 
        if (!field) {
-               field = pevent_find_field(event, "fmt");
+               field = tep_find_field(event, "fmt");
                if (!field) {
                        do_warning_event(event, "can't find format field for binary printk");
                        return NULL;
@@ -4421,7 +4407,7 @@ get_bprint_format(void *data, int size __maybe_unused,
                pevent->bprint_fmt_field = field;
        }
 
-       addr = pevent_read_number(pevent, data + field->offset, field->size);
+       addr = tep_read_number(pevent, data + field->offset, field->size);
 
        printk = find_printk(pevent, addr);
        if (!printk) {
@@ -4457,7 +4443,7 @@ static void print_mac_arg(struct trace_seq *s, int mac, void *data, int size,
                fmt = "%.2x%.2x%.2x%.2x%.2x%.2x";
        if (!arg->field.field) {
                arg->field.field =
-                       pevent_find_any_field(event, arg->field.name);
+                       tep_find_any_field(event, arg->field.name);
                if (!arg->field.field) {
                        do_warning_event(event, "%s: field %s not found",
                                         __func__, arg->field.name);
@@ -4607,7 +4593,7 @@ static int print_ipv4_arg(struct trace_seq *s, const char *ptr, char i,
 
        if (!arg->field.field) {
                arg->field.field =
-                       pevent_find_any_field(event, arg->field.name);
+                       tep_find_any_field(event, arg->field.name);
                if (!arg->field.field) {
                        do_warning("%s: field %s not found",
                                   __func__, arg->field.name);
@@ -4653,7 +4639,7 @@ static int print_ipv6_arg(struct trace_seq *s, const char *ptr, char i,
 
        if (!arg->field.field) {
                arg->field.field =
-                       pevent_find_any_field(event, arg->field.name);
+                       tep_find_any_field(event, arg->field.name);
                if (!arg->field.field) {
                        do_warning("%s: field %s not found",
                                   __func__, arg->field.name);
@@ -4711,7 +4697,7 @@ static int print_ipsa_arg(struct trace_seq *s, const char *ptr, char i,
 
        if (!arg->field.field) {
                arg->field.field =
-                       pevent_find_any_field(event, arg->field.name);
+                       tep_find_any_field(event, arg->field.name);
                if (!arg->field.field) {
                        do_warning("%s: field %s not found",
                                   __func__, arg->field.name);
@@ -4800,18 +4786,18 @@ static int is_printable_array(char *p, unsigned int len)
        return 1;
 }
 
-void pevent_print_field(struct trace_seq *s, void *data,
-                       struct format_field *field)
+void tep_print_field(struct trace_seq *s, void *data,
+                    struct format_field *field)
 {
        unsigned long long val;
        unsigned int offset, len, i;
-       struct pevent *pevent = field->event->pevent;
+       struct tep_handle *pevent = field->event->pevent;
 
        if (field->flags & FIELD_IS_ARRAY) {
                offset = field->offset;
                len = field->size;
                if (field->flags & FIELD_IS_DYNAMIC) {
-                       val = pevent_read_number(pevent, data + offset, len);
+                       val = tep_read_number(pevent, data + offset, len);
                        offset = val;
                        len = offset >> 16;
                        offset &= 0xffff;
@@ -4831,8 +4817,8 @@ void pevent_print_field(struct trace_seq *s, void *data,
                        field->flags &= ~FIELD_IS_STRING;
                }
        } else {
-               val = pevent_read_number(pevent, data + field->offset,
-                                        field->size);
+               val = tep_read_number(pevent, data + field->offset,
+                                     field->size);
                if (field->flags & FIELD_IS_POINTER) {
                        trace_seq_printf(s, "0x%llx", val);
                } else if (field->flags & FIELD_IS_SIGNED) {
@@ -4865,22 +4851,22 @@ void pevent_print_field(struct trace_seq *s, void *data,
        }
 }
 
-void pevent_print_fields(struct trace_seq *s, void *data,
-                        int size __maybe_unused, struct event_format *event)
+void tep_print_fields(struct trace_seq *s, void *data,
+                     int size __maybe_unused, struct event_format *event)
 {
        struct format_field *field;
 
        field = event->format.fields;
        while (field) {
                trace_seq_printf(s, " %s=", field->name);
-               pevent_print_field(s, data, field);
+               tep_print_field(s, data, field);
                field = field->next;
        }
 }
 
 static void pretty_print(struct trace_seq *s, void *data, int size, struct event_format *event)
 {
-       struct pevent *pevent = event->pevent;
+       struct tep_handle *pevent = event->pevent;
        struct print_fmt *print_fmt = &event->print_fmt;
        struct print_arg *arg = print_fmt->args;
        struct print_arg *args = NULL;
@@ -4899,7 +4885,7 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct event
 
        if (event->flags & EVENT_FL_FAILED) {
                trace_seq_printf(s, "[FAILED TO PARSE]");
-               pevent_print_fields(s, data, size, event);
+               tep_print_fields(s, data, size, event);
                return;
        }
 
@@ -5140,7 +5126,7 @@ out_failed:
 }
 
 /**
- * pevent_data_lat_fmt - parse the data for the latency format
+ * tep_data_lat_fmt - parse the data for the latency format
  * @pevent: a handle to the pevent
  * @s: the trace_seq to write to
  * @record: the record to read from
@@ -5149,8 +5135,8 @@ out_failed:
  * need rescheduling, in hard/soft interrupt, preempt count
  * and lock depth) and places it into the trace_seq.
  */
-void pevent_data_lat_fmt(struct pevent *pevent,
-                        struct trace_seq *s, struct pevent_record *record)
+void tep_data_lat_fmt(struct tep_handle *pevent,
+                     struct trace_seq *s, struct tep_record *record)
 {
        static int check_lock_depth = 1;
        static int check_migrate_disable = 1;
@@ -5223,55 +5209,55 @@ void pevent_data_lat_fmt(struct pevent *pevent,
 }
 
 /**
- * pevent_data_type - parse out the given event type
+ * tep_data_type - parse out the given event type
  * @pevent: a handle to the pevent
  * @rec: the record to read from
  *
  * This returns the event id from the @rec.
  */
-int pevent_data_type(struct pevent *pevent, struct pevent_record *rec)
+int tep_data_type(struct tep_handle *pevent, struct tep_record *rec)
 {
        return trace_parse_common_type(pevent, rec->data);
 }
 
 /**
- * pevent_data_event_from_type - find the event by a given type
+ * tep_data_event_from_type - find the event by a given type
  * @pevent: a handle to the pevent
  * @type: the type of the event.
  *
  * This returns the event form a given @type;
  */
-struct event_format *pevent_data_event_from_type(struct pevent *pevent, int type)
+struct event_format *tep_data_event_from_type(struct tep_handle *pevent, int type)
 {
-       return pevent_find_event(pevent, type);
+       return tep_find_event(pevent, type);
 }
 
 /**
- * pevent_data_pid - parse the PID from record
+ * tep_data_pid - parse the PID from record
  * @pevent: a handle to the pevent
  * @rec: the record to parse
  *
  * This returns the PID from a record.
  */
-int pevent_data_pid(struct pevent *pevent, struct pevent_record *rec)
+int tep_data_pid(struct tep_handle *pevent, struct tep_record *rec)
 {
        return parse_common_pid(pevent, rec->data);
 }
 
 /**
- * pevent_data_preempt_count - parse the preempt count from the record
+ * tep_data_preempt_count - parse the preempt count from the record
  * @pevent: a handle to the pevent
  * @rec: the record to parse
  *
  * This returns the preempt count from a record.
  */
-int pevent_data_preempt_count(struct pevent *pevent, struct pevent_record *rec)
+int tep_data_preempt_count(struct tep_handle *pevent, struct tep_record *rec)
 {
        return parse_common_pc(pevent, rec->data);
 }
 
 /**
- * pevent_data_flags - parse the latency flags from the record
+ * tep_data_flags - parse the latency flags from the record
  * @pevent: a handle to the pevent
  * @rec: the record to parse
  *
@@ -5279,20 +5265,20 @@ int pevent_data_preempt_count(struct pevent *pevent, struct pevent_record *rec)
  *
  *  Use trace_flag_type enum for the flags (see event-parse.h).
  */
-int pevent_data_flags(struct pevent *pevent, struct pevent_record *rec)
+int tep_data_flags(struct tep_handle *pevent, struct tep_record *rec)
 {
        return parse_common_flags(pevent, rec->data);
 }
 
 /**
- * pevent_data_comm_from_pid - return the command line from PID
+ * tep_data_comm_from_pid - return the command line from PID
  * @pevent: a handle to the pevent
  * @pid: the PID of the task to search for
  *
  * This returns a pointer to the command line that has the given
  * @pid.
  */
-const char *pevent_data_comm_from_pid(struct pevent *pevent, int pid)
+const char *tep_data_comm_from_pid(struct tep_handle *pevent, int pid)
 {
        const char *comm;
 
@@ -5301,7 +5287,7 @@ const char *pevent_data_comm_from_pid(struct pevent *pevent, int pid)
 }
 
 static struct cmdline *
-pid_from_cmdlist(struct pevent *pevent, const char *comm, struct cmdline *next)
+pid_from_cmdlist(struct tep_handle *pevent, const char *comm, struct cmdline *next)
 {
        struct cmdline_list *cmdlist = (struct cmdline_list *)next;
 
@@ -5317,7 +5303,7 @@ pid_from_cmdlist(struct pevent *pevent, const char *comm, struct cmdline *next)
 }
 
 /**
- * pevent_data_pid_from_comm - return the pid from a given comm
+ * tep_data_pid_from_comm - return the pid from a given comm
  * @pevent: a handle to the pevent
  * @comm: the cmdline to find the pid from
  * @next: the cmdline structure to find the next comm
@@ -5329,8 +5315,8 @@ pid_from_cmdlist(struct pevent *pevent, const char *comm, struct cmdline *next)
  * next pid.
  * Also, it does a linear seach, so it may be slow.
  */
-struct cmdline *pevent_data_pid_from_comm(struct pevent *pevent, const char *comm,
-                                         struct cmdline *next)
+struct cmdline *tep_data_pid_from_comm(struct tep_handle *pevent, const char *comm,
+                                      struct cmdline *next)
 {
        struct cmdline *cmdline;
 
@@ -5365,13 +5351,13 @@ struct cmdline *pevent_data_pid_from_comm(struct pevent *pevent, const char *com
 }
 
 /**
- * pevent_cmdline_pid - return the pid associated to a given cmdline
+ * tep_cmdline_pid - return the pid associated to a given cmdline
  * @cmdline: The cmdline structure to get the pid from
  *
  * Returns the pid for a give cmdline. If @cmdline is NULL, then
  * -1 is returned.
  */
-int pevent_cmdline_pid(struct pevent *pevent, struct cmdline *cmdline)
+int tep_cmdline_pid(struct tep_handle *pevent, struct cmdline *cmdline)
 {
        struct cmdline_list *cmdlist = (struct cmdline_list *)cmdline;
 
@@ -5391,7 +5377,7 @@ int pevent_cmdline_pid(struct pevent *pevent, struct cmdline *cmdline)
 }
 
 /**
- * pevent_data_comm_from_pid - parse the data into the print format
+ * tep_event_info - parse the data into the print format
  * @s: the trace_seq to write to
  * @event: the handle to the event
  * @record: the record to read from
@@ -5399,13 +5385,13 @@ int pevent_cmdline_pid(struct pevent *pevent, struct cmdline *cmdline)
  * This parses the raw @data using the given @event information and
  * writes the print format into the trace_seq.
  */
-void pevent_event_info(struct trace_seq *s, struct event_format *event,
-                      struct pevent_record *record)
+void tep_event_info(struct trace_seq *s, struct event_format *event,
+                   struct tep_record *record)
 {
        int print_pretty = 1;
 
        if (event->pevent->print_raw || (event->flags & EVENT_FL_PRINTRAW))
-               pevent_print_fields(s, record->data, record->size, event);
+               tep_print_fields(s, record->data, record->size, event);
        else {
 
                if (event->handler && !(event->flags & EVENT_FL_NOHANDLE))
@@ -5433,7 +5419,7 @@ static bool is_timestamp_in_us(char *trace_clock, bool use_trace_clock)
 }
 
 /**
- * pevent_find_event_by_record - return the event from a given record
+ * tep_find_event_by_record - return the event from a given record
  * @pevent: a handle to the pevent
  * @record: The record to get the event from
  *
@@ -5441,7 +5427,7 @@ static bool is_timestamp_in_us(char *trace_clock, bool use_trace_clock)
  * is found.
  */
 struct event_format *
-pevent_find_event_by_record(struct pevent *pevent, struct pevent_record *record)
+tep_find_event_by_record(struct tep_handle *pevent, struct tep_record *record)
 {
        int type;
 
@@ -5452,11 +5438,11 @@ pevent_find_event_by_record(struct pevent *pevent, struct pevent_record *record)
 
        type = trace_parse_common_type(pevent, record->data);
 
-       return pevent_find_event(pevent, type);
+       return tep_find_event(pevent, type);
 }
 
 /**
- * pevent_print_event_task - Write the event task comm, pid and CPU
+ * tep_print_event_task - Write the event task comm, pid and CPU
  * @pevent: a handle to the pevent
  * @s: the trace_seq to write to
  * @event: the handle to the record's event
@@ -5464,9 +5450,9 @@ pevent_find_event_by_record(struct pevent *pevent, struct pevent_record *record)
  *
  * Writes the tasks comm, pid and CPU to @s.
  */
-void pevent_print_event_task(struct pevent *pevent, struct trace_seq *s,
-                            struct event_format *event,
-                            struct pevent_record *record)
+void tep_print_event_task(struct tep_handle *pevent, struct trace_seq *s,
+                         struct event_format *event,
+                         struct tep_record *record)
 {
        void *data = record->data;
        const char *comm;
@@ -5483,7 +5469,7 @@ void pevent_print_event_task(struct pevent *pevent, struct trace_seq *s,
 }
 
 /**
- * pevent_print_event_time - Write the event timestamp
+ * tep_print_event_time - Write the event timestamp
  * @pevent: a handle to the pevent
  * @s: the trace_seq to write to
  * @event: the handle to the record's event
@@ -5492,10 +5478,10 @@ void pevent_print_event_task(struct pevent *pevent, struct trace_seq *s,
  *
  * Writes the timestamp of the record into @s.
  */
-void pevent_print_event_time(struct pevent *pevent, struct trace_seq *s,
-                            struct event_format *event,
-                            struct pevent_record *record,
-                            bool use_trace_clock)
+void tep_print_event_time(struct tep_handle *pevent, struct trace_seq *s,
+                         struct event_format *event,
+                         struct tep_record *record,
+                         bool use_trace_clock)
 {
        unsigned long secs;
        unsigned long usecs;
@@ -5511,11 +5497,11 @@ void pevent_print_event_time(struct pevent *pevent, struct trace_seq *s,
        }
 
        if (pevent->latency_format) {
-               pevent_data_lat_fmt(pevent, s, record);
+               tep_data_lat_fmt(pevent, s, record);
        }
 
        if (use_usec_format) {
-               if (pevent->flags & PEVENT_NSEC_OUTPUT) {
+               if (pevent->flags & TEP_NSEC_OUTPUT) {
                        usecs = nsecs;
                        p = 9;
                } else {
@@ -5534,7 +5520,7 @@ void pevent_print_event_time(struct pevent *pevent, struct trace_seq *s,
 }
 
 /**
- * pevent_print_event_data - Write the event data section
+ * tep_print_event_data - Write the event data section
  * @pevent: a handle to the pevent
  * @s: the trace_seq to write to
  * @event: the handle to the record's event
@@ -5542,9 +5528,9 @@ void pevent_print_event_time(struct pevent *pevent, struct trace_seq *s,
  *
  * Writes the parsing of the record's data to @s.
  */
-void pevent_print_event_data(struct pevent *pevent, struct trace_seq *s,
-                            struct event_format *event,
-                            struct pevent_record *record)
+void tep_print_event_data(struct tep_handle *pevent, struct trace_seq *s,
+                         struct event_format *event,
+                         struct tep_record *record)
 {
        static const char *spaces = "                    "; /* 20 spaces */
        int len;
@@ -5556,15 +5542,15 @@ void pevent_print_event_data(struct pevent *pevent, struct trace_seq *s,
        if (len < 20)
                trace_seq_printf(s, "%.*s", 20 - len, spaces);
 
-       pevent_event_info(s, event, record);
+       tep_event_info(s, event, record);
 }
 
-void pevent_print_event(struct pevent *pevent, struct trace_seq *s,
-                       struct pevent_record *record, bool use_trace_clock)
+void tep_print_event(struct tep_handle *pevent, struct trace_seq *s,
+                    struct tep_record *record, bool use_trace_clock)
 {
        struct event_format *event;
 
-       event = pevent_find_event_by_record(pevent, record);
+       event = tep_find_event_by_record(pevent, record);
        if (!event) {
                int i;
                int type = trace_parse_common_type(pevent, record->data);
@@ -5577,9 +5563,9 @@ void pevent_print_event(struct pevent *pevent, struct trace_seq *s,
                return;
        }
 
-       pevent_print_event_task(pevent, s, event, record);
-       pevent_print_event_time(pevent, s, event, record, use_trace_clock);
-       pevent_print_event_data(pevent, s, event, record);
+       tep_print_event_task(pevent, s, event, record);
+       tep_print_event_time(pevent, s, event, record, use_trace_clock);
+       tep_print_event_data(pevent, s, event, record);
 }
 
 static int events_id_cmp(const void *a, const void *b)
@@ -5630,7 +5616,7 @@ static int events_system_cmp(const void *a, const void *b)
        return events_id_cmp(a, b);
 }
 
-struct event_format **pevent_list_events(struct pevent *pevent, enum event_sort_type sort_type)
+struct event_format **tep_list_events(struct tep_handle *pevent, enum event_sort_type sort_type)
 {
        struct event_format **events;
        int (*sort)(const void *a, const void *b);
@@ -5709,13 +5695,13 @@ get_event_fields(const char *type, const char *name,
 }
 
 /**
- * pevent_event_common_fields - return a list of common fields for an event
+ * tep_event_common_fields - return a list of common fields for an event
  * @event: the event to return the common fields of.
  *
  * Returns an allocated array of fields. The last item in the array is NULL.
  * The array must be freed with free().
  */
-struct format_field **pevent_event_common_fields(struct event_format *event)
+struct format_field **tep_event_common_fields(struct event_format *event)
 {
        return get_event_fields("common", event->name,
                                event->format.nr_common,
@@ -5723,13 +5709,13 @@ struct format_field **pevent_event_common_fields(struct event_format *event)
 }
 
 /**
- * pevent_event_fields - return a list of event specific fields for an event
+ * tep_event_fields - return a list of event specific fields for an event
  * @event: the event to return the fields of.
  *
  * Returns an allocated array of fields. The last item in the array is NULL.
  * The array must be freed with free().
  */
-struct format_field **pevent_event_fields(struct event_format *event)
+struct format_field **tep_event_fields(struct event_format *event)
 {
        return get_event_fields("event", event->name,
                                event->format.nr_fields,
@@ -5930,7 +5916,7 @@ static void parse_header_field(const char *field,
 }
 
 /**
- * pevent_parse_header_page - parse the data stored in the header page
+ * tep_parse_header_page - parse the data stored in the header page
  * @pevent: the handle to the pevent
  * @buf: the buffer storing the header page format string
  * @size: the size of @buf
@@ -5941,8 +5927,8 @@ static void parse_header_field(const char *field,
  *
  * /sys/kernel/debug/tracing/events/header_page
  */
-int pevent_parse_header_page(struct pevent *pevent, char *buf, unsigned long size,
-                            int long_size)
+int tep_parse_header_page(struct tep_handle *pevent, char *buf, unsigned long size,
+                         int long_size)
 {
        int ignore;
 
@@ -5994,7 +5980,7 @@ static void free_handler(struct event_handler *handle)
        free(handle);
 }
 
-static int find_event_handle(struct pevent *pevent, struct event_format *event)
+static int find_event_handle(struct tep_handle *pevent, struct event_format *event)
 {
        struct event_handler *handle, **next;
 
@@ -6023,7 +6009,7 @@ static int find_event_handle(struct pevent *pevent, struct event_format *event)
 }
 
 /**
- * __pevent_parse_format - parse the event format
+ * __tep_parse_format - parse the event format
  * @buf: the buffer storing the event format string
  * @size: the size of @buf
  * @sys: the system the event belongs to
@@ -6035,9 +6021,9 @@ static int find_event_handle(struct pevent *pevent, struct event_format *event)
  *
  * /sys/kernel/debug/tracing/events/.../.../format
  */
-enum pevent_errno __pevent_parse_format(struct event_format **eventp,
-                                       struct pevent *pevent, const char *buf,
-                                       unsigned long size, const char *sys)
+enum tep_errno __tep_parse_format(struct event_format **eventp,
+                                 struct tep_handle *pevent, const char *buf,
+                                 unsigned long size, const char *sys)
 {
        struct event_format *event;
        int ret;
@@ -6046,12 +6032,12 @@ enum pevent_errno __pevent_parse_format(struct event_format **eventp,
 
        *eventp = event = alloc_event();
        if (!event)
-               return PEVENT_ERRNO__MEM_ALLOC_FAILED;
+               return TEP_ERRNO__MEM_ALLOC_FAILED;
 
        event->name = event_read_name();
        if (!event->name) {
                /* Bad event? */
-               ret = PEVENT_ERRNO__MEM_ALLOC_FAILED;
+               ret = TEP_ERRNO__MEM_ALLOC_FAILED;
                goto event_alloc_failed;
        }
 
@@ -6064,7 +6050,7 @@ enum pevent_errno __pevent_parse_format(struct event_format **eventp,
                
        event->id = event_read_id();
        if (event->id < 0) {
-               ret = PEVENT_ERRNO__READ_ID_FAILED;
+               ret = TEP_ERRNO__READ_ID_FAILED;
                /*
                 * This isn't an allocation error actually.
                 * But as the ID is critical, just bail out.
@@ -6074,7 +6060,7 @@ enum pevent_errno __pevent_parse_format(struct event_format **eventp,
 
        event->system = strdup(sys);
        if (!event->system) {
-               ret = PEVENT_ERRNO__MEM_ALLOC_FAILED;
+               ret = TEP_ERRNO__MEM_ALLOC_FAILED;
                goto event_alloc_failed;
        }
 
@@ -6083,7 +6069,7 @@ enum pevent_errno __pevent_parse_format(struct event_format **eventp,
 
        ret = event_read_format(event);
        if (ret < 0) {
-               ret = PEVENT_ERRNO__READ_FORMAT_FAILED;
+               ret = TEP_ERRNO__READ_FORMAT_FAILED;
                goto event_parse_failed;
        }
 
@@ -6098,7 +6084,7 @@ enum pevent_errno __pevent_parse_format(struct event_format **eventp,
        show_warning = 1;
 
        if (ret < 0) {
-               ret = PEVENT_ERRNO__READ_PRINT_FAILED;
+               ret = TEP_ERRNO__READ_PRINT_FAILED;
                goto event_parse_failed;
        }
 
@@ -6112,14 +6098,14 @@ enum pevent_errno __pevent_parse_format(struct event_format **eventp,
                        arg = alloc_arg();
                        if (!arg) {
                                event->flags |= EVENT_FL_FAILED;
-                               return PEVENT_ERRNO__OLD_FTRACE_ARG_FAILED;
+                               return TEP_ERRNO__OLD_FTRACE_ARG_FAILED;
                        }
                        arg->type = PRINT_FIELD;
                        arg->field.name = strdup(field->name);
                        if (!arg->field.name) {
                                event->flags |= EVENT_FL_FAILED;
                                free_arg(arg);
-                               return PEVENT_ERRNO__OLD_FTRACE_ARG_FAILED;
+                               return TEP_ERRNO__OLD_FTRACE_ARG_FAILED;
                        }
                        arg->field.field = field;
                        *list = arg;
@@ -6142,20 +6128,20 @@ enum pevent_errno __pevent_parse_format(struct event_format **eventp,
        return ret;
 }
 
-static enum pevent_errno
-__pevent_parse_event(struct pevent *pevent,
-                    struct event_format **eventp,
-                    const char *buf, unsigned long size,
-                    const char *sys)
+static enum tep_errno
+__parse_event(struct tep_handle *pevent,
+             struct event_format **eventp,
+             const char *buf, unsigned long size,
+             const char *sys)
 {
-       int ret = __pevent_parse_format(eventp, pevent, buf, size, sys);
+       int ret = __tep_parse_format(eventp, pevent, buf, size, sys);
        struct event_format *event = *eventp;
 
        if (event == NULL)
                return ret;
 
        if (pevent && add_event(pevent, event)) {
-               ret = PEVENT_ERRNO__MEM_ALLOC_FAILED;
+               ret = TEP_ERRNO__MEM_ALLOC_FAILED;
                goto event_add_failed;
        }
 
@@ -6166,12 +6152,12 @@ __pevent_parse_event(struct pevent *pevent,
        return 0;
 
 event_add_failed:
-       pevent_free_format(event);
+       tep_free_format(event);
        return ret;
 }
 
 /**
- * pevent_parse_format - parse the event format
+ * tep_parse_format - parse the event format
  * @pevent: the handle to the pevent
  * @eventp: returned format
  * @buf: the buffer storing the event format string
@@ -6185,16 +6171,16 @@ event_add_failed:
  *
  * /sys/kernel/debug/tracing/events/.../.../format
  */
-enum pevent_errno pevent_parse_format(struct pevent *pevent,
-                                     struct event_format **eventp,
-                                     const char *buf,
-                                     unsigned long size, const char *sys)
+enum tep_errno tep_parse_format(struct tep_handle *pevent,
+                               struct event_format **eventp,
+                               const char *buf,
+                               unsigned long size, const char *sys)
 {
-       return __pevent_parse_event(pevent, eventp, buf, size, sys);
+       return __parse_event(pevent, eventp, buf, size, sys);
 }
 
 /**
- * pevent_parse_event - parse the event format
+ * tep_parse_event - parse the event format
  * @pevent: the handle to the pevent
  * @buf: the buffer storing the event format string
  * @size: the size of @buf
@@ -6207,22 +6193,22 @@ enum pevent_errno pevent_parse_format(struct pevent *pevent,
  *
  * /sys/kernel/debug/tracing/events/.../.../format
  */
-enum pevent_errno pevent_parse_event(struct pevent *pevent, const char *buf,
-                                    unsigned long size, const char *sys)
+enum tep_errno tep_parse_event(struct tep_handle *pevent, const char *buf,
+                              unsigned long size, const char *sys)
 {
        struct event_format *event = NULL;
-       return __pevent_parse_event(pevent, &event, buf, size, sys);
+       return __parse_event(pevent, &event, buf, size, sys);
 }
 
 #undef _PE
 #define _PE(code, str) str
-static const char * const pevent_error_str[] = {
-       PEVENT_ERRORS
+static const char * const tep_error_str[] = {
+       TEP_ERRORS
 };
 #undef _PE
 
-int pevent_strerror(struct pevent *pevent __maybe_unused,
-                   enum pevent_errno errnum, char *buf, size_t buflen)
+int tep_strerror(struct tep_handle *pevent __maybe_unused,
+                enum tep_errno errnum, char *buf, size_t buflen)
 {
        int idx;
        const char *msg;
@@ -6232,19 +6218,19 @@ int pevent_strerror(struct pevent *pevent __maybe_unused,
                return 0;
        }
 
-       if (errnum <= __PEVENT_ERRNO__START ||
-           errnum >= __PEVENT_ERRNO__END)
+       if (errnum <= __TEP_ERRNO__START ||
+           errnum >= __TEP_ERRNO__END)
                return -1;
 
-       idx = errnum - __PEVENT_ERRNO__START - 1;
-       msg = pevent_error_str[idx];
+       idx = errnum - __TEP_ERRNO__START - 1;
+       msg = tep_error_str[idx];
        snprintf(buf, buflen, "%s", msg);
 
        return 0;
 }
 
 int get_field_val(struct trace_seq *s, struct format_field *field,
-                 const char *name, struct pevent_record *record,
+                 const char *name, struct tep_record *record,
                  unsigned long long *val, int err)
 {
        if (!field) {
@@ -6253,7 +6239,7 @@ int get_field_val(struct trace_seq *s, struct format_field *field,
                return -1;
        }
 
-       if (pevent_read_number_field(field, record->data, val)) {
+       if (tep_read_number_field(field, record->data, val)) {
                if (err)
                        trace_seq_printf(s, " %s=INVALID", name);
                return -1;
@@ -6263,7 +6249,7 @@ int get_field_val(struct trace_seq *s, struct format_field *field,
 }
 
 /**
- * pevent_get_field_raw - return the raw pointer into the data field
+ * tep_get_field_raw - return the raw pointer into the data field
  * @s: The seq to print to on error
  * @event: the event that the field is for
  * @name: The name of the field
@@ -6276,9 +6262,9 @@ int get_field_val(struct trace_seq *s, struct format_field *field,
  *
  * On failure, it returns NULL.
  */
-void *pevent_get_field_raw(struct trace_seq *s, struct event_format *event,
-                          const char *name, struct pevent_record *record,
-                          int *len, int err)
+void *tep_get_field_raw(struct trace_seq *s, struct event_format *event,
+                       const char *name, struct tep_record *record,
+                       int *len, int err)
 {
        struct format_field *field;
        void *data = record->data;
@@ -6288,7 +6274,7 @@ void *pevent_get_field_raw(struct trace_seq *s, struct event_format *event,
        if (!event)
                return NULL;
 
-       field = pevent_find_field(event, name);
+       field = tep_find_field(event, name);
 
        if (!field) {
                if (err)
@@ -6302,7 +6288,7 @@ void *pevent_get_field_raw(struct trace_seq *s, struct event_format *event,
 
        offset = field->offset;
        if (field->flags & FIELD_IS_DYNAMIC) {
-               offset = pevent_read_number(event->pevent,
+               offset = tep_read_number(event->pevent,
                                            data + offset, field->size);
                *len = offset >> 16;
                offset &= 0xffff;
@@ -6313,7 +6299,7 @@ void *pevent_get_field_raw(struct trace_seq *s, struct event_format *event,
 }
 
 /**
- * pevent_get_field_val - find a field and return its value
+ * tep_get_field_val - find a field and return its value
  * @s: The seq to print to on error
  * @event: the event that the field is for
  * @name: The name of the field
@@ -6323,22 +6309,22 @@ void *pevent_get_field_raw(struct trace_seq *s, struct event_format *event,
  *
  * Returns 0 on success -1 on field not found.
  */
-int pevent_get_field_val(struct trace_seq *s, struct event_format *event,
-                        const char *name, struct pevent_record *record,
-                        unsigned long long *val, int err)
+int tep_get_field_val(struct trace_seq *s, struct event_format *event,
+                     const char *name, struct tep_record *record,
+                     unsigned long long *val, int err)
 {
        struct format_field *field;
 
        if (!event)
                return -1;
 
-       field = pevent_find_field(event, name);
+       field = tep_find_field(event, name);
 
        return get_field_val(s, field, name, record, val, err);
 }
 
 /**
- * pevent_get_common_field_val - find a common field and return its value
+ * tep_get_common_field_val - find a common field and return its value
  * @s: The seq to print to on error
  * @event: the event that the field is for
  * @name: The name of the field
@@ -6348,22 +6334,22 @@ int pevent_get_field_val(struct trace_seq *s, struct event_format *event,
  *
  * Returns 0 on success -1 on field not found.
  */
-int pevent_get_common_field_val(struct trace_seq *s, struct event_format *event,
-                               const char *name, struct pevent_record *record,
-                               unsigned long long *val, int err)
+int tep_get_common_field_val(struct trace_seq *s, struct event_format *event,
+                            const char *name, struct tep_record *record,
+                            unsigned long long *val, int err)
 {
        struct format_field *field;
 
        if (!event)
                return -1;
 
-       field = pevent_find_common_field(event, name);
+       field = tep_find_common_field(event, name);
 
        return get_field_val(s, field, name, record, val, err);
 }
 
 /**
- * pevent_get_any_field_val - find a any field and return its value
+ * tep_get_any_field_val - find a any field and return its value
  * @s: The seq to print to on error
  * @event: the event that the field is for
  * @name: The name of the field
@@ -6373,22 +6359,22 @@ int pevent_get_common_field_val(struct trace_seq *s, struct event_format *event,
  *
  * Returns 0 on success -1 on field not found.
  */
-int pevent_get_any_field_val(struct trace_seq *s, struct event_format *event,
-                            const char *name, struct pevent_record *record,
-                            unsigned long long *val, int err)
+int tep_get_any_field_val(struct trace_seq *s, struct event_format *event,
+                         const char *name, struct tep_record *record,
+                         unsigned long long *val, int err)
 {
        struct format_field *field;
 
        if (!event)
                return -1;
 
-       field = pevent_find_any_field(event, name);
+       field = tep_find_any_field(event, name);
 
        return get_field_val(s, field, name, record, val, err);
 }
 
 /**
- * pevent_print_num_field - print a field and a format
+ * tep_print_num_field - print a field and a format
  * @s: The seq to print to
  * @fmt: The printf format to print the field with.
  * @event: the event that the field is for
@@ -6398,17 +6384,17 @@ int pevent_get_any_field_val(struct trace_seq *s, struct event_format *event,
  *
  * Returns: 0 on success, -1 field not found, or 1 if buffer is full.
  */
-int pevent_print_num_field(struct trace_seq *s, const char *fmt,
-                          struct event_format *event, const char *name,
-                          struct pevent_record *record, int err)
+int tep_print_num_field(struct trace_seq *s, const char *fmt,
+                       struct event_format *event, const char *name,
+                       struct tep_record *record, int err)
 {
-       struct format_field *field = pevent_find_field(event, name);
+       struct format_field *field = tep_find_field(event, name);
        unsigned long long val;
 
        if (!field)
                goto failed;
 
-       if (pevent_read_number_field(field, record->data, &val))
+       if (tep_read_number_field(field, record->data, &val))
                goto failed;
 
        return trace_seq_printf(s, fmt, val);
@@ -6420,7 +6406,7 @@ int pevent_print_num_field(struct trace_seq *s, const char *fmt,
 }
 
 /**
- * pevent_print_func_field - print a field and a format for function pointers
+ * tep_print_func_field - print a field and a format for function pointers
  * @s: The seq to print to
  * @fmt: The printf format to print the field with.
  * @event: the event that the field is for
@@ -6430,12 +6416,12 @@ int pevent_print_num_field(struct trace_seq *s, const char *fmt,
  *
  * Returns: 0 on success, -1 field not found, or 1 if buffer is full.
  */
-int pevent_print_func_field(struct trace_seq *s, const char *fmt,
-                           struct event_format *event, const char *name,
-                           struct pevent_record *record, int err)
+int tep_print_func_field(struct trace_seq *s, const char *fmt,
+                        struct event_format *event, const char *name,
+                        struct tep_record *record, int err)
 {
-       struct format_field *field = pevent_find_field(event, name);
-       struct pevent *pevent = event->pevent;
+       struct format_field *field = tep_find_field(event, name);
+       struct tep_handle *pevent = event->pevent;
        unsigned long long val;
        struct func_map *func;
        char tmp[128];
@@ -6443,7 +6429,7 @@ int pevent_print_func_field(struct trace_seq *s, const char *fmt,
        if (!field)
                goto failed;
 
-       if (pevent_read_number_field(field, record->data, &val))
+       if (tep_read_number_field(field, record->data, &val))
                goto failed;
 
        func = find_func(pevent, val);
@@ -6461,9 +6447,9 @@ int pevent_print_func_field(struct trace_seq *s, const char *fmt,
        return -1;
 }
 
-static void free_func_handle(struct pevent_function_handler *func)
+static void free_func_handle(struct tep_function_handler *func)
 {
-       struct pevent_func_params *params;
+       struct func_params *params;
 
        free(func->name);
 
@@ -6477,29 +6463,29 @@ static void free_func_handle(struct pevent_function_handler *func)
 }
 
 /**
- * pevent_register_print_function - register a helper function
+ * tep_register_print_function - register a helper function
  * @pevent: the handle to the pevent
  * @func: the function to process the helper function
  * @ret_type: the return type of the helper function
  * @name: the name of the helper function
- * @parameters: A list of enum pevent_func_arg_type
+ * @parameters: A list of enum tep_func_arg_type
  *
  * Some events may have helper functions in the print format arguments.
  * This allows a plugin to dynamically create a way to process one
  * of these functions.
  *
- * The @parameters is a variable list of pevent_func_arg_type enums that
- * must end with PEVENT_FUNC_ARG_VOID.
+ * The @parameters is a variable list of tep_func_arg_type enums that
+ * must end with TEP_FUNC_ARG_VOID.
  */
-int pevent_register_print_function(struct pevent *pevent,
-                                  pevent_func_handler func,
-                                  enum pevent_func_arg_type ret_type,
-                                  char *name, ...)
-{
-       struct pevent_function_handler *func_handle;
-       struct pevent_func_params **next_param;
-       struct pevent_func_params *param;
-       enum pevent_func_arg_type type;
+int tep_register_print_function(struct tep_handle *pevent,
+                               tep_func_handler func,
+                               enum tep_func_arg_type ret_type,
+                               char *name, ...)
+{
+       struct tep_function_handler *func_handle;
+       struct func_params **next_param;
+       struct func_params *param;
+       enum tep_func_arg_type type;
        va_list ap;
        int ret;
 
@@ -6517,7 +6503,7 @@ int pevent_register_print_function(struct pevent *pevent,
        func_handle = calloc(1, sizeof(*func_handle));
        if (!func_handle) {
                do_warning("Failed to allocate function handler");
-               return PEVENT_ERRNO__MEM_ALLOC_FAILED;
+               return TEP_ERRNO__MEM_ALLOC_FAILED;
        }
 
        func_handle->ret_type = ret_type;
@@ -6526,26 +6512,26 @@ int pevent_register_print_function(struct pevent *pevent,
        if (!func_handle->name) {
                do_warning("Failed to allocate function name");
                free(func_handle);
-               return PEVENT_ERRNO__MEM_ALLOC_FAILED;
+               return TEP_ERRNO__MEM_ALLOC_FAILED;
        }
 
        next_param = &(func_handle->params);
        va_start(ap, name);
        for (;;) {
-               type = va_arg(ap, enum pevent_func_arg_type);
-               if (type == PEVENT_FUNC_ARG_VOID)
+               type = va_arg(ap, enum tep_func_arg_type);
+               if (type == TEP_FUNC_ARG_VOID)
                        break;
 
-               if (type >= PEVENT_FUNC_ARG_MAX_TYPES) {
+               if (type >= TEP_FUNC_ARG_MAX_TYPES) {
                        do_warning("Invalid argument type %d", type);
-                       ret = PEVENT_ERRNO__INVALID_ARG_TYPE;
+                       ret = TEP_ERRNO__INVALID_ARG_TYPE;
                        goto out_free;
                }
 
                param = malloc(sizeof(*param));
                if (!param) {
                        do_warning("Failed to allocate function param");
-                       ret = PEVENT_ERRNO__MEM_ALLOC_FAILED;
+                       ret = TEP_ERRNO__MEM_ALLOC_FAILED;
                        goto out_free;
                }
                param->type = type;
@@ -6569,7 +6555,7 @@ int pevent_register_print_function(struct pevent *pevent,
 }
 
 /**
- * pevent_unregister_print_function - unregister a helper function
+ * tep_unregister_print_function - unregister a helper function
  * @pevent: the handle to the pevent
  * @func: the function to process the helper function
  * @name: the name of the helper function
@@ -6578,10 +6564,10 @@ int pevent_register_print_function(struct pevent *pevent,
  *
  * Returns 0 if the handler was removed successully, -1 otherwise.
  */
-int pevent_unregister_print_function(struct pevent *pevent,
-                                    pevent_func_handler func, char *name)
+int tep_unregister_print_function(struct tep_handle *pevent,
+                                 tep_func_handler func, char *name)
 {
-       struct pevent_function_handler *func_handle;
+       struct tep_function_handler *func_handle;
 
        func_handle = find_func_handler(pevent, name);
        if (func_handle && func_handle->func == func) {
@@ -6591,15 +6577,15 @@ int pevent_unregister_print_function(struct pevent *pevent,
        return -1;
 }
 
-static struct event_format *pevent_search_event(struct pevent *pevent, int id,
-                                               const char *sys_name,
-                                               const char *event_name)
+static struct event_format *search_event(struct tep_handle *pevent, int id,
+                                        const char *sys_name,
+                                        const char *event_name)
 {
        struct event_format *event;
 
        if (id >= 0) {
                /* search by id */
-               event = pevent_find_event(pevent, id);
+               event = tep_find_event(pevent, id);
                if (!event)
                        return NULL;
                if (event_name && (strcmp(event_name, event->name) != 0))
@@ -6607,7 +6593,7 @@ static struct event_format *pevent_search_event(struct pevent *pevent, int id,
                if (sys_name && (strcmp(sys_name, event->system) != 0))
                        return NULL;
        } else {
-               event = pevent_find_event_by_name(pevent, sys_name, event_name);
+               event = tep_find_event_by_name(pevent, sys_name, event_name);
                if (!event)
                        return NULL;
        }
@@ -6615,7 +6601,7 @@ static struct event_format *pevent_search_event(struct pevent *pevent, int id,
 }
 
 /**
- * pevent_register_event_handler - register a way to parse an event
+ * tep_register_event_handler - register a way to parse an event
  * @pevent: the handle to the pevent
  * @id: the id of the event to register
  * @sys_name: the system name the event belongs to
@@ -6631,14 +6617,14 @@ static struct event_format *pevent_search_event(struct pevent *pevent, int id,
  * If @id is >= 0, then it is used to find the event.
  * else @sys_name and @event_name are used.
  */
-int pevent_register_event_handler(struct pevent *pevent, int id,
-                                 const char *sys_name, const char *event_name,
-                                 pevent_event_handler_func func, void *context)
+int tep_register_event_handler(struct tep_handle *pevent, int id,
+                              const char *sys_name, const char *event_name,
+                              tep_event_handler_func func, void *context)
 {
        struct event_format *event;
        struct event_handler *handle;
 
-       event = pevent_search_event(pevent, id, sys_name, event_name);
+       event = search_event(pevent, id, sys_name, event_name);
        if (event == NULL)
                goto not_found;
 
@@ -6654,7 +6640,7 @@ int pevent_register_event_handler(struct pevent *pevent, int id,
        handle = calloc(1, sizeof(*handle));
        if (!handle) {
                do_warning("Failed to allocate event handler");
-               return PEVENT_ERRNO__MEM_ALLOC_FAILED;
+               return TEP_ERRNO__MEM_ALLOC_FAILED;
        }
 
        handle->id = id;
@@ -6669,7 +6655,7 @@ int pevent_register_event_handler(struct pevent *pevent, int id,
                free((void *)handle->event_name);
                free((void *)handle->sys_name);
                free(handle);
-               return PEVENT_ERRNO__MEM_ALLOC_FAILED;
+               return TEP_ERRNO__MEM_ALLOC_FAILED;
        }
 
        handle->func = func;
@@ -6682,7 +6668,7 @@ int pevent_register_event_handler(struct pevent *pevent, int id,
 
 static int handle_matches(struct event_handler *handler, int id,
                          const char *sys_name, const char *event_name,
-                         pevent_event_handler_func func, void *context)
+                         tep_event_handler_func func, void *context)
 {
        if (id >= 0 && id != handler->id)
                return 0;
@@ -6700,7 +6686,7 @@ static int handle_matches(struct event_handler *handler, int id,
 }
 
 /**
- * pevent_unregister_event_handler - unregister an existing event handler
+ * tep_unregister_event_handler - unregister an existing event handler
  * @pevent: the handle to the pevent
  * @id: the id of the event to unregister
  * @sys_name: the system name the handler belongs to
@@ -6715,15 +6701,15 @@ static int handle_matches(struct event_handler *handler, int id,
  *
  * Returns 0 if handler was removed successfully, -1 if event was not found.
  */
-int pevent_unregister_event_handler(struct pevent *pevent, int id,
-                                   const char *sys_name, const char *event_name,
-                                   pevent_event_handler_func func, void *context)
+int tep_unregister_event_handler(struct tep_handle *pevent, int id,
+                                const char *sys_name, const char *event_name,
+                                tep_event_handler_func func, void *context)
 {
        struct event_format *event;
        struct event_handler *handle;
        struct event_handler **next;
 
-       event = pevent_search_event(pevent, id, sys_name, event_name);
+       event = search_event(pevent, id, sys_name, event_name);
        if (event == NULL)
                goto not_found;
 
@@ -6754,11 +6740,11 @@ not_found:
 }
 
 /**
- * pevent_alloc - create a pevent handle
+ * tep_alloc - create a pevent handle
  */
-struct pevent *pevent_alloc(void)
+struct tep_handle *tep_alloc(void)
 {
-       struct pevent *pevent = calloc(1, sizeof(*pevent));
+       struct tep_handle *pevent = calloc(1, sizeof(*pevent));
 
        if (pevent)
                pevent->ref_count = 1;
@@ -6766,12 +6752,12 @@ struct pevent *pevent_alloc(void)
        return pevent;
 }
 
-void pevent_ref(struct pevent *pevent)
+void tep_ref(struct tep_handle *pevent)
 {
        pevent->ref_count++;
 }
 
-void pevent_free_format_field(struct format_field *field)
+void tep_free_format_field(struct format_field *field)
 {
        free(field->type);
        if (field->alias != field->name)
@@ -6786,7 +6772,7 @@ static void free_format_fields(struct format_field *field)
 
        while (field) {
                next = field->next;
-               pevent_free_format_field(field);
+               tep_free_format_field(field);
                field = next;
        }
 }
@@ -6797,7 +6783,7 @@ static void free_formats(struct format *format)
        free_format_fields(format->fields);
 }
 
-void pevent_free_format(struct event_format *event)
+void tep_free_format(struct event_format *event)
 {
        free(event->name);
        free(event->system);
@@ -6811,15 +6797,15 @@ void pevent_free_format(struct event_format *event)
 }
 
 /**
- * pevent_free - free a pevent handle
+ * tep_free - free a pevent handle
  * @pevent: the pevent handle to free
  */
-void pevent_free(struct pevent *pevent)
+void tep_free(struct tep_handle *pevent)
 {
        struct cmdline_list *cmdlist, *cmdnext;
        struct func_list *funclist, *funcnext;
        struct printk_list *printklist, *printknext;
-       struct pevent_function_handler *func_handler;
+       struct tep_function_handler *func_handler;
        struct event_handler *handle;
        int i;
 
@@ -6883,7 +6869,7 @@ void pevent_free(struct pevent *pevent)
        }
 
        for (i = 0; i < pevent->nr_events; i++)
-               pevent_free_format(pevent->events[i]);
+               tep_free_format(pevent->events[i]);
 
        while (pevent->handlers) {
                handle = pevent->handlers;
@@ -6899,7 +6885,7 @@ void pevent_free(struct pevent *pevent)
        free(pevent);
 }
 
-void pevent_unref(struct pevent *pevent)
+void tep_unref(struct tep_handle *pevent)
 {
-       pevent_free(pevent);
+       tep_free(pevent);
 }
index 0c03538..44b7c2d 100644 (file)
@@ -41,7 +41,7 @@
 #define DEBUG_RECORD 0
 #endif
 
-struct pevent_record {
+struct tep_record {
        unsigned long long      ts;
        unsigned long long      offset;
        long long               missed_events;  /* buffer dropped events before */
@@ -53,8 +53,8 @@ struct pevent_record {
        int                     locked;         /* Do not free, even if ref_count is zero */
        void                    *priv;
 #if DEBUG_RECORD
-       struct pevent_record    *prev;
-       struct pevent_record    *next;
+       struct tep_record       *prev;
+       struct tep_record       *next;
        long                    alloc_addr;
 #endif
 };
@@ -98,19 +98,19 @@ extern int trace_seq_do_printf(struct trace_seq *s);
 
 /* ----------------------- pevent ----------------------- */
 
-struct pevent;
+struct tep_handle;
 struct event_format;
 
-typedef int (*pevent_event_handler_func)(struct trace_seq *s,
-                                        struct pevent_record *record,
-                                        struct event_format *event,
-                                        void *context);
+typedef int (*tep_event_handler_func)(struct trace_seq *s,
+                                     struct tep_record *record,
+                                     struct event_format *event,
+                                     void *context);
 
-typedef int (*pevent_plugin_load_func)(struct pevent *pevent);
-typedef int (*pevent_plugin_unload_func)(struct pevent *pevent);
+typedef int (*tep_plugin_load_func)(struct tep_handle *pevent);
+typedef int (*tep_plugin_unload_func)(struct tep_handle *pevent);
 
-struct pevent_plugin_option {
-       struct pevent_plugin_option     *next;
+struct tep_plugin_option {
+       struct tep_plugin_option        *next;
        void                            *handle;
        char                            *file;
        char                            *name;
@@ -124,20 +124,20 @@ struct pevent_plugin_option {
 /*
  * Plugin hooks that can be called:
  *
- * PEVENT_PLUGIN_LOADER:  (required)
+ * TEP_PLUGIN_LOADER:  (required)
  *   The function name to initialized the plugin.
  *
- *   int PEVENT_PLUGIN_LOADER(struct pevent *pevent)
+ *   int TEP_PLUGIN_LOADER(struct tep_handle *pevent)
  *
- * PEVENT_PLUGIN_UNLOADER:  (optional)
+ * TEP_PLUGIN_UNLOADER:  (optional)
  *   The function called just before unloading
  *
- *   int PEVENT_PLUGIN_UNLOADER(struct pevent *pevent)
+ *   int TEP_PLUGIN_UNLOADER(struct tep_handle *pevent)
  *
- * PEVENT_PLUGIN_OPTIONS:  (optional)
+ * TEP_PLUGIN_OPTIONS:  (optional)
  *   Plugin options that can be set before loading
  *
- *   struct pevent_plugin_option PEVENT_PLUGIN_OPTIONS[] = {
+ *   struct tep_plugin_option TEP_PLUGIN_OPTIONS[] = {
  *     {
  *             .name = "option-name",
  *             .plugin_alias = "override-file-name", (optional)
@@ -158,19 +158,19 @@ struct pevent_plugin_option {
  *   .set will be processed. If .value is defined, then it is considered
  *   a string option and .set will be ignored.
  *
- * PEVENT_PLUGIN_ALIAS: (optional)
+ * TEP_PLUGIN_ALIAS: (optional)
  *   The name to use for finding options (uses filename if not defined)
  */
-#define PEVENT_PLUGIN_LOADER pevent_plugin_loader
-#define PEVENT_PLUGIN_UNLOADER pevent_plugin_unloader
-#define PEVENT_PLUGIN_OPTIONS pevent_plugin_options
-#define PEVENT_PLUGIN_ALIAS pevent_plugin_alias
+#define TEP_PLUGIN_LOADER tep_plugin_loader
+#define TEP_PLUGIN_UNLOADER tep_plugin_unloader
+#define TEP_PLUGIN_OPTIONS tep_plugin_options
+#define TEP_PLUGIN_ALIAS tep_plugin_alias
 #define _MAKE_STR(x)   #x
 #define MAKE_STR(x)    _MAKE_STR(x)
-#define PEVENT_PLUGIN_LOADER_NAME MAKE_STR(PEVENT_PLUGIN_LOADER)
-#define PEVENT_PLUGIN_UNLOADER_NAME MAKE_STR(PEVENT_PLUGIN_UNLOADER)
-#define PEVENT_PLUGIN_OPTIONS_NAME MAKE_STR(PEVENT_PLUGIN_OPTIONS)
-#define PEVENT_PLUGIN_ALIAS_NAME MAKE_STR(PEVENT_PLUGIN_ALIAS)
+#define TEP_PLUGIN_LOADER_NAME MAKE_STR(TEP_PLUGIN_LOADER)
+#define TEP_PLUGIN_UNLOADER_NAME MAKE_STR(TEP_PLUGIN_UNLOADER)
+#define TEP_PLUGIN_OPTIONS_NAME MAKE_STR(TEP_PLUGIN_OPTIONS)
+#define TEP_PLUGIN_ALIAS_NAME MAKE_STR(TEP_PLUGIN_ALIAS)
 
 enum format_flags {
        FIELD_IS_ARRAY          = 1,
@@ -269,10 +269,10 @@ struct print_arg_op {
        struct print_arg        *right;
 };
 
-struct pevent_function_handler;
+struct tep_function_handler;
 
 struct print_arg_func {
-       struct pevent_function_handler  *func;
+       struct tep_function_handler     *func;
        struct print_arg                *args;
 };
 
@@ -320,14 +320,14 @@ struct print_fmt {
 };
 
 struct event_format {
-       struct pevent           *pevent;
+       struct tep_handle       *pevent;
        char                    *name;
        int                     id;
        int                     flags;
        struct format           format;
        struct print_fmt        print_fmt;
        char                    *system;
-       pevent_event_handler_func handler;
+       tep_event_handler_func  handler;
        void                    *context;
 };
 
@@ -361,25 +361,25 @@ enum event_type {
        EVENT_SQUOTE,
 };
 
-typedef unsigned long long (*pevent_func_handler)(struct trace_seq *s,
-                                            unsigned long long *args);
+typedef unsigned long long (*tep_func_handler)(struct trace_seq *s,
+                                              unsigned long long *args);
 
-enum pevent_func_arg_type {
-       PEVENT_FUNC_ARG_VOID,
-       PEVENT_FUNC_ARG_INT,
-       PEVENT_FUNC_ARG_LONG,
-       PEVENT_FUNC_ARG_STRING,
-       PEVENT_FUNC_ARG_PTR,
-       PEVENT_FUNC_ARG_MAX_TYPES
+enum tep_func_arg_type {
+       TEP_FUNC_ARG_VOID,
+       TEP_FUNC_ARG_INT,
+       TEP_FUNC_ARG_LONG,
+       TEP_FUNC_ARG_STRING,
+       TEP_FUNC_ARG_PTR,
+       TEP_FUNC_ARG_MAX_TYPES
 };
 
-enum pevent_flag {
-       PEVENT_NSEC_OUTPUT              = 1,    /* output in NSECS */
-       PEVENT_DISABLE_SYS_PLUGINS      = 1 << 1,
-       PEVENT_DISABLE_PLUGINS          = 1 << 2,
+enum tep_flag {
+       TEP_NSEC_OUTPUT         = 1,    /* output in NSECS */
+       TEP_DISABLE_SYS_PLUGINS = 1 << 1,
+       TEP_DISABLE_PLUGINS     = 1 << 2,
 };
 
-#define PEVENT_ERRORS                                                        \
+#define TEP_ERRORS                                                           \
        _PE(MEM_ALLOC_FAILED,   "failed to allocate memory"),                 \
        _PE(PARSE_EVENT_FAILED, "failed to parse event"),                     \
        _PE(READ_ID_FAILED,     "failed to read event id"),                   \
@@ -411,10 +411,10 @@ enum pevent_flag {
        _PE(FILTER_MISS,        "record does not match to filter")
 
 #undef _PE
-#define _PE(__code, __str) PEVENT_ERRNO__ ## __code
-enum pevent_errno {
-       PEVENT_ERRNO__SUCCESS                   = 0,
-       PEVENT_ERRNO__FILTER_MATCH              = PEVENT_ERRNO__SUCCESS,
+#define _PE(__code, __str) TEP_ERRNO__ ## __code
+enum tep_errno {
+       TEP_ERRNO__SUCCESS                      = 0,
+       TEP_ERRNO__FILTER_MATCH                 = TEP_ERRNO__SUCCESS,
 
        /*
         * Choose an arbitrary negative big number not to clash with standard
@@ -423,11 +423,11 @@ enum pevent_errno {
         *
         * http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/errno.h.html
         */
-       __PEVENT_ERRNO__START                   = -100000,
+       __TEP_ERRNO__START                      = -100000,
 
-       PEVENT_ERRORS,
+       TEP_ERRORS,
 
-       __PEVENT_ERRNO__END,
+       __TEP_ERRNO__END,
 };
 #undef _PE
 
@@ -435,17 +435,17 @@ struct plugin_list;
 
 #define INVALID_PLUGIN_LIST_OPTION     ((char **)((unsigned long)-1))
 
-struct plugin_list *traceevent_load_plugins(struct pevent *pevent);
-void traceevent_unload_plugins(struct plugin_list *plugin_list,
-                              struct pevent *pevent);
-char **traceevent_plugin_list_options(void);
-void traceevent_plugin_free_options_list(char **list);
-int traceevent_plugin_add_options(const char *name,
-                                 struct pevent_plugin_option *options);
-void traceevent_plugin_remove_options(struct pevent_plugin_option *options);
-void traceevent_print_plugins(struct trace_seq *s,
-                             const char *prefix, const char *suffix,
-                             const struct plugin_list *list);
+struct plugin_list *tep_load_plugins(struct tep_handle *pevent);
+void tep_unload_plugins(struct plugin_list *plugin_list,
+                       struct tep_handle *pevent);
+char **tep_plugin_list_options(void);
+void tep_plugin_free_options_list(char **list);
+int tep_plugin_add_options(const char *name,
+                          struct tep_plugin_option *options);
+void tep_plugin_remove_options(struct tep_plugin_option *options);
+void tep_print_plugins(struct trace_seq *s,
+                       const char *prefix, const char *suffix,
+                       const struct plugin_list *list);
 
 struct cmdline;
 struct cmdline_list;
@@ -454,10 +454,10 @@ struct func_list;
 struct event_handler;
 struct func_resolver;
 
-typedef char *(pevent_func_resolver_t)(void *priv,
-                                      unsigned long long *addrp, char **modp);
+typedef char *(tep_func_resolver_t)(void *priv,
+                                   unsigned long long *addrp, char **modp);
 
-struct pevent {
+struct tep_handle {
        int ref_count;
 
        int header_page_ts_offset;
@@ -524,7 +524,7 @@ struct pevent {
        struct format_field *bprint_buf_field;
 
        struct event_handler *handlers;
-       struct pevent_function_handler *func_handlers;
+       struct tep_function_handler *func_handlers;
 
        /* cache */
        struct event_format *last_event;
@@ -532,13 +532,13 @@ struct pevent {
        char *trace_clock;
 };
 
-static inline void pevent_set_flag(struct pevent *pevent, int flag)
+static inline void tep_set_flag(struct tep_handle *pevent, int flag)
 {
        pevent->flags |= flag;
 }
 
 static inline unsigned short
-__data2host2(struct pevent *pevent, unsigned short data)
+__data2host2(struct tep_handle *pevent, unsigned short data)
 {
        unsigned short swap;
 
@@ -552,7 +552,7 @@ __data2host2(struct pevent *pevent, unsigned short data)
 }
 
 static inline unsigned int
-__data2host4(struct pevent *pevent, unsigned int data)
+__data2host4(struct tep_handle *pevent, unsigned int data)
 {
        unsigned int swap;
 
@@ -568,7 +568,7 @@ __data2host4(struct pevent *pevent, unsigned int data)
 }
 
 static inline unsigned long long
-__data2host8(struct pevent *pevent, unsigned long long data)
+__data2host8(struct tep_handle *pevent, unsigned long long data)
 {
        unsigned long long swap;
 
@@ -597,7 +597,7 @@ __data2host8(struct pevent *pevent, unsigned long long data)
        __data2host8(pevent, __val);                            \
 })
 
-static inline int traceevent_host_bigendian(void)
+static inline int tep_host_bigendian(void)
 {
        unsigned char str[] = { 0x1, 0x2, 0x3, 0x4 };
        unsigned int val;
@@ -615,198 +615,198 @@ enum trace_flag_type {
        TRACE_FLAG_SOFTIRQ              = 0x10,
 };
 
-int pevent_set_function_resolver(struct pevent *pevent,
-                                pevent_func_resolver_t *func, void *priv);
-void pevent_reset_function_resolver(struct pevent *pevent);
-int pevent_register_comm(struct pevent *pevent, const char *comm, int pid);
-int pevent_register_trace_clock(struct pevent *pevent, const char *trace_clock);
-int pevent_register_function(struct pevent *pevent, char *name,
-                            unsigned long long addr, char *mod);
-int pevent_register_print_string(struct pevent *pevent, const char *fmt,
-                                unsigned long long addr);
-int pevent_pid_is_registered(struct pevent *pevent, int pid);
-
-void pevent_print_event_task(struct pevent *pevent, struct trace_seq *s,
-                            struct event_format *event,
-                            struct pevent_record *record);
-void pevent_print_event_time(struct pevent *pevent, struct trace_seq *s,
-                            struct event_format *event,
-                            struct pevent_record *record,
-                            bool use_trace_clock);
-void pevent_print_event_data(struct pevent *pevent, struct trace_seq *s,
-                            struct event_format *event,
-                            struct pevent_record *record);
-void pevent_print_event(struct pevent *pevent, struct trace_seq *s,
-                       struct pevent_record *record, bool use_trace_clock);
-
-int pevent_parse_header_page(struct pevent *pevent, char *buf, unsigned long size,
-                            int long_size);
-
-enum pevent_errno pevent_parse_event(struct pevent *pevent, const char *buf,
-                                    unsigned long size, const char *sys);
-enum pevent_errno pevent_parse_format(struct pevent *pevent,
-                                     struct event_format **eventp,
-                                     const char *buf,
-                                     unsigned long size, const char *sys);
-void pevent_free_format(struct event_format *event);
-void pevent_free_format_field(struct format_field *field);
-
-void *pevent_get_field_raw(struct trace_seq *s, struct event_format *event,
-                          const char *name, struct pevent_record *record,
-                          int *len, int err);
-
-int pevent_get_field_val(struct trace_seq *s, struct event_format *event,
-                        const char *name, struct pevent_record *record,
-                        unsigned long long *val, int err);
-int pevent_get_common_field_val(struct trace_seq *s, struct event_format *event,
-                               const char *name, struct pevent_record *record,
-                               unsigned long long *val, int err);
-int pevent_get_any_field_val(struct trace_seq *s, struct event_format *event,
-                            const char *name, struct pevent_record *record,
+int tep_set_function_resolver(struct tep_handle *pevent,
+                             tep_func_resolver_t *func, void *priv);
+void tep_reset_function_resolver(struct tep_handle *pevent);
+int tep_register_comm(struct tep_handle *pevent, const char *comm, int pid);
+int tep_register_trace_clock(struct tep_handle *pevent, const char *trace_clock);
+int tep_register_function(struct tep_handle *pevent, char *name,
+                         unsigned long long addr, char *mod);
+int tep_register_print_string(struct tep_handle *pevent, const char *fmt,
+                             unsigned long long addr);
+int tep_pid_is_registered(struct tep_handle *pevent, int pid);
+
+void tep_print_event_task(struct tep_handle *pevent, struct trace_seq *s,
+                         struct event_format *event,
+                         struct tep_record *record);
+void tep_print_event_time(struct tep_handle *pevent, struct trace_seq *s,
+                         struct event_format *event,
+                         struct tep_record *record,
+                         bool use_trace_clock);
+void tep_print_event_data(struct tep_handle *pevent, struct trace_seq *s,
+                         struct event_format *event,
+                         struct tep_record *record);
+void tep_print_event(struct tep_handle *pevent, struct trace_seq *s,
+                    struct tep_record *record, bool use_trace_clock);
+
+int tep_parse_header_page(struct tep_handle *pevent, char *buf, unsigned long size,
+                         int long_size);
+
+enum tep_errno tep_parse_event(struct tep_handle *pevent, const char *buf,
+                              unsigned long size, const char *sys);
+enum tep_errno tep_parse_format(struct tep_handle *pevent,
+                               struct event_format **eventp,
+                               const char *buf,
+                               unsigned long size, const char *sys);
+void tep_free_format(struct event_format *event);
+void tep_free_format_field(struct format_field *field);
+
+void *tep_get_field_raw(struct trace_seq *s, struct event_format *event,
+                       const char *name, struct tep_record *record,
+                       int *len, int err);
+
+int tep_get_field_val(struct trace_seq *s, struct event_format *event,
+                     const char *name, struct tep_record *record,
+                     unsigned long long *val, int err);
+int tep_get_common_field_val(struct trace_seq *s, struct event_format *event,
+                            const char *name, struct tep_record *record,
                             unsigned long long *val, int err);
+int tep_get_any_field_val(struct trace_seq *s, struct event_format *event,
+                         const char *name, struct tep_record *record,
+                         unsigned long long *val, int err);
 
-int pevent_print_num_field(struct trace_seq *s, const char *fmt,
+int tep_print_num_field(struct trace_seq *s, const char *fmt,
                           struct event_format *event, const char *name,
-                          struct pevent_record *record, int err);
-
-int pevent_print_func_field(struct trace_seq *s, const char *fmt,
-                          struct event_format *event, const char *name,
-                          struct pevent_record *record, int err);
-
-int pevent_register_event_handler(struct pevent *pevent, int id,
-                                 const char *sys_name, const char *event_name,
-                                 pevent_event_handler_func func, void *context);
-int pevent_unregister_event_handler(struct pevent *pevent, int id,
-                                   const char *sys_name, const char *event_name,
-                                   pevent_event_handler_func func, void *context);
-int pevent_register_print_function(struct pevent *pevent,
-                                  pevent_func_handler func,
-                                  enum pevent_func_arg_type ret_type,
-                                  char *name, ...);
-int pevent_unregister_print_function(struct pevent *pevent,
-                                    pevent_func_handler func, char *name);
-
-struct format_field *pevent_find_common_field(struct event_format *event, const char *name);
-struct format_field *pevent_find_field(struct event_format *event, const char *name);
-struct format_field *pevent_find_any_field(struct event_format *event, const char *name);
-
-const char *pevent_find_function(struct pevent *pevent, unsigned long long addr);
+                          struct tep_record *record, int err);
+
+int tep_print_func_field(struct trace_seq *s, const char *fmt,
+                        struct event_format *event, const char *name,
+                        struct tep_record *record, int err);
+
+int tep_register_event_handler(struct tep_handle *pevent, int id,
+                              const char *sys_name, const char *event_name,
+                              tep_event_handler_func func, void *context);
+int tep_unregister_event_handler(struct tep_handle *pevent, int id,
+                                const char *sys_name, const char *event_name,
+                                tep_event_handler_func func, void *context);
+int tep_register_print_function(struct tep_handle *pevent,
+                               tep_func_handler func,
+                               enum tep_func_arg_type ret_type,
+                               char *name, ...);
+int tep_unregister_print_function(struct tep_handle *pevent,
+                                 tep_func_handler func, char *name);
+
+struct format_field *tep_find_common_field(struct event_format *event, const char *name);
+struct format_field *tep_find_field(struct event_format *event, const char *name);
+struct format_field *tep_find_any_field(struct event_format *event, const char *name);
+
+const char *tep_find_function(struct tep_handle *pevent, unsigned long long addr);
 unsigned long long
-pevent_find_function_address(struct pevent *pevent, unsigned long long addr);
-unsigned long long pevent_read_number(struct pevent *pevent, const void *ptr, int size);
-int pevent_read_number_field(struct format_field *field, const void *data,
-                            unsigned long long *value);
+tep_find_function_address(struct tep_handle *pevent, unsigned long long addr);
+unsigned long long tep_read_number(struct tep_handle *pevent, const void *ptr, int size);
+int tep_read_number_field(struct format_field *field, const void *data,
+                         unsigned long long *value);
 
-struct event_format *pevent_find_event(struct pevent *pevent, int id);
+struct event_format *tep_find_event(struct tep_handle *pevent, int id);
 
 struct event_format *
-pevent_find_event_by_name(struct pevent *pevent, const char *sys, const char *name);
+tep_find_event_by_name(struct tep_handle *pevent, const char *sys, const char *name);
 
 struct event_format *
-pevent_find_event_by_record(struct pevent *pevent, struct pevent_record *record);
-
-void pevent_data_lat_fmt(struct pevent *pevent,
-                        struct trace_seq *s, struct pevent_record *record);
-int pevent_data_type(struct pevent *pevent, struct pevent_record *rec);
-struct event_format *pevent_data_event_from_type(struct pevent *pevent, int type);
-int pevent_data_pid(struct pevent *pevent, struct pevent_record *rec);
-int pevent_data_preempt_count(struct pevent *pevent, struct pevent_record *rec);
-int pevent_data_flags(struct pevent *pevent, struct pevent_record *rec);
-const char *pevent_data_comm_from_pid(struct pevent *pevent, int pid);
+tep_find_event_by_record(struct tep_handle *pevent, struct tep_record *record);
+
+void tep_data_lat_fmt(struct tep_handle *pevent,
+                     struct trace_seq *s, struct tep_record *record);
+int tep_data_type(struct tep_handle *pevent, struct tep_record *rec);
+struct event_format *tep_data_event_from_type(struct tep_handle *pevent, int type);
+int tep_data_pid(struct tep_handle *pevent, struct tep_record *rec);
+int tep_data_preempt_count(struct tep_handle *pevent, struct tep_record *rec);
+int tep_data_flags(struct tep_handle *pevent, struct tep_record *rec);
+const char *tep_data_comm_from_pid(struct tep_handle *pevent, int pid);
 struct cmdline;
-struct cmdline *pevent_data_pid_from_comm(struct pevent *pevent, const char *comm,
-                                         struct cmdline *next);
-int pevent_cmdline_pid(struct pevent *pevent, struct cmdline *cmdline);
-
-void pevent_print_field(struct trace_seq *s, void *data,
-                       struct format_field *field);
-void pevent_print_fields(struct trace_seq *s, void *data,
-                        int size __maybe_unused, struct event_format *event);
-void pevent_event_info(struct trace_seq *s, struct event_format *event,
-                      struct pevent_record *record);
-int pevent_strerror(struct pevent *pevent, enum pevent_errno errnum,
+struct cmdline *tep_data_pid_from_comm(struct tep_handle *pevent, const char *comm,
+                                      struct cmdline *next);
+int tep_cmdline_pid(struct tep_handle *pevent, struct cmdline *cmdline);
+
+void tep_print_field(struct trace_seq *s, void *data,
+                    struct format_field *field);
+void tep_print_fields(struct trace_seq *s, void *data,
+                     int size __maybe_unused, struct event_format *event);
+void tep_event_info(struct trace_seq *s, struct event_format *event,
+                      struct tep_record *record);
+int tep_strerror(struct tep_handle *pevent, enum tep_errno errnum,
                    char *buf, size_t buflen);
 
-struct event_format **pevent_list_events(struct pevent *pevent, enum event_sort_type);
-struct format_field **pevent_event_common_fields(struct event_format *event);
-struct format_field **pevent_event_fields(struct event_format *event);
+struct event_format **tep_list_events(struct tep_handle *pevent, enum event_sort_type);
+struct format_field **tep_event_common_fields(struct event_format *event);
+struct format_field **tep_event_fields(struct event_format *event);
 
-static inline int pevent_get_cpus(struct pevent *pevent)
+static inline int tep_get_cpus(struct tep_handle *pevent)
 {
        return pevent->cpus;
 }
 
-static inline void pevent_set_cpus(struct pevent *pevent, int cpus)
+static inline void tep_set_cpus(struct tep_handle *pevent, int cpus)
 {
        pevent->cpus = cpus;
 }
 
-static inline int pevent_get_long_size(struct pevent *pevent)
+static inline int tep_get_long_size(struct tep_handle *pevent)
 {
        return pevent->long_size;
 }
 
-static inline void pevent_set_long_size(struct pevent *pevent, int long_size)
+static inline void tep_set_long_size(struct tep_handle *pevent, int long_size)
 {
        pevent->long_size = long_size;
 }
 
-static inline int pevent_get_page_size(struct pevent *pevent)
+static inline int tep_get_page_size(struct tep_handle *pevent)
 {
        return pevent->page_size;
 }
 
-static inline void pevent_set_page_size(struct pevent *pevent, int _page_size)
+static inline void tep_set_page_size(struct tep_handle *pevent, int _page_size)
 {
        pevent->page_size = _page_size;
 }
 
-static inline int pevent_is_file_bigendian(struct pevent *pevent)
+static inline int tep_is_file_bigendian(struct tep_handle *pevent)
 {
        return pevent->file_bigendian;
 }
 
-static inline void pevent_set_file_bigendian(struct pevent *pevent, int endian)
+static inline void tep_set_file_bigendian(struct tep_handle *pevent, int endian)
 {
        pevent->file_bigendian = endian;
 }
 
-static inline int pevent_is_host_bigendian(struct pevent *pevent)
+static inline int tep_is_host_bigendian(struct tep_handle *pevent)
 {
        return pevent->host_bigendian;
 }
 
-static inline void pevent_set_host_bigendian(struct pevent *pevent, int endian)
+static inline void tep_set_host_bigendian(struct tep_handle *pevent, int endian)
 {
        pevent->host_bigendian = endian;
 }
 
-static inline int pevent_is_latency_format(struct pevent *pevent)
+static inline int tep_is_latency_format(struct tep_handle *pevent)
 {
        return pevent->latency_format;
 }
 
-static inline void pevent_set_latency_format(struct pevent *pevent, int lat)
+static inline void tep_set_latency_format(struct tep_handle *pevent, int lat)
 {
        pevent->latency_format = lat;
 }
 
-struct pevent *pevent_alloc(void);
-void pevent_free(struct pevent *pevent);
-void pevent_ref(struct pevent *pevent);
-void pevent_unref(struct pevent *pevent);
+struct tep_handle *tep_alloc(void);
+void tep_free(struct tep_handle *pevent);
+void tep_ref(struct tep_handle *pevent);
+void tep_unref(struct tep_handle *pevent);
 
 /* access to the internal parser */
-void pevent_buffer_init(const char *buf, unsigned long long size);
-enum event_type pevent_read_token(char **tok);
-void pevent_free_token(char *token);
-int pevent_peek_char(void);
-const char *pevent_get_input_buf(void);
-unsigned long long pevent_get_input_buf_ptr(void);
+void tep_buffer_init(const char *buf, unsigned long long size);
+enum event_type tep_read_token(char **tok);
+void tep_free_token(char *token);
+int tep_peek_char(void);
+const char *tep_get_input_buf(void);
+unsigned long long tep_get_input_buf_ptr(void);
 
 /* for debugging */
-void pevent_print_funcs(struct pevent *pevent);
-void pevent_print_printk(struct pevent *pevent);
+void tep_print_funcs(struct tep_handle *pevent);
+void tep_print_printk(struct tep_handle *pevent);
 
 /* ----------------------- filtering ----------------------- */
 
@@ -930,22 +930,22 @@ struct filter_type {
        struct filter_arg       *filter;
 };
 
-#define PEVENT_FILTER_ERROR_BUFSZ  1024
+#define TEP_FILTER_ERROR_BUFSZ  1024
 
 struct event_filter {
-       struct pevent           *pevent;
+       struct tep_handle       *pevent;
        int                     filters;
        struct filter_type      *event_filters;
-       char                    error_buffer[PEVENT_FILTER_ERROR_BUFSZ];
+       char                    error_buffer[TEP_FILTER_ERROR_BUFSZ];
 };
 
-struct event_filter *pevent_filter_alloc(struct pevent *pevent);
+struct event_filter *tep_filter_alloc(struct tep_handle *pevent);
 
 /* for backward compatibility */
-#define FILTER_NONE            PEVENT_ERRNO__NO_FILTER
-#define FILTER_NOEXIST         PEVENT_ERRNO__FILTER_NOT_FOUND
-#define FILTER_MISS            PEVENT_ERRNO__FILTER_MISS
-#define FILTER_MATCH           PEVENT_ERRNO__FILTER_MATCH
+#define FILTER_NONE            TEP_ERRNO__NO_FILTER
+#define FILTER_NOEXIST         TEP_ERRNO__FILTER_NOT_FOUND
+#define FILTER_MISS            TEP_ERRNO__FILTER_MISS
+#define FILTER_MATCH           TEP_ERRNO__FILTER_MATCH
 
 enum filter_trivial_type {
        FILTER_TRIVIAL_FALSE,
@@ -953,39 +953,39 @@ enum filter_trivial_type {
        FILTER_TRIVIAL_BOTH,
 };
 
-enum pevent_errno pevent_filter_add_filter_str(struct event_filter *filter,
-                                              const char *filter_str);
+enum tep_errno tep_filter_add_filter_str(struct event_filter *filter,
+                                        const char *filter_str);
 
-enum pevent_errno pevent_filter_match(struct event_filter *filter,
-                                     struct pevent_record *record);
+enum tep_errno tep_filter_match(struct event_filter *filter,
+                               struct tep_record *record);
 
-int pevent_filter_strerror(struct event_filter *filter, enum pevent_errno err,
-                          char *buf, size_t buflen);
+int tep_filter_strerror(struct event_filter *filter, enum tep_errno err,
+                       char *buf, size_t buflen);
 
-int pevent_event_filtered(struct event_filter *filter,
-                         int event_id);
+int tep_event_filtered(struct event_filter *filter,
+                      int event_id);
 
-void pevent_filter_reset(struct event_filter *filter);
+void tep_filter_reset(struct event_filter *filter);
 
-int pevent_filter_clear_trivial(struct event_filter *filter,
-                                enum filter_trivial_type type);
+int tep_filter_clear_trivial(struct event_filter *filter,
+                            enum filter_trivial_type type);
 
-void pevent_filter_free(struct event_filter *filter);
+void tep_filter_free(struct event_filter *filter);
 
-char *pevent_filter_make_string(struct event_filter *filter, int event_id);
+char *tep_filter_make_string(struct event_filter *filter, int event_id);
 
-int pevent_filter_remove_event(struct event_filter *filter,
-                              int event_id);
+int tep_filter_remove_event(struct event_filter *filter,
+                           int event_id);
 
-int pevent_filter_event_has_trivial(struct event_filter *filter,
-                                   int event_id,
-                                   enum filter_trivial_type type);
+int tep_filter_event_has_trivial(struct event_filter *filter,
+                                int event_id,
+                                enum filter_trivial_type type);
 
-int pevent_filter_copy(struct event_filter *dest, struct event_filter *source);
+int tep_filter_copy(struct event_filter *dest, struct event_filter *source);
 
-int pevent_update_trivial(struct event_filter *dest, struct event_filter *source,
-                         enum filter_trivial_type type);
+int tep_update_trivial(struct event_filter *dest, struct event_filter *source,
+                       enum filter_trivial_type type);
 
-int pevent_filter_compare(struct event_filter *filter1, struct event_filter *filter2);
+int tep_filter_compare(struct event_filter *filter1, struct event_filter *filter2);
 
 #endif /* _PARSE_EVENTS_H */
index d542cb6..f17e250 100644 (file)
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: LGPL-2.1
 /*
  * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
  *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License (not later!)
- *
- * 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not,  see <http://www.gnu.org/licenses>
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  */
 
 #include <ctype.h>
@@ -34,7 +20,7 @@
 
 static struct registered_plugin_options {
        struct registered_plugin_options        *next;
-       struct pevent_plugin_option             *options;
+       struct tep_plugin_option                *options;
 } *registered_options;
 
 static struct trace_plugin_options {
@@ -58,7 +44,7 @@ static void lower_case(char *str)
                *str = tolower(*str);
 }
 
-static int update_option_value(struct pevent_plugin_option *op, const char *val)
+static int update_option_value(struct tep_plugin_option *op, const char *val)
 {
        char *op_val;
 
@@ -97,7 +83,7 @@ static int update_option_value(struct pevent_plugin_option *op, const char *val)
 }
 
 /**
- * traceevent_plugin_list_options - get list of plugin options
+ * tep_plugin_list_options - get list of plugin options
  *
  * Returns an array of char strings that list the currently registered
  * plugin options in the format of <plugin>:<option>. This list can be
@@ -106,12 +92,12 @@ static int update_option_value(struct pevent_plugin_option *op, const char *val)
  * Returns NULL if there's no options registered. On error it returns
  * INVALID_PLUGIN_LIST_OPTION
  *
- * Must be freed with traceevent_plugin_free_options_list().
+ * Must be freed with tep_plugin_free_options_list().
  */
-char **traceevent_plugin_list_options(void)
+char **tep_plugin_list_options(void)
 {
        struct registered_plugin_options *reg;
-       struct pevent_plugin_option *op;
+       struct tep_plugin_option *op;
        char **list = NULL;
        char *name;
        int count = 0;
@@ -146,7 +132,7 @@ char **traceevent_plugin_list_options(void)
        return INVALID_PLUGIN_LIST_OPTION;
 }
 
-void traceevent_plugin_free_options_list(char **list)
+void tep_plugin_free_options_list(char **list)
 {
        int i;
 
@@ -163,7 +149,7 @@ void traceevent_plugin_free_options_list(char **list)
 }
 
 static int
-update_option(const char *file, struct pevent_plugin_option *option)
+update_option(const char *file, struct tep_plugin_option *option)
 {
        struct trace_plugin_options *op;
        char *plugin;
@@ -215,14 +201,14 @@ update_option(const char *file, struct pevent_plugin_option *option)
 }
 
 /**
- * traceevent_plugin_add_options - Add a set of options by a plugin
+ * tep_plugin_add_options - Add a set of options by a plugin
  * @name: The name of the plugin adding the options
  * @options: The set of options being loaded
  *
  * Sets the options with the values that have been added by user.
  */
-int traceevent_plugin_add_options(const char *name,
-                                 struct pevent_plugin_option *options)
+int tep_plugin_add_options(const char *name,
+                          struct tep_plugin_option *options)
 {
        struct registered_plugin_options *reg;
 
@@ -241,10 +227,10 @@ int traceevent_plugin_add_options(const char *name,
 }
 
 /**
- * traceevent_plugin_remove_options - remove plugin options that were registered
- * @options: Options to removed that were registered with traceevent_plugin_add_options
+ * tep_plugin_remove_options - remove plugin options that were registered
+ * @options: Options to removed that were registered with tep_plugin_add_options
  */
-void traceevent_plugin_remove_options(struct pevent_plugin_option *options)
+void tep_plugin_remove_options(struct tep_plugin_option *options)
 {
        struct registered_plugin_options **last;
        struct registered_plugin_options *reg;
@@ -260,19 +246,19 @@ void traceevent_plugin_remove_options(struct pevent_plugin_option *options)
 }
 
 /**
- * traceevent_print_plugins - print out the list of plugins loaded
+ * tep_print_plugins - print out the list of plugins loaded
  * @s: the trace_seq descripter to write to
  * @prefix: The prefix string to add before listing the option name
  * @suffix: The suffix string ot append after the option name
- * @list: The list of plugins (usually returned by traceevent_load_plugins()
+ * @list: The list of plugins (usually returned by tep_load_plugins()
  *
  * Writes to the trace_seq @s the list of plugins (files) that is
- * returned by traceevent_load_plugins(). Use @prefix and @suffix for formating:
+ * returned by tep_load_plugins(). Use @prefix and @suffix for formating:
  * @prefix = "  ", @suffix = "\n".
  */
-void traceevent_print_plugins(struct trace_seq *s,
-                             const char *prefix, const char *suffix,
-                             const struct plugin_list *list)
+void tep_print_plugins(struct trace_seq *s,
+                      const char *prefix, const char *suffix,
+                      const struct plugin_list *list)
 {
        while (list) {
                trace_seq_printf(s, "%s%s%s", prefix, list->name, suffix);
@@ -281,11 +267,11 @@ void traceevent_print_plugins(struct trace_seq *s,
 }
 
 static void
-load_plugin(struct pevent *pevent, const char *path,
+load_plugin(struct tep_handle *pevent, const char *path,
            const char *file, void *data)
 {
        struct plugin_list **plugin_list = data;
-       pevent_plugin_load_func func;
+       tep_plugin_load_func func;
        struct plugin_list *list;
        const char *alias;
        char *plugin;
@@ -305,14 +291,14 @@ load_plugin(struct pevent *pevent, const char *path,
                goto out_free;
        }
 
-       alias = dlsym(handle, PEVENT_PLUGIN_ALIAS_NAME);
+       alias = dlsym(handle, TEP_PLUGIN_ALIAS_NAME);
        if (!alias)
                alias = file;
 
-       func = dlsym(handle, PEVENT_PLUGIN_LOADER_NAME);
+       func = dlsym(handle, TEP_PLUGIN_LOADER_NAME);
        if (!func) {
                warning("could not find func '%s' in plugin '%s'\n%s\n",
-                       PEVENT_PLUGIN_LOADER_NAME, plugin, dlerror());
+                       TEP_PLUGIN_LOADER_NAME, plugin, dlerror());
                goto out_free;
        }
 
@@ -336,9 +322,9 @@ load_plugin(struct pevent *pevent, const char *path,
 }
 
 static void
-load_plugins_dir(struct pevent *pevent, const char *suffix,
+load_plugins_dir(struct tep_handle *pevent, const char *suffix,
                 const char *path,
-                void (*load_plugin)(struct pevent *pevent,
+                void (*load_plugin)(struct tep_handle *pevent,
                                     const char *path,
                                     const char *name,
                                     void *data),
@@ -378,8 +364,8 @@ load_plugins_dir(struct pevent *pevent, const char *suffix,
 }
 
 static void
-load_plugins(struct pevent *pevent, const char *suffix,
-            void (*load_plugin)(struct pevent *pevent,
+load_plugins(struct tep_handle *pevent, const char *suffix,
+            void (*load_plugin)(struct tep_handle *pevent,
                                 const char *path,
                                 const char *name,
                                 void *data),
@@ -390,7 +376,7 @@ load_plugins(struct pevent *pevent, const char *suffix,
        char *envdir;
        int ret;
 
-       if (pevent->flags & PEVENT_DISABLE_PLUGINS)
+       if (pevent->flags & TEP_DISABLE_PLUGINS)
                return;
 
        /*
@@ -398,7 +384,7 @@ load_plugins(struct pevent *pevent, const char *suffix,
         * check that first.
         */
 #ifdef PLUGIN_DIR
-       if (!(pevent->flags & PEVENT_DISABLE_SYS_PLUGINS))
+       if (!(pevent->flags & TEP_DISABLE_SYS_PLUGINS))
                load_plugins_dir(pevent, suffix, PLUGIN_DIR,
                                 load_plugin, data);
 #endif
@@ -431,7 +417,7 @@ load_plugins(struct pevent *pevent, const char *suffix,
 }
 
 struct plugin_list*
-traceevent_load_plugins(struct pevent *pevent)
+tep_load_plugins(struct tep_handle *pevent)
 {
        struct plugin_list *list = NULL;
 
@@ -440,15 +426,15 @@ traceevent_load_plugins(struct pevent *pevent)
 }
 
 void
-traceevent_unload_plugins(struct plugin_list *plugin_list, struct pevent *pevent)
+tep_unload_plugins(struct plugin_list *plugin_list, struct tep_handle *pevent)
 {
-       pevent_plugin_unload_func func;
+       tep_plugin_unload_func func;
        struct plugin_list *list;
 
        while (plugin_list) {
                list = plugin_list;
                plugin_list = list->next;
-               func = dlsym(list->handle, PEVENT_PLUGIN_UNLOADER_NAME);
+               func = dlsym(list->handle, TEP_PLUGIN_UNLOADER_NAME);
                if (func)
                        func(pevent);
                dlclose(list->handle);
index d1dc217..0560b96 100644 (file)
@@ -1,21 +1,7 @@
+/* SPDX-License-Identifier: LGPL-2.1 */
 /*
  * Copyright (C) 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
  *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License (not later!)
- *
- * 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not,  see <http://www.gnu.org/licenses>
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  */
 #ifndef __UTIL_H
 #define __UTIL_H
index ca424b1..af2a1f3 100644 (file)
@@ -1,22 +1,7 @@
+// SPDX-License-Identifier: LGPL-2.1
 /*
  * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
  *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License (not later!)
- *
- * 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  */
 #include <stdio.h>
 #include <stdlib.h>
index 431e8b3..e76154c 100644 (file)
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: LGPL-2.1
 /*
  * Copyright (C) 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
  *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License (not later!)
- *
- * 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not,  see <http://www.gnu.org/licenses>
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  */
 #include <stdio.h>
 #include <stdlib.h>
@@ -51,8 +37,8 @@ static void show_error(char *error_buf, const char *fmt, ...)
        int len;
        int i;
 
-       input = pevent_get_input_buf();
-       index = pevent_get_input_buf_ptr();
+       input = tep_get_input_buf();
+       index = tep_get_input_buf_ptr();
        len = input ? strlen(input) : 0;
 
        if (len) {
@@ -66,13 +52,13 @@ static void show_error(char *error_buf, const char *fmt, ...)
        }
 
        va_start(ap, fmt);
-       vsnprintf(error_buf + len, PEVENT_FILTER_ERROR_BUFSZ - len, fmt, ap);
+       vsnprintf(error_buf + len, TEP_FILTER_ERROR_BUFSZ - len, fmt, ap);
        va_end(ap);
 }
 
 static void free_token(char *token)
 {
-       pevent_free_token(token);
+       tep_free_token(token);
 }
 
 static enum event_type read_token(char **tok)
@@ -82,13 +68,13 @@ static enum event_type read_token(char **tok)
 
        do {
                free_token(token);
-               type = pevent_read_token(&token);
+               type = tep_read_token(&token);
        } while (type == EVENT_NEWLINE || type == EVENT_SPACE);
 
        /* If token is = or ! check to see if the next char is ~ */
        if (token &&
            (strcmp(token, "=") == 0 || strcmp(token, "!") == 0) &&
-           pevent_peek_char() == '~') {
+           tep_peek_char() == '~') {
                /* append it */
                *tok = malloc(3);
                if (*tok == NULL) {
@@ -98,7 +84,7 @@ static enum event_type read_token(char **tok)
                sprintf(*tok, "%c%c", *token, '~');
                free_token(token);
                /* Now remove the '~' from the buffer */
-               pevent_read_token(&token);
+               tep_read_token(&token);
                free_token(token);
        } else
                *tok = token;
@@ -167,7 +153,7 @@ add_filter_type(struct event_filter *filter, int id)
 
        filter_type = &filter->event_filters[i];
        filter_type->event_id = id;
-       filter_type->event = pevent_find_event(filter->pevent, id);
+       filter_type->event = tep_find_event(filter->pevent, id);
        filter_type->filter = NULL;
 
        filter->filters++;
@@ -176,10 +162,10 @@ add_filter_type(struct event_filter *filter, int id)
 }
 
 /**
- * pevent_filter_alloc - create a new event filter
+ * tep_filter_alloc - create a new event filter
  * @pevent: The pevent that this filter is associated with
  */
-struct event_filter *pevent_filter_alloc(struct pevent *pevent)
+struct event_filter *tep_filter_alloc(struct tep_handle *pevent)
 {
        struct event_filter *filter;
 
@@ -189,7 +175,7 @@ struct event_filter *pevent_filter_alloc(struct pevent *pevent)
 
        memset(filter, 0, sizeof(*filter));
        filter->pevent = pevent;
-       pevent_ref(pevent);
+       tep_ref(pevent);
 
        return filter;
 }
@@ -268,8 +254,8 @@ static int event_match(struct event_format *event,
                !regexec(ereg, event->name, 0, NULL, 0);
 }
 
-static enum pevent_errno
-find_event(struct pevent *pevent, struct event_list **events,
+static enum tep_errno
+find_event(struct tep_handle *pevent, struct event_list **events,
           char *sys_name, char *event_name)
 {
        struct event_format *event;
@@ -289,26 +275,26 @@ find_event(struct pevent *pevent, struct event_list **events,
 
        ret = asprintf(&reg, "^%s$", event_name);
        if (ret < 0)
-               return PEVENT_ERRNO__MEM_ALLOC_FAILED;
+               return TEP_ERRNO__MEM_ALLOC_FAILED;
 
        ret = regcomp(&ereg, reg, REG_ICASE|REG_NOSUB);
        free(reg);
 
        if (ret)
-               return PEVENT_ERRNO__INVALID_EVENT_NAME;
+               return TEP_ERRNO__INVALID_EVENT_NAME;
 
        if (sys_name) {
                ret = asprintf(&reg, "^%s$", sys_name);
                if (ret < 0) {
                        regfree(&ereg);
-                       return PEVENT_ERRNO__MEM_ALLOC_FAILED;
+                       return TEP_ERRNO__MEM_ALLOC_FAILED;
                }
 
                ret = regcomp(&sreg, reg, REG_ICASE|REG_NOSUB);
                free(reg);
                if (ret) {
                        regfree(&ereg);
-                       return PEVENT_ERRNO__INVALID_EVENT_NAME;
+                       return TEP_ERRNO__INVALID_EVENT_NAME;
                }
        }
 
@@ -328,9 +314,9 @@ find_event(struct pevent *pevent, struct event_list **events,
                regfree(&sreg);
 
        if (!match)
-               return PEVENT_ERRNO__EVENT_NOT_FOUND;
+               return TEP_ERRNO__EVENT_NOT_FOUND;
        if (fail)
-               return PEVENT_ERRNO__MEM_ALLOC_FAILED;
+               return TEP_ERRNO__MEM_ALLOC_FAILED;
 
        return 0;
 }
@@ -346,7 +332,7 @@ static void free_events(struct event_list *events)
        }
 }
 
-static enum pevent_errno
+static enum tep_errno
 create_arg_item(struct event_format *event, const char *token,
                enum event_type type, struct filter_arg **parg, char *error_str)
 {
@@ -356,7 +342,7 @@ create_arg_item(struct event_format *event, const char *token,
        arg = allocate_arg();
        if (arg == NULL) {
                show_error(error_str, "failed to allocate filter arg");
-               return PEVENT_ERRNO__MEM_ALLOC_FAILED;
+               return TEP_ERRNO__MEM_ALLOC_FAILED;
        }
 
        switch (type) {
@@ -370,7 +356,7 @@ create_arg_item(struct event_format *event, const char *token,
                if (!arg->value.str) {
                        free_arg(arg);
                        show_error(error_str, "failed to allocate string filter arg");
-                       return PEVENT_ERRNO__MEM_ALLOC_FAILED;
+                       return TEP_ERRNO__MEM_ALLOC_FAILED;
                }
                break;
        case EVENT_ITEM:
@@ -382,7 +368,7 @@ create_arg_item(struct event_format *event, const char *token,
                        break;
                }
                /* Consider this a field */
-               field = pevent_find_any_field(event, token);
+               field = tep_find_any_field(event, token);
                if (!field) {
                        /* If token is 'COMM' or 'CPU' then it is special */
                        if (strcmp(token, COMM) == 0) {
@@ -402,7 +388,7 @@ create_arg_item(struct event_format *event, const char *token,
        default:
                free_arg(arg);
                show_error(error_str, "expected a value but found %s", token);
-               return PEVENT_ERRNO__UNEXPECTED_TYPE;
+               return TEP_ERRNO__UNEXPECTED_TYPE;
        }
        *parg = arg;
        return 0;
@@ -454,7 +440,7 @@ create_arg_cmp(enum filter_cmp_type ctype)
        return arg;
 }
 
-static enum pevent_errno
+static enum tep_errno
 add_right(struct filter_arg *op, struct filter_arg *arg, char *error_str)
 {
        struct filter_arg *left;
@@ -487,7 +473,7 @@ add_right(struct filter_arg *op, struct filter_arg *arg, char *error_str)
                        break;
                default:
                        show_error(error_str, "Illegal rvalue");
-                       return PEVENT_ERRNO__ILLEGAL_RVALUE;
+                       return TEP_ERRNO__ILLEGAL_RVALUE;
                }
 
                /*
@@ -534,7 +520,7 @@ add_right(struct filter_arg *op, struct filter_arg *arg, char *error_str)
                        if (left->type != FILTER_ARG_FIELD) {
                                show_error(error_str,
                                           "Illegal lvalue for string comparison");
-                               return PEVENT_ERRNO__ILLEGAL_LVALUE;
+                               return TEP_ERRNO__ILLEGAL_LVALUE;
                        }
 
                        /* Make sure this is a valid string compare */
@@ -553,13 +539,13 @@ add_right(struct filter_arg *op, struct filter_arg *arg, char *error_str)
                                        show_error(error_str,
                                                   "RegEx '%s' did not compute",
                                                   str);
-                                       return PEVENT_ERRNO__INVALID_REGEX;
+                                       return TEP_ERRNO__INVALID_REGEX;
                                }
                                break;
                        default:
                                show_error(error_str,
                                           "Illegal comparison for string");
-                               return PEVENT_ERRNO__ILLEGAL_STRING_CMP;
+                               return TEP_ERRNO__ILLEGAL_STRING_CMP;
                        }
 
                        op->type = FILTER_ARG_STR;
@@ -568,7 +554,7 @@ add_right(struct filter_arg *op, struct filter_arg *arg, char *error_str)
                        op->str.val = strdup(str);
                        if (!op->str.val) {
                                show_error(error_str, "Failed to allocate string filter");
-                               return PEVENT_ERRNO__MEM_ALLOC_FAILED;
+                               return TEP_ERRNO__MEM_ALLOC_FAILED;
                        }
                        /*
                         * Need a buffer to copy data for tests
@@ -576,7 +562,7 @@ add_right(struct filter_arg *op, struct filter_arg *arg, char *error_str)
                        op->str.buffer = malloc(op->str.field->size + 1);
                        if (!op->str.buffer) {
                                show_error(error_str, "Failed to allocate string filter");
-                               return PEVENT_ERRNO__MEM_ALLOC_FAILED;
+                               return TEP_ERRNO__MEM_ALLOC_FAILED;
                        }
                        /* Null terminate this buffer */
                        op->str.buffer[op->str.field->size] = 0;
@@ -595,7 +581,7 @@ add_right(struct filter_arg *op, struct filter_arg *arg, char *error_str)
                        case FILTER_CMP_NOT_REGEX:
                                show_error(error_str,
                                           "Op not allowed with integers");
-                               return PEVENT_ERRNO__ILLEGAL_INTEGER_CMP;
+                               return TEP_ERRNO__ILLEGAL_INTEGER_CMP;
 
                        default:
                                break;
@@ -616,7 +602,7 @@ add_right(struct filter_arg *op, struct filter_arg *arg, char *error_str)
 
  out_fail:
        show_error(error_str, "Syntax error");
-       return PEVENT_ERRNO__SYNTAX_ERROR;
+       return TEP_ERRNO__SYNTAX_ERROR;
 }
 
 static struct filter_arg *
@@ -629,7 +615,7 @@ rotate_op_right(struct filter_arg *a, struct filter_arg *b)
        return arg;
 }
 
-static enum pevent_errno add_left(struct filter_arg *op, struct filter_arg *arg)
+static enum tep_errno add_left(struct filter_arg *op, struct filter_arg *arg)
 {
        switch (op->type) {
        case FILTER_ARG_EXP:
@@ -648,11 +634,11 @@ static enum pevent_errno add_left(struct filter_arg *op, struct filter_arg *arg)
                /* left arg of compares must be a field */
                if (arg->type != FILTER_ARG_FIELD &&
                    arg->type != FILTER_ARG_BOOLEAN)
-                       return PEVENT_ERRNO__INVALID_ARG_TYPE;
+                       return TEP_ERRNO__INVALID_ARG_TYPE;
                op->num.left = arg;
                break;
        default:
-               return PEVENT_ERRNO__INVALID_ARG_TYPE;
+               return TEP_ERRNO__INVALID_ARG_TYPE;
        }
        return 0;
 }
@@ -765,7 +751,7 @@ enum filter_vals {
        FILTER_VAL_TRUE,
 };
 
-static enum pevent_errno
+static enum tep_errno
 reparent_op_arg(struct filter_arg *parent, struct filter_arg *old_child,
                struct filter_arg *arg, char *error_str)
 {
@@ -775,7 +761,7 @@ reparent_op_arg(struct filter_arg *parent, struct filter_arg *old_child,
        if (parent->type != FILTER_ARG_OP &&
            arg->type != FILTER_ARG_OP) {
                show_error(error_str, "can not reparent other than OP");
-               return PEVENT_ERRNO__REPARENT_NOT_OP;
+               return TEP_ERRNO__REPARENT_NOT_OP;
        }
 
        /* Get the sibling */
@@ -787,7 +773,7 @@ reparent_op_arg(struct filter_arg *parent, struct filter_arg *old_child,
                other_child = old_child->op.right;
        } else {
                show_error(error_str, "Error in reparent op, find other child");
-               return PEVENT_ERRNO__REPARENT_FAILED;
+               return TEP_ERRNO__REPARENT_FAILED;
        }
 
        /* Detach arg from old_child */
@@ -808,7 +794,7 @@ reparent_op_arg(struct filter_arg *parent, struct filter_arg *old_child,
                ptr = &parent->op.left;
        else {
                show_error(error_str, "Error in reparent op");
-               return PEVENT_ERRNO__REPARENT_FAILED;
+               return TEP_ERRNO__REPARENT_FAILED;
        }
 
        *ptr = arg;
@@ -817,7 +803,7 @@ reparent_op_arg(struct filter_arg *parent, struct filter_arg *old_child,
        return 0;
 }
 
-/* Returns either filter_vals (success) or pevent_errno (failfure) */
+/* Returns either filter_vals (success) or tep_errno (failfure) */
 static int test_arg(struct filter_arg *parent, struct filter_arg *arg,
                    char *error_str)
 {
@@ -912,7 +898,7 @@ static int test_arg(struct filter_arg *parent, struct filter_arg *arg,
                return rval;
        default:
                show_error(error_str, "bad arg in filter tree");
-               return PEVENT_ERRNO__BAD_FILTER_ARG;
+               return TEP_ERRNO__BAD_FILTER_ARG;
        }
        return FILTER_VAL_NORM;
 }
@@ -937,7 +923,7 @@ static int collapse_tree(struct filter_arg *arg,
                        arg->boolean.value = ret == FILTER_VAL_TRUE;
                } else {
                        show_error(error_str, "Failed to allocate filter arg");
-                       ret = PEVENT_ERRNO__MEM_ALLOC_FAILED;
+                       ret = TEP_ERRNO__MEM_ALLOC_FAILED;
                }
                break;
 
@@ -952,7 +938,7 @@ static int collapse_tree(struct filter_arg *arg,
        return ret;
 }
 
-static enum pevent_errno
+static enum tep_errno
 process_filter(struct event_format *event, struct filter_arg **parg,
               char *error_str, int not)
 {
@@ -966,7 +952,7 @@ process_filter(struct event_format *event, struct filter_arg **parg,
        enum filter_op_type btype;
        enum filter_exp_type etype;
        enum filter_cmp_type ctype;
-       enum pevent_errno ret;
+       enum tep_errno ret;
 
        *parg = NULL;
 
@@ -1004,7 +990,7 @@ process_filter(struct event_format *event, struct filter_arg **parg,
                case EVENT_DELIM:
                        if (*token == ',') {
                                show_error(error_str, "Illegal token ','");
-                               ret = PEVENT_ERRNO__ILLEGAL_TOKEN;
+                               ret = TEP_ERRNO__ILLEGAL_TOKEN;
                                goto fail;
                        }
 
@@ -1012,22 +998,22 @@ process_filter(struct event_format *event, struct filter_arg **parg,
                                if (left_item) {
                                        show_error(error_str,
                                                   "Open paren can not come after item");
-                                       ret = PEVENT_ERRNO__INVALID_PAREN;
+                                       ret = TEP_ERRNO__INVALID_PAREN;
                                        goto fail;
                                }
                                if (current_exp) {
                                        show_error(error_str,
                                                   "Open paren can not come after expression");
-                                       ret = PEVENT_ERRNO__INVALID_PAREN;
+                                       ret = TEP_ERRNO__INVALID_PAREN;
                                        goto fail;
                                }
 
                                ret = process_filter(event, &arg, error_str, 0);
-                               if (ret != PEVENT_ERRNO__UNBALANCED_PAREN) {
+                               if (ret != TEP_ERRNO__UNBALANCED_PAREN) {
                                        if (ret == 0) {
                                                show_error(error_str,
                                                           "Unbalanced number of '('");
-                                               ret = PEVENT_ERRNO__UNBALANCED_PAREN;
+                                               ret = TEP_ERRNO__UNBALANCED_PAREN;
                                        }
                                        goto fail;
                                }
@@ -1064,7 +1050,7 @@ process_filter(struct event_format *event, struct filter_arg **parg,
                                else
                                        *parg = current_exp;
                                free(token);
-                               return PEVENT_ERRNO__UNBALANCED_PAREN;
+                               return TEP_ERRNO__UNBALANCED_PAREN;
                        }
                        break;
 
@@ -1091,7 +1077,7 @@ process_filter(struct event_format *event, struct filter_arg **parg,
                        case OP_NONE:
                                show_error(error_str,
                                           "Unknown op token %s", token);
-                               ret = PEVENT_ERRNO__UNKNOWN_TOKEN;
+                               ret = TEP_ERRNO__UNKNOWN_TOKEN;
                                goto fail;
                        }
 
@@ -1179,11 +1165,11 @@ process_filter(struct event_format *event, struct filter_arg **parg,
 
  fail_alloc:
        show_error(error_str, "failed to allocate filter arg");
-       ret = PEVENT_ERRNO__MEM_ALLOC_FAILED;
+       ret = TEP_ERRNO__MEM_ALLOC_FAILED;
        goto fail;
  fail_syntax:
        show_error(error_str, "Syntax error");
-       ret = PEVENT_ERRNO__SYNTAX_ERROR;
+       ret = TEP_ERRNO__SYNTAX_ERROR;
  fail:
        free_arg(current_op);
        free_arg(current_exp);
@@ -1192,13 +1178,13 @@ process_filter(struct event_format *event, struct filter_arg **parg,
        return ret;
 }
 
-static enum pevent_errno
+static enum tep_errno
 process_event(struct event_format *event, const char *filter_str,
              struct filter_arg **parg, char *error_str)
 {
        int ret;
 
-       pevent_buffer_init(filter_str, strlen(filter_str));
+       tep_buffer_init(filter_str, strlen(filter_str));
 
        ret = process_filter(event, parg, error_str, 0);
        if (ret < 0)
@@ -1208,7 +1194,7 @@ process_event(struct event_format *event, const char *filter_str,
        if (!*parg) {
                *parg = allocate_arg();
                if (*parg == NULL)
-                       return PEVENT_ERRNO__MEM_ALLOC_FAILED;
+                       return TEP_ERRNO__MEM_ALLOC_FAILED;
 
                (*parg)->type = FILTER_ARG_BOOLEAN;
                (*parg)->boolean.value = FILTER_FALSE;
@@ -1217,13 +1203,13 @@ process_event(struct event_format *event, const char *filter_str,
        return 0;
 }
 
-static enum pevent_errno
+static enum tep_errno
 filter_event(struct event_filter *filter, struct event_format *event,
             const char *filter_str, char *error_str)
 {
        struct filter_type *filter_type;
        struct filter_arg *arg;
-       enum pevent_errno ret;
+       enum tep_errno ret;
 
        if (filter_str) {
                ret = process_event(event, filter_str, &arg, error_str);
@@ -1234,7 +1220,7 @@ filter_event(struct event_filter *filter, struct event_format *event,
                /* just add a TRUE arg */
                arg = allocate_arg();
                if (arg == NULL)
-                       return PEVENT_ERRNO__MEM_ALLOC_FAILED;
+                       return TEP_ERRNO__MEM_ALLOC_FAILED;
 
                arg->type = FILTER_ARG_BOOLEAN;
                arg->boolean.value = FILTER_TRUE;
@@ -1242,7 +1228,7 @@ filter_event(struct event_filter *filter, struct event_format *event,
 
        filter_type = add_filter_type(filter, event->id);
        if (filter_type == NULL)
-               return PEVENT_ERRNO__MEM_ALLOC_FAILED;
+               return TEP_ERRNO__MEM_ALLOC_FAILED;
 
        if (filter_type->filter)
                free_arg(filter_type->filter);
@@ -1254,23 +1240,23 @@ filter_event(struct event_filter *filter, struct event_format *event,
 static void filter_init_error_buf(struct event_filter *filter)
 {
        /* clear buffer to reset show error */
-       pevent_buffer_init("", 0);
+       tep_buffer_init("", 0);
        filter->error_buffer[0] = '\0';
 }
 
 /**
- * pevent_filter_add_filter_str - add a new filter
+ * tep_filter_add_filter_str - add a new filter
  * @filter: the event filter to add to
  * @filter_str: the filter string that contains the filter
  *
  * Returns 0 if the filter was successfully added or a
- * negative error code.  Use pevent_filter_strerror() to see
+ * negative error code.  Use tep_filter_strerror() to see
  * actual error message in case of error.
  */
-enum pevent_errno pevent_filter_add_filter_str(struct event_filter *filter,
-                                              const char *filter_str)
+enum tep_errno tep_filter_add_filter_str(struct event_filter *filter,
+                                        const char *filter_str)
 {
-       struct pevent *pevent = filter->pevent;
+       struct tep_handle *pevent = filter->pevent;
        struct event_list *event;
        struct event_list *events = NULL;
        const char *filter_start;
@@ -1279,7 +1265,7 @@ enum pevent_errno pevent_filter_add_filter_str(struct event_filter *filter,
        char *event_name = NULL;
        char *sys_name = NULL;
        char *sp;
-       enum pevent_errno rtn = 0; /* PEVENT_ERRNO__SUCCESS */
+       enum tep_errno rtn = 0; /* TEP_ERRNO__SUCCESS */
        int len;
        int ret;
 
@@ -1305,7 +1291,7 @@ enum pevent_errno pevent_filter_add_filter_str(struct event_filter *filter,
                if (this_event == NULL) {
                        /* This can only happen when events is NULL, but still */
                        free_events(events);
-                       return PEVENT_ERRNO__MEM_ALLOC_FAILED;
+                       return TEP_ERRNO__MEM_ALLOC_FAILED;
                }
                memcpy(this_event, filter_str, len);
                this_event[len] = 0;
@@ -1322,7 +1308,7 @@ enum pevent_errno pevent_filter_add_filter_str(struct event_filter *filter,
                        /* This can only happen when events is NULL, but still */
                        free_events(events);
                        free(this_event);
-                       return PEVENT_ERRNO__FILTER_NOT_FOUND;
+                       return TEP_ERRNO__FILTER_NOT_FOUND;
                }
 
                /* Find this event */
@@ -1349,7 +1335,7 @@ enum pevent_errno pevent_filter_add_filter_str(struct event_filter *filter,
 
                if (ret >= 0 && pevent->test_filters) {
                        char *test;
-                       test = pevent_filter_make_string(filter, event->event->id);
+                       test = tep_filter_make_string(filter, event->event->id);
                        if (test) {
                                printf(" '%s: %s'\n", event->event->name, test);
                                free(test);
@@ -1371,7 +1357,7 @@ static void free_filter_type(struct filter_type *filter_type)
 }
 
 /**
- * pevent_filter_strerror - fill error message in a buffer
+ * tep_filter_strerror - fill error message in a buffer
  * @filter: the event filter contains error
  * @err: the error code
  * @buf: the buffer to be filled in
@@ -1379,10 +1365,10 @@ static void free_filter_type(struct filter_type *filter_type)
  *
  * Returns 0 if message was filled successfully, -1 if error
  */
-int pevent_filter_strerror(struct event_filter *filter, enum pevent_errno err,
-                          char *buf, size_t buflen)
+int tep_filter_strerror(struct event_filter *filter, enum tep_errno err,
+                       char *buf, size_t buflen)
 {
-       if (err <= __PEVENT_ERRNO__START || err >= __PEVENT_ERRNO__END)
+       if (err <= __TEP_ERRNO__START || err >= __TEP_ERRNO__END)
                return -1;
 
        if (strlen(filter->error_buffer) > 0) {
@@ -1393,11 +1379,11 @@ int pevent_filter_strerror(struct event_filter *filter, enum pevent_errno err,
                return 0;
        }
 
-       return pevent_strerror(filter->pevent, err, buf, buflen);
+       return tep_strerror(filter->pevent, err, buf, buflen);
 }
 
 /**
- * pevent_filter_remove_event - remove a filter for an event
+ * tep_filter_remove_event - remove a filter for an event
  * @filter: the event filter to remove from
  * @event_id: the event to remove a filter for
  *
@@ -1407,8 +1393,8 @@ int pevent_filter_strerror(struct event_filter *filter, enum pevent_errno err,
  * Returns 1: if an event was removed
  *   0: if the event was not found
  */
-int pevent_filter_remove_event(struct event_filter *filter,
-                              int event_id)
+int tep_filter_remove_event(struct event_filter *filter,
+                           int event_id)
 {
        struct filter_type *filter_type;
        unsigned long len;
@@ -1437,12 +1423,12 @@ int pevent_filter_remove_event(struct event_filter *filter,
 }
 
 /**
- * pevent_filter_reset - clear all filters in a filter
+ * tep_filter_reset - clear all filters in a filter
  * @filter: the event filter to reset
  *
  * Removes all filters from a filter and resets it.
  */
-void pevent_filter_reset(struct event_filter *filter)
+void tep_filter_reset(struct event_filter *filter)
 {
        int i;
 
@@ -1454,11 +1440,11 @@ void pevent_filter_reset(struct event_filter *filter)
        filter->event_filters = NULL;
 }
 
-void pevent_filter_free(struct event_filter *filter)
+void tep_filter_free(struct event_filter *filter)
 {
-       pevent_unref(filter->pevent);
+       tep_unref(filter->pevent);
 
-       pevent_filter_reset(filter);
+       tep_filter_reset(filter);
 
        free(filter);
 }
@@ -1478,7 +1464,7 @@ static int copy_filter_type(struct event_filter *filter,
        /* Can't assume that the pevent's are the same */
        sys = filter_type->event->system;
        name = filter_type->event->name;
-       event = pevent_find_event_by_name(filter->pevent, sys, name);
+       event = tep_find_event_by_name(filter->pevent, sys, name);
        if (!event)
                return -1;
 
@@ -1515,18 +1501,18 @@ static int copy_filter_type(struct event_filter *filter,
 }
 
 /**
- * pevent_filter_copy - copy a filter using another filter
+ * tep_filter_copy - copy a filter using another filter
  * @dest - the filter to copy to
  * @source - the filter to copy from
  *
  * Returns 0 on success and -1 if not all filters were copied
  */
-int pevent_filter_copy(struct event_filter *dest, struct event_filter *source)
+int tep_filter_copy(struct event_filter *dest, struct event_filter *source)
 {
        int ret = 0;
        int i;
 
-       pevent_filter_reset(dest);
+       tep_filter_reset(dest);
 
        for (i = 0; i < source->filters; i++) {
                if (copy_filter_type(dest, source, &source->event_filters[i]))
@@ -1537,7 +1523,7 @@ int pevent_filter_copy(struct event_filter *dest, struct event_filter *source)
 
 
 /**
- * pevent_update_trivial - update the trivial filters with the given filter
+ * tep_update_trivial - update the trivial filters with the given filter
  * @dest - the filter to update
  * @source - the filter as the source of the update
  * @type - the type of trivial filter to update.
@@ -1547,11 +1533,11 @@ int pevent_filter_copy(struct event_filter *dest, struct event_filter *source)
  * Returns 0 on success and -1 if there was a problem updating, but
  *   events may have still been updated on error.
  */
-int pevent_update_trivial(struct event_filter *dest, struct event_filter *source,
-                         enum filter_trivial_type type)
+int tep_update_trivial(struct event_filter *dest, struct event_filter *source,
+                      enum filter_trivial_type type)
 {
-       struct pevent *src_pevent;
-       struct pevent *dest_pevent;
+       struct tep_handle *src_pevent;
+       struct tep_handle *dest_pevent;
        struct event_format *event;
        struct filter_type *filter_type;
        struct filter_arg *arg;
@@ -1578,14 +1564,14 @@ int pevent_update_trivial(struct event_filter *dest, struct event_filter *source
 
                if (src_pevent != dest_pevent) {
                        /* do a look up */
-                       event = pevent_find_event_by_name(src_pevent,
-                                                         event->system,
-                                                         event->name);
+                       event = tep_find_event_by_name(src_pevent,
+                                                      event->system,
+                                                      event->name);
                        if (!event)
                                return -1;
                }
 
-               str = pevent_filter_make_string(source, event->id);
+               str = tep_filter_make_string(source, event->id);
                if (!str)
                        continue;
 
@@ -1598,7 +1584,7 @@ int pevent_update_trivial(struct event_filter *dest, struct event_filter *source
 }
 
 /**
- * pevent_filter_clear_trivial - clear TRUE and FALSE filters
+ * tep_filter_clear_trivial - clear TRUE and FALSE filters
  * @filter: the filter to remove trivial filters from
  * @type: remove only true, false, or both
  *
@@ -1606,8 +1592,8 @@ int pevent_update_trivial(struct event_filter *dest, struct event_filter *source
  *
  * Returns 0 on success and -1 if there was a problem.
  */
-int pevent_filter_clear_trivial(struct event_filter *filter,
-                                enum filter_trivial_type type)
+int tep_filter_clear_trivial(struct event_filter *filter,
+                            enum filter_trivial_type type)
 {
        struct filter_type *filter_type;
        int count = 0;
@@ -1653,14 +1639,14 @@ int pevent_filter_clear_trivial(struct event_filter *filter,
                return 0;
 
        for (i = 0; i < count; i++)
-               pevent_filter_remove_event(filter, ids[i]);
+               tep_filter_remove_event(filter, ids[i]);
 
        free(ids);
        return 0;
 }
 
 /**
- * pevent_filter_event_has_trivial - return true event contains trivial filter
+ * tep_filter_event_has_trivial - return true event contains trivial filter
  * @filter: the filter with the information
  * @event_id: the id of the event to test
  * @type: trivial type to test for (TRUE, FALSE, EITHER)
@@ -1668,9 +1654,9 @@ int pevent_filter_clear_trivial(struct event_filter *filter,
  * Returns 1 if the event contains a matching trivial type
  *  otherwise 0.
  */
-int pevent_filter_event_has_trivial(struct event_filter *filter,
-                                   int event_id,
-                                   enum filter_trivial_type type)
+int tep_filter_event_has_trivial(struct event_filter *filter,
+                                int event_id,
+                                enum filter_trivial_type type)
 {
        struct filter_type *filter_type;
 
@@ -1697,22 +1683,22 @@ int pevent_filter_event_has_trivial(struct event_filter *filter,
 }
 
 static int test_filter(struct event_format *event, struct filter_arg *arg,
-                      struct pevent_record *record, enum pevent_errno *err);
+                      struct tep_record *record, enum tep_errno *err);
 
 static const char *
-get_comm(struct event_format *event, struct pevent_record *record)
+get_comm(struct event_format *event, struct tep_record *record)
 {
        const char *comm;
        int pid;
 
-       pid = pevent_data_pid(event->pevent, record);
-       comm = pevent_data_comm_from_pid(event->pevent, pid);
+       pid = tep_data_pid(event->pevent, record);
+       comm = tep_data_comm_from_pid(event->pevent, pid);
        return comm;
 }
 
 static unsigned long long
 get_value(struct event_format *event,
-         struct format_field *field, struct pevent_record *record)
+         struct format_field *field, struct tep_record *record)
 {
        unsigned long long val;
 
@@ -1728,7 +1714,7 @@ get_value(struct event_format *event,
        if (field == &cpu)
                return record->cpu;
 
-       pevent_read_number_field(field, record->data, &val);
+       tep_read_number_field(field, record->data, &val);
 
        if (!(field->flags & FIELD_IS_SIGNED))
                return val;
@@ -1748,11 +1734,11 @@ get_value(struct event_format *event,
 
 static unsigned long long
 get_arg_value(struct event_format *event, struct filter_arg *arg,
-             struct pevent_record *record, enum pevent_errno *err);
+             struct tep_record *record, enum tep_errno *err);
 
 static unsigned long long
 get_exp_value(struct event_format *event, struct filter_arg *arg,
-             struct pevent_record *record, enum pevent_errno *err)
+             struct tep_record *record, enum tep_errno *err)
 {
        unsigned long long lval, rval;
 
@@ -1800,14 +1786,14 @@ get_exp_value(struct event_format *event, struct filter_arg *arg,
        case FILTER_EXP_NOT:
        default:
                if (!*err)
-                       *err = PEVENT_ERRNO__INVALID_EXP_TYPE;
+                       *err = TEP_ERRNO__INVALID_EXP_TYPE;
        }
        return 0;
 }
 
 static unsigned long long
 get_arg_value(struct event_format *event, struct filter_arg *arg,
-             struct pevent_record *record, enum pevent_errno *err)
+             struct tep_record *record, enum tep_errno *err)
 {
        switch (arg->type) {
        case FILTER_ARG_FIELD:
@@ -1816,7 +1802,7 @@ get_arg_value(struct event_format *event, struct filter_arg *arg,
        case FILTER_ARG_VALUE:
                if (arg->value.type != FILTER_NUMBER) {
                        if (!*err)
-                               *err = PEVENT_ERRNO__NOT_A_NUMBER;
+                               *err = TEP_ERRNO__NOT_A_NUMBER;
                }
                return arg->value.val;
 
@@ -1825,13 +1811,13 @@ get_arg_value(struct event_format *event, struct filter_arg *arg,
 
        default:
                if (!*err)
-                       *err = PEVENT_ERRNO__INVALID_ARG_TYPE;
+                       *err = TEP_ERRNO__INVALID_ARG_TYPE;
        }
        return 0;
 }
 
 static int test_num(struct event_format *event, struct filter_arg *arg,
-                   struct pevent_record *record, enum pevent_errno *err)
+                   struct tep_record *record, enum tep_errno *err)
 {
        unsigned long long lval, rval;
 
@@ -1866,15 +1852,15 @@ static int test_num(struct event_format *event, struct filter_arg *arg,
 
        default:
                if (!*err)
-                       *err = PEVENT_ERRNO__ILLEGAL_INTEGER_CMP;
+                       *err = TEP_ERRNO__ILLEGAL_INTEGER_CMP;
                return 0;
        }
 }
 
-static const char *get_field_str(struct filter_arg *arg, struct pevent_record *record)
+static const char *get_field_str(struct filter_arg *arg, struct tep_record *record)
 {
        struct event_format *event;
-       struct pevent *pevent;
+       struct tep_handle *pevent;
        unsigned long long addr;
        const char *val = NULL;
        unsigned int size;
@@ -1909,7 +1895,7 @@ static const char *get_field_str(struct filter_arg *arg, struct pevent_record *r
 
                if (arg->str.field->flags & (FIELD_IS_POINTER | FIELD_IS_LONG))
                        /* convert to a kernel symbol */
-                       val = pevent_find_function(pevent, addr);
+                       val = tep_find_function(pevent, addr);
 
                if (val == NULL) {
                        /* just use the hex of the string name */
@@ -1922,7 +1908,7 @@ static const char *get_field_str(struct filter_arg *arg, struct pevent_record *r
 }
 
 static int test_str(struct event_format *event, struct filter_arg *arg,
-                   struct pevent_record *record, enum pevent_errno *err)
+                   struct tep_record *record, enum tep_errno *err)
 {
        const char *val;
 
@@ -1947,13 +1933,13 @@ static int test_str(struct event_format *event, struct filter_arg *arg,
 
        default:
                if (!*err)
-                       *err = PEVENT_ERRNO__ILLEGAL_STRING_CMP;
+                       *err = TEP_ERRNO__ILLEGAL_STRING_CMP;
                return 0;
        }
 }
 
 static int test_op(struct event_format *event, struct filter_arg *arg,
-                  struct pevent_record *record, enum pevent_errno *err)
+                  struct tep_record *record, enum tep_errno *err)
 {
        switch (arg->op.type) {
        case FILTER_OP_AND:
@@ -1969,13 +1955,13 @@ static int test_op(struct event_format *event, struct filter_arg *arg,
 
        default:
                if (!*err)
-                       *err = PEVENT_ERRNO__INVALID_OP_TYPE;
+                       *err = TEP_ERRNO__INVALID_OP_TYPE;
                return 0;
        }
 }
 
 static int test_filter(struct event_format *event, struct filter_arg *arg,
-                      struct pevent_record *record, enum pevent_errno *err)
+                      struct tep_record *record, enum tep_errno *err)
 {
        if (*err) {
                /*
@@ -2009,20 +1995,20 @@ static int test_filter(struct event_format *event, struct filter_arg *arg,
 
        default:
                if (!*err)
-                       *err = PEVENT_ERRNO__INVALID_ARG_TYPE;
+                       *err = TEP_ERRNO__INVALID_ARG_TYPE;
                return 0;
        }
 }
 
 /**
- * pevent_event_filtered - return true if event has filter
+ * tep_event_filtered - return true if event has filter
  * @filter: filter struct with filter information
  * @event_id: event id to test if filter exists
  *
  * Returns 1 if filter found for @event_id
  *   otherwise 0;
  */
-int pevent_event_filtered(struct event_filter *filter, int event_id)
+int tep_event_filtered(struct event_filter *filter, int event_id)
 {
        struct filter_type *filter_type;
 
@@ -2035,42 +2021,42 @@ int pevent_event_filtered(struct event_filter *filter, int event_id)
 }
 
 /**
- * pevent_filter_match - test if a record matches a filter
+ * tep_filter_match - test if a record matches a filter
  * @filter: filter struct with filter information
  * @record: the record to test against the filter
  *
- * Returns: match result or error code (prefixed with PEVENT_ERRNO__)
+ * Returns: match result or error code (prefixed with TEP_ERRNO__)
  * FILTER_MATCH - filter found for event and @record matches
  * FILTER_MISS  - filter found for event and @record does not match
  * FILTER_NOT_FOUND - no filter found for @record's event
  * NO_FILTER - if no filters exist
  * otherwise - error occurred during test
  */
-enum pevent_errno pevent_filter_match(struct event_filter *filter,
-                                     struct pevent_record *record)
+enum tep_errno tep_filter_match(struct event_filter *filter,
+                               struct tep_record *record)
 {
-       struct pevent *pevent = filter->pevent;
+       struct tep_handle *pevent = filter->pevent;
        struct filter_type *filter_type;
        int event_id;
        int ret;
-       enum pevent_errno err = 0;
+       enum tep_errno err = 0;
 
        filter_init_error_buf(filter);
 
        if (!filter->filters)
-               return PEVENT_ERRNO__NO_FILTER;
+               return TEP_ERRNO__NO_FILTER;
 
-       event_id = pevent_data_type(pevent, record);
+       event_id = tep_data_type(pevent, record);
 
        filter_type = find_filter_type(filter, event_id);
        if (!filter_type)
-               return PEVENT_ERRNO__FILTER_NOT_FOUND;
+               return TEP_ERRNO__FILTER_NOT_FOUND;
 
        ret = test_filter(filter_type->event, filter_type->filter, record, &err);
        if (err)
                return err;
 
-       return ret ? PEVENT_ERRNO__FILTER_MATCH : PEVENT_ERRNO__FILTER_MISS;
+       return ret ? TEP_ERRNO__FILTER_MATCH : TEP_ERRNO__FILTER_MISS;
 }
 
 static char *op_to_str(struct event_filter *filter, struct filter_arg *arg)
@@ -2364,7 +2350,7 @@ static char *arg_to_str(struct event_filter *filter, struct filter_arg *arg)
 }
 
 /**
- * pevent_filter_make_string - return a string showing the filter
+ * tep_filter_make_string - return a string showing the filter
  * @filter: filter struct with filter information
  * @event_id: the event id to return the filter string with
  *
@@ -2373,7 +2359,7 @@ static char *arg_to_str(struct event_filter *filter, struct filter_arg *arg)
  *  NULL is returned if no filter is found or allocation failed.
  */
 char *
-pevent_filter_make_string(struct event_filter *filter, int event_id)
+tep_filter_make_string(struct event_filter *filter, int event_id)
 {
        struct filter_type *filter_type;
 
@@ -2389,7 +2375,7 @@ pevent_filter_make_string(struct event_filter *filter, int event_id)
 }
 
 /**
- * pevent_filter_compare - compare two filters and return if they are the same
+ * tep_filter_compare - compare two filters and return if they are the same
  * @filter1: Filter to compare with @filter2
  * @filter2: Filter to compare with @filter1
  *
@@ -2397,7 +2383,7 @@ pevent_filter_make_string(struct event_filter *filter, int event_id)
  *  1 if the two filters hold the same content.
  *  0 if they do not.
  */
-int pevent_filter_compare(struct event_filter *filter1, struct event_filter *filter2)
+int tep_filter_compare(struct event_filter *filter1, struct event_filter *filter2)
 {
        struct filter_type *filter_type1;
        struct filter_type *filter_type2;
index eda07fa..77e4ec6 100644 (file)
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: LGPL-2.1
 /*
  * Copyright (C) 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
  *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License (not later!)
- *
- * 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not,  see <http://www.gnu.org/licenses>
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  */
 #include <stdio.h>
 #include <stdlib.h>
index 8f85869..a51b366 100644 (file)
@@ -25,19 +25,19 @@ process___le16_to_cpup(struct trace_seq *s, unsigned long long *args)
        return val ? (long long) le16toh(*val) : 0;
 }
 
-int PEVENT_PLUGIN_LOADER(struct pevent *pevent)
+int TEP_PLUGIN_LOADER(struct tep_handle *pevent)
 {
-       pevent_register_print_function(pevent,
-                                      process___le16_to_cpup,
-                                      PEVENT_FUNC_ARG_INT,
-                                      "__le16_to_cpup",
-                                      PEVENT_FUNC_ARG_PTR,
-                                      PEVENT_FUNC_ARG_VOID);
+       tep_register_print_function(pevent,
+                                   process___le16_to_cpup,
+                                   TEP_FUNC_ARG_INT,
+                                   "__le16_to_cpup",
+                                   TEP_FUNC_ARG_PTR,
+                                   TEP_FUNC_ARG_VOID);
        return 0;
 }
 
-void PEVENT_PLUGIN_UNLOADER(struct pevent *pevent)
+void TEP_PLUGIN_UNLOADER(struct tep_handle *pevent)
 {
-       pevent_unregister_print_function(pevent, process___le16_to_cpup,
-                                        "__le16_to_cpup");
+       tep_unregister_print_function(pevent, process___le16_to_cpup,
+                                     "__le16_to_cpup");
 }
index 42dbf73..4247474 100644 (file)
@@ -33,7 +33,7 @@ static int cpus = -1;
 
 #define STK_BLK 10
 
-struct pevent_plugin_option plugin_options[] =
+struct tep_plugin_option plugin_options[] =
 {
        {
                .name = "parent",
@@ -53,8 +53,8 @@ struct pevent_plugin_option plugin_options[] =
        }
 };
 
-static struct pevent_plugin_option *ftrace_parent = &plugin_options[0];
-static struct pevent_plugin_option *ftrace_indent = &plugin_options[1];
+static struct tep_plugin_option *ftrace_parent = &plugin_options[0];
+static struct tep_plugin_option *ftrace_indent = &plugin_options[1];
 
 static void add_child(struct func_stack *stack, const char *child, int pos)
 {
@@ -122,25 +122,25 @@ static int add_and_get_index(const char *parent, const char *child, int cpu)
        return 0;
 }
 
-static int function_handler(struct trace_seq *s, struct pevent_record *record,
+static int function_handler(struct trace_seq *s, struct tep_record *record,
                            struct event_format *event, void *context)
 {
-       struct pevent *pevent = event->pevent;
+       struct tep_handle *pevent = event->pevent;
        unsigned long long function;
        unsigned long long pfunction;
        const char *func;
        const char *parent;
        int index = 0;
 
-       if (pevent_get_field_val(s, event, "ip", record, &function, 1))
+       if (tep_get_field_val(s, event, "ip", record, &function, 1))
                return trace_seq_putc(s, '!');
 
-       func = pevent_find_function(pevent, function);
+       func = tep_find_function(pevent, function);
 
-       if (pevent_get_field_val(s, event, "parent_ip", record, &pfunction, 1))
+       if (tep_get_field_val(s, event, "parent_ip", record, &pfunction, 1))
                return trace_seq_putc(s, '!');
 
-       parent = pevent_find_function(pevent, pfunction);
+       parent = tep_find_function(pevent, pfunction);
 
        if (parent && ftrace_indent->set)
                index = add_and_get_index(parent, func, record->cpu);
@@ -163,22 +163,22 @@ static int function_handler(struct trace_seq *s, struct pevent_record *record,
        return 0;
 }
 
-int PEVENT_PLUGIN_LOADER(struct pevent *pevent)
+int TEP_PLUGIN_LOADER(struct tep_handle *pevent)
 {
-       pevent_register_event_handler(pevent, -1, "ftrace", "function",
-                                     function_handler, NULL);
+       tep_register_event_handler(pevent, -1, "ftrace", "function",
+                                  function_handler, NULL);
 
-       traceevent_plugin_add_options("ftrace", plugin_options);
+       tep_plugin_add_options("ftrace", plugin_options);
 
        return 0;
 }
 
-void PEVENT_PLUGIN_UNLOADER(struct pevent *pevent)
+void TEP_PLUGIN_UNLOADER(struct tep_handle *pevent)
 {
        int i, x;
 
-       pevent_unregister_event_handler(pevent, -1, "ftrace", "function",
-                                       function_handler, NULL);
+       tep_unregister_event_handler(pevent, -1, "ftrace", "function",
+                                    function_handler, NULL);
 
        for (i = 0; i <= cpus; i++) {
                for (x = 0; x < fstack[i].size && fstack[i].stack[x]; x++)
@@ -186,7 +186,7 @@ void PEVENT_PLUGIN_UNLOADER(struct pevent *pevent)
                free(fstack[i].stack);
        }
 
-       traceevent_plugin_remove_options(plugin_options);
+       tep_plugin_remove_options(plugin_options);
 
        free(fstack);
        fstack = NULL;
index 12bf14c..b43bfec 100644 (file)
 #include "event-parse.h"
 
 static int timer_expire_handler(struct trace_seq *s,
-                               struct pevent_record *record,
+                               struct tep_record *record,
                                struct event_format *event, void *context)
 {
        trace_seq_printf(s, "hrtimer=");
 
-       if (pevent_print_num_field(s, "0x%llx", event, "timer",
-                                  record, 0) == -1)
-               pevent_print_num_field(s, "0x%llx", event, "hrtimer",
-                                      record, 1);
+       if (tep_print_num_field(s, "0x%llx", event, "timer",
+                               record, 0) == -1)
+               tep_print_num_field(s, "0x%llx", event, "hrtimer",
+                                   record, 1);
 
        trace_seq_printf(s, " now=");
 
-       pevent_print_num_field(s, "%llu", event, "now", record, 1);
+       tep_print_num_field(s, "%llu", event, "now", record, 1);
 
-       pevent_print_func_field(s, " function=%s", event, "function",
+       tep_print_func_field(s, " function=%s", event, "function",
                                record, 0);
        return 0;
 }
 
 static int timer_start_handler(struct trace_seq *s,
-                              struct pevent_record *record,
+                              struct tep_record *record,
                               struct event_format *event, void *context)
 {
        trace_seq_printf(s, "hrtimer=");
 
-       if (pevent_print_num_field(s, "0x%llx", event, "timer",
-                                  record, 0) == -1)
-               pevent_print_num_field(s, "0x%llx", event, "hrtimer",
-                                      record, 1);
+       if (tep_print_num_field(s, "0x%llx", event, "timer",
+                               record, 0) == -1)
+               tep_print_num_field(s, "0x%llx", event, "hrtimer",
+                                   record, 1);
 
-       pevent_print_func_field(s, " function=%s", event, "function",
-                               record, 0);
+       tep_print_func_field(s, " function=%s", event, "function",
+                            record, 0);
 
        trace_seq_printf(s, " expires=");
-       pevent_print_num_field(s, "%llu", event, "expires", record, 1);
+       tep_print_num_field(s, "%llu", event, "expires", record, 1);
 
        trace_seq_printf(s, " softexpires=");
-       pevent_print_num_field(s, "%llu", event, "softexpires", record, 1);
+       tep_print_num_field(s, "%llu", event, "softexpires", record, 1);
        return 0;
 }
 
-int PEVENT_PLUGIN_LOADER(struct pevent *pevent)
+int TEP_PLUGIN_LOADER(struct tep_handle *pevent)
 {
-       pevent_register_event_handler(pevent, -1,
-                                     "timer", "hrtimer_expire_entry",
-                                     timer_expire_handler, NULL);
+       tep_register_event_handler(pevent, -1,
+                                  "timer", "hrtimer_expire_entry",
+                                  timer_expire_handler, NULL);
 
-       pevent_register_event_handler(pevent, -1, "timer", "hrtimer_start",
-                                     timer_start_handler, NULL);
+       tep_register_event_handler(pevent, -1, "timer", "hrtimer_start",
+                                  timer_start_handler, NULL);
        return 0;
 }
 
-void PEVENT_PLUGIN_UNLOADER(struct pevent *pevent)
+void TEP_PLUGIN_UNLOADER(struct tep_handle *pevent)
 {
-       pevent_unregister_event_handler(pevent, -1,
-                                       "timer", "hrtimer_expire_entry",
-                                       timer_expire_handler, NULL);
+       tep_unregister_event_handler(pevent, -1,
+                                    "timer", "hrtimer_expire_entry",
+                                    timer_expire_handler, NULL);
 
-       pevent_unregister_event_handler(pevent, -1, "timer", "hrtimer_start",
-                                       timer_start_handler, NULL);
+       tep_unregister_event_handler(pevent, -1, "timer", "hrtimer_start",
+                                    timer_start_handler, NULL);
 }
index 5c23d5b..45a9acd 100644 (file)
@@ -47,29 +47,29 @@ process_jiffies_to_msecs(struct trace_seq *s, unsigned long long *args)
        return jiffies;
 }
 
-int PEVENT_PLUGIN_LOADER(struct pevent *pevent)
+int TEP_PLUGIN_LOADER(struct tep_handle *pevent)
 {
-       pevent_register_print_function(pevent,
-                                      process_jbd2_dev_to_name,
-                                      PEVENT_FUNC_ARG_STRING,
-                                      "jbd2_dev_to_name",
-                                      PEVENT_FUNC_ARG_INT,
-                                      PEVENT_FUNC_ARG_VOID);
+       tep_register_print_function(pevent,
+                                   process_jbd2_dev_to_name,
+                                   TEP_FUNC_ARG_STRING,
+                                   "jbd2_dev_to_name",
+                                   TEP_FUNC_ARG_INT,
+                                   TEP_FUNC_ARG_VOID);
 
-       pevent_register_print_function(pevent,
-                                      process_jiffies_to_msecs,
-                                      PEVENT_FUNC_ARG_LONG,
-                                      "jiffies_to_msecs",
-                                      PEVENT_FUNC_ARG_LONG,
-                                      PEVENT_FUNC_ARG_VOID);
+       tep_register_print_function(pevent,
+                                   process_jiffies_to_msecs,
+                                   TEP_FUNC_ARG_LONG,
+                                   "jiffies_to_msecs",
+                                   TEP_FUNC_ARG_LONG,
+                                   TEP_FUNC_ARG_VOID);
        return 0;
 }
 
-void PEVENT_PLUGIN_UNLOADER(struct pevent *pevent)
+void TEP_PLUGIN_UNLOADER(struct tep_handle *pevent)
 {
-       pevent_unregister_print_function(pevent, process_jbd2_dev_to_name,
-                                        "jbd2_dev_to_name");
+       tep_unregister_print_function(pevent, process_jbd2_dev_to_name,
+                                     "jbd2_dev_to_name");
 
-       pevent_unregister_print_function(pevent, process_jiffies_to_msecs,
-                                        "jiffies_to_msecs");
+       tep_unregister_print_function(pevent, process_jiffies_to_msecs,
+                                     "jiffies_to_msecs");
 }
index 70650ff..73966b0 100644 (file)
@@ -23,7 +23,7 @@
 
 #include "event-parse.h"
 
-static int call_site_handler(struct trace_seq *s, struct pevent_record *record,
+static int call_site_handler(struct trace_seq *s, struct tep_record *record,
                             struct event_format *event, void *context)
 {
        struct format_field *field;
@@ -31,64 +31,64 @@ static int call_site_handler(struct trace_seq *s, struct pevent_record *record,
        void *data = record->data;
        const char *func;
 
-       field = pevent_find_field(event, "call_site");
+       field = tep_find_field(event, "call_site");
        if (!field)
                return 1;
 
-       if (pevent_read_number_field(field, data, &val))
+       if (tep_read_number_field(field, data, &val))
                return 1;
 
-       func = pevent_find_function(event->pevent, val);
+       func = tep_find_function(event->pevent, val);
        if (!func)
                return 1;
 
-       addr = pevent_find_function_address(event->pevent, val);
+       addr = tep_find_function_address(event->pevent, val);
 
        trace_seq_printf(s, "(%s+0x%x) ", func, (int)(val - addr));
        return 1;
 }
 
-int PEVENT_PLUGIN_LOADER(struct pevent *pevent)
+int TEP_PLUGIN_LOADER(struct tep_handle *pevent)
 {
-       pevent_register_event_handler(pevent, -1, "kmem", "kfree",
-                                     call_site_handler, NULL);
+       tep_register_event_handler(pevent, -1, "kmem", "kfree",
+                                  call_site_handler, NULL);
 
-       pevent_register_event_handler(pevent, -1, "kmem", "kmalloc",
-                                     call_site_handler, NULL);
+       tep_register_event_handler(pevent, -1, "kmem", "kmalloc",
+                                  call_site_handler, NULL);
 
-       pevent_register_event_handler(pevent, -1, "kmem", "kmalloc_node",
-                                     call_site_handler, NULL);
+       tep_register_event_handler(pevent, -1, "kmem", "kmalloc_node",
+                                  call_site_handler, NULL);
 
-       pevent_register_event_handler(pevent, -1, "kmem", "kmem_cache_alloc",
-                                     call_site_handler, NULL);
+       tep_register_event_handler(pevent, -1, "kmem", "kmem_cache_alloc",
+                                  call_site_handler, NULL);
 
-       pevent_register_event_handler(pevent, -1, "kmem",
-                                     "kmem_cache_alloc_node",
-                                     call_site_handler, NULL);
+       tep_register_event_handler(pevent, -1, "kmem",
+                                  "kmem_cache_alloc_node",
+                                  call_site_handler, NULL);
 
-       pevent_register_event_handler(pevent, -1, "kmem", "kmem_cache_free",
-                                     call_site_handler, NULL);
+       tep_register_event_handler(pevent, -1, "kmem", "kmem_cache_free",
+                                  call_site_handler, NULL);
        return 0;
 }
 
-void PEVENT_PLUGIN_UNLOADER(struct pevent *pevent)
+void TEP_PLUGIN_UNLOADER(struct tep_handle *pevent)
 {
-       pevent_unregister_event_handler(pevent, -1, "kmem", "kfree",
-                                       call_site_handler, NULL);
+       tep_unregister_event_handler(pevent, -1, "kmem", "kfree",
+                                    call_site_handler, NULL);
 
-       pevent_unregister_event_handler(pevent, -1, "kmem", "kmalloc",
-                                       call_site_handler, NULL);
+       tep_unregister_event_handler(pevent, -1, "kmem", "kmalloc",
+                                    call_site_handler, NULL);
 
-       pevent_unregister_event_handler(pevent, -1, "kmem", "kmalloc_node",
-                                       call_site_handler, NULL);
+       tep_unregister_event_handler(pevent, -1, "kmem", "kmalloc_node",
+                                    call_site_handler, NULL);
 
-       pevent_unregister_event_handler(pevent, -1, "kmem", "kmem_cache_alloc",
-                                       call_site_handler, NULL);
+       tep_unregister_event_handler(pevent, -1, "kmem", "kmem_cache_alloc",
+                                    call_site_handler, NULL);
 
-       pevent_unregister_event_handler(pevent, -1, "kmem",
-                                       "kmem_cache_alloc_node",
-                                       call_site_handler, NULL);
+       tep_unregister_event_handler(pevent, -1, "kmem",
+                                    "kmem_cache_alloc_node",
+                                    call_site_handler, NULL);
 
-       pevent_unregister_event_handler(pevent, -1, "kmem", "kmem_cache_free",
-                                       call_site_handler, NULL);
+       tep_unregister_event_handler(pevent, -1, "kmem", "kmem_cache_free",
+                                    call_site_handler, NULL);
 }
index 18536f7..1d0d159 100644 (file)
@@ -247,17 +247,17 @@ static const char *find_exit_reason(unsigned isa, int val)
        return strings[i].str;
 }
 
-static int print_exit_reason(struct trace_seq *s, struct pevent_record *record,
+static int print_exit_reason(struct trace_seq *s, struct tep_record *record,
                             struct event_format *event, const char *field)
 {
        unsigned long long isa;
        unsigned long long val;
        const char *reason;
 
-       if (pevent_get_field_val(s, event, field, record, &val, 1) < 0)
+       if (tep_get_field_val(s, event, field, record, &val, 1) < 0)
                return -1;
 
-       if (pevent_get_field_val(s, event, "isa", record, &isa, 0) < 0)
+       if (tep_get_field_val(s, event, "isa", record, &isa, 0) < 0)
                isa = 1;
 
        reason = find_exit_reason(isa, val);
@@ -268,7 +268,7 @@ static int print_exit_reason(struct trace_seq *s, struct pevent_record *record,
        return 0;
 }
 
-static int kvm_exit_handler(struct trace_seq *s, struct pevent_record *record,
+static int kvm_exit_handler(struct trace_seq *s, struct tep_record *record,
                            struct event_format *event, void *context)
 {
        unsigned long long info1 = 0, info2 = 0;
@@ -276,10 +276,10 @@ static int kvm_exit_handler(struct trace_seq *s, struct pevent_record *record,
        if (print_exit_reason(s, record, event, "exit_reason") < 0)
                return -1;
 
-       pevent_print_num_field(s, " rip 0x%lx", event, "guest_rip", record, 1);
+       tep_print_num_field(s, " rip 0x%lx", event, "guest_rip", record, 1);
 
-       if (pevent_get_field_val(s, event, "info1", record, &info1, 0) >= 0
-           && pevent_get_field_val(s, event, "info2", record, &info2, 0) >= 0)
+       if (tep_get_field_val(s, event, "info1", record, &info1, 0) >= 0
+           && tep_get_field_val(s, event, "info2", record, &info2, 0) >= 0)
                trace_seq_printf(s, " info %llx %llx", info1, info2);
 
        return 0;
@@ -291,7 +291,7 @@ static int kvm_exit_handler(struct trace_seq *s, struct pevent_record *record,
 #define KVM_EMUL_INSN_F_CS_L   (1 << 3)
 
 static int kvm_emulate_insn_handler(struct trace_seq *s,
-                                   struct pevent_record *record,
+                                   struct tep_record *record,
                                    struct event_format *event, void *context)
 {
        unsigned long long rip, csbase, len, flags, failed;
@@ -299,22 +299,22 @@ static int kvm_emulate_insn_handler(struct trace_seq *s,
        uint8_t *insn;
        const char *disasm;
 
-       if (pevent_get_field_val(s, event, "rip", record, &rip, 1) < 0)
+       if (tep_get_field_val(s, event, "rip", record, &rip, 1) < 0)
                return -1;
 
-       if (pevent_get_field_val(s, event, "csbase", record, &csbase, 1) < 0)
+       if (tep_get_field_val(s, event, "csbase", record, &csbase, 1) < 0)
                return -1;
 
-       if (pevent_get_field_val(s, event, "len", record, &len, 1) < 0)
+       if (tep_get_field_val(s, event, "len", record, &len, 1) < 0)
                return -1;
 
-       if (pevent_get_field_val(s, event, "flags", record, &flags, 1) < 0)
+       if (tep_get_field_val(s, event, "flags", record, &flags, 1) < 0)
                return -1;
 
-       if (pevent_get_field_val(s, event, "failed", record, &failed, 1) < 0)
+       if (tep_get_field_val(s, event, "failed", record, &failed, 1) < 0)
                return -1;
 
-       insn = pevent_get_field_raw(s, event, "insn", record, &llen, 1);
+       insn = tep_get_field_raw(s, event, "insn", record, &llen, 1);
        if (!insn)
                return -1;
 
@@ -330,24 +330,24 @@ static int kvm_emulate_insn_handler(struct trace_seq *s,
 }
 
 
-static int kvm_nested_vmexit_inject_handler(struct trace_seq *s, struct pevent_record *record,
+static int kvm_nested_vmexit_inject_handler(struct trace_seq *s, struct tep_record *record,
                                            struct event_format *event, void *context)
 {
        if (print_exit_reason(s, record, event, "exit_code") < 0)
                return -1;
 
-       pevent_print_num_field(s, " info1 %llx", event, "exit_info1", record, 1);
-       pevent_print_num_field(s, " info2 %llx", event, "exit_info2", record, 1);
-       pevent_print_num_field(s, " int_info %llx", event, "exit_int_info", record, 1);
-       pevent_print_num_field(s, " int_info_err %llx", event, "exit_int_info_err", record, 1);
+       tep_print_num_field(s, " info1 %llx", event, "exit_info1", record, 1);
+       tep_print_num_field(s, " info2 %llx", event, "exit_info2", record, 1);
+       tep_print_num_field(s, " int_info %llx", event, "exit_int_info", record, 1);
+       tep_print_num_field(s, " int_info_err %llx", event, "exit_int_info_err", record, 1);
 
        return 0;
 }
 
-static int kvm_nested_vmexit_handler(struct trace_seq *s, struct pevent_record *record,
+static int kvm_nested_vmexit_handler(struct trace_seq *s, struct tep_record *record,
                                     struct event_format *event, void *context)
 {
-       pevent_print_num_field(s, "rip %llx ", event, "rip", record, 1);
+       tep_print_num_field(s, "rip %llx ", event, "rip", record, 1);
 
        return kvm_nested_vmexit_inject_handler(s, record, event, context);
 }
@@ -370,7 +370,7 @@ union kvm_mmu_page_role {
        };
 };
 
-static int kvm_mmu_print_role(struct trace_seq *s, struct pevent_record *record,
+static int kvm_mmu_print_role(struct trace_seq *s, struct tep_record *record,
                              struct event_format *event, void *context)
 {
        unsigned long long val;
@@ -379,7 +379,7 @@ static int kvm_mmu_print_role(struct trace_seq *s, struct pevent_record *record,
        };
        union kvm_mmu_page_role role;
 
-       if (pevent_get_field_val(s, event, "role", record, &val, 1) < 0)
+       if (tep_get_field_val(s, event, "role", record, &val, 1) < 0)
                return -1;
 
        role.word = (int)val;
@@ -388,8 +388,8 @@ static int kvm_mmu_print_role(struct trace_seq *s, struct pevent_record *record,
         * We can only use the structure if file is of the same
         * endianess.
         */
-       if (pevent_is_file_bigendian(event->pevent) ==
-           pevent_is_host_bigendian(event->pevent)) {
+       if (tep_is_file_bigendian(event->pevent) ==
+           tep_is_host_bigendian(event->pevent)) {
 
                trace_seq_printf(s, "%u q%u%s %s%s %spae %snxe %swp%s%s%s",
                                 role.level,
@@ -406,10 +406,10 @@ static int kvm_mmu_print_role(struct trace_seq *s, struct pevent_record *record,
        } else
                trace_seq_printf(s, "WORD: %08x", role.word);
 
-       pevent_print_num_field(s, " root %u ",  event,
-                              "root_count", record, 1);
+       tep_print_num_field(s, " root %u ",  event,
+                           "root_count", record, 1);
 
-       if (pevent_get_field_val(s, event, "unsync", record, &val, 1) < 0)
+       if (tep_get_field_val(s, event, "unsync", record, &val, 1) < 0)
                return -1;
 
        trace_seq_printf(s, "%s%c",  val ? "unsync" : "sync", 0);
@@ -417,17 +417,17 @@ static int kvm_mmu_print_role(struct trace_seq *s, struct pevent_record *record,
 }
 
 static int kvm_mmu_get_page_handler(struct trace_seq *s,
-                                   struct pevent_record *record,
+                                   struct tep_record *record,
                                    struct event_format *event, void *context)
 {
        unsigned long long val;
 
-       if (pevent_get_field_val(s, event, "created", record, &val, 1) < 0)
+       if (tep_get_field_val(s, event, "created", record, &val, 1) < 0)
                return -1;
 
        trace_seq_printf(s, "%s ", val ? "new" : "existing");
 
-       if (pevent_get_field_val(s, event, "gfn", record, &val, 1) < 0)
+       if (tep_get_field_val(s, event, "gfn", record, &val, 1) < 0)
                return -1;
 
        trace_seq_printf(s, "sp gfn %llx ", val);
@@ -444,79 +444,79 @@ process_is_writable_pte(struct trace_seq *s, unsigned long long *args)
        return pte & PT_WRITABLE_MASK;
 }
 
-int PEVENT_PLUGIN_LOADER(struct pevent *pevent)
+int TEP_PLUGIN_LOADER(struct tep_handle *pevent)
 {
        init_disassembler();
 
-       pevent_register_event_handler(pevent, -1, "kvm", "kvm_exit",
-                                     kvm_exit_handler, NULL);
+       tep_register_event_handler(pevent, -1, "kvm", "kvm_exit",
+                                  kvm_exit_handler, NULL);
 
-       pevent_register_event_handler(pevent, -1, "kvm", "kvm_emulate_insn",
-                                     kvm_emulate_insn_handler, NULL);
+       tep_register_event_handler(pevent, -1, "kvm", "kvm_emulate_insn",
+                                  kvm_emulate_insn_handler, NULL);
 
-       pevent_register_event_handler(pevent, -1, "kvm", "kvm_nested_vmexit",
-                                     kvm_nested_vmexit_handler, NULL);
+       tep_register_event_handler(pevent, -1, "kvm", "kvm_nested_vmexit",
+                                  kvm_nested_vmexit_handler, NULL);
 
-       pevent_register_event_handler(pevent, -1, "kvm", "kvm_nested_vmexit_inject",
-                                     kvm_nested_vmexit_inject_handler, NULL);
+       tep_register_event_handler(pevent, -1, "kvm", "kvm_nested_vmexit_inject",
+                                  kvm_nested_vmexit_inject_handler, NULL);
 
-       pevent_register_event_handler(pevent, -1, "kvmmmu", "kvm_mmu_get_page",
-                                     kvm_mmu_get_page_handler, NULL);
+       tep_register_event_handler(pevent, -1, "kvmmmu", "kvm_mmu_get_page",
+                                  kvm_mmu_get_page_handler, NULL);
 
-       pevent_register_event_handler(pevent, -1, "kvmmmu", "kvm_mmu_sync_page",
-                                     kvm_mmu_print_role, NULL);
+       tep_register_event_handler(pevent, -1, "kvmmmu", "kvm_mmu_sync_page",
+                                  kvm_mmu_print_role, NULL);
 
-       pevent_register_event_handler(pevent, -1,
-                                     "kvmmmu", "kvm_mmu_unsync_page",
-                                     kvm_mmu_print_role, NULL);
+       tep_register_event_handler(pevent, -1,
+                                  "kvmmmu", "kvm_mmu_unsync_page",
+                                  kvm_mmu_print_role, NULL);
 
-       pevent_register_event_handler(pevent, -1, "kvmmmu", "kvm_mmu_zap_page",
-                                     kvm_mmu_print_role, NULL);
+       tep_register_event_handler(pevent, -1, "kvmmmu", "kvm_mmu_zap_page",
+                                  kvm_mmu_print_role, NULL);
 
-       pevent_register_event_handler(pevent, -1, "kvmmmu",
+       tep_register_event_handler(pevent, -1, "kvmmmu",
                        "kvm_mmu_prepare_zap_page", kvm_mmu_print_role,
                        NULL);
 
-       pevent_register_print_function(pevent,
-                                      process_is_writable_pte,
-                                      PEVENT_FUNC_ARG_INT,
-                                      "is_writable_pte",
-                                      PEVENT_FUNC_ARG_LONG,
-                                      PEVENT_FUNC_ARG_VOID);
+       tep_register_print_function(pevent,
+                                   process_is_writable_pte,
+                                   TEP_FUNC_ARG_INT,
+                                   "is_writable_pte",
+                                   TEP_FUNC_ARG_LONG,
+                                   TEP_FUNC_ARG_VOID);
        return 0;
 }
 
-void PEVENT_PLUGIN_UNLOADER(struct pevent *pevent)
+void TEP_PLUGIN_UNLOADER(struct tep_handle *pevent)
 {
-       pevent_unregister_event_handler(pevent, -1, "kvm", "kvm_exit",
-                                       kvm_exit_handler, NULL);
+       tep_unregister_event_handler(pevent, -1, "kvm", "kvm_exit",
+                                    kvm_exit_handler, NULL);
 
-       pevent_unregister_event_handler(pevent, -1, "kvm", "kvm_emulate_insn",
-                                       kvm_emulate_insn_handler, NULL);
+       tep_unregister_event_handler(pevent, -1, "kvm", "kvm_emulate_insn",
+                                    kvm_emulate_insn_handler, NULL);
 
-       pevent_unregister_event_handler(pevent, -1, "kvm", "kvm_nested_vmexit",
-                                       kvm_nested_vmexit_handler, NULL);
+       tep_unregister_event_handler(pevent, -1, "kvm", "kvm_nested_vmexit",
+                                    kvm_nested_vmexit_handler, NULL);
 
-       pevent_unregister_event_handler(pevent, -1, "kvm", "kvm_nested_vmexit_inject",
-                                       kvm_nested_vmexit_inject_handler, NULL);
+       tep_unregister_event_handler(pevent, -1, "kvm", "kvm_nested_vmexit_inject",
+                                    kvm_nested_vmexit_inject_handler, NULL);
 
-       pevent_unregister_event_handler(pevent, -1, "kvmmmu", "kvm_mmu_get_page",
-                                       kvm_mmu_get_page_handler, NULL);
+       tep_unregister_event_handler(pevent, -1, "kvmmmu", "kvm_mmu_get_page",
+                                    kvm_mmu_get_page_handler, NULL);
 
-       pevent_unregister_event_handler(pevent, -1, "kvmmmu", "kvm_mmu_sync_page",
-                                       kvm_mmu_print_role, NULL);
+       tep_unregister_event_handler(pevent, -1, "kvmmmu", "kvm_mmu_sync_page",
+                                    kvm_mmu_print_role, NULL);
 
-       pevent_unregister_event_handler(pevent, -1,
-                                       "kvmmmu", "kvm_mmu_unsync_page",
-                                       kvm_mmu_print_role, NULL);
+       tep_unregister_event_handler(pevent, -1,
+                                    "kvmmmu", "kvm_mmu_unsync_page",
+                                    kvm_mmu_print_role, NULL);
 
-       pevent_unregister_event_handler(pevent, -1, "kvmmmu", "kvm_mmu_zap_page",
-                                       kvm_mmu_print_role, NULL);
+       tep_unregister_event_handler(pevent, -1, "kvmmmu", "kvm_mmu_zap_page",
+                                    kvm_mmu_print_role, NULL);
 
-       pevent_unregister_event_handler(pevent, -1, "kvmmmu",
+       tep_unregister_event_handler(pevent, -1, "kvmmmu",
                        "kvm_mmu_prepare_zap_page", kvm_mmu_print_role,
                        NULL);
 
-       pevent_unregister_print_function(pevent, process_is_writable_pte,
-                                        "is_writable_pte");
+       tep_unregister_print_function(pevent, process_is_writable_pte,
+                                     "is_writable_pte");
 }
index 7e15a0f..de50a53 100644 (file)
@@ -28,7 +28,7 @@
 static void print_string(struct trace_seq *s, struct event_format *event,
                         const char *name, const void *data)
 {
-       struct format_field *f = pevent_find_field(event, name);
+       struct format_field *f = tep_find_field(event, name);
        int offset;
        int length;
 
@@ -42,7 +42,7 @@ static void print_string(struct trace_seq *s, struct event_format *event,
 
        if (!strncmp(f->type, "__data_loc", 10)) {
                unsigned long long v;
-               if (pevent_read_number_field(f, data, &v)) {
+               if (tep_read_number_field(f, data, &v)) {
                        trace_seq_printf(s, "invalid_data_loc");
                        return;
                }
@@ -53,12 +53,12 @@ static void print_string(struct trace_seq *s, struct event_format *event,
        trace_seq_printf(s, "%.*s", length, (char *)data + offset);
 }
 
-#define SF(fn) pevent_print_num_field(s, fn ":%d", event, fn, record, 0)
-#define SFX(fn)        pevent_print_num_field(s, fn ":%#x", event, fn, record, 0)
+#define SF(fn) tep_print_num_field(s, fn ":%d", event, fn, record, 0)
+#define SFX(fn)        tep_print_num_field(s, fn ":%#x", event, fn, record, 0)
 #define SP()   trace_seq_putc(s, ' ')
 
 static int drv_bss_info_changed(struct trace_seq *s,
-                               struct pevent_record *record,
+                               struct tep_record *record,
                                struct event_format *event, void *context)
 {
        void *data = record->data;
@@ -66,7 +66,7 @@ static int drv_bss_info_changed(struct trace_seq *s,
        print_string(s, event, "wiphy_name", data);
        trace_seq_printf(s, " vif:");
        print_string(s, event, "vif_name", data);
-       pevent_print_num_field(s, "(%d)", event, "vif_type", record, 1);
+       tep_print_num_field(s, "(%d)", event, "vif_type", record, 1);
 
        trace_seq_printf(s, "\n%*s", INDENT, "");
        SF("assoc"); SP();
@@ -86,17 +86,17 @@ static int drv_bss_info_changed(struct trace_seq *s,
        return 0;
 }
 
-int PEVENT_PLUGIN_LOADER(struct pevent *pevent)
+int TEP_PLUGIN_LOADER(struct tep_handle *pevent)
 {
-       pevent_register_event_handler(pevent, -1, "mac80211",
-                                     "drv_bss_info_changed",
-                                     drv_bss_info_changed, NULL);
+       tep_register_event_handler(pevent, -1, "mac80211",
+                                  "drv_bss_info_changed",
+                                  drv_bss_info_changed, NULL);
        return 0;
 }
 
-void PEVENT_PLUGIN_UNLOADER(struct pevent *pevent)
+void TEP_PLUGIN_UNLOADER(struct tep_handle *pevent)
 {
-       pevent_unregister_event_handler(pevent, -1, "mac80211",
-                                       "drv_bss_info_changed",
-                                       drv_bss_info_changed, NULL);
+       tep_unregister_event_handler(pevent, -1, "mac80211",
+                                    "drv_bss_info_changed",
+                                    drv_bss_info_changed, NULL);
 }
index ec30c2f..eecb4bd 100644 (file)
@@ -45,7 +45,7 @@ static void write_state(struct trace_seq *s, int val)
 }
 
 static void write_and_save_comm(struct format_field *field,
-                               struct pevent_record *record,
+                               struct tep_record *record,
                                struct trace_seq *s, int pid)
 {
        const char *comm;
@@ -61,100 +61,100 @@ static void write_and_save_comm(struct format_field *field,
        comm = &s->buffer[len];
 
        /* Help out the comm to ids. This will handle dups */
-       pevent_register_comm(field->event->pevent, comm, pid);
+       tep_register_comm(field->event->pevent, comm, pid);
 }
 
 static int sched_wakeup_handler(struct trace_seq *s,
-                               struct pevent_record *record,
+                               struct tep_record *record,
                                struct event_format *event, void *context)
 {
        struct format_field *field;
        unsigned long long val;
 
-       if (pevent_get_field_val(s, event, "pid", record, &val, 1))
+       if (tep_get_field_val(s, event, "pid", record, &val, 1))
                return trace_seq_putc(s, '!');
 
-       field = pevent_find_any_field(event, "comm");
+       field = tep_find_any_field(event, "comm");
        if (field) {
                write_and_save_comm(field, record, s, val);
                trace_seq_putc(s, ':');
        }
        trace_seq_printf(s, "%lld", val);
 
-       if (pevent_get_field_val(s, event, "prio", record, &val, 0) == 0)
+       if (tep_get_field_val(s, event, "prio", record, &val, 0) == 0)
                trace_seq_printf(s, " [%lld]", val);
 
-       if (pevent_get_field_val(s, event, "success", record, &val, 1) == 0)
+       if (tep_get_field_val(s, event, "success", record, &val, 1) == 0)
                trace_seq_printf(s, " success=%lld", val);
 
-       if (pevent_get_field_val(s, event, "target_cpu", record, &val, 0) == 0)
+       if (tep_get_field_val(s, event, "target_cpu", record, &val, 0) == 0)
                trace_seq_printf(s, " CPU:%03llu", val);
 
        return 0;
 }
 
 static int sched_switch_handler(struct trace_seq *s,
-                               struct pevent_record *record,
+                               struct tep_record *record,
                                struct event_format *event, void *context)
 {
        struct format_field *field;
        unsigned long long val;
 
-       if (pevent_get_field_val(s, event, "prev_pid", record, &val, 1))
+       if (tep_get_field_val(s, event, "prev_pid", record, &val, 1))
                return trace_seq_putc(s, '!');
 
-       field = pevent_find_any_field(event, "prev_comm");
+       field = tep_find_any_field(event, "prev_comm");
        if (field) {
                write_and_save_comm(field, record, s, val);
                trace_seq_putc(s, ':');
        }
        trace_seq_printf(s, "%lld ", val);
 
-       if (pevent_get_field_val(s, event, "prev_prio", record, &val, 0) == 0)
+       if (tep_get_field_val(s, event, "prev_prio", record, &val, 0) == 0)
                trace_seq_printf(s, "[%d] ", (int) val);
 
-       if (pevent_get_field_val(s,  event, "prev_state", record, &val, 0) == 0)
+       if (tep_get_field_val(s,  event, "prev_state", record, &val, 0) == 0)
                write_state(s, val);
 
        trace_seq_puts(s, " ==> ");
 
-       if (pevent_get_field_val(s, event, "next_pid", record, &val, 1))
+       if (tep_get_field_val(s, event, "next_pid", record, &val, 1))
                return trace_seq_putc(s, '!');
 
-       field = pevent_find_any_field(event, "next_comm");
+       field = tep_find_any_field(event, "next_comm");
        if (field) {
                write_and_save_comm(field, record, s, val);
                trace_seq_putc(s, ':');
        }
        trace_seq_printf(s, "%lld", val);
 
-       if (pevent_get_field_val(s, event, "next_prio", record, &val, 0) == 0)
+       if (tep_get_field_val(s, event, "next_prio", record, &val, 0) == 0)
                trace_seq_printf(s, " [%d]", (int) val);
 
        return 0;
 }
 
-int PEVENT_PLUGIN_LOADER(struct pevent *pevent)
+int TEP_PLUGIN_LOADER(struct tep_handle *pevent)
 {
-       pevent_register_event_handler(pevent, -1, "sched", "sched_switch",
-                                     sched_switch_handler, NULL);
+       tep_register_event_handler(pevent, -1, "sched", "sched_switch",
+                                  sched_switch_handler, NULL);
 
-       pevent_register_event_handler(pevent, -1, "sched", "sched_wakeup",
-                                     sched_wakeup_handler, NULL);
+       tep_register_event_handler(pevent, -1, "sched", "sched_wakeup",
+                                  sched_wakeup_handler, NULL);
 
-       pevent_register_event_handler(pevent, -1, "sched", "sched_wakeup_new",
-                                     sched_wakeup_handler, NULL);
+       tep_register_event_handler(pevent, -1, "sched", "sched_wakeup_new",
+                                  sched_wakeup_handler, NULL);
        return 0;
 }
 
-void PEVENT_PLUGIN_UNLOADER(struct pevent *pevent)
+void TEP_PLUGIN_UNLOADER(struct tep_handle *pevent)
 {
-       pevent_unregister_event_handler(pevent, -1, "sched", "sched_switch",
-                                       sched_switch_handler, NULL);
+       tep_unregister_event_handler(pevent, -1, "sched", "sched_switch",
+                                    sched_switch_handler, NULL);
 
-       pevent_unregister_event_handler(pevent, -1, "sched", "sched_wakeup",
-                                       sched_wakeup_handler, NULL);
+       tep_unregister_event_handler(pevent, -1, "sched", "sched_wakeup",
+                                    sched_wakeup_handler, NULL);
 
-       pevent_unregister_event_handler(pevent, -1, "sched", "sched_wakeup_new",
-                                       sched_wakeup_handler, NULL);
+       tep_unregister_event_handler(pevent, -1, "sched", "sched_wakeup_new",
+                                    sched_wakeup_handler, NULL);
 }
index 5e750af..5ec346f 100644 (file)
@@ -413,21 +413,21 @@ unsigned long long process_scsi_trace_parse_cdb(struct trace_seq *s,
        return 0;
 }
 
-int PEVENT_PLUGIN_LOADER(struct pevent *pevent)
+int TEP_PLUGIN_LOADER(struct tep_handle *pevent)
 {
-       pevent_register_print_function(pevent,
-                                      process_scsi_trace_parse_cdb,
-                                      PEVENT_FUNC_ARG_STRING,
-                                      "scsi_trace_parse_cdb",
-                                      PEVENT_FUNC_ARG_PTR,
-                                      PEVENT_FUNC_ARG_PTR,
-                                      PEVENT_FUNC_ARG_INT,
-                                      PEVENT_FUNC_ARG_VOID);
+       tep_register_print_function(pevent,
+                                   process_scsi_trace_parse_cdb,
+                                   TEP_FUNC_ARG_STRING,
+                                   "scsi_trace_parse_cdb",
+                                   TEP_FUNC_ARG_PTR,
+                                   TEP_FUNC_ARG_PTR,
+                                   TEP_FUNC_ARG_INT,
+                                   TEP_FUNC_ARG_VOID);
        return 0;
 }
 
-void PEVENT_PLUGIN_UNLOADER(struct pevent *pevent)
+void TEP_PLUGIN_UNLOADER(struct tep_handle *pevent)
 {
-       pevent_unregister_print_function(pevent, process_scsi_trace_parse_cdb,
-                                        "scsi_trace_parse_cdb");
+       tep_unregister_print_function(pevent, process_scsi_trace_parse_cdb,
+                                     "scsi_trace_parse_cdb");
 }
index 690173b..b2acbd6 100644 (file)
@@ -119,19 +119,19 @@ unsigned long long process_xen_hypercall_name(struct trace_seq *s,
        return 0;
 }
 
-int PEVENT_PLUGIN_LOADER(struct pevent *pevent)
+int TEP_PLUGIN_LOADER(struct tep_handle *pevent)
 {
-       pevent_register_print_function(pevent,
-                                      process_xen_hypercall_name,
-                                      PEVENT_FUNC_ARG_STRING,
-                                      "xen_hypercall_name",
-                                      PEVENT_FUNC_ARG_INT,
-                                      PEVENT_FUNC_ARG_VOID);
+       tep_register_print_function(pevent,
+                                   process_xen_hypercall_name,
+                                   TEP_FUNC_ARG_STRING,
+                                   "xen_hypercall_name",
+                                   TEP_FUNC_ARG_INT,
+                                   TEP_FUNC_ARG_VOID);
        return 0;
 }
 
-void PEVENT_PLUGIN_UNLOADER(struct pevent *pevent)
+void TEP_PLUGIN_UNLOADER(struct tep_handle *pevent)
 {
-       pevent_unregister_print_function(pevent, process_xen_hypercall_name,
-                                        "xen_hypercall_name");
+       tep_unregister_print_function(pevent, process_xen_hypercall_name,
+                                     "xen_hypercall_name");
 }
index 292dc9f..e3bac45 100644 (file)
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: LGPL-2.1
 /*
  * Copyright (C) 2009 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
  *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License (not later!)
- *
- * 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not,  see <http://www.gnu.org/licenses>
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  */
 #include <stdio.h>
 #include <stdlib.h>
index 749cc60..e8c972f 100644 (file)
@@ -118,6 +118,15 @@ OPTIONS
 --group::
        Show event group information together
 
+--percent-type::
+       Set annotation percent type from following choices:
+         global-period, local-period, global-hits, local-hits
+
+       The local/global keywords set if the percentage is computed
+       in the scope of the function (local) or the whole data (global).
+       The period/hits keywords set the base the percentage is computed
+       on - the samples period or the number of samples (hits).
+
 SEE ALSO
 --------
 linkperf:perf-record[1], linkperf:perf-report[1]
index 917e36f..474a494 100644 (file)
@@ -477,6 +477,15 @@ include::itrace.txt[]
        Display monitored tasks stored in perf data. Displaying pid/tid/ppid
        plus the command string aligned to distinguish parent and child tasks.
 
+--percent-type::
+       Set annotation percent type from following choices:
+         global-period, local-period, global-hits, local-hits
+
+       The local/global keywords set if the percentage is computed
+       in the scope of the function (local) or the whole data (global).
+       The period/hits keywords set the base the percentage is computed
+       on - the samples period or the number of samples (hits).
+
 include::callchain-overhead-calculation.txt[]
 
 SEE ALSO
index 2254544..7902a56 100644 (file)
@@ -84,10 +84,10 @@ endif # has_clean
 endif # MAKECMDGOALS
 
 #
-# The clean target is not really parallel, don't print the jobs info:
+# Explicitly disable parallelism for the clean target.
 #
 clean:
-       $(make)
+       $(make) -j1
 
 #
 # The build-test target is not really parallel, don't print the jobs info,
index 1120e39..5ccfce8 100644 (file)
@@ -194,6 +194,7 @@ struct auxtrace_record *arm_spe_recording_init(int *err,
        sper->itr.read_finish = arm_spe_read_finish;
        sper->itr.alignment = 0;
 
+       *err = 0;
        return &sper->itr;
 }
 
index 53d83d7..20e7d74 100644 (file)
@@ -141,8 +141,10 @@ void arch__post_process_probe_trace_events(struct perf_probe_event *pev,
        for (i = 0; i < ntevs; i++) {
                tev = &pev->tevs[i];
                map__for_each_symbol(map, sym, tmp) {
-                       if (map->unmap_ip(map, sym->start) == tev->point.address)
+                       if (map->unmap_ip(map, sym->start) == tev->point.address) {
                                arch__fix_tev_from_maps(pev, tev, map, sym);
+                               break;
+                       }
                }
        }
 }
index 3afe825..44c8573 100644 (file)
@@ -30,6 +30,7 @@ cpumsf_info_fill(struct auxtrace_record *itr __maybe_unused,
                 struct auxtrace_info_event *auxtrace_info __maybe_unused,
                 size_t priv_size __maybe_unused)
 {
+       auxtrace_info->type = PERF_AUXTRACE_S390_CPUMSF;
        return 0;
 }
 
index 1a38e78..8cc6642 100644 (file)
@@ -19,9 +19,6 @@ systbl := $(sys)/syscalltbl.sh
 _dummy := $(shell [ -d '$(out)' ] || mkdir -p '$(out)')
 
 $(header): $(sys)/syscall_64.tbl $(systbl)
-       @(test -d ../../kernel -a -d ../../tools -a -d ../perf && ( \
-        (diff -B arch/x86/entry/syscalls/syscall_64.tbl ../../arch/x86/entry/syscalls/syscall_64.tbl >/dev/null) \
-        || echo "Warning: Kernel ABI header at 'tools/perf/arch/x86/entry/syscalls/syscall_64.tbl' differs from latest version at 'arch/x86/entry/syscalls/syscall_64.tbl'" >&2 )) || true
        $(Q)$(SHELL) '$(systbl)' $(sys)/syscall_64.tbl 'x86_64' > $@
 
 clean::
index 8180319..830481b 100644 (file)
@@ -542,6 +542,10 @@ int cmd_annotate(int argc, const char **argv)
        OPT_CALLBACK_DEFAULT(0, "stdio-color", NULL, "mode",
                             "'always' (default), 'never' or 'auto' only applicable to --stdio mode",
                             stdio__config_color, "always"),
+       OPT_CALLBACK(0, "percent-type", &annotate.opts, "local-period",
+                    "Set percent type local/global-period/hits",
+                    annotate_parse_percent_type),
+
        OPT_END()
        };
        int ret;
index 54d3f21..b63bca4 100644 (file)
@@ -729,7 +729,7 @@ static char *compact_gfp_string(unsigned long gfp_flags)
 static int parse_gfp_flags(struct perf_evsel *evsel, struct perf_sample *sample,
                           unsigned int gfp_flags)
 {
-       struct pevent_record record = {
+       struct tep_record record = {
                .cpu = sample->cpu,
                .data = sample->raw_data,
                .size = sample->raw_size,
@@ -747,7 +747,7 @@ static int parse_gfp_flags(struct perf_evsel *evsel, struct perf_sample *sample,
        }
 
        trace_seq_init(&seq);
-       pevent_event_info(&seq, evsel->tp_format, &record);
+       tep_event_info(&seq, evsel->tp_format, &record);
 
        str = strtok_r(seq.buffer, " ", &pos);
        while (str) {
@@ -1974,7 +1974,7 @@ int cmd_kmem(int argc, const char **argv)
                        goto out_delete;
                }
 
-               kmem_page_size = pevent_get_page_size(evsel->tp_format->pevent);
+               kmem_page_size = tep_get_page_size(evsel->tp_format->pevent);
                symbol_conf.use_callchain = true;
        }
 
index 02f7a3c..76e12bc 100644 (file)
@@ -1124,6 +1124,9 @@ int cmd_report(int argc, const char **argv)
                   "Time span of interest (start,stop)"),
        OPT_BOOLEAN(0, "inline", &symbol_conf.inline_name,
                    "Show inline function"),
+       OPT_CALLBACK(0, "percent-type", &report.annotation_opts, "local-period",
+                    "Set percent type local/global-period/hits",
+                    annotate_parse_percent_type),
        OPT_END()
        };
        struct perf_data data = {
@@ -1366,9 +1369,9 @@ repeat:
        }
 
        if (session->tevent.pevent &&
-           pevent_set_function_resolver(session->tevent.pevent,
-                                        machine__resolve_kernel_addr,
-                                        &session->machines.host) < 0) {
+           tep_set_function_resolver(session->tevent.pevent,
+                                     machine__resolve_kernel_addr,
+                                     &session->machines.host) < 0) {
                pr_err("%s: failed to set libtraceevent function resolver\n",
                       __func__);
                return -1;
index 568ddfa..ba481d7 100644 (file)
@@ -3429,9 +3429,9 @@ int cmd_script(int argc, const char **argv)
                symbol_conf.use_callchain = false;
 
        if (session->tevent.pevent &&
-           pevent_set_function_resolver(session->tevent.pevent,
-                                        machine__resolve_kernel_addr,
-                                        &session->machines.host) < 0) {
+           tep_set_function_resolver(session->tevent.pevent,
+                                     machine__resolve_kernel_addr,
+                                     &session->machines.host) < 0) {
                pr_err("%s: failed to set libtraceevent function resolver\n", __func__);
                err = -1;
                goto out_delete;
index 88561ee..22ab8e6 100644 (file)
@@ -77,7 +77,8 @@ struct trace {
                struct syscall  *table;
                struct {
                        struct perf_evsel *sys_enter,
-                                         *sys_exit;
+                                         *sys_exit,
+                                         *augmented;
                }               events;
        } syscalls;
        struct record_opts      opts;
@@ -121,7 +122,6 @@ struct trace {
        bool                    force;
        bool                    vfs_getname;
        int                     trace_pgfaults;
-       int                     open_id;
 };
 
 struct tp_field {
@@ -157,13 +157,11 @@ TP_UINT_FIELD__SWAPPED(16);
 TP_UINT_FIELD__SWAPPED(32);
 TP_UINT_FIELD__SWAPPED(64);
 
-static int tp_field__init_uint(struct tp_field *field,
-                              struct format_field *format_field,
-                              bool needs_swap)
+static int __tp_field__init_uint(struct tp_field *field, int size, int offset, bool needs_swap)
 {
-       field->offset = format_field->offset;
+       field->offset = offset;
 
-       switch (format_field->size) {
+       switch (size) {
        case 1:
                field->integer = tp_field__u8;
                break;
@@ -183,18 +181,28 @@ static int tp_field__init_uint(struct tp_field *field,
        return 0;
 }
 
+static int tp_field__init_uint(struct tp_field *field, struct format_field *format_field, bool needs_swap)
+{
+       return __tp_field__init_uint(field, format_field->size, format_field->offset, needs_swap);
+}
+
 static void *tp_field__ptr(struct tp_field *field, struct perf_sample *sample)
 {
        return sample->raw_data + field->offset;
 }
 
-static int tp_field__init_ptr(struct tp_field *field, struct format_field *format_field)
+static int __tp_field__init_ptr(struct tp_field *field, int offset)
 {
-       field->offset = format_field->offset;
+       field->offset = offset;
        field->pointer = tp_field__ptr;
        return 0;
 }
 
+static int tp_field__init_ptr(struct tp_field *field, struct format_field *format_field)
+{
+       return __tp_field__init_ptr(field, format_field->offset);
+}
+
 struct syscall_tp {
        struct tp_field id;
        union {
@@ -240,7 +248,47 @@ static void perf_evsel__delete_priv(struct perf_evsel *evsel)
        perf_evsel__delete(evsel);
 }
 
-static int perf_evsel__init_syscall_tp(struct perf_evsel *evsel, void *handler)
+static int perf_evsel__init_syscall_tp(struct perf_evsel *evsel)
+{
+       struct syscall_tp *sc = evsel->priv = malloc(sizeof(struct syscall_tp));
+
+       if (evsel->priv != NULL) {
+               if (perf_evsel__init_tp_uint_field(evsel, &sc->id, "__syscall_nr"))
+                       goto out_delete;
+               return 0;
+       }
+
+       return -ENOMEM;
+out_delete:
+       zfree(&evsel->priv);
+       return -ENOENT;
+}
+
+static int perf_evsel__init_augmented_syscall_tp(struct perf_evsel *evsel)
+{
+       struct syscall_tp *sc = evsel->priv = malloc(sizeof(struct syscall_tp));
+
+       if (evsel->priv != NULL) {       /* field, sizeof_field, offsetof_field */
+               if (__tp_field__init_uint(&sc->id, sizeof(long), sizeof(long long), evsel->needs_swap))
+                       goto out_delete;
+
+               return 0;
+       }
+
+       return -ENOMEM;
+out_delete:
+       zfree(&evsel->priv);
+       return -EINVAL;
+}
+
+static int perf_evsel__init_augmented_syscall_tp_args(struct perf_evsel *evsel)
+{
+       struct syscall_tp *sc = evsel->priv;
+
+       return __tp_field__init_ptr(&sc->args, sc->id.offset + sizeof(u64));
+}
+
+static int perf_evsel__init_raw_syscall_tp(struct perf_evsel *evsel, void *handler)
 {
        evsel->priv = malloc(sizeof(struct syscall_tp));
        if (evsel->priv != NULL) {
@@ -258,7 +306,7 @@ out_delete:
        return -ENOENT;
 }
 
-static struct perf_evsel *perf_evsel__syscall_newtp(const char *direction, void *handler)
+static struct perf_evsel *perf_evsel__raw_syscall_newtp(const char *direction, void *handler)
 {
        struct perf_evsel *evsel = perf_evsel__newtp("raw_syscalls", direction);
 
@@ -269,7 +317,7 @@ static struct perf_evsel *perf_evsel__syscall_newtp(const char *direction, void
        if (IS_ERR(evsel))
                return NULL;
 
-       if (perf_evsel__init_syscall_tp(evsel, handler))
+       if (perf_evsel__init_raw_syscall_tp(evsel, handler))
                goto out_delete;
 
        return evsel;
@@ -805,12 +853,17 @@ static struct syscall_fmt *syscall_fmt__find(const char *name)
        return bsearch(name, syscall_fmts, nmemb, sizeof(struct syscall_fmt), syscall_fmt__cmp);
 }
 
+/*
+ * is_exit: is this "exit" or "exit_group"?
+ * is_open: is this "open" or "openat"? To associate the fd returned in sys_exit with the pathname in sys_enter.
+ */
 struct syscall {
        struct event_format *tp_format;
        int                 nr_args;
+       bool                is_exit;
+       bool                is_open;
        struct format_field *args;
        const char          *name;
-       bool                is_exit;
        struct syscall_fmt  *fmt;
        struct syscall_arg_fmt *arg_fmt;
 };
@@ -1299,6 +1352,7 @@ static int trace__read_syscall_info(struct trace *trace, int id)
        }
 
        sc->is_exit = !strcmp(name, "exit_group") || !strcmp(name, "exit");
+       sc->is_open = !strcmp(name, "open") || !strcmp(name, "openat");
 
        return syscall__set_arg_fmts(sc);
 }
@@ -1661,6 +1715,37 @@ out_put:
        return err;
 }
 
+static int trace__fprintf_sys_enter(struct trace *trace, struct perf_evsel *evsel,
+                                   struct perf_sample *sample)
+{
+       struct thread_trace *ttrace;
+       struct thread *thread;
+       int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1;
+       struct syscall *sc = trace__syscall_info(trace, evsel, id);
+       char msg[1024];
+       void *args;
+
+       if (sc == NULL)
+               return -1;
+
+       thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
+       ttrace = thread__trace(thread, trace->output);
+       /*
+        * We need to get ttrace just to make sure it is there when syscall__scnprintf_args()
+        * and the rest of the beautifiers accessing it via struct syscall_arg touches it.
+        */
+       if (ttrace == NULL)
+               goto out_put;
+
+       args = perf_evsel__sc_tp_ptr(evsel, args, sample);
+       syscall__scnprintf_args(sc, msg, sizeof(msg), args, trace, thread);
+       fprintf(trace->output, "%s", msg);
+       err = 0;
+out_put:
+       thread__put(thread);
+       return err;
+}
+
 static int trace__resolve_callchain(struct trace *trace, struct perf_evsel *evsel,
                                    struct perf_sample *sample,
                                    struct callchain_cursor *cursor)
@@ -1722,7 +1807,7 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
 
        ret = perf_evsel__sc_tp_uint(evsel, ret, sample);
 
-       if (id == trace->open_id && ret >= 0 && ttrace->filename.pending_open) {
+       if (sc->is_open && ret >= 0 && ttrace->filename.pending_open) {
                trace__set_fd_pathname(thread, ret, ttrace->filename.name);
                ttrace->filename.pending_open = false;
                ++trace->stats.vfs_getname;
@@ -1957,11 +2042,17 @@ static int trace__event_handler(struct trace *trace, struct perf_evsel *evsel,
        fprintf(trace->output, "%s:", evsel->name);
 
        if (perf_evsel__is_bpf_output(evsel)) {
-               bpf_output__fprintf(trace, sample);
+               if (evsel == trace->syscalls.events.augmented)
+                       trace__fprintf_sys_enter(trace, evsel, sample);
+               else
+                       bpf_output__fprintf(trace, sample);
        } else if (evsel->tp_format) {
-               event_format__fprintf(evsel->tp_format, sample->cpu,
-                                     sample->raw_data, sample->raw_size,
-                                     trace->output);
+               if (strncmp(evsel->tp_format->name, "sys_enter_", 10) ||
+                   trace__fprintf_sys_enter(trace, evsel, sample)) {
+                       event_format__fprintf(evsel->tp_format, sample->cpu,
+                                             sample->raw_data, sample->raw_size,
+                                             trace->output);
+               }
        }
 
        fprintf(trace->output, "\n");
@@ -2242,14 +2333,14 @@ static int trace__add_syscall_newtp(struct trace *trace)
        struct perf_evlist *evlist = trace->evlist;
        struct perf_evsel *sys_enter, *sys_exit;
 
-       sys_enter = perf_evsel__syscall_newtp("sys_enter", trace__sys_enter);
+       sys_enter = perf_evsel__raw_syscall_newtp("sys_enter", trace__sys_enter);
        if (sys_enter == NULL)
                goto out;
 
        if (perf_evsel__init_sc_tp_ptr_field(sys_enter, args))
                goto out_delete_sys_enter;
 
-       sys_exit = perf_evsel__syscall_newtp("sys_exit", trace__sys_exit);
+       sys_exit = perf_evsel__raw_syscall_newtp("sys_exit", trace__sys_exit);
        if (sys_exit == NULL)
                goto out_delete_sys_enter;
 
@@ -2671,7 +2762,7 @@ static int trace__replay(struct trace *trace)
                                                             "syscalls:sys_enter");
 
        if (evsel &&
-           (perf_evsel__init_syscall_tp(evsel, trace__sys_enter) < 0 ||
+           (perf_evsel__init_raw_syscall_tp(evsel, trace__sys_enter) < 0 ||
            perf_evsel__init_sc_tp_ptr_field(evsel, args))) {
                pr_err("Error during initialize raw_syscalls:sys_enter event\n");
                goto out;
@@ -2683,7 +2774,7 @@ static int trace__replay(struct trace *trace)
                evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
                                                             "syscalls:sys_exit");
        if (evsel &&
-           (perf_evsel__init_syscall_tp(evsel, trace__sys_exit) < 0 ||
+           (perf_evsel__init_raw_syscall_tp(evsel, trace__sys_exit) < 0 ||
            perf_evsel__init_sc_tp_uint_field(evsel, ret))) {
                pr_err("Error during initialize raw_syscalls:sys_exit event\n");
                goto out;
@@ -2923,6 +3014,36 @@ static void evlist__set_evsel_handler(struct perf_evlist *evlist, void *handler)
                evsel->handler = handler;
 }
 
+static int evlist__set_syscall_tp_fields(struct perf_evlist *evlist)
+{
+       struct perf_evsel *evsel;
+
+       evlist__for_each_entry(evlist, evsel) {
+               if (evsel->priv || !evsel->tp_format)
+                       continue;
+
+               if (strcmp(evsel->tp_format->system, "syscalls"))
+                       continue;
+
+               if (perf_evsel__init_syscall_tp(evsel))
+                       return -1;
+
+               if (!strncmp(evsel->tp_format->name, "sys_enter_", 10)) {
+                       struct syscall_tp *sc = evsel->priv;
+
+                       if (__tp_field__init_ptr(&sc->args, sc->id.offset + sizeof(u64)))
+                               return -1;
+               } else if (!strncmp(evsel->tp_format->name, "sys_exit_", 9)) {
+                       struct syscall_tp *sc = evsel->priv;
+
+                       if (__tp_field__init_uint(&sc->ret, sizeof(u64), sc->id.offset + sizeof(u64), evsel->needs_swap))
+                               return -1;
+               }
+       }
+
+       return 0;
+}
+
 /*
  * XXX: Hackish, just splitting the combined -e+--event (syscalls
  * (raw_syscalls:{sys_{enter,exit}} + events (tracepoints, HW, SW, etc) to use
@@ -3123,8 +3244,9 @@ int cmd_trace(int argc, const char **argv)
        };
        bool __maybe_unused max_stack_user_set = true;
        bool mmap_pages_user_set = true;
+       struct perf_evsel *evsel;
        const char * const trace_subcommands[] = { "record", NULL };
-       int err;
+       int err = -1;
        char bf[BUFSIZ];
 
        signal(SIGSEGV, sighandler_dump_stack);
@@ -3147,6 +3269,20 @@ int cmd_trace(int argc, const char **argv)
                                       "cgroup monitoring only available in system-wide mode");
        }
 
+       evsel = bpf__setup_output_event(trace.evlist, "__augmented_syscalls__");
+       if (IS_ERR(evsel)) {
+               bpf__strerror_setup_output_event(trace.evlist, PTR_ERR(evsel), bf, sizeof(bf));
+               pr_err("ERROR: Setup trace syscalls enter failed: %s\n", bf);
+               goto out;
+       }
+
+       if (evsel) {
+               if (perf_evsel__init_augmented_syscall_tp(evsel) ||
+                   perf_evsel__init_augmented_syscall_tp_args(evsel))
+                       goto out;
+               trace.syscalls.events.augmented = evsel;
+       }
+
        err = bpf__setup_stdout(trace.evlist);
        if (err) {
                bpf__strerror_setup_stdout(trace.evlist, err, bf, sizeof(bf));
@@ -3182,8 +3318,13 @@ int cmd_trace(int argc, const char **argv)
                symbol_conf.use_callchain = true;
        }
 
-       if (trace.evlist->nr_entries > 0)
+       if (trace.evlist->nr_entries > 0) {
                evlist__set_evsel_handler(trace.evlist, trace__event_handler);
+               if (evlist__set_syscall_tp_fields(trace.evlist)) {
+                       perror("failed to set syscalls:* tracepoint fields");
+                       goto out;
+               }
+       }
 
        if ((argc >= 1) && (strcmp(argv[0], "record") == 0))
                return trace__record(&trace, argc-1, &argv[1]);
@@ -3205,8 +3346,6 @@ int cmd_trace(int argc, const char **argv)
                }
        }
 
-       trace.open_id = syscalltbl__id(trace.sctbl, "open");
-
        err = target__validate(&trace.opts.target);
        if (err) {
                target__strerror(&trace.opts.target, err, bf, sizeof(bf));
index de28466..466540e 100755 (executable)
@@ -67,8 +67,12 @@ check_2 () {
 
   cmd="diff $* $file1 $file2 > /dev/null"
 
-  test -f $file2 &&
-  eval $cmd || echo "Warning: Kernel ABI header at 'tools/$file' differs from latest version at '$file'" >&2
+  test -f $file2 && {
+    eval $cmd || {
+      echo "Warning: Kernel ABI header at '$file1' differs from latest version at '$file2'" >&2
+      echo diff -u $file1 $file2
+    }
+  }
 }
 
 check () {
@@ -76,7 +80,7 @@ check () {
 
   shift
 
-  check_2 ../$file ../../$file $*
+  check_2 tools/$file $file $*
 }
 
 # Check if we have the kernel headers (tools/perf/../../include), else
@@ -84,6 +88,8 @@ check () {
 # differences.
 test -d ../../include || exit 0
 
+cd ../..
+
 # simple diff check
 for i in $HEADERS; do
   check $i -B
@@ -94,3 +100,8 @@ check arch/x86/lib/memcpy_64.S        '-I "^EXPORT_SYMBOL" -I "^#include <asm/ex
 check arch/x86/lib/memset_64.S        '-I "^EXPORT_SYMBOL" -I "^#include <asm/export.h>"'
 check include/uapi/asm-generic/mman.h '-I "^#include <\(uapi/\)*asm-generic/mman-common.h>"'
 check include/uapi/linux/mman.h       '-I "^#include <\(uapi/\)*asm/mman.h>"'
+
+# diff non-symmetric files
+check_2 tools/perf/arch/x86/entry/syscalls/syscall_64.tbl arch/x86/entry/syscalls/syscall_64.tbl
+
+cd tools/perf
diff --git a/tools/perf/examples/bpf/augmented_syscalls.c b/tools/perf/examples/bpf/augmented_syscalls.c
new file mode 100644 (file)
index 0000000..69a3138
--- /dev/null
@@ -0,0 +1,55 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Augment the openat syscall with the contents of the filename pointer argument.
+ *
+ * Test it with:
+ *
+ * perf trace -e tools/perf/examples/bpf/augmented_syscalls.c cat /etc/passwd > /dev/null
+ *
+ * It'll catch some openat syscalls related to the dynamic linked and
+ * the last one should be the one for '/etc/passwd'.
+ *
+ * This matches what is marshalled into the raw_syscall:sys_enter payload
+ * expected by the 'perf trace' beautifiers, and can be used by them unmodified,
+ * which will be done as that feature is implemented in the next csets, for now
+ * it will appear in a dump done by the default tracepoint handler in 'perf trace',
+ * that uses bpf_output__fprintf() to just dump those contents, as done with
+ * the bpf-output event associated with the __bpf_output__ map declared in
+ * tools/perf/include/bpf/stdio.h.
+ */
+
+#include <stdio.h>
+
+struct bpf_map SEC("maps") __augmented_syscalls__ = {
+       .type = BPF_MAP_TYPE_PERF_EVENT_ARRAY,
+       .key_size = sizeof(int),
+       .value_size = sizeof(u32),
+       .max_entries = __NR_CPUS__,
+};
+
+struct syscall_enter_openat_args {
+       unsigned long long common_tp_fields;
+       long               syscall_nr;
+       long               dfd;
+       char               *filename_ptr;
+       long               flags;
+       long               mode;
+};
+
+struct augmented_enter_openat_args {
+       struct syscall_enter_openat_args args;
+       char                             filename[64];
+};
+
+int syscall_enter(openat)(struct syscall_enter_openat_args *args)
+{
+       struct augmented_enter_openat_args augmented_args;
+
+       probe_read(&augmented_args.args, sizeof(augmented_args.args), args);
+       probe_read_str(&augmented_args.filename, sizeof(augmented_args.filename), args->filename_ptr);
+       perf_event_output(args, &__augmented_syscalls__, BPF_F_CURRENT_CPU,
+                         &augmented_args, sizeof(augmented_args));
+       return 1;
+}
+
+license(GPL);
diff --git a/tools/perf/examples/bpf/hello.c b/tools/perf/examples/bpf/hello.c
new file mode 100644 (file)
index 0000000..cf3c2fd
--- /dev/null
@@ -0,0 +1,9 @@
+#include <stdio.h>
+
+int syscall_enter(openat)(void *args)
+{
+       puts("Hello, world\n");
+       return 0;
+}
+
+license(GPL);
diff --git a/tools/perf/examples/bpf/sys_enter_openat.c b/tools/perf/examples/bpf/sys_enter_openat.c
new file mode 100644 (file)
index 0000000..9cd124b
--- /dev/null
@@ -0,0 +1,33 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Hook into 'openat' syscall entry tracepoint
+ *
+ * Test it with:
+ *
+ * perf trace -e tools/perf/examples/bpf/sys_enter_openat.c cat /etc/passwd > /dev/null
+ *
+ * It'll catch some openat syscalls related to the dynamic linked and
+ * the last one should be the one for '/etc/passwd'.
+ *
+ * The syscall_enter_openat_args can be used to get the syscall fields
+ * and use them for filtering calls, i.e. use in expressions for
+ * the return value.
+ */
+
+#include <bpf.h>
+
+struct syscall_enter_openat_args {
+       unsigned long long unused;
+       long               syscall_nr;
+       long               dfd;
+       char               *filename_ptr;
+       long               flags;
+       long               mode;
+};
+
+int syscall_enter(openat)(struct syscall_enter_openat_args *args)
+{
+       return 1;
+}
+
+license(GPL);
index a63aa62..47897d6 100644 (file)
@@ -4,13 +4,33 @@
 
 #include <uapi/linux/bpf.h>
 
+/*
+ * A helper structure used by eBPF C program to describe map attributes to
+ * elf_bpf loader, taken from tools/testing/selftests/bpf/bpf_helpers.h:
+ */
+struct bpf_map {
+        unsigned int type;
+        unsigned int key_size;
+        unsigned int value_size;
+        unsigned int max_entries;
+        unsigned int map_flags;
+        unsigned int inner_map_idx;
+        unsigned int numa_node;
+};
+
 #define SEC(NAME) __attribute__((section(NAME),  used))
 
 #define probe(function, vars) \
        SEC(#function "=" #function " " #vars) function
 
+#define syscall_enter(name) \
+       SEC("syscalls:sys_enter_" #name) syscall_enter_ ## name
+
 #define license(name) \
 char _license[] SEC("license") = #name; \
 int _version SEC("version") = LINUX_VERSION_CODE;
 
+static int (*probe_read)(void *dst, int size, const void *unsafe_addr) = (void *)BPF_FUNC_probe_read;
+static int (*probe_read_str)(void *dst, int size, const void *unsafe_addr) = (void *)BPF_FUNC_probe_read_str;
+
 #endif /* _PERF_BPF_H */
diff --git a/tools/perf/include/bpf/stdio.h b/tools/perf/include/bpf/stdio.h
new file mode 100644 (file)
index 0000000..2899cb7
--- /dev/null
@@ -0,0 +1,19 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <bpf.h>
+
+struct bpf_map SEC("maps") __bpf_stdout__ = {
+       .type = BPF_MAP_TYPE_PERF_EVENT_ARRAY,
+       .key_size = sizeof(int),
+       .value_size = sizeof(u32),
+       .max_entries = __NR_CPUS__,
+};
+
+static int (*perf_event_output)(void *, struct bpf_map *, int, void *, unsigned long) =
+       (void *)BPF_FUNC_perf_event_output;
+
+#define puts(from) \
+       ({ const int __len = sizeof(from); \
+          char __from[__len] = from; \
+          perf_event_output(args, &__bpf_stdout__, BPF_F_CURRENT_CPU, \
+                         &__from, __len & (sizeof(from) - 1)); })
diff --git a/tools/perf/pmu-events/arch/arm64/ampere/emag/core-imp-def.json b/tools/perf/pmu-events/arch/arm64/ampere/emag/core-imp-def.json
new file mode 100644 (file)
index 0000000..bc03c06
--- /dev/null
@@ -0,0 +1,32 @@
+[
+    {
+        "ArchStdEvent": "L1D_CACHE_RD",
+    },
+    {
+        "ArchStdEvent": "L1D_CACHE_WR",
+    },
+    {
+        "ArchStdEvent": "L1D_CACHE_REFILL_RD",
+    },
+    {
+        "ArchStdEvent": "L1D_CACHE_REFILL_WR",
+    },
+    {
+        "ArchStdEvent": "L1D_TLB_REFILL_RD",
+    },
+    {
+        "ArchStdEvent": "L1D_TLB_REFILL_WR",
+    },
+    {
+        "ArchStdEvent": "L1D_TLB_RD",
+    },
+    {
+        "ArchStdEvent": "L1D_TLB_WR",
+    },
+    {
+        "ArchStdEvent": "BUS_ACCESS_RD",
+   },
+   {
+        "ArchStdEvent": "BUS_ACCESS_WR",
+   }
+]
index f03e26e..59cd860 100644 (file)
@@ -16,3 +16,4 @@
 0x00000000420f5160,v1,cavium/thunderx2,core
 0x00000000430f0af0,v1,cavium/thunderx2,core
 0x00000000480fd010,v1,hisilicon/hip08,core
+0x00000000500f0000,v1,ampere/emag,core
index 47bedf2..96e7fc1 100644 (file)
@@ -16,8 +16,6 @@ static unsigned long *get_bitmap(const char *str, int nbits)
        bm = bitmap_alloc(nbits);
 
        if (map && bm) {
-               bitmap_zero(bm, nbits);
-
                for (i = 0; i < map->nr; i++)
                        set_bit(map->map[i], bm);
        }
index 4892bd2..6b049f3 100644 (file)
@@ -232,6 +232,7 @@ static int read_object_code(u64 addr, size_t len, u8 cpumode,
        u64 objdump_addr;
        const char *objdump_name;
        char decomp_name[KMOD_DECOMP_LEN];
+       bool decomp = false;
        int ret;
 
        pr_debug("Reading object code for memory address: %#"PRIx64"\n", addr);
@@ -305,6 +306,7 @@ static int read_object_code(u64 addr, size_t len, u8 cpumode,
                        return -1;
                }
 
+               decomp = true;
                objdump_name = decomp_name;
        }
 
@@ -312,7 +314,7 @@ static int read_object_code(u64 addr, size_t len, u8 cpumode,
        objdump_addr = map__rip_2objdump(al.map, al.addr);
        ret = read_via_objdump(objdump_name, objdump_addr, buf2, len);
 
-       if (dso__needs_decompress(al.map->dso))
+       if (decomp)
                unlink(objdump_name);
 
        if (ret > 0) {
index 148dd31..0579a70 100644 (file)
@@ -5,34 +5,28 @@
 #include "dso.h"
 #include "debug.h"
 
-static int test(const char *path, bool alloc_name, bool alloc_ext,
-               bool kmod, bool comp, const char *name, const char *ext)
+static int test(const char *path, bool alloc_name, bool kmod,
+               int comp, const char *name)
 {
        struct kmod_path m;
 
        memset(&m, 0x0, sizeof(m));
 
        TEST_ASSERT_VAL("kmod_path__parse",
-                       !__kmod_path__parse(&m, path, alloc_name, alloc_ext));
+                       !__kmod_path__parse(&m, path, alloc_name));
 
-       pr_debug("%s - alloc name %d, alloc ext %d, kmod %d, comp %d, name '%s', ext '%s'\n",
-                path, alloc_name, alloc_ext, m.kmod, m.comp, m.name, m.ext);
+       pr_debug("%s - alloc name %d, kmod %d, comp %d, name '%s'\n",
+                path, alloc_name, m.kmod, m.comp, m.name);
 
        TEST_ASSERT_VAL("wrong kmod", m.kmod == kmod);
        TEST_ASSERT_VAL("wrong comp", m.comp == comp);
 
-       if (ext)
-               TEST_ASSERT_VAL("wrong ext", m.ext && !strcmp(ext, m.ext));
-       else
-               TEST_ASSERT_VAL("wrong ext", !m.ext);
-
        if (name)
                TEST_ASSERT_VAL("wrong name", m.name && !strcmp(name, m.name));
        else
                TEST_ASSERT_VAL("wrong name", !m.name);
 
        free(m.name);
-       free(m.ext);
        return 0;
 }
 
@@ -45,118 +39,118 @@ static int test_is_kernel_module(const char *path, int cpumode, bool expect)
        return 0;
 }
 
-#define T(path, an, ae, k, c, n, e) \
-       TEST_ASSERT_VAL("failed", !test(path, an, ae, k, c, n, e))
+#define T(path, an, k, c, n) \
+       TEST_ASSERT_VAL("failed", !test(path, an, k, c, n))
 
 #define M(path, c, e) \
        TEST_ASSERT_VAL("failed", !test_is_kernel_module(path, c, e))
 
 int test__kmod_path__parse(struct test *t __maybe_unused, int subtest __maybe_unused)
 {
-       /* path                alloc_name  alloc_ext   kmod  comp   name     ext */
-       T("/xxxx/xxxx/x-x.ko", true      , true      , true, false, "[x_x]", NULL);
-       T("/xxxx/xxxx/x-x.ko", false     , true      , true, false, NULL   , NULL);
-       T("/xxxx/xxxx/x-x.ko", true      , false     , true, false, "[x_x]", NULL);
-       T("/xxxx/xxxx/x-x.ko", false     , false     , true, false, NULL   , NULL);
+       /* path                alloc_name  kmod  comp   name   */
+       T("/xxxx/xxxx/x-x.ko", true      , true, 0    , "[x_x]");
+       T("/xxxx/xxxx/x-x.ko", false     , true, 0    , NULL   );
+       T("/xxxx/xxxx/x-x.ko", true      , true, 0    , "[x_x]");
+       T("/xxxx/xxxx/x-x.ko", false     , true, 0    , NULL   );
        M("/xxxx/xxxx/x-x.ko", PERF_RECORD_MISC_CPUMODE_UNKNOWN, true);
        M("/xxxx/xxxx/x-x.ko", PERF_RECORD_MISC_KERNEL, true);
        M("/xxxx/xxxx/x-x.ko", PERF_RECORD_MISC_USER, false);
 
 #ifdef HAVE_ZLIB_SUPPORT
-       /* path                alloc_name  alloc_ext   kmod  comp  name   ext */
-       T("/xxxx/xxxx/x.ko.gz", true     , true      , true, true, "[x]", "gz");
-       T("/xxxx/xxxx/x.ko.gz", false    , true      , true, true, NULL , "gz");
-       T("/xxxx/xxxx/x.ko.gz", true     , false     , true, true, "[x]", NULL);
-       T("/xxxx/xxxx/x.ko.gz", false    , false     , true, true, NULL , NULL);
+       /* path                alloc_name   kmod  comp  name  */
+       T("/xxxx/xxxx/x.ko.gz", true     , true, 1   , "[x]");
+       T("/xxxx/xxxx/x.ko.gz", false    , true, 1   , NULL );
+       T("/xxxx/xxxx/x.ko.gz", true     , true, 1   , "[x]");
+       T("/xxxx/xxxx/x.ko.gz", false    , true, 1   , NULL );
        M("/xxxx/xxxx/x.ko.gz", PERF_RECORD_MISC_CPUMODE_UNKNOWN, true);
        M("/xxxx/xxxx/x.ko.gz", PERF_RECORD_MISC_KERNEL, true);
        M("/xxxx/xxxx/x.ko.gz", PERF_RECORD_MISC_USER, false);
 
-       /* path              alloc_name  alloc_ext  kmod   comp  name    ext */
-       T("/xxxx/xxxx/x.gz", true      , true     , false, true, "x.gz" ,"gz");
-       T("/xxxx/xxxx/x.gz", false     , true     , false, true, NULL   ,"gz");
-       T("/xxxx/xxxx/x.gz", true      , false    , false, true, "x.gz" , NULL);
-       T("/xxxx/xxxx/x.gz", false     , false    , false, true, NULL   , NULL);
+       /* path              alloc_name  kmod   comp  name  */
+       T("/xxxx/xxxx/x.gz", true      , false, 1   , "x.gz");
+       T("/xxxx/xxxx/x.gz", false     , false, 1   , NULL  );
+       T("/xxxx/xxxx/x.gz", true      , false, 1   , "x.gz");
+       T("/xxxx/xxxx/x.gz", false     , false, 1   , NULL  );
        M("/xxxx/xxxx/x.gz", PERF_RECORD_MISC_CPUMODE_UNKNOWN, false);
        M("/xxxx/xxxx/x.gz", PERF_RECORD_MISC_KERNEL, false);
        M("/xxxx/xxxx/x.gz", PERF_RECORD_MISC_USER, false);
 
-       /* path   alloc_name  alloc_ext  kmod   comp  name     ext */
-       T("x.gz", true      , true     , false, true, "x.gz", "gz");
-       T("x.gz", false     , true     , false, true, NULL  , "gz");
-       T("x.gz", true      , false    , false, true, "x.gz", NULL);
-       T("x.gz", false     , false    , false, true, NULL  , NULL);
+       /* path   alloc_name  kmod   comp  name   */
+       T("x.gz", true      , false, 1   , "x.gz");
+       T("x.gz", false     , false, 1   , NULL  );
+       T("x.gz", true      , false, 1   , "x.gz");
+       T("x.gz", false     , false, 1   , NULL  );
        M("x.gz", PERF_RECORD_MISC_CPUMODE_UNKNOWN, false);
        M("x.gz", PERF_RECORD_MISC_KERNEL, false);
        M("x.gz", PERF_RECORD_MISC_USER, false);
 
-       /* path      alloc_name  alloc_ext  kmod  comp  name  ext */
-       T("x.ko.gz", true      , true     , true, true, "[x]", "gz");
-       T("x.ko.gz", false     , true     , true, true, NULL , "gz");
-       T("x.ko.gz", true      , false    , true, true, "[x]", NULL);
-       T("x.ko.gz", false     , false    , true, true, NULL , NULL);
+       /* path      alloc_name  kmod  comp  name  */
+       T("x.ko.gz", true      , true, 1   , "[x]");
+       T("x.ko.gz", false     , true, 1   , NULL );
+       T("x.ko.gz", true      , true, 1   , "[x]");
+       T("x.ko.gz", false     , true, 1   , NULL );
        M("x.ko.gz", PERF_RECORD_MISC_CPUMODE_UNKNOWN, true);
        M("x.ko.gz", PERF_RECORD_MISC_KERNEL, true);
        M("x.ko.gz", PERF_RECORD_MISC_USER, false);
 #endif
 
-       /* path            alloc_name  alloc_ext  kmod  comp   name             ext */
-       T("[test_module]", true      , true     , true, false, "[test_module]", NULL);
-       T("[test_module]", false     , true     , true, false, NULL           , NULL);
-       T("[test_module]", true      , false    , true, false, "[test_module]", NULL);
-       T("[test_module]", false     , false    , true, false, NULL           , NULL);
+       /* path            alloc_name  kmod  comp   name           */
+       T("[test_module]", true      , true, false, "[test_module]");
+       T("[test_module]", false     , true, false, NULL           );
+       T("[test_module]", true      , true, false, "[test_module]");
+       T("[test_module]", false     , true, false, NULL           );
        M("[test_module]", PERF_RECORD_MISC_CPUMODE_UNKNOWN, true);
        M("[test_module]", PERF_RECORD_MISC_KERNEL, true);
        M("[test_module]", PERF_RECORD_MISC_USER, false);
 
-       /* path            alloc_name  alloc_ext  kmod  comp   name             ext */
-       T("[test.module]", true      , true     , true, false, "[test.module]", NULL);
-       T("[test.module]", false     , true     , true, false, NULL           , NULL);
-       T("[test.module]", true      , false    , true, false, "[test.module]", NULL);
-       T("[test.module]", false     , false    , true, false, NULL           , NULL);
+       /* path            alloc_name  kmod  comp   name           */
+       T("[test.module]", true      , true, false, "[test.module]");
+       T("[test.module]", false     , true, false, NULL           );
+       T("[test.module]", true      , true, false, "[test.module]");
+       T("[test.module]", false     , true, false, NULL           );
        M("[test.module]", PERF_RECORD_MISC_CPUMODE_UNKNOWN, true);
        M("[test.module]", PERF_RECORD_MISC_KERNEL, true);
        M("[test.module]", PERF_RECORD_MISC_USER, false);
 
-       /* path     alloc_name  alloc_ext  kmod   comp   name      ext */
-       T("[vdso]", true      , true     , false, false, "[vdso]", NULL);
-       T("[vdso]", false     , true     , false, false, NULL    , NULL);
-       T("[vdso]", true      , false    , false, false, "[vdso]", NULL);
-       T("[vdso]", false     , false    , false, false, NULL    , NULL);
+       /* path     alloc_name  kmod   comp   name    */
+       T("[vdso]", true      , false, false, "[vdso]");
+       T("[vdso]", false     , false, false, NULL    );
+       T("[vdso]", true      , false, false, "[vdso]");
+       T("[vdso]", false     , false, false, NULL    );
        M("[vdso]", PERF_RECORD_MISC_CPUMODE_UNKNOWN, false);
        M("[vdso]", PERF_RECORD_MISC_KERNEL, false);
        M("[vdso]", PERF_RECORD_MISC_USER, false);
 
-       T("[vdso32]", true      , true     , false, false, "[vdso32]", NULL);
-       T("[vdso32]", false     , true     , false, false, NULL    , NULL);
-       T("[vdso32]", true      , false    , false, false, "[vdso32]", NULL);
-       T("[vdso32]", false     , false    , false, false, NULL    , NULL);
+       T("[vdso32]", true      , false, false, "[vdso32]");
+       T("[vdso32]", false     , false, false, NULL      );
+       T("[vdso32]", true      , false, false, "[vdso32]");
+       T("[vdso32]", false     , false, false, NULL      );
        M("[vdso32]", PERF_RECORD_MISC_CPUMODE_UNKNOWN, false);
        M("[vdso32]", PERF_RECORD_MISC_KERNEL, false);
        M("[vdso32]", PERF_RECORD_MISC_USER, false);
 
-       T("[vdsox32]", true      , true     , false, false, "[vdsox32]", NULL);
-       T("[vdsox32]", false     , true     , false, false, NULL    , NULL);
-       T("[vdsox32]", true      , false    , false, false, "[vdsox32]", NULL);
-       T("[vdsox32]", false     , false    , false, false, NULL    , NULL);
+       T("[vdsox32]", true      , false, false, "[vdsox32]");
+       T("[vdsox32]", false     , false, false, NULL       );
+       T("[vdsox32]", true      , false, false, "[vdsox32]");
+       T("[vdsox32]", false     , false, false, NULL       );
        M("[vdsox32]", PERF_RECORD_MISC_CPUMODE_UNKNOWN, false);
        M("[vdsox32]", PERF_RECORD_MISC_KERNEL, false);
        M("[vdsox32]", PERF_RECORD_MISC_USER, false);
 
-       /* path         alloc_name  alloc_ext  kmod   comp   name          ext */
-       T("[vsyscall]", true      , true     , false, false, "[vsyscall]", NULL);
-       T("[vsyscall]", false     , true     , false, false, NULL        , NULL);
-       T("[vsyscall]", true      , false    , false, false, "[vsyscall]", NULL);
-       T("[vsyscall]", false     , false    , false, false, NULL        , NULL);
+       /* path         alloc_name  kmod   comp   name        */
+       T("[vsyscall]", true      , false, false, "[vsyscall]");
+       T("[vsyscall]", false     , false, false, NULL        );
+       T("[vsyscall]", true      , false, false, "[vsyscall]");
+       T("[vsyscall]", false     , false, false, NULL        );
        M("[vsyscall]", PERF_RECORD_MISC_CPUMODE_UNKNOWN, false);
        M("[vsyscall]", PERF_RECORD_MISC_KERNEL, false);
        M("[vsyscall]", PERF_RECORD_MISC_USER, false);
 
-       /* path                alloc_name  alloc_ext  kmod   comp   name      ext */
-       T("[kernel.kallsyms]", true      , true     , false, false, "[kernel.kallsyms]", NULL);
-       T("[kernel.kallsyms]", false     , true     , false, false, NULL               , NULL);
-       T("[kernel.kallsyms]", true      , false    , false, false, "[kernel.kallsyms]", NULL);
-       T("[kernel.kallsyms]", false     , false    , false, false, NULL               , NULL);
+       /* path                alloc_name  kmod   comp   name      */
+       T("[kernel.kallsyms]", true      , false, false, "[kernel.kallsyms]");
+       T("[kernel.kallsyms]", false     , false, false, NULL               );
+       T("[kernel.kallsyms]", true      , false, false, "[kernel.kallsyms]");
+       T("[kernel.kallsyms]", false     , false, false, NULL               );
        M("[kernel.kallsyms]", PERF_RECORD_MISC_CPUMODE_UNKNOWN, false);
        M("[kernel.kallsyms]", PERF_RECORD_MISC_KERNEL, false);
        M("[kernel.kallsyms]", PERF_RECORD_MISC_USER, false);
index 0c3c87f..9e9e4d3 100644 (file)
@@ -24,8 +24,6 @@ static unsigned long *get_bitmap(const char *str, int nbits)
        bm = bitmap_alloc(nbits);
 
        if (map && bm) {
-               bitmap_zero(bm, nbits);
-
                for (i = 0; i < map->nr; i++) {
                        set_bit(map->map[i], bm);
                }
index 3b4f1c1..1d00e5e 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <sys/ttydefaults.h>
+#include <asm/bug.h>
 
 struct disasm_line_samples {
        double                percent;
@@ -115,7 +116,7 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int
        if (!browser->navkeypressed)
                ops.width += 1;
 
-       annotation_line__write(al, notes, &ops);
+       annotation_line__write(al, notes, &ops, ab->opts);
 
        if (ops.current_entry)
                ab->selection = al;
@@ -227,10 +228,10 @@ static int disasm__cmp(struct annotation_line *a, struct annotation_line *b)
 {
        int i;
 
-       for (i = 0; i < a->samples_nr; i++) {
-               if (a->samples[i].percent == b->samples[i].percent)
+       for (i = 0; i < a->data_nr; i++) {
+               if (a->data[i].percent == b->data[i].percent)
                        continue;
-               return a->samples[i].percent < b->samples[i].percent;
+               return a->data[i].percent < b->data[i].percent;
        }
        return 0;
 }
@@ -314,11 +315,14 @@ static void annotate_browser__calc_percent(struct annotate_browser *browser,
                        continue;
                }
 
-               for (i = 0; i < pos->al.samples_nr; i++) {
-                       struct annotation_data *sample = &pos->al.samples[i];
+               for (i = 0; i < pos->al.data_nr; i++) {
+                       double percent;
 
-                       if (max_percent < sample->percent)
-                               max_percent = sample->percent;
+                       percent = annotation_data__percent(&pos->al.data[i],
+                                                          browser->opts->percent_type);
+
+                       if (max_percent < percent)
+                               max_percent = percent;
                }
 
                if (max_percent < 0.01 && pos->al.ipc == 0) {
@@ -380,9 +384,10 @@ static void ui_browser__init_asm_mode(struct ui_browser *browser)
 #define SYM_TITLE_MAX_SIZE (PATH_MAX + 64)
 
 static int sym_title(struct symbol *sym, struct map *map, char *title,
-                    size_t sz)
+                    size_t sz, int percent_type)
 {
-       return snprintf(title, sz, "%s  %s", sym->name, map->dso->long_name);
+       return snprintf(title, sz, "%s  %s [Percent: %s]", sym->name, map->dso->long_name,
+                       percent_type_str(percent_type));
 }
 
 /*
@@ -420,7 +425,7 @@ static bool annotate_browser__callq(struct annotate_browser *browser,
 
        pthread_mutex_unlock(&notes->lock);
        symbol__tui_annotate(dl->ops.target.sym, ms->map, evsel, hbt, browser->opts);
-       sym_title(ms->sym, ms->map, title, sizeof(title));
+       sym_title(ms->sym, ms->map, title, sizeof(title), browser->opts->percent_type);
        ui_browser__show_title(&browser->b, title);
        return true;
 }
@@ -595,6 +600,7 @@ bool annotate_browser__continue_search_reverse(struct annotate_browser *browser,
 
 static int annotate_browser__show(struct ui_browser *browser, char *title, const char *help)
 {
+       struct annotate_browser *ab = container_of(browser, struct annotate_browser, b);
        struct map_symbol *ms = browser->priv;
        struct symbol *sym = ms->sym;
        char symbol_dso[SYM_TITLE_MAX_SIZE];
@@ -602,7 +608,7 @@ static int annotate_browser__show(struct ui_browser *browser, char *title, const
        if (ui_browser__show(browser, title, help) < 0)
                return -1;
 
-       sym_title(sym, ms->map, symbol_dso, sizeof(symbol_dso));
+       sym_title(sym, ms->map, symbol_dso, sizeof(symbol_dso), ab->opts->percent_type);
 
        ui_browser__gotorc_title(browser, 0, 0);
        ui_browser__set_color(browser, HE_COLORSET_ROOT);
@@ -610,6 +616,39 @@ static int annotate_browser__show(struct ui_browser *browser, char *title, const
        return 0;
 }
 
+static void
+switch_percent_type(struct annotation_options *opts, bool base)
+{
+       switch (opts->percent_type) {
+       case PERCENT_HITS_LOCAL:
+               if (base)
+                       opts->percent_type = PERCENT_PERIOD_LOCAL;
+               else
+                       opts->percent_type = PERCENT_HITS_GLOBAL;
+               break;
+       case PERCENT_HITS_GLOBAL:
+               if (base)
+                       opts->percent_type = PERCENT_PERIOD_GLOBAL;
+               else
+                       opts->percent_type = PERCENT_HITS_LOCAL;
+               break;
+       case PERCENT_PERIOD_LOCAL:
+               if (base)
+                       opts->percent_type = PERCENT_HITS_LOCAL;
+               else
+                       opts->percent_type = PERCENT_PERIOD_GLOBAL;
+               break;
+       case PERCENT_PERIOD_GLOBAL:
+               if (base)
+                       opts->percent_type = PERCENT_HITS_GLOBAL;
+               else
+                       opts->percent_type = PERCENT_PERIOD_LOCAL;
+               break;
+       default:
+               WARN_ON(1);
+       }
+}
+
 static int annotate_browser__run(struct annotate_browser *browser,
                                 struct perf_evsel *evsel,
                                 struct hist_browser_timer *hbt)
@@ -624,8 +663,7 @@ static int annotate_browser__run(struct annotate_browser *browser,
        char title[256];
        int key;
 
-       annotation__scnprintf_samples_period(notes, title, sizeof(title), evsel);
-
+       hists__scnprintf_title(hists, title, sizeof(title));
        if (annotate_browser__show(&browser->b, title, help) < 0)
                return -1;
 
@@ -701,6 +739,8 @@ static int annotate_browser__run(struct annotate_browser *browser,
                "k             Toggle line numbers\n"
                "P             Print to [symbol_name].annotation file.\n"
                "r             Run available scripts\n"
+               "p             Toggle percent type [local/global]\n"
+               "b             Toggle percent base [period/hits]\n"
                "?             Search string backwards\n");
                        continue;
                case 'r':
@@ -781,7 +821,7 @@ show_sup_ins:
                        continue;
                }
                case 'P':
-                       map_symbol__annotation_dump(ms, evsel);
+                       map_symbol__annotation_dump(ms, evsel, browser->opts);
                        continue;
                case 't':
                        if (notes->options->show_total_period) {
@@ -800,6 +840,12 @@ show_sup_ins:
                                notes->options->show_minmax_cycle = true;
                        annotation__update_column_widths(notes);
                        continue;
+               case 'p':
+               case 'b':
+                       switch_percent_type(browser->opts, key == 'b');
+                       hists__scnprintf_title(hists, title, sizeof(title));
+                       annotate_browser__show(&browser->b, title, help);
+                       continue;
                case K_LEFT:
                case K_ESC:
                case 'q':
index b604ef3..7efe15b 100644 (file)
@@ -87,6 +87,7 @@ libperf-$(CONFIG_AUXTRACE) += intel-pt.o
 libperf-$(CONFIG_AUXTRACE) += intel-bts.o
 libperf-$(CONFIG_AUXTRACE) += arm-spe.o
 libperf-$(CONFIG_AUXTRACE) += arm-spe-pkt-decoder.o
+libperf-$(CONFIG_AUXTRACE) += s390-cpumsf.o
 
 ifdef CONFIG_LIBOPENCSD
 libperf-$(CONFIG_AUXTRACE) += cs-etm.o
index f91775b..20061cf 100644 (file)
@@ -49,6 +49,7 @@ struct annotation_options annotation__default_options = {
        .jump_arrows    = true,
        .annotate_src   = true,
        .offset_level   = ANNOTATION__OFFSET_JUMP_TARGETS,
+       .percent_type   = PERCENT_PERIOD_LOCAL,
 };
 
 static regex_t  file_lineno;
@@ -1108,7 +1109,7 @@ annotation_line__new(struct annotate_args *args, size_t privsize)
        if (perf_evsel__is_group_event(evsel))
                nr = evsel->nr_members;
 
-       size += sizeof(al->samples[0]) * nr;
+       size += sizeof(al->data[0]) * nr;
 
        al = zalloc(size);
        if (al) {
@@ -1117,7 +1118,7 @@ annotation_line__new(struct annotate_args *args, size_t privsize)
                al->offset     = args->offset;
                al->line       = strdup(args->line);
                al->line_nr    = args->line_nr;
-               al->samples_nr = nr;
+               al->data_nr    = nr;
        }
 
        return al;
@@ -1297,7 +1298,8 @@ static int disasm_line__print(struct disasm_line *dl, u64 start, int addr_fmt_wi
 static int
 annotation_line__print(struct annotation_line *al, struct symbol *sym, u64 start,
                       struct perf_evsel *evsel, u64 len, int min_pcnt, int printed,
-                      int max_lines, struct annotation_line *queue, int addr_fmt_width)
+                      int max_lines, struct annotation_line *queue, int addr_fmt_width,
+                      int percent_type)
 {
        struct disasm_line *dl = container_of(al, struct disasm_line, al);
        static const char *prev_line;
@@ -1309,15 +1311,18 @@ annotation_line__print(struct annotation_line *al, struct symbol *sym, u64 start
                const char *color;
                struct annotation *notes = symbol__annotation(sym);
 
-               for (i = 0; i < al->samples_nr; i++) {
-                       struct annotation_data *sample = &al->samples[i];
+               for (i = 0; i < al->data_nr; i++) {
+                       double percent;
 
-                       if (sample->percent > max_percent)
-                               max_percent = sample->percent;
+                       percent = annotation_data__percent(&al->data[i],
+                                                          percent_type);
+
+                       if (percent > max_percent)
+                               max_percent = percent;
                }
 
-               if (al->samples_nr > nr_percent)
-                       nr_percent = al->samples_nr;
+               if (al->data_nr > nr_percent)
+                       nr_percent = al->data_nr;
 
                if (max_percent < min_pcnt)
                        return -1;
@@ -1330,7 +1335,8 @@ annotation_line__print(struct annotation_line *al, struct symbol *sym, u64 start
                                if (queue == al)
                                        break;
                                annotation_line__print(queue, sym, start, evsel, len,
-                                                      0, 0, 1, NULL, addr_fmt_width);
+                                                      0, 0, 1, NULL, addr_fmt_width,
+                                                      percent_type);
                        }
                }
 
@@ -1351,18 +1357,20 @@ annotation_line__print(struct annotation_line *al, struct symbol *sym, u64 start
                }
 
                for (i = 0; i < nr_percent; i++) {
-                       struct annotation_data *sample = &al->samples[i];
+                       struct annotation_data *data = &al->data[i];
+                       double percent;
 
-                       color = get_percent_color(sample->percent);
+                       percent = annotation_data__percent(data, percent_type);
+                       color = get_percent_color(percent);
 
                        if (symbol_conf.show_total_period)
                                color_fprintf(stdout, color, " %11" PRIu64,
-                                             sample->he.period);
+                                             data->he.period);
                        else if (symbol_conf.show_nr_samples)
                                color_fprintf(stdout, color, " %7" PRIu64,
-                                             sample->he.nr_samples);
+                                             data->he.nr_samples);
                        else
-                               color_fprintf(stdout, color, " %7.2f", sample->percent);
+                               color_fprintf(stdout, color, " %7.2f", percent);
                }
 
                printf(" : ");
@@ -1621,6 +1629,7 @@ static int symbol__disassemble(struct symbol *sym, struct annotate_args *args)
        char symfs_filename[PATH_MAX];
        struct kcore_extract kce;
        bool delete_extract = false;
+       bool decomp = false;
        int stdout_fd[2];
        int lineno = 0;
        int nline;
@@ -1654,6 +1663,7 @@ static int symbol__disassemble(struct symbol *sym, struct annotate_args *args)
                                                 tmp, sizeof(tmp)) < 0)
                        goto out;
 
+               decomp = true;
                strcpy(symfs_filename, tmp);
        }
 
@@ -1740,7 +1750,7 @@ out_free_command:
 out_remove_tmp:
        close(stdout_fd[0]);
 
-       if (dso__needs_decompress(dso))
+       if (decomp)
                unlink(symfs_filename);
 
        if (delete_extract)
@@ -1753,34 +1763,45 @@ out_close_stdout:
        goto out_free_command;
 }
 
-static void calc_percent(struct sym_hist *hist,
-                        struct annotation_data *sample,
+static void calc_percent(struct sym_hist *sym_hist,
+                        struct hists *hists,
+                        struct annotation_data *data,
                         s64 offset, s64 end)
 {
        unsigned int hits = 0;
        u64 period = 0;
 
        while (offset < end) {
-               hits   += hist->addr[offset].nr_samples;
-               period += hist->addr[offset].period;
+               hits   += sym_hist->addr[offset].nr_samples;
+               period += sym_hist->addr[offset].period;
                ++offset;
        }
 
-       if (hist->nr_samples) {
-               sample->he.period     = period;
-               sample->he.nr_samples = hits;
-               sample->percent = 100.0 * hits / hist->nr_samples;
+       if (sym_hist->nr_samples) {
+               data->he.period     = period;
+               data->he.nr_samples = hits;
+               data->percent[PERCENT_HITS_LOCAL] = 100.0 * hits / sym_hist->nr_samples;
        }
+
+       if (hists->stats.nr_non_filtered_samples)
+               data->percent[PERCENT_HITS_GLOBAL] = 100.0 * hits / hists->stats.nr_non_filtered_samples;
+
+       if (sym_hist->period)
+               data->percent[PERCENT_PERIOD_LOCAL] = 100.0 * period / sym_hist->period;
+
+       if (hists->stats.total_period)
+               data->percent[PERCENT_PERIOD_GLOBAL] = 100.0 * period / hists->stats.total_period;
 }
 
 static void annotation__calc_percent(struct annotation *notes,
-                                    struct perf_evsel *evsel, s64 len)
+                                    struct perf_evsel *leader, s64 len)
 {
        struct annotation_line *al, *next;
+       struct perf_evsel *evsel;
 
        list_for_each_entry(al, &notes->src->source, node) {
                s64 end;
-               int i;
+               int i = 0;
 
                if (al->offset == -1)
                        continue;
@@ -1788,14 +1809,17 @@ static void annotation__calc_percent(struct annotation *notes,
                next = annotation_line__next(al, &notes->src->source);
                end  = next ? next->offset : len;
 
-               for (i = 0; i < al->samples_nr; i++) {
-                       struct annotation_data *sample;
-                       struct sym_hist *hist;
+               for_each_group_evsel(evsel, leader) {
+                       struct hists *hists = evsel__hists(evsel);
+                       struct annotation_data *data;
+                       struct sym_hist *sym_hist;
+
+                       BUG_ON(i >= al->data_nr);
 
-                       hist   = annotation__histogram(notes, evsel->idx + i);
-                       sample = &al->samples[i];
+                       sym_hist = annotation__histogram(notes, evsel->idx);
+                       data = &al->data[i++];
 
-                       calc_percent(hist, sample, al->offset, end);
+                       calc_percent(sym_hist, hists, data, al->offset, end);
                }
        }
 }
@@ -1846,7 +1870,8 @@ int symbol__annotate(struct symbol *sym, struct map *map,
        return symbol__disassemble(sym, &args);
 }
 
-static void insert_source_line(struct rb_root *root, struct annotation_line *al)
+static void insert_source_line(struct rb_root *root, struct annotation_line *al,
+                              struct annotation_options *opts)
 {
        struct annotation_line *iter;
        struct rb_node **p = &root->rb_node;
@@ -1859,8 +1884,10 @@ static void insert_source_line(struct rb_root *root, struct annotation_line *al)
 
                ret = strcmp(iter->path, al->path);
                if (ret == 0) {
-                       for (i = 0; i < al->samples_nr; i++)
-                               iter->samples[i].percent_sum += al->samples[i].percent;
+                       for (i = 0; i < al->data_nr; i++) {
+                               iter->data[i].percent_sum += annotation_data__percent(&al->data[i],
+                                                                                     opts->percent_type);
+                       }
                        return;
                }
 
@@ -1870,8 +1897,10 @@ static void insert_source_line(struct rb_root *root, struct annotation_line *al)
                        p = &(*p)->rb_right;
        }
 
-       for (i = 0; i < al->samples_nr; i++)
-               al->samples[i].percent_sum = al->samples[i].percent;
+       for (i = 0; i < al->data_nr; i++) {
+               al->data[i].percent_sum = annotation_data__percent(&al->data[i],
+                                                                  opts->percent_type);
+       }
 
        rb_link_node(&al->rb_node, parent, p);
        rb_insert_color(&al->rb_node, root);
@@ -1881,10 +1910,10 @@ static int cmp_source_line(struct annotation_line *a, struct annotation_line *b)
 {
        int i;
 
-       for (i = 0; i < a->samples_nr; i++) {
-               if (a->samples[i].percent_sum == b->samples[i].percent_sum)
+       for (i = 0; i < a->data_nr; i++) {
+               if (a->data[i].percent_sum == b->data[i].percent_sum)
                        continue;
-               return a->samples[i].percent_sum > b->samples[i].percent_sum;
+               return a->data[i].percent_sum > b->data[i].percent_sum;
        }
 
        return 0;
@@ -1949,8 +1978,8 @@ static void print_summary(struct rb_root *root, const char *filename)
                int i;
 
                al = rb_entry(node, struct annotation_line, rb_node);
-               for (i = 0; i < al->samples_nr; i++) {
-                       percent = al->samples[i].percent_sum;
+               for (i = 0; i < al->data_nr; i++) {
+                       percent = al->data[i].percent_sum;
                        color = get_percent_color(percent);
                        color_fprintf(stdout, color, " %7.2f", percent);
 
@@ -2029,10 +2058,12 @@ int symbol__annotate_printf(struct symbol *sym, struct map *map,
                evsel_name = buf;
        }
 
-       graph_dotted_len = printf(" %-*.*s|     Source code & Disassembly of %s for %s (%" PRIu64 " samples)\n",
+       graph_dotted_len = printf(" %-*.*s|     Source code & Disassembly of %s for %s (%" PRIu64 " samples, "
+                                 "percent: %s)\n",
                                  width, width, symbol_conf.show_total_period ? "Period" :
                                  symbol_conf.show_nr_samples ? "Samples" : "Percent",
-                                 d_filename, evsel_name, h->nr_samples);
+                                 d_filename, evsel_name, h->nr_samples,
+                                 percent_type_str(opts->percent_type));
 
        printf("%-*.*s----\n",
               graph_dotted_len, graph_dotted_len, graph_dotted_line);
@@ -2052,7 +2083,7 @@ int symbol__annotate_printf(struct symbol *sym, struct map *map,
 
                err = annotation_line__print(pos, sym, start, evsel, len,
                                             opts->min_pcnt, printed, opts->max_lines,
-                                            queue, addr_fmt_width);
+                                            queue, addr_fmt_width, opts->percent_type);
 
                switch (err) {
                case 0:
@@ -2129,10 +2160,11 @@ static void FILE__write_graph(void *fp, int graph)
        fputs(s, fp);
 }
 
-int symbol__annotate_fprintf2(struct symbol *sym, FILE *fp)
+static int symbol__annotate_fprintf2(struct symbol *sym, FILE *fp,
+                                    struct annotation_options *opts)
 {
        struct annotation *notes = symbol__annotation(sym);
-       struct annotation_write_ops ops = {
+       struct annotation_write_ops wops = {
                .first_line              = true,
                .obj                     = fp,
                .set_color               = FILE__set_color,
@@ -2146,15 +2178,16 @@ int symbol__annotate_fprintf2(struct symbol *sym, FILE *fp)
        list_for_each_entry(al, &notes->src->source, node) {
                if (annotation_line__filter(al, notes))
                        continue;
-               annotation_line__write(al, notes, &ops);
+               annotation_line__write(al, notes, &wops, opts);
                fputc('\n', fp);
-               ops.first_line = false;
+               wops.first_line = false;
        }
 
        return 0;
 }
 
-int map_symbol__annotation_dump(struct map_symbol *ms, struct perf_evsel *evsel)
+int map_symbol__annotation_dump(struct map_symbol *ms, struct perf_evsel *evsel,
+                               struct annotation_options *opts)
 {
        const char *ev_name = perf_evsel__name(evsel);
        char buf[1024];
@@ -2176,7 +2209,7 @@ int map_symbol__annotation_dump(struct map_symbol *ms, struct perf_evsel *evsel)
 
        fprintf(fp, "%s() %s\nEvent: %s\n\n",
                ms->sym->name, ms->map->dso->long_name, ev_name);
-       symbol__annotate_fprintf2(ms->sym, fp);
+       symbol__annotate_fprintf2(ms->sym, fp, opts);
 
        fclose(fp);
        err = 0;
@@ -2346,7 +2379,8 @@ void annotation__update_column_widths(struct annotation *notes)
 }
 
 static void annotation__calc_lines(struct annotation *notes, struct map *map,
-                                 struct rb_root *root)
+                                  struct rb_root *root,
+                                  struct annotation_options *opts)
 {
        struct annotation_line *al;
        struct rb_root tmp_root = RB_ROOT;
@@ -2355,13 +2389,14 @@ static void annotation__calc_lines(struct annotation *notes, struct map *map,
                double percent_max = 0.0;
                int i;
 
-               for (i = 0; i < al->samples_nr; i++) {
-                       struct annotation_data *sample;
+               for (i = 0; i < al->data_nr; i++) {
+                       double percent;
 
-                       sample = &al->samples[i];
+                       percent = annotation_data__percent(&al->data[i],
+                                                          opts->percent_type);
 
-                       if (sample->percent > percent_max)
-                               percent_max = sample->percent;
+                       if (percent > percent_max)
+                               percent_max = percent;
                }
 
                if (percent_max <= 0.5)
@@ -2369,18 +2404,19 @@ static void annotation__calc_lines(struct annotation *notes, struct map *map,
 
                al->path = get_srcline(map->dso, notes->start + al->offset, NULL,
                                       false, true, notes->start + al->offset);
-               insert_source_line(&tmp_root, al);
+               insert_source_line(&tmp_root, al, opts);
        }
 
        resort_source_line(root, &tmp_root);
 }
 
 static void symbol__calc_lines(struct symbol *sym, struct map *map,
-                             struct rb_root *root)
+                              struct rb_root *root,
+                              struct annotation_options *opts)
 {
        struct annotation *notes = symbol__annotation(sym);
 
-       annotation__calc_lines(notes, map, root);
+       annotation__calc_lines(notes, map, root, opts);
 }
 
 int symbol__tty_annotate2(struct symbol *sym, struct map *map,
@@ -2389,7 +2425,7 @@ int symbol__tty_annotate2(struct symbol *sym, struct map *map,
 {
        struct dso *dso = map->dso;
        struct rb_root source_line = RB_ROOT;
-       struct annotation *notes = symbol__annotation(sym);
+       struct hists *hists = evsel__hists(evsel);
        char buf[1024];
 
        if (symbol__annotate2(sym, map, evsel, opts, NULL) < 0)
@@ -2397,13 +2433,14 @@ int symbol__tty_annotate2(struct symbol *sym, struct map *map,
 
        if (opts->print_lines) {
                srcline_full_filename = opts->full_path;
-               symbol__calc_lines(sym, map, &source_line);
+               symbol__calc_lines(sym, map, &source_line, opts);
                print_summary(&source_line, dso->long_name);
        }
 
-       annotation__scnprintf_samples_period(notes, buf, sizeof(buf), evsel);
-       fprintf(stdout, "%s\n%s() %s\n", buf, sym->name, dso->long_name);
-       symbol__annotate_fprintf2(sym, stdout);
+       hists__scnprintf_title(hists, buf, sizeof(buf));
+       fprintf(stdout, "%s, [percent: %s]\n%s() %s\n",
+               buf, percent_type_str(opts->percent_type), sym->name, dso->long_name);
+       symbol__annotate_fprintf2(sym, stdout, opts);
 
        annotated_source__purge(symbol__annotation(sym)->src);
 
@@ -2424,7 +2461,7 @@ int symbol__tty_annotate(struct symbol *sym, struct map *map,
 
        if (opts->print_lines) {
                srcline_full_filename = opts->full_path;
-               symbol__calc_lines(sym, map, &source_line);
+               symbol__calc_lines(sym, map, &source_line, opts);
                print_summary(&source_line, dso->long_name);
        }
 
@@ -2441,14 +2478,21 @@ bool ui__has_annotation(void)
 }
 
 
-double annotation_line__max_percent(struct annotation_line *al, struct annotation *notes)
+static double annotation_line__max_percent(struct annotation_line *al,
+                                          struct annotation *notes,
+                                          unsigned int percent_type)
 {
        double percent_max = 0.0;
        int i;
 
        for (i = 0; i < notes->nr_events; i++) {
-               if (al->samples[i].percent > percent_max)
-                       percent_max = al->samples[i].percent;
+               double percent;
+
+               percent = annotation_data__percent(&al->data[i],
+                                                  percent_type);
+
+               if (percent > percent_max)
+                       percent_max = percent;
        }
 
        return percent_max;
@@ -2487,7 +2531,7 @@ call_like:
 
 static void __annotation_line__write(struct annotation_line *al, struct annotation *notes,
                                     bool first_line, bool current_entry, bool change_color, int width,
-                                    void *obj,
+                                    void *obj, unsigned int percent_type,
                                     int  (*obj__set_color)(void *obj, int color),
                                     void (*obj__set_percent_color)(void *obj, double percent, bool current),
                                     int  (*obj__set_jumps_percent_color)(void *obj, int nr, bool current),
@@ -2495,7 +2539,7 @@ static void __annotation_line__write(struct annotation_line *al, struct annotati
                                     void (*obj__write_graph)(void *obj, int graph))
 
 {
-       double percent_max = annotation_line__max_percent(al, notes);
+       double percent_max = annotation_line__max_percent(al, notes, percent_type);
        int pcnt_width = annotation__pcnt_width(notes),
            cycles_width = annotation__cycles_width(notes);
        bool show_title = false;
@@ -2514,15 +2558,18 @@ static void __annotation_line__write(struct annotation_line *al, struct annotati
                int i;
 
                for (i = 0; i < notes->nr_events; i++) {
-                       obj__set_percent_color(obj, al->samples[i].percent, current_entry);
+                       double percent;
+
+                       percent = annotation_data__percent(&al->data[i], percent_type);
+
+                       obj__set_percent_color(obj, percent, current_entry);
                        if (notes->options->show_total_period) {
-                               obj__printf(obj, "%11" PRIu64 " ", al->samples[i].he.period);
+                               obj__printf(obj, "%11" PRIu64 " ", al->data[i].he.period);
                        } else if (notes->options->show_nr_samples) {
                                obj__printf(obj, "%6" PRIu64 " ",
-                                                  al->samples[i].he.nr_samples);
+                                                  al->data[i].he.nr_samples);
                        } else {
-                               obj__printf(obj, "%6.2f ",
-                                                  al->samples[i].percent);
+                               obj__printf(obj, "%6.2f ", percent);
                        }
                }
        } else {
@@ -2640,13 +2687,15 @@ print_addr:
 }
 
 void annotation_line__write(struct annotation_line *al, struct annotation *notes,
-                           struct annotation_write_ops *ops)
+                           struct annotation_write_ops *wops,
+                           struct annotation_options *opts)
 {
-       __annotation_line__write(al, notes, ops->first_line, ops->current_entry,
-                                ops->change_color, ops->width, ops->obj,
-                                ops->set_color, ops->set_percent_color,
-                                ops->set_jumps_percent_color, ops->printf,
-                                ops->write_graph);
+       __annotation_line__write(al, notes, wops->first_line, wops->current_entry,
+                                wops->change_color, wops->width, wops->obj,
+                                opts->percent_type,
+                                wops->set_color, wops->set_percent_color,
+                                wops->set_jumps_percent_color, wops->printf,
+                                wops->write_graph);
 }
 
 int symbol__annotate2(struct symbol *sym, struct map *map, struct perf_evsel *evsel,
@@ -2688,46 +2737,6 @@ out_free_offsets:
        return -1;
 }
 
-int __annotation__scnprintf_samples_period(struct annotation *notes,
-                                          char *bf, size_t size,
-                                          struct perf_evsel *evsel,
-                                          bool show_freq)
-{
-       const char *ev_name = perf_evsel__name(evsel);
-       char buf[1024], ref[30] = " show reference callgraph, ";
-       char sample_freq_str[64] = "";
-       unsigned long nr_samples = 0;
-       int nr_members = 1;
-       bool enable_ref = false;
-       u64 nr_events = 0;
-       char unit;
-       int i;
-
-       if (perf_evsel__is_group_event(evsel)) {
-               perf_evsel__group_desc(evsel, buf, sizeof(buf));
-               ev_name = buf;
-                nr_members = evsel->nr_members;
-       }
-
-       for (i = 0; i < nr_members; i++) {
-               struct sym_hist *ah = annotation__histogram(notes, evsel->idx + i);
-
-               nr_samples += ah->nr_samples;
-               nr_events  += ah->period;
-       }
-
-       if (symbol_conf.show_ref_callgraph && strstr(ev_name, "call-graph=no"))
-               enable_ref = true;
-
-       if (show_freq)
-               scnprintf(sample_freq_str, sizeof(sample_freq_str), " %d Hz,", evsel->attr.sample_freq);
-
-       nr_samples = convert_unit(nr_samples, &unit);
-       return scnprintf(bf, size, "Samples: %lu%c of event%s '%s',%s%sEvent count (approx.): %" PRIu64,
-                        nr_samples, unit, evsel->nr_members > 1 ? "s" : "",
-                        ev_name, sample_freq_str, enable_ref ? ref : " ", nr_events);
-}
-
 #define ANNOTATION__CFG(n) \
        { .name = #n, .value = &annotation__default_options.n, }
 
@@ -2792,3 +2801,55 @@ void annotation_config__init(void)
        annotation__default_options.show_total_period = symbol_conf.show_total_period;
        annotation__default_options.show_nr_samples   = symbol_conf.show_nr_samples;
 }
+
+static unsigned int parse_percent_type(char *str1, char *str2)
+{
+       unsigned int type = (unsigned int) -1;
+
+       if (!strcmp("period", str1)) {
+               if (!strcmp("local", str2))
+                       type = PERCENT_PERIOD_LOCAL;
+               else if (!strcmp("global", str2))
+                       type = PERCENT_PERIOD_GLOBAL;
+       }
+
+       if (!strcmp("hits", str1)) {
+               if (!strcmp("local", str2))
+                       type = PERCENT_HITS_LOCAL;
+               else if (!strcmp("global", str2))
+                       type = PERCENT_HITS_GLOBAL;
+       }
+
+       return type;
+}
+
+int annotate_parse_percent_type(const struct option *opt, const char *_str,
+                               int unset __maybe_unused)
+{
+       struct annotation_options *opts = opt->value;
+       unsigned int type;
+       char *str1, *str2;
+       int err = -1;
+
+       str1 = strdup(_str);
+       if (!str1)
+               return -ENOMEM;
+
+       str2 = strchr(str1, '-');
+       if (!str2)
+               goto out;
+
+       *str2++ = 0;
+
+       type = parse_percent_type(str1, str2);
+       if (type == (unsigned int) -1)
+               type = parse_percent_type(str2, str1);
+       if (type != (unsigned int) -1) {
+               opts->percent_type = type;
+               err = 0;
+       }
+
+out:
+       free(str1);
+       return err;
+}
index a4c0d91..005a5fe 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/list.h>
 #include <linux/rbtree.h>
 #include <pthread.h>
+#include <asm/bug.h>
 
 struct ins_ops;
 
@@ -82,6 +83,7 @@ struct annotation_options {
        int  context;
        const char *objdump_path;
        const char *disassembler_style;
+       unsigned int percent_type;
 };
 
 enum {
@@ -101,8 +103,16 @@ struct sym_hist_entry {
        u64             period;
 };
 
+enum {
+       PERCENT_HITS_LOCAL,
+       PERCENT_HITS_GLOBAL,
+       PERCENT_PERIOD_LOCAL,
+       PERCENT_PERIOD_GLOBAL,
+       PERCENT_MAX,
+};
+
 struct annotation_data {
-       double                   percent;
+       double                   percent[PERCENT_MAX];
        double                   percent_sum;
        struct sym_hist_entry    he;
 };
@@ -122,8 +132,8 @@ struct annotation_line {
        char                    *path;
        u32                      idx;
        int                      idx_asm;
-       int                      samples_nr;
-       struct annotation_data   samples[0];
+       int                      data_nr;
+       struct annotation_data   data[0];
 };
 
 struct disasm_line {
@@ -134,6 +144,27 @@ struct disasm_line {
        struct annotation_line   al;
 };
 
+static inline double annotation_data__percent(struct annotation_data *data,
+                                             unsigned int which)
+{
+       return which < PERCENT_MAX ? data->percent[which] : -1;
+}
+
+static inline const char *percent_type_str(unsigned int type)
+{
+       static const char *str[PERCENT_MAX] = {
+               "local hits",
+               "global hits",
+               "local period",
+               "global period",
+       };
+
+       if (WARN_ON(type >= PERCENT_MAX))
+               return "N/A";
+
+       return str[type];
+}
+
 static inline struct disasm_line *disasm_line(struct annotation_line *al)
 {
        return al ? container_of(al, struct disasm_line, al) : NULL;
@@ -169,22 +200,15 @@ struct annotation_write_ops {
        void (*write_graph)(void *obj, int graph);
 };
 
-double annotation_line__max_percent(struct annotation_line *al, struct annotation *notes);
 void annotation_line__write(struct annotation_line *al, struct annotation *notes,
-                           struct annotation_write_ops *ops);
+                           struct annotation_write_ops *ops,
+                           struct annotation_options *opts);
 
 int __annotation__scnprintf_samples_period(struct annotation *notes,
                                           char *bf, size_t size,
                                           struct perf_evsel *evsel,
                                           bool show_freq);
 
-static inline int annotation__scnprintf_samples_period(struct annotation *notes,
-                                                      char *bf, size_t size,
-                                                      struct perf_evsel *evsel)
-{
-       return __annotation__scnprintf_samples_period(notes, bf, size, evsel, true);
-}
-
 int disasm_line__scnprintf(struct disasm_line *dl, char *bf, size_t size, bool raw);
 size_t disasm__fprintf(struct list_head *head, FILE *fp);
 void symbol__calc_percent(struct symbol *sym, struct perf_evsel *evsel);
@@ -340,12 +364,12 @@ int symbol__strerror_disassemble(struct symbol *sym, struct map *map,
 int symbol__annotate_printf(struct symbol *sym, struct map *map,
                            struct perf_evsel *evsel,
                            struct annotation_options *options);
-int symbol__annotate_fprintf2(struct symbol *sym, FILE *fp);
 void symbol__annotate_zero_histogram(struct symbol *sym, int evidx);
 void symbol__annotate_decay_histogram(struct symbol *sym, int evidx);
 void annotated_source__purge(struct annotated_source *as);
 
-int map_symbol__annotation_dump(struct map_symbol *ms, struct perf_evsel *evsel);
+int map_symbol__annotation_dump(struct map_symbol *ms, struct perf_evsel *evsel,
+                               struct annotation_options *opts);
 
 bool ui__has_annotation(void);
 
@@ -373,4 +397,6 @@ static inline int symbol__tui_annotate(struct symbol *sym __maybe_unused,
 
 void annotation_config__init(void);
 
+int annotate_parse_percent_type(const struct option *opt, const char *_str,
+                               int unset);
 #endif /* __PERF_ANNOTATE_H */
index d056447..db15113 100644 (file)
@@ -56,6 +56,7 @@
 #include "intel-pt.h"
 #include "intel-bts.h"
 #include "arm-spe.h"
+#include "s390-cpumsf.h"
 
 #include "sane_ctype.h"
 #include "symbol/kallsyms.h"
@@ -202,6 +203,9 @@ static int auxtrace_queues__grow(struct auxtrace_queues *queues,
        for (i = 0; i < queues->nr_queues; i++) {
                list_splice_tail(&queues->queue_array[i].head,
                                 &queue_array[i].head);
+               queue_array[i].tid = queues->queue_array[i].tid;
+               queue_array[i].cpu = queues->queue_array[i].cpu;
+               queue_array[i].set = queues->queue_array[i].set;
                queue_array[i].priv = queues->queue_array[i].priv;
        }
 
@@ -920,6 +924,8 @@ int perf_event__process_auxtrace_info(struct perf_tool *tool __maybe_unused,
                return arm_spe_process_auxtrace_info(event, session);
        case PERF_AUXTRACE_CS_ETM:
                return cs_etm__process_auxtrace_info(event, session);
+       case PERF_AUXTRACE_S390_CPUMSF:
+               return s390_cpumsf_process_auxtrace_info(event, session);
        case PERF_AUXTRACE_UNKNOWN:
        default:
                return -EINVAL;
index e731f55..71fc3bd 100644 (file)
@@ -44,6 +44,7 @@ enum auxtrace_type {
        PERF_AUXTRACE_INTEL_BTS,
        PERF_AUXTRACE_CS_ETM,
        PERF_AUXTRACE_ARM_SPE,
+       PERF_AUXTRACE_S390_CPUMSF,
 };
 
 enum itrace_period_type {
index 3d02ae3..47aac41 100644 (file)
@@ -1529,13 +1529,13 @@ int bpf__apply_obj_config(void)
        bpf_object__for_each_safe(obj, objtmp)  \
                bpf_map__for_each(pos, obj)
 
-#define bpf__for_each_stdout_map(pos, obj, objtmp)     \
+#define bpf__for_each_map_named(pos, obj, objtmp, name)        \
        bpf__for_each_map(pos, obj, objtmp)             \
                if (bpf_map__name(pos) &&               \
-                       (strcmp("__bpf_stdout__",       \
+                       (strcmp(name,                   \
                                bpf_map__name(pos)) == 0))
 
-int bpf__setup_stdout(struct perf_evlist *evlist)
+struct perf_evsel *bpf__setup_output_event(struct perf_evlist *evlist, const char *name)
 {
        struct bpf_map_priv *tmpl_priv = NULL;
        struct bpf_object *obj, *tmp;
@@ -1544,11 +1544,11 @@ int bpf__setup_stdout(struct perf_evlist *evlist)
        int err;
        bool need_init = false;
 
-       bpf__for_each_stdout_map(map, obj, tmp) {
+       bpf__for_each_map_named(map, obj, tmp, name) {
                struct bpf_map_priv *priv = bpf_map__priv(map);
 
                if (IS_ERR(priv))
-                       return -BPF_LOADER_ERRNO__INTERNAL;
+                       return ERR_PTR(-BPF_LOADER_ERRNO__INTERNAL);
 
                /*
                 * No need to check map type: type should have been
@@ -1561,49 +1561,61 @@ int bpf__setup_stdout(struct perf_evlist *evlist)
        }
 
        if (!need_init)
-               return 0;
+               return NULL;
 
        if (!tmpl_priv) {
-               err = parse_events(evlist, "bpf-output/no-inherit=1,name=__bpf_stdout__/",
-                                  NULL);
+               char *event_definition = NULL;
+
+               if (asprintf(&event_definition, "bpf-output/no-inherit=1,name=%s/", name) < 0)
+                       return ERR_PTR(-ENOMEM);
+
+               err = parse_events(evlist, event_definition, NULL);
+               free(event_definition);
+
                if (err) {
-                       pr_debug("ERROR: failed to create bpf-output event\n");
-                       return -err;
+                       pr_debug("ERROR: failed to create the \"%s\" bpf-output event\n", name);
+                       return ERR_PTR(-err);
                }
 
                evsel = perf_evlist__last(evlist);
        }
 
-       bpf__for_each_stdout_map(map, obj, tmp) {
+       bpf__for_each_map_named(map, obj, tmp, name) {
                struct bpf_map_priv *priv = bpf_map__priv(map);
 
                if (IS_ERR(priv))
-                       return -BPF_LOADER_ERRNO__INTERNAL;
+                       return ERR_PTR(-BPF_LOADER_ERRNO__INTERNAL);
                if (priv)
                        continue;
 
                if (tmpl_priv) {
                        priv = bpf_map_priv__clone(tmpl_priv);
                        if (!priv)
-                               return -ENOMEM;
+                               return ERR_PTR(-ENOMEM);
 
                        err = bpf_map__set_priv(map, priv, bpf_map_priv__clear);
                        if (err) {
                                bpf_map_priv__clear(map, priv);
-                               return err;
+                               return ERR_PTR(err);
                        }
                } else if (evsel) {
                        struct bpf_map_op *op;
 
                        op = bpf_map__add_newop(map, NULL);
                        if (IS_ERR(op))
-                               return PTR_ERR(op);
+                               return ERR_PTR(PTR_ERR(op));
                        op->op_type = BPF_MAP_OP_SET_EVSEL;
                        op->v.evsel = evsel;
                }
        }
 
-       return 0;
+       return evsel;
+}
+
+int bpf__setup_stdout(struct perf_evlist *evlist)
+{
+       struct perf_evsel *evsel = bpf__setup_output_event(evlist, "__bpf_stdout__");
+       return IS_ERR(evsel) ? PTR_ERR(evsel) : 0;
 }
 
 #define ERRNO_OFFSET(e)                ((e) - __BPF_LOADER_ERRNO__START)
@@ -1780,8 +1792,8 @@ int bpf__strerror_apply_obj_config(int err, char *buf, size_t size)
        return 0;
 }
 
-int bpf__strerror_setup_stdout(struct perf_evlist *evlist __maybe_unused,
-                              int err, char *buf, size_t size)
+int bpf__strerror_setup_output_event(struct perf_evlist *evlist __maybe_unused,
+                                    int err, char *buf, size_t size)
 {
        bpf__strerror_head(err, buf, size);
        bpf__strerror_end(buf, size);
index 5d3aefd..62d245a 100644 (file)
@@ -43,6 +43,7 @@ enum bpf_loader_errno {
        __BPF_LOADER_ERRNO__END,
 };
 
+struct perf_evsel;
 struct bpf_object;
 struct parse_events_term;
 #define PERF_BPF_PROBE_GROUP "perf_bpf_probe"
@@ -82,9 +83,8 @@ int bpf__apply_obj_config(void);
 int bpf__strerror_apply_obj_config(int err, char *buf, size_t size);
 
 int bpf__setup_stdout(struct perf_evlist *evlist);
-int bpf__strerror_setup_stdout(struct perf_evlist *evlist, int err,
-                              char *buf, size_t size);
-
+struct perf_evsel *bpf__setup_output_event(struct perf_evlist *evlist, const char *name);
+int bpf__strerror_setup_output_event(struct perf_evlist *evlist, int err, char *buf, size_t size);
 #else
 #include <errno.h>
 
@@ -138,6 +138,12 @@ bpf__setup_stdout(struct perf_evlist *evlist __maybe_unused)
        return 0;
 }
 
+static inline struct perf_evsel *
+bpf__setup_output_event(struct perf_evlist *evlist __maybe_unused, const char *name __maybe_unused)
+{
+       return NULL;
+}
+
 static inline int
 __bpf_strerror(char *buf, size_t size)
 {
@@ -193,11 +199,16 @@ bpf__strerror_apply_obj_config(int err __maybe_unused,
 }
 
 static inline int
-bpf__strerror_setup_stdout(struct perf_evlist *evlist __maybe_unused,
-                          int err __maybe_unused, char *buf,
-                          size_t size)
+bpf__strerror_setup_output_event(struct perf_evlist *evlist __maybe_unused,
+                                int err __maybe_unused, char *buf, size_t size)
 {
        return __bpf_strerror(buf, size);
 }
+
 #endif
+
+static inline int bpf__strerror_setup_stdout(struct perf_evlist *evlist, int err, char *buf, size_t size)
+{
+       return bpf__strerror_setup_output_event(evlist, err, buf, size);
+}
 #endif
index ecca688..892e92e 100644 (file)
@@ -4,10 +4,12 @@
 
 #ifdef HAVE_ZLIB_SUPPORT
 int gzip_decompress_to_file(const char *input, int output_fd);
+bool gzip_is_compressed(const char *input);
 #endif
 
 #ifdef HAVE_LZMA_SUPPORT
 int lzma_decompress_to_file(const char *input, int output_fd);
+bool lzma_is_compressed(const char *input);
 #endif
 
 #endif /* PERF_COMPRESS_H */
index 5744c12..abd38ab 100644 (file)
@@ -310,8 +310,8 @@ static int add_tracepoint_field_value(struct ctf_writer *cw,
        if (flags & FIELD_IS_DYNAMIC) {
                unsigned long long tmp_val;
 
-               tmp_val = pevent_read_number(fmtf->event->pevent,
-                               data + offset, len);
+               tmp_val = tep_read_number(fmtf->event->pevent,
+                                         data + offset, len);
                offset = tmp_val;
                len = offset >> 16;
                offset &= 0xffff;
@@ -353,7 +353,7 @@ static int add_tracepoint_field_value(struct ctf_writer *cw,
                else {
                        unsigned long long value_int;
 
-                       value_int = pevent_read_number(
+                       value_int = tep_read_number(
                                        fmtf->event->pevent,
                                        data + offset + i * len, len);
 
index 51cf82c..bbed90e 100644 (file)
@@ -189,28 +189,34 @@ int dso__read_binary_type_filename(const struct dso *dso,
        return ret;
 }
 
+enum {
+       COMP_ID__NONE = 0,
+};
+
 static const struct {
        const char *fmt;
        int (*decompress)(const char *input, int output);
+       bool (*is_compressed)(const char *input);
 } compressions[] = {
+       [COMP_ID__NONE] = { .fmt = NULL, },
 #ifdef HAVE_ZLIB_SUPPORT
-       { "gz", gzip_decompress_to_file },
+       { "gz", gzip_decompress_to_file, gzip_is_compressed },
 #endif
 #ifdef HAVE_LZMA_SUPPORT
-       { "xz", lzma_decompress_to_file },
+       { "xz", lzma_decompress_to_file, lzma_is_compressed },
 #endif
-       { NULL, NULL },
+       { NULL, NULL, NULL },
 };
 
-bool is_supported_compression(const char *ext)
+static int is_supported_compression(const char *ext)
 {
        unsigned i;
 
-       for (i = 0; compressions[i].fmt; i++) {
+       for (i = 1; compressions[i].fmt; i++) {
                if (!strcmp(ext, compressions[i].fmt))
-                       return true;
+                       return i;
        }
-       return false;
+       return COMP_ID__NONE;
 }
 
 bool is_kernel_module(const char *pathname, int cpumode)
@@ -239,80 +245,73 @@ bool is_kernel_module(const char *pathname, int cpumode)
        return m.kmod;
 }
 
-bool decompress_to_file(const char *ext, const char *filename, int output_fd)
-{
-       unsigned i;
-
-       for (i = 0; compressions[i].fmt; i++) {
-               if (!strcmp(ext, compressions[i].fmt))
-                       return !compressions[i].decompress(filename,
-                                                          output_fd);
-       }
-       return false;
-}
-
 bool dso__needs_decompress(struct dso *dso)
 {
        return dso->symtab_type == DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP ||
                dso->symtab_type == DSO_BINARY_TYPE__GUEST_KMODULE_COMP;
 }
 
-static int decompress_kmodule(struct dso *dso, const char *name, char *tmpbuf)
+static int decompress_kmodule(struct dso *dso, const char *name,
+                             char *pathname, size_t len)
 {
+       char tmpbuf[] = KMOD_DECOMP_NAME;
        int fd = -1;
-       struct kmod_path m;
 
        if (!dso__needs_decompress(dso))
                return -1;
 
-       if (kmod_path__parse_ext(&m, dso->long_name))
+       if (dso->comp == COMP_ID__NONE)
                return -1;
 
-       if (!m.comp)
-               goto out;
+       /*
+        * We have proper compression id for DSO and yet the file
+        * behind the 'name' can still be plain uncompressed object.
+        *
+        * The reason is behind the logic we open the DSO object files,
+        * when we try all possible 'debug' objects until we find the
+        * data. So even if the DSO is represented by 'krava.xz' module,
+        * we can end up here opening ~/.debug/....23432432/debug' file
+        * which is not compressed.
+        *
+        * To keep this transparent, we detect this and return the file
+        * descriptor to the uncompressed file.
+        */
+       if (!compressions[dso->comp].is_compressed(name))
+               return open(name, O_RDONLY);
 
        fd = mkstemp(tmpbuf);
        if (fd < 0) {
                dso->load_errno = errno;
-               goto out;
+               return -1;
        }
 
-       if (!decompress_to_file(m.ext, name, fd)) {
+       if (compressions[dso->comp].decompress(name, fd)) {
                dso->load_errno = DSO_LOAD_ERRNO__DECOMPRESSION_FAILURE;
                close(fd);
                fd = -1;
        }
 
-out:
-       free(m.ext);
+       if (!pathname || (fd < 0))
+               unlink(tmpbuf);
+
+       if (pathname && (fd >= 0))
+               strncpy(pathname, tmpbuf, len);
+
        return fd;
 }
 
 int dso__decompress_kmodule_fd(struct dso *dso, const char *name)
 {
-       char tmpbuf[] = KMOD_DECOMP_NAME;
-       int fd;
-
-       fd = decompress_kmodule(dso, name, tmpbuf);
-       unlink(tmpbuf);
-       return fd;
+       return decompress_kmodule(dso, name, NULL, 0);
 }
 
 int dso__decompress_kmodule_path(struct dso *dso, const char *name,
                                 char *pathname, size_t len)
 {
-       char tmpbuf[] = KMOD_DECOMP_NAME;
-       int fd;
+       int fd = decompress_kmodule(dso, name, pathname, len);
 
-       fd = decompress_kmodule(dso, name, tmpbuf);
-       if (fd < 0) {
-               unlink(tmpbuf);
-               return -1;
-       }
-
-       strncpy(pathname, tmpbuf, len);
        close(fd);
-       return 0;
+       return fd >= 0 ? 0 : -1;
 }
 
 /*
@@ -332,7 +331,7 @@ int dso__decompress_kmodule_path(struct dso *dso, const char *name,
  * Returns 0 if there's no strdup error, -ENOMEM otherwise.
  */
 int __kmod_path__parse(struct kmod_path *m, const char *path,
-                      bool alloc_name, bool alloc_ext)
+                      bool alloc_name)
 {
        const char *name = strrchr(path, '/');
        const char *ext  = strrchr(path, '.');
@@ -372,10 +371,9 @@ int __kmod_path__parse(struct kmod_path *m, const char *path,
                return 0;
        }
 
-       if (is_supported_compression(ext + 1)) {
-               m->comp = true;
+       m->comp = is_supported_compression(ext + 1);
+       if (m->comp > COMP_ID__NONE)
                ext -= 3;
-       }
 
        /* Check .ko extension only if there's enough name left. */
        if (ext > name)
@@ -393,14 +391,6 @@ int __kmod_path__parse(struct kmod_path *m, const char *path,
                strxfrchar(m->name, '-', '_');
        }
 
-       if (alloc_ext && m->comp) {
-               m->ext = strdup(ext + 4);
-               if (!m->ext) {
-                       free((void *) m->name);
-                       return -ENOMEM;
-               }
-       }
-
        return 0;
 }
 
@@ -413,8 +403,10 @@ void dso__set_module_info(struct dso *dso, struct kmod_path *m,
                dso->symtab_type = DSO_BINARY_TYPE__GUEST_KMODULE;
 
        /* _KMODULE_COMP should be next to _KMODULE */
-       if (m->kmod && m->comp)
+       if (m->kmod && m->comp) {
                dso->symtab_type++;
+               dso->comp = m->comp;
+       }
 
        dso__set_short_name(dso, strdup(m->name), true);
 }
@@ -468,6 +460,7 @@ static int __open_dso(struct dso *dso, struct machine *machine)
        int fd = -EINVAL;
        char *root_dir = (char *)"";
        char *name = malloc(PATH_MAX);
+       bool decomp = false;
 
        if (!name)
                return -ENOMEM;
@@ -491,12 +484,13 @@ static int __open_dso(struct dso *dso, struct machine *machine)
                        goto out;
                }
 
+               decomp = true;
                strcpy(name, newpath);
        }
 
        fd = do_open(name);
 
-       if (dso__needs_decompress(dso))
+       if (decomp)
                unlink(name);
 
 out:
@@ -1218,6 +1212,7 @@ struct dso *dso__new(const char *name)
                dso->a2l_fails = 1;
                dso->kernel = DSO_TYPE_USER;
                dso->needs_swap = DSO_SWAP__UNSET;
+               dso->comp = COMP_ID__NONE;
                RB_CLEAR_NODE(&dso->rb_node);
                dso->root = NULL;
                INIT_LIST_HEAD(&dso->node);
index ef69de2..c538050 100644 (file)
@@ -175,6 +175,7 @@ struct dso {
        u16              short_name_len;
        void            *dwfl;                  /* DWARF debug info */
        struct auxtrace_cache *auxtrace_cache;
+       int              comp;
 
        /* dso data file */
        struct {
@@ -250,9 +251,7 @@ int dso__kernel_module_get_build_id(struct dso *dso, const char *root_dir);
 char dso__symtab_origin(const struct dso *dso);
 int dso__read_binary_type_filename(const struct dso *dso, enum dso_binary_type type,
                                   char *root_dir, char *filename, size_t size);
-bool is_supported_compression(const char *ext);
 bool is_kernel_module(const char *pathname, int cpumode);
-bool decompress_to_file(const char *ext, const char *filename, int output_fd);
 bool dso__needs_decompress(struct dso *dso);
 int dso__decompress_kmodule_fd(struct dso *dso, const char *name);
 int dso__decompress_kmodule_path(struct dso *dso, const char *name,
@@ -263,17 +262,15 @@ int dso__decompress_kmodule_path(struct dso *dso, const char *name,
 
 struct kmod_path {
        char *name;
-       char *ext;
-       bool  comp;
+       int   comp;
        bool  kmod;
 };
 
 int __kmod_path__parse(struct kmod_path *m, const char *path,
-                    bool alloc_name, bool alloc_ext);
+                    bool alloc_name);
 
-#define kmod_path__parse(__m, __p)      __kmod_path__parse(__m, __p, false, false)
-#define kmod_path__parse_name(__m, __p) __kmod_path__parse(__m, __p, true , false)
-#define kmod_path__parse_ext(__m, __p)  __kmod_path__parse(__m, __p, false, true)
+#define kmod_path__parse(__m, __p)      __kmod_path__parse(__m, __p, false)
+#define kmod_path__parse_name(__m, __p) __kmod_path__parse(__m, __p, true)
 
 void dso__set_module_info(struct dso *dso, struct kmod_path *m,
                          struct machine *machine);
index 0c8ecf0..0cd4215 100644 (file)
@@ -541,10 +541,17 @@ static int __event__synthesize_thread(union perf_event *comm_event,
                                                      tgid, process, machine) < 0)
                        return -1;
 
+               /*
+                * send mmap only for thread group leader
+                * see thread__init_map_groups
+                */
+               if (pid == tgid &&
+                   perf_event__synthesize_mmap_events(tool, mmap_event, pid, tgid,
+                                                      process, machine, mmap_data,
+                                                      proc_map_timeout))
+                       return -1;
 
-               return perf_event__synthesize_mmap_events(tool, mmap_event, pid, tgid,
-                                                         process, machine, mmap_data,
-                                                         proc_map_timeout);
+               return 0;
        }
 
        if (machine__is_default_guest(machine))
index e7a4b31..be440df 100644 (file)
@@ -803,7 +803,7 @@ static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx,
                if (*output == -1) {
                        *output = fd;
 
-                       if (perf_mmap__mmap(&maps[idx], mp, *output < 0)
+                       if (perf_mmap__mmap(&maps[idx], mp, *output, evlist_cpu) < 0)
                                return -1;
                } else {
                        if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT, *output) != 0)
index ddf84b9..c980bbf 100644 (file)
@@ -2683,7 +2683,7 @@ int perf_event__synthesize_sample(union perf_event *event, u64 type,
 
 struct format_field *perf_evsel__field(struct perf_evsel *evsel, const char *name)
 {
-       return pevent_find_field(evsel->tp_format, name);
+       return tep_find_field(evsel->tp_format, name);
 }
 
 void *perf_evsel__rawptr(struct perf_evsel *evsel, struct perf_sample *sample,
index 973c031..163c960 100644 (file)
@@ -452,11 +452,18 @@ static inline int perf_evsel__group_idx(struct perf_evsel *evsel)
        return evsel->idx - evsel->leader->idx;
 }
 
+/* Iterates group WITHOUT the leader. */
 #define for_each_group_member(_evsel, _leader)                                         \
 for ((_evsel) = list_entry((_leader)->node.next, struct perf_evsel, node);     \
      (_evsel) && (_evsel)->leader == (_leader);                                        \
      (_evsel) = list_entry((_evsel)->node.next, struct perf_evsel, node))
 
+/* Iterates group WITH the leader. */
+#define for_each_group_evsel(_evsel, _leader)                                  \
+for ((_evsel) = _leader;                                                       \
+     (_evsel) && (_evsel)->leader == (_leader);                                        \
+     (_evsel) = list_entry((_evsel)->node.next, struct perf_evsel, node))
+
 static inline bool perf_evsel__has_branch_callstack(const struct perf_evsel *evsel)
 {
        return evsel->attr.branch_sample_type & PERF_SAMPLE_BRANCH_CALL_STACK;
index 5af58aa..3cadc25 100644 (file)
@@ -279,8 +279,6 @@ static int do_read_bitmap(struct feat_fd *ff, unsigned long **pset, u64 *psize)
        if (!set)
                return -ENOMEM;
 
-       bitmap_zero(set, size);
-
        p = (u64 *) set;
 
        for (i = 0; (u64) i < BITS_TO_U64(size); i++) {
@@ -1285,7 +1283,6 @@ static int memory_node__read(struct memory_node *n, unsigned long idx)
                return -ENOMEM;
        }
 
-       bitmap_zero(n->set, size);
        n->node = idx;
        n->size = size;
 
@@ -3207,7 +3204,7 @@ static int read_attr(int fd, struct perf_header *ph,
 }
 
 static int perf_evsel__prepare_tracepoint_event(struct perf_evsel *evsel,
-                                               struct pevent *pevent)
+                                               struct tep_handle *pevent)
 {
        struct event_format *event;
        char bf[128];
@@ -3221,7 +3218,7 @@ static int perf_evsel__prepare_tracepoint_event(struct perf_evsel *evsel,
                return -1;
        }
 
-       event = pevent_find_event(pevent, evsel->attr.config);
+       event = tep_find_event(pevent, evsel->attr.config);
        if (event == NULL) {
                pr_debug("cannot find event format for %d\n", (int)evsel->attr.config);
                return -1;
@@ -3239,7 +3236,7 @@ static int perf_evsel__prepare_tracepoint_event(struct perf_evsel *evsel,
 }
 
 static int perf_evlist__prepare_tracepoint_events(struct perf_evlist *evlist,
-                                                 struct pevent *pevent)
+                                                 struct tep_handle *pevent)
 {
        struct perf_evsel *pos;
 
index 5e94857..19262f9 100644 (file)
                "$CLANG_OPTIONS $KERNEL_INC_OPTIONS $PERF_BPF_INC_OPTIONS " \
                "-Wno-unused-value -Wno-pointer-sign "          \
                "-working-directory $WORKING_DIR "              \
-               "-c \"$CLANG_SOURCE\" -target bpf -O2 -o -"
+               "-c \"$CLANG_SOURCE\" -target bpf $CLANG_EMIT_LLVM -O2 -o - $LLVM_OPTIONS_PIPE"
 
 struct llvm_param llvm_param = {
        .clang_path = "clang",
+       .llc_path = "llc",
        .clang_bpf_cmd_template = CLANG_BPF_CMD_DEFAULT_TEMPLATE,
        .clang_opt = NULL,
+       .opts = NULL,
        .kbuild_dir = NULL,
        .kbuild_opts = NULL,
        .user_set_param = false,
@@ -51,6 +53,8 @@ int perf_llvm_config(const char *var, const char *value)
                llvm_param.kbuild_opts = strdup(value);
        else if (!strcmp(var, "dump-obj"))
                llvm_param.dump_obj = !!perf_config_bool(var, value);
+       else if (!strcmp(var, "opts"))
+               llvm_param.opts = strdup(value);
        else {
                pr_debug("Invalid LLVM config option: %s\n", value);
                return -1;
@@ -430,11 +434,13 @@ int llvm__compile_bpf(const char *path, void **p_obj_buf,
        unsigned int kernel_version;
        char linux_version_code_str[64];
        const char *clang_opt = llvm_param.clang_opt;
-       char clang_path[PATH_MAX], abspath[PATH_MAX], nr_cpus_avail_str[64];
+       char clang_path[PATH_MAX], llc_path[PATH_MAX], abspath[PATH_MAX], nr_cpus_avail_str[64];
        char serr[STRERR_BUFSIZE];
        char *kbuild_dir = NULL, *kbuild_include_opts = NULL,
             *perf_bpf_include_opts = NULL;
        const char *template = llvm_param.clang_bpf_cmd_template;
+       char *pipe_template = NULL;
+       const char *opts = llvm_param.opts;
        char *command_echo = NULL, *command_out;
        char *perf_include_dir = system_path(PERF_INCLUDE_DIR);
 
@@ -484,6 +490,26 @@ int llvm__compile_bpf(const char *path, void **p_obj_buf,
        force_set_env("PERF_BPF_INC_OPTIONS", perf_bpf_include_opts);
        force_set_env("WORKING_DIR", kbuild_dir ? : ".");
 
+       if (opts) {
+               err = search_program(llvm_param.llc_path, "llc", llc_path);
+               if (err) {
+                       pr_err("ERROR:\tunable to find llc.\n"
+                              "Hint:\tTry to install latest clang/llvm to support BPF. Check your $PATH\n"
+                              "     \tand 'llc-path' option in [llvm] section of ~/.perfconfig.\n");
+                       version_notice();
+                       goto errout;
+               }
+
+               if (asprintf(&pipe_template, "%s -emit-llvm | %s -march=bpf %s -filetype=obj -o -",
+                             template, llc_path, opts) < 0) {
+                       pr_err("ERROR:\tnot enough memory to setup command line\n");
+                       goto errout;
+               }
+
+               template = pipe_template;
+
+       }
+
        /*
         * Since we may reset clang's working dir, path of source file
         * should be transferred into absolute path, except we want
@@ -535,6 +561,7 @@ errout:
        free(obj_buf);
        free(perf_bpf_include_opts);
        free(perf_include_dir);
+       free(pipe_template);
        if (p_obj_buf)
                *p_obj_buf = NULL;
        if (p_obj_buf_sz)
index d3ad8de..bf3f3f4 100644 (file)
@@ -11,6 +11,8 @@
 struct llvm_param {
        /* Path of clang executable */
        const char *clang_path;
+       /* Path of llc executable */
+       const char *llc_path;
        /*
         * Template of clang bpf compiling. 5 env variables
         * can be used:
@@ -23,6 +25,13 @@ struct llvm_param {
        const char *clang_bpf_cmd_template;
        /* Will be filled in $CLANG_OPTIONS */
        const char *clang_opt;
+       /*
+        * If present it'll add -emit-llvm to $CLANG_OPTIONS to pipe
+        * the clang output to llc, useful for new llvm options not
+        * yet selectable via 'clang -mllvm option', such as -mattr=dwarfris
+        * in clang 6.0/llvm 7
+        */
+       const char *opts;
        /* Where to find kbuild system */
        const char *kbuild_dir;
        /*
index 07498ea..b1dd29a 100644 (file)
@@ -3,9 +3,13 @@
 #include <lzma.h>
 #include <stdio.h>
 #include <linux/compiler.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
 #include "compress.h"
 #include "util.h"
 #include "debug.h"
+#include <unistd.h>
 
 #define BUFSIZE 8192
 
@@ -99,3 +103,19 @@ err_fclose:
        fclose(infile);
        return err;
 }
+
+bool lzma_is_compressed(const char *input)
+{
+       int fd = open(input, O_RDONLY);
+       const uint8_t magic[6] = { 0xFD, '7', 'z', 'X', 'Z', 0x00 };
+       char buf[6] = { 0 };
+       ssize_t rc;
+
+       if (fd < 0)
+               return -1;
+
+       rc = read(fd, buf, sizeof(buf));
+       close(fd);
+       return rc == sizeof(buf) ?
+              memcmp(buf, magic, sizeof(buf)) == 0 : false;
+}
index b300a39..c4acd20 100644 (file)
@@ -1212,8 +1212,10 @@ static int map_groups__set_module_path(struct map_groups *mg, const char *path,
         * Full name could reveal us kmod compression, so
         * we need to update the symtab_type if needed.
         */
-       if (m->comp && is_kmod_dso(map->dso))
+       if (m->comp && is_kmod_dso(map->dso)) {
                map->dso->symtab_type++;
+               map->dso->comp = m->comp;
+       }
 
        return 0;
 }
index 1de7660..d856b85 100644 (file)
@@ -265,7 +265,7 @@ pid_t machine__get_current_tid(struct machine *machine, int cpu);
 int machine__set_current_tid(struct machine *machine, int cpu, pid_t pid,
                             pid_t tid);
 /*
- * For use with libtraceevent's pevent_set_function_resolver()
+ * For use with libtraceevent's tep_set_function_resolver()
  */
 char *machine__resolve_kernel_addr(void *vmachine, unsigned long long *addrp, char **modp);
 
index 89ac5b5..36d0763 100644 (file)
@@ -381,20 +381,6 @@ struct map *map__clone(struct map *from)
        return map;
 }
 
-int map__overlap(struct map *l, struct map *r)
-{
-       if (l->start > r->start) {
-               struct map *t = l;
-               l = r;
-               r = t;
-       }
-
-       if (l->end > r->start)
-               return 1;
-
-       return 0;
-}
-
 size_t map__fprintf(struct map *map, FILE *fp)
 {
        return fprintf(fp, " %" PRIx64 "-%" PRIx64 " %" PRIx64 " %s\n",
@@ -675,20 +661,42 @@ static void __map_groups__insert(struct map_groups *mg, struct map *map)
 static int maps__fixup_overlappings(struct maps *maps, struct map *map, FILE *fp)
 {
        struct rb_root *root;
-       struct rb_node *next;
+       struct rb_node *next, *first;
        int err = 0;
 
        down_write(&maps->lock);
 
        root = &maps->entries;
-       next = rb_first(root);
 
+       /*
+        * Find first map where end > map->start.
+        * Same as find_vma() in kernel.
+        */
+       next = root->rb_node;
+       first = NULL;
+       while (next) {
+               struct map *pos = rb_entry(next, struct map, rb_node);
+
+               if (pos->end > map->start) {
+                       first = next;
+                       if (pos->start <= map->start)
+                               break;
+                       next = next->rb_left;
+               } else
+                       next = next->rb_right;
+       }
+
+       next = first;
        while (next) {
                struct map *pos = rb_entry(next, struct map, rb_node);
                next = rb_next(&pos->rb_node);
 
-               if (!map__overlap(pos, map))
-                       continue;
+               /*
+                * Stop if current map starts after map->end.
+                * Maps are ordered by start: next will not overlap for sure.
+                */
+               if (pos->start >= map->end)
+                       break;
 
                if (verbose >= 2) {
 
index 4cb90f2..e0f327b 100644 (file)
@@ -166,7 +166,6 @@ static inline void __map__zput(struct map **map)
 
 #define map__zput(map) __map__zput(&map)
 
-int map__overlap(struct map *l, struct map *r);
 size_t map__fprintf(struct map *map, FILE *fp);
 size_t map__fprintf_dsoname(struct map *map, FILE *fp);
 char *map__srcline(struct map *map, u64 addr, struct symbol *sym);
index fc83267..215f69f 100644 (file)
@@ -164,7 +164,7 @@ void perf_mmap__munmap(struct perf_mmap *map)
        auxtrace_mmap__munmap(&map->auxtrace_mmap);
 }
 
-int perf_mmap__mmap(struct perf_mmap *map, struct mmap_params *mp, int fd)
+int perf_mmap__mmap(struct perf_mmap *map, struct mmap_params *mp, int fd, int cpu)
 {
        /*
         * The last one will be done at perf_mmap__consume(), so that we
@@ -191,6 +191,7 @@ int perf_mmap__mmap(struct perf_mmap *map, struct mmap_params *mp, int fd)
                return -1;
        }
        map->fd = fd;
+       map->cpu = cpu;
 
        if (auxtrace_mmap__mmap(&map->auxtrace_mmap,
                                &mp->auxtrace_mp, map->base, fd))
index d82294d..05a6d47 100644 (file)
@@ -18,6 +18,7 @@ struct perf_mmap {
        void             *base;
        int              mask;
        int              fd;
+       int              cpu;
        refcount_t       refcnt;
        u64              prev;
        u64              start;
@@ -60,7 +61,7 @@ struct mmap_params {
        struct auxtrace_mmap_params auxtrace_mp;
 };
 
-int perf_mmap__mmap(struct perf_mmap *map, struct mmap_params *mp, int fd);
+int perf_mmap__mmap(struct perf_mmap *map, struct mmap_params *mp, int fd, int cpu);
 void perf_mmap__munmap(struct perf_mmap *map);
 
 void perf_mmap__get(struct perf_mmap *map);
index 5be0217..cf8bd12 100644 (file)
@@ -139,6 +139,9 @@ struct nsinfo *nsinfo__copy(struct nsinfo *nsi)
 {
        struct nsinfo *nnsi;
 
+       if (nsi == NULL)
+               return NULL;
+
        nnsi = calloc(1, sizeof(*nnsi));
        if (nnsi != NULL) {
                nnsi->pid = nsi->pid;
index 15eec49..f8cd3e7 100644 (file)
@@ -1991,8 +1991,11 @@ static int set_filter(struct perf_evsel *evsel, const void *arg)
        int nr_addr_filters = 0;
        struct perf_pmu *pmu = NULL;
 
-       if (evsel == NULL)
-               goto err;
+       if (evsel == NULL) {
+               fprintf(stderr,
+                       "--filter option should follow a -e tracepoint or HW tracer option\n");
+               return -1;
+       }
 
        if (evsel->attr.type == PERF_TYPE_TRACEPOINT) {
                if (perf_evsel__append_tp_filter(evsel, str) < 0) {
@@ -2014,8 +2017,11 @@ static int set_filter(struct perf_evsel *evsel, const void *arg)
                perf_pmu__scan_file(pmu, "nr_addr_filters",
                                    "%d", &nr_addr_filters);
 
-       if (!nr_addr_filters)
-               goto err;
+       if (!nr_addr_filters) {
+               fprintf(stderr,
+                       "This CPU does not support address filtering\n");
+               return -1;
+       }
 
        if (perf_evsel__append_addr_filter(evsel, str) < 0) {
                fprintf(stderr,
@@ -2024,12 +2030,6 @@ static int set_filter(struct perf_evsel *evsel, const void *arg)
        }
 
        return 0;
-
-err:
-       fprintf(stderr,
-               "--filter option should follow a -e tracepoint or HW tracer option\n");
-
-       return -1;
 }
 
 int parse_filter(const struct option *opt, const char *str,
index 863b614..ce501ba 100644 (file)
@@ -11,6 +11,7 @@
 #include "cpumap.h"
 #include "print_binary.h"
 #include "thread_map.h"
+#include "mmap.h"
 
 #if PY_MAJOR_VERSION < 3
 #define _PyUnicode_FromString(arg) \
@@ -341,7 +342,7 @@ static bool is_tracepoint(struct pyrf_event *pevent)
 static PyObject*
 tracepoint_field(struct pyrf_event *pe, struct format_field *field)
 {
-       struct pevent *pevent = field->event->pevent;
+       struct tep_handle *pevent = field->event->pevent;
        void *data = pe->sample.raw_data;
        PyObject *ret = NULL;
        unsigned long long val;
@@ -351,7 +352,7 @@ tracepoint_field(struct pyrf_event *pe, struct format_field *field)
                offset = field->offset;
                len    = field->size;
                if (field->flags & FIELD_IS_DYNAMIC) {
-                       val     = pevent_read_number(pevent, data + offset, len);
+                       val     = tep_read_number(pevent, data + offset, len);
                        offset  = val;
                        len     = offset >> 16;
                        offset &= 0xffff;
@@ -364,8 +365,8 @@ tracepoint_field(struct pyrf_event *pe, struct format_field *field)
                        field->flags &= ~FIELD_IS_STRING;
                }
        } else {
-               val = pevent_read_number(pevent, data + field->offset,
-                                        field->size);
+               val = tep_read_number(pevent, data + field->offset,
+                                     field->size);
                if (field->flags & FIELD_IS_POINTER)
                        ret = PyLong_FromUnsignedLong((unsigned long) val);
                else if (field->flags & FIELD_IS_SIGNED)
@@ -394,7 +395,7 @@ get_tracepoint_field(struct pyrf_event *pevent, PyObject *attr_name)
                evsel->tp_format = tp_format;
        }
 
-       field = pevent_find_any_field(evsel->tp_format, str);
+       field = tep_find_any_field(evsel->tp_format, str);
        if (!field)
                return NULL;
 
@@ -976,6 +977,20 @@ static PyObject *pyrf_evlist__add(struct pyrf_evlist *pevlist,
        return Py_BuildValue("i", evlist->nr_entries);
 }
 
+static struct perf_mmap *get_md(struct perf_evlist *evlist, int cpu)
+{
+       int i;
+
+       for (i = 0; i < evlist->nr_mmaps; i++) {
+               struct perf_mmap *md = &evlist->mmap[i];
+
+               if (md->cpu == cpu)
+                       return md;
+       }
+
+       return NULL;
+}
+
 static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist,
                                          PyObject *args, PyObject *kwargs)
 {
@@ -990,7 +1005,10 @@ static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist,
                                         &cpu, &sample_id_all))
                return NULL;
 
-       md = &evlist->mmap[cpu];
+       md = get_md(evlist, cpu);
+       if (!md)
+               return NULL;
+
        if (perf_mmap__read_init(md) < 0)
                goto end;
 
diff --git a/tools/perf/util/s390-cpumsf-kernel.h b/tools/perf/util/s390-cpumsf-kernel.h
new file mode 100644 (file)
index 0000000..de8c7ad
--- /dev/null
@@ -0,0 +1,71 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Auxtrace support for s390 CPU measurement sampling facility
+ *
+ *  Copyright IBM Corp. 2018
+ *  Author(s): Hendrik Brueckner <brueckner@linux.ibm.com>
+ *            Thomas Richter <tmricht@linux.ibm.com>
+ */
+#ifndef S390_CPUMSF_KERNEL_H
+#define S390_CPUMSF_KERNEL_H
+
+#define        S390_CPUMSF_PAGESZ      4096    /* Size of sample block units */
+#define        S390_CPUMSF_DIAG_DEF_FIRST      0x8001  /* Diagnostic entry lowest id */
+
+struct hws_basic_entry {
+       unsigned int def:16;        /* 0-15  Data Entry Format           */
+       unsigned int R:4;           /* 16-19 reserved                    */
+       unsigned int U:4;           /* 20-23 Number of unique instruct.  */
+       unsigned int z:2;           /* zeros                             */
+       unsigned int T:1;           /* 26 PSW DAT mode                   */
+       unsigned int W:1;           /* 27 PSW wait state                 */
+       unsigned int P:1;           /* 28 PSW Problem state              */
+       unsigned int AS:2;          /* 29-30 PSW address-space control   */
+       unsigned int I:1;           /* 31 entry valid or invalid         */
+       unsigned int CL:2;          /* 32-33 Configuration Level         */
+       unsigned int:14;
+       unsigned int prim_asn:16;   /* primary ASN                       */
+       unsigned long long ia;      /* Instruction Address               */
+       unsigned long long gpp;     /* Guest Program Parameter           */
+       unsigned long long hpp;     /* Host Program Parameter            */
+};
+
+struct hws_diag_entry {
+       unsigned int def:16;        /* 0-15  Data Entry Format           */
+       unsigned int R:15;          /* 16-19 and 20-30 reserved          */
+       unsigned int I:1;           /* 31 entry valid or invalid         */
+       u8           data[];        /* Machine-dependent sample data     */
+};
+
+struct hws_combined_entry {
+       struct hws_basic_entry  basic;  /* Basic-sampling data entry */
+       struct hws_diag_entry   diag;   /* Diagnostic-sampling data entry */
+};
+
+struct hws_trailer_entry {
+       union {
+               struct {
+                       unsigned int f:1;       /* 0 - Block Full Indicator   */
+                       unsigned int a:1;       /* 1 - Alert request control  */
+                       unsigned int t:1;       /* 2 - Timestamp format       */
+                       unsigned int:29;        /* 3 - 31: Reserved           */
+                       unsigned int bsdes:16;  /* 32-47: size of basic SDE   */
+                       unsigned int dsdes:16;  /* 48-63: size of diagnostic SDE */
+               };
+               unsigned long long flags;       /* 0 - 64: All indicators     */
+       };
+       unsigned long long overflow;     /* 64 - sample Overflow count        */
+       unsigned char timestamp[16];     /* 16 - 31 timestamp                 */
+       unsigned long long reserved1;    /* 32 -Reserved                      */
+       unsigned long long reserved2;    /*                                   */
+       union {                          /* 48 - reserved for programming use */
+               struct {
+                       unsigned long long clock_base:1; /* in progusage2 */
+                       unsigned long long progusage1:63;
+                       unsigned long long progusage2;
+               };
+               unsigned long long progusage[2];
+       };
+};
+
+#endif
diff --git a/tools/perf/util/s390-cpumsf.c b/tools/perf/util/s390-cpumsf.c
new file mode 100644 (file)
index 0000000..d2c78ff
--- /dev/null
@@ -0,0 +1,945 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright IBM Corp. 2018
+ * Auxtrace support for s390 CPU-Measurement Sampling Facility
+ *
+ * Author(s):  Thomas Richter <tmricht@linux.ibm.com>
+ *
+ * Auxiliary traces are collected during 'perf record' using rbd000 event.
+ * Several PERF_RECORD_XXX are generated during recording:
+ *
+ * PERF_RECORD_AUX:
+ *     Records that new data landed in the AUX buffer part.
+ * PERF_RECORD_AUXTRACE:
+ *     Defines auxtrace data. Followed by the actual data. The contents of
+ *     the auxtrace data is dependent on the event and the CPU.
+ *     This record is generated by perf record command. For details
+ *     see Documentation/perf.data-file-format.txt.
+ * PERF_RECORD_AUXTRACE_INFO:
+ *     Defines a table of contains for PERF_RECORD_AUXTRACE records. This
+ *     record is generated during 'perf record' command. Each record contains up
+ *     to 256 entries describing offset and size of the AUXTRACE data in the
+ *     perf.data file.
+ * PERF_RECORD_AUXTRACE_ERROR:
+ *     Indicates an error during AUXTRACE collection such as buffer overflow.
+ * PERF_RECORD_FINISHED_ROUND:
+ *     Perf events are not necessarily in time stamp order, as they can be
+ *     collected in parallel on different CPUs. If the events should be
+ *     processed in time order they need to be sorted first.
+ *     Perf report guarantees that there is no reordering over a
+ *     PERF_RECORD_FINISHED_ROUND boundary event. All perf records with a
+ *     time stamp lower than this record are processed (and displayed) before
+ *     the succeeding perf record are processed.
+ *
+ * These records are evaluated during perf report command.
+ *
+ * 1. PERF_RECORD_AUXTRACE_INFO is used to set up the infrastructure for
+ * auxiliary trace data processing. See s390_cpumsf_process_auxtrace_info()
+ * below.
+ * Auxiliary trace data is collected per CPU. To merge the data into the report
+ * an auxtrace_queue is created for each CPU. It is assumed that the auxtrace
+ * data is in ascending order.
+ *
+ * Each queue has a double linked list of auxtrace_buffers. This list contains
+ * the offset and size of a CPU's auxtrace data. During auxtrace processing
+ * the data portion is mmap()'ed.
+ *
+ * To sort the queues in chronological order, all queue access is controlled
+ * by the auxtrace_heap. This is basicly a stack, each stack element has two
+ * entries, the queue number and a time stamp. However the stack is sorted by
+ * the time stamps. The highest time stamp is at the bottom the lowest
+ * (nearest) time stamp is at the top. That sort order is maintained at all
+ * times!
+ *
+ * After the auxtrace infrastructure has been setup, the auxtrace queues are
+ * filled with data (offset/size pairs) and the auxtrace_heap is populated.
+ *
+ * 2. PERF_RECORD_XXX processing triggers access to the auxtrace_queues.
+ * Each record is handled by s390_cpumsf_process_event(). The time stamp of
+ * the perf record is compared with the time stamp located on the auxtrace_heap
+ * top element. If that time stamp is lower than the time stamp from the
+ * record sample, the auxtrace queues will be processed. As auxtrace queues
+ * control many auxtrace_buffers and each buffer can be quite large, the
+ * auxtrace buffer might be processed only partially. In this case the
+ * position in the auxtrace_buffer of that queue is remembered and the time
+ * stamp of the last processed entry of the auxtrace_buffer replaces the
+ * current auxtrace_heap top.
+ *
+ * 3. Auxtrace_queues might run of out data and are feeded by the
+ * PERF_RECORD_AUXTRACE handling, see s390_cpumsf_process_auxtrace_event().
+ *
+ * Event Generation
+ * Each sampling-data entry in the auxilary trace data generates a perf sample.
+ * This sample is filled
+ * with data from the auxtrace such as PID/TID, instruction address, CPU state,
+ * etc. This sample is processed with perf_session__deliver_synth_event() to
+ * be included into the GUI.
+ *
+ * 4. PERF_RECORD_FINISHED_ROUND event is used to process all the remaining
+ * auxiliary traces entries until the time stamp of this record is reached
+ * auxtrace_heap top. This is triggered by ordered_event->deliver().
+ *
+ *
+ * Perf event processing.
+ * Event processing of PERF_RECORD_XXX entries relies on time stamp entries.
+ * This is the function call sequence:
+ *
+ * __cmd_report()
+ * |
+ * perf_session__process_events()
+ * |
+ * __perf_session__process_events()
+ * |
+ * perf_session__process_event()
+ * |  This functions splits the PERF_RECORD_XXX records.
+ * |  - Those generated by perf record command (type number equal or higher
+ * |    than PERF_RECORD_USER_TYPE_START) are handled by
+ * |    perf_session__process_user_event(see below)
+ * |  - Those generated by the kernel are handled by
+ * |    perf_evlist__parse_sample_timestamp()
+ * |
+ * perf_evlist__parse_sample_timestamp()
+ * |  Extract time stamp from sample data.
+ * |
+ * perf_session__queue_event()
+ * |  If timestamp is positive the sample is entered into an ordered_event
+ * |  list, sort order is the timestamp. The event processing is deferred until
+ * |  later (see perf_session__process_user_event()).
+ * |  Other timestamps (0 or -1) are handled immediately by
+ * |  perf_session__deliver_event(). These are events generated at start up
+ * |  of command perf record. They create PERF_RECORD_COMM and PERF_RECORD_MMAP*
+ * |  records. They are needed to create a list of running processes and its
+ * |  memory mappings and layout. They are needed at the beginning to enable
+ * |  command perf report to create process trees and memory mappings.
+ * |
+ * perf_session__deliver_event()
+ * |  Delivers a PERF_RECORD_XXX entry for handling.
+ * |
+ * auxtrace__process_event()
+ * |  The timestamp of the PERF_RECORD_XXX entry is taken to correlate with
+ * |  time stamps from the auxiliary trace buffers. This enables
+ * |  synchronization between auxiliary trace data and the events on the
+ * |  perf.data file.
+ * |
+ * machine__deliver_event()
+ * |  Handles the PERF_RECORD_XXX event. This depends on the record type.
+ *    It might update the process tree, update a process memory map or enter
+ *    a sample with IP and call back chain data into GUI data pool.
+ *
+ *
+ * Deferred processing determined by perf_session__process_user_event() is
+ * finally processed when a PERF_RECORD_FINISHED_ROUND is encountered. These
+ * are generated during command perf record.
+ * The timestamp of PERF_RECORD_FINISHED_ROUND event is taken to process all
+ * PERF_RECORD_XXX entries stored in the ordered_event list. This list was
+ * built up while reading the perf.data file.
+ * Each event is now processed by calling perf_session__deliver_event().
+ * This enables time synchronization between the data in the perf.data file and
+ * the data in the auxiliary trace buffers.
+ */
+
+#include <endian.h>
+#include <errno.h>
+#include <byteswap.h>
+#include <inttypes.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/bitops.h>
+#include <linux/log2.h>
+
+#include "cpumap.h"
+#include "color.h"
+#include "evsel.h"
+#include "evlist.h"
+#include "machine.h"
+#include "session.h"
+#include "util.h"
+#include "thread.h"
+#include "debug.h"
+#include "auxtrace.h"
+#include "s390-cpumsf.h"
+#include "s390-cpumsf-kernel.h"
+
+struct s390_cpumsf {
+       struct auxtrace         auxtrace;
+       struct auxtrace_queues  queues;
+       struct auxtrace_heap    heap;
+       struct perf_session     *session;
+       struct machine          *machine;
+       u32                     auxtrace_type;
+       u32                     pmu_type;
+       u16                     machine_type;
+       bool                    data_queued;
+};
+
+struct s390_cpumsf_queue {
+       struct s390_cpumsf      *sf;
+       unsigned int            queue_nr;
+       struct auxtrace_buffer  *buffer;
+       int                     cpu;
+};
+
+/* Display s390 CPU measurement facility basic-sampling data entry */
+static bool s390_cpumsf_basic_show(const char *color, size_t pos,
+                                  struct hws_basic_entry *basic)
+{
+       if (basic->def != 1) {
+               pr_err("Invalid AUX trace basic entry [%#08zx]\n", pos);
+               return false;
+       }
+       color_fprintf(stdout, color, "    [%#08zx] Basic   Def:%04x Inst:%#04x"
+                     " %c%c%c%c AS:%d ASN:%#04x IA:%#018llx\n"
+                     "\t\tCL:%d HPP:%#018llx GPP:%#018llx\n",
+                     pos, basic->def, basic->U,
+                     basic->T ? 'T' : ' ',
+                     basic->W ? 'W' : ' ',
+                     basic->P ? 'P' : ' ',
+                     basic->I ? 'I' : ' ',
+                     basic->AS, basic->prim_asn, basic->ia, basic->CL,
+                     basic->hpp, basic->gpp);
+       return true;
+}
+
+/* Display s390 CPU measurement facility diagnostic-sampling data entry */
+static bool s390_cpumsf_diag_show(const char *color, size_t pos,
+                                 struct hws_diag_entry *diag)
+{
+       if (diag->def < S390_CPUMSF_DIAG_DEF_FIRST) {
+               pr_err("Invalid AUX trace diagnostic entry [%#08zx]\n", pos);
+               return false;
+       }
+       color_fprintf(stdout, color, "    [%#08zx] Diag    Def:%04x %c\n",
+                     pos, diag->def, diag->I ? 'I' : ' ');
+       return true;
+}
+
+/* Return TOD timestamp contained in an trailer entry */
+static unsigned long long trailer_timestamp(struct hws_trailer_entry *te)
+{
+       /* te->t set: TOD in STCKE format, bytes 8-15
+        * to->t not set: TOD in STCK format, bytes 0-7
+        */
+       unsigned long long ts;
+
+       memcpy(&ts, &te->timestamp[te->t], sizeof(ts));
+       return ts;
+}
+
+/* Display s390 CPU measurement facility trailer entry */
+static bool s390_cpumsf_trailer_show(const char *color, size_t pos,
+                                    struct hws_trailer_entry *te)
+{
+       if (te->bsdes != sizeof(struct hws_basic_entry)) {
+               pr_err("Invalid AUX trace trailer entry [%#08zx]\n", pos);
+               return false;
+       }
+       color_fprintf(stdout, color, "    [%#08zx] Trailer %c%c%c bsdes:%d"
+                     " dsdes:%d Overflow:%lld Time:%#llx\n"
+                     "\t\tC:%d TOD:%#lx 1:%#llx 2:%#llx\n",
+                     pos,
+                     te->f ? 'F' : ' ',
+                     te->a ? 'A' : ' ',
+                     te->t ? 'T' : ' ',
+                     te->bsdes, te->dsdes, te->overflow,
+                     trailer_timestamp(te), te->clock_base, te->progusage2,
+                     te->progusage[0], te->progusage[1]);
+       return true;
+}
+
+/* Test a sample data block. It must be 4KB or a multiple thereof in size and
+ * 4KB page aligned. Each sample data page has a trailer entry at the
+ * end which contains the sample entry data sizes.
+ *
+ * Return true if the sample data block passes the checks and set the
+ * basic set entry size and diagnostic set entry size.
+ *
+ * Return false on failure.
+ *
+ * Note: Old hardware does not set the basic or diagnostic entry sizes
+ * in the trailer entry. Use the type number instead.
+ */
+static bool s390_cpumsf_validate(int machine_type,
+                                unsigned char *buf, size_t len,
+                                unsigned short *bsdes,
+                                unsigned short *dsdes)
+{
+       struct hws_basic_entry *basic = (struct hws_basic_entry *)buf;
+       struct hws_trailer_entry *te;
+
+       *dsdes = *bsdes = 0;
+       if (len & (S390_CPUMSF_PAGESZ - 1))     /* Illegal size */
+               return false;
+       if (basic->def != 1)            /* No basic set entry, must be first */
+               return false;
+       /* Check for trailer entry at end of SDB */
+       te = (struct hws_trailer_entry *)(buf + S390_CPUMSF_PAGESZ
+                                             - sizeof(*te));
+       *bsdes = te->bsdes;
+       *dsdes = te->dsdes;
+       if (!te->bsdes && !te->dsdes) {
+               /* Very old hardware, use CPUID */
+               switch (machine_type) {
+               case 2097:
+               case 2098:
+                       *dsdes = 64;
+                       *bsdes = 32;
+                       break;
+               case 2817:
+               case 2818:
+                       *dsdes = 74;
+                       *bsdes = 32;
+                       break;
+               case 2827:
+               case 2828:
+                       *dsdes = 85;
+                       *bsdes = 32;
+                       break;
+               default:
+                       /* Illegal trailer entry */
+                       return false;
+               }
+       }
+       return true;
+}
+
+/* Return true if there is room for another entry */
+static bool s390_cpumsf_reached_trailer(size_t entry_sz, size_t pos)
+{
+       size_t payload = S390_CPUMSF_PAGESZ - sizeof(struct hws_trailer_entry);
+
+       if (payload - (pos & (S390_CPUMSF_PAGESZ - 1)) < entry_sz)
+               return false;
+       return true;
+}
+
+/* Dump an auxiliary buffer. These buffers are multiple of
+ * 4KB SDB pages.
+ */
+static void s390_cpumsf_dump(struct s390_cpumsf *sf,
+                            unsigned char *buf, size_t len)
+{
+       const char *color = PERF_COLOR_BLUE;
+       struct hws_basic_entry *basic;
+       struct hws_diag_entry *diag;
+       unsigned short bsdes, dsdes;
+       size_t pos = 0;
+
+       color_fprintf(stdout, color,
+                     ". ... s390 AUX data: size %zu bytes\n",
+                     len);
+
+       if (!s390_cpumsf_validate(sf->machine_type, buf, len, &bsdes,
+                                 &dsdes)) {
+               pr_err("Invalid AUX trace data block size:%zu"
+                      " (type:%d bsdes:%hd dsdes:%hd)\n",
+                      len, sf->machine_type, bsdes, dsdes);
+               return;
+       }
+
+       /* s390 kernel always returns 4KB blocks fully occupied,
+        * no partially filled SDBs.
+        */
+       while (pos < len) {
+               /* Handle Basic entry */
+               basic = (struct hws_basic_entry *)(buf + pos);
+               if (s390_cpumsf_basic_show(color, pos, basic))
+                       pos += bsdes;
+               else
+                       return;
+
+               /* Handle Diagnostic entry */
+               diag = (struct hws_diag_entry *)(buf + pos);
+               if (s390_cpumsf_diag_show(color, pos, diag))
+                       pos += dsdes;
+               else
+                       return;
+
+               /* Check for trailer entry */
+               if (!s390_cpumsf_reached_trailer(bsdes + dsdes, pos)) {
+                       /* Show trailer entry */
+                       struct hws_trailer_entry te;
+
+                       pos = (pos + S390_CPUMSF_PAGESZ)
+                              & ~(S390_CPUMSF_PAGESZ - 1);
+                       pos -= sizeof(te);
+                       memcpy(&te, buf + pos, sizeof(te));
+                       /* Set descriptor sizes in case of old hardware
+                        * where these values are not set.
+                        */
+                       te.bsdes = bsdes;
+                       te.dsdes = dsdes;
+                       if (s390_cpumsf_trailer_show(color, pos, &te))
+                               pos += sizeof(te);
+                       else
+                               return;
+               }
+       }
+}
+
+static void s390_cpumsf_dump_event(struct s390_cpumsf *sf, unsigned char *buf,
+                                  size_t len)
+{
+       printf(".\n");
+       s390_cpumsf_dump(sf, buf, len);
+}
+
+#define        S390_LPP_PID_MASK       0xffffffff
+
+static bool s390_cpumsf_make_event(size_t pos,
+                                  struct hws_basic_entry *basic,
+                                  struct s390_cpumsf_queue *sfq)
+{
+       struct perf_sample sample = {
+                               .ip = basic->ia,
+                               .pid = basic->hpp & S390_LPP_PID_MASK,
+                               .tid = basic->hpp & S390_LPP_PID_MASK,
+                               .cpumode = PERF_RECORD_MISC_CPUMODE_UNKNOWN,
+                               .cpu = sfq->cpu,
+                               .period = 1
+                           };
+       union perf_event event;
+
+       memset(&event, 0, sizeof(event));
+       if (basic->CL == 1)     /* Native LPAR mode */
+               sample.cpumode = basic->P ? PERF_RECORD_MISC_USER
+                                         : PERF_RECORD_MISC_KERNEL;
+       else if (basic->CL == 2)        /* Guest kernel/user space */
+               sample.cpumode = basic->P ? PERF_RECORD_MISC_GUEST_USER
+                                         : PERF_RECORD_MISC_GUEST_KERNEL;
+       else if (basic->gpp || basic->prim_asn != 0xffff)
+               /* Use heuristics on old hardware */
+               sample.cpumode = basic->P ? PERF_RECORD_MISC_GUEST_USER
+                                         : PERF_RECORD_MISC_GUEST_KERNEL;
+       else
+               sample.cpumode = basic->P ? PERF_RECORD_MISC_USER
+                                         : PERF_RECORD_MISC_KERNEL;
+
+       event.sample.header.type = PERF_RECORD_SAMPLE;
+       event.sample.header.misc = sample.cpumode;
+       event.sample.header.size = sizeof(struct perf_event_header);
+
+       pr_debug4("%s pos:%#zx ip:%#" PRIx64 " P:%d CL:%d pid:%d.%d cpumode:%d cpu:%d\n",
+                __func__, pos, sample.ip, basic->P, basic->CL, sample.pid,
+                sample.tid, sample.cpumode, sample.cpu);
+       if (perf_session__deliver_synth_event(sfq->sf->session, &event,
+                                             &sample)) {
+               pr_err("s390 Auxiliary Trace: failed to deliver event\n");
+               return false;
+       }
+       return true;
+}
+
+static unsigned long long get_trailer_time(const unsigned char *buf)
+{
+       struct hws_trailer_entry *te;
+       unsigned long long aux_time;
+
+       te = (struct hws_trailer_entry *)(buf + S390_CPUMSF_PAGESZ
+                                             - sizeof(*te));
+
+       if (!te->clock_base)    /* TOD_CLOCK_BASE value missing */
+               return 0;
+
+       /* Correct calculation to convert time stamp in trailer entry to
+        * nano seconds (taken from arch/s390 function tod_to_ns()).
+        * TOD_CLOCK_BASE is stored in trailer entry member progusage2.
+        */
+       aux_time = trailer_timestamp(te) - te->progusage2;
+       aux_time = (aux_time >> 9) * 125 + (((aux_time & 0x1ff) * 125) >> 9);
+       return aux_time;
+}
+
+/* Process the data samples of a single queue. The first parameter is a
+ * pointer to the queue, the second parameter is the time stamp. This
+ * is the time stamp:
+ * - of the event that triggered this processing.
+ * - or the time stamp when the last proccesing of this queue stopped.
+ *   In this case it stopped at a 4KB page boundary and record the
+ *   position on where to continue processing on the next invocation
+ *   (see buffer->use_data and buffer->use_size).
+ *
+ * When this function returns the second parameter is updated to
+ * reflect the time stamp of the last processed auxiliary data entry
+ * (taken from the trailer entry of that page). The caller uses this
+ * returned time stamp to record the last processed entry in this
+ * queue.
+ *
+ * The function returns:
+ * 0:  Processing successful. The second parameter returns the
+ *     time stamp from the trailer entry until which position
+ *     processing took place. Subsequent calls resume from this
+ *     position.
+ * <0: An error occurred during processing. The second parameter
+ *     returns the maximum time stamp.
+ * >0: Done on this queue. The second parameter returns the
+ *     maximum time stamp.
+ */
+static int s390_cpumsf_samples(struct s390_cpumsf_queue *sfq, u64 *ts)
+{
+       struct s390_cpumsf *sf = sfq->sf;
+       unsigned char *buf = sfq->buffer->use_data;
+       size_t len = sfq->buffer->use_size;
+       struct hws_basic_entry *basic;
+       unsigned short bsdes, dsdes;
+       size_t pos = 0;
+       int err = 1;
+       u64 aux_ts;
+
+       if (!s390_cpumsf_validate(sf->machine_type, buf, len, &bsdes,
+                                 &dsdes)) {
+               *ts = ~0ULL;
+               return -1;
+       }
+
+       /* Get trailer entry time stamp and check if entries in
+        * this auxiliary page are ready for processing. If the
+        * time stamp of the first entry is too high, whole buffer
+        * can be skipped. In this case return time stamp.
+        */
+       aux_ts = get_trailer_time(buf);
+       if (!aux_ts) {
+               pr_err("[%#08" PRIx64 "] Invalid AUX trailer entry TOD clock base\n",
+                      sfq->buffer->data_offset);
+               aux_ts = ~0ULL;
+               goto out;
+       }
+       if (aux_ts > *ts) {
+               *ts = aux_ts;
+               return 0;
+       }
+
+       while (pos < len) {
+               /* Handle Basic entry */
+               basic = (struct hws_basic_entry *)(buf + pos);
+               if (s390_cpumsf_make_event(pos, basic, sfq))
+                       pos += bsdes;
+               else {
+                       err = -EBADF;
+                       goto out;
+               }
+
+               pos += dsdes;   /* Skip diagnositic entry */
+
+               /* Check for trailer entry */
+               if (!s390_cpumsf_reached_trailer(bsdes + dsdes, pos)) {
+                       pos = (pos + S390_CPUMSF_PAGESZ)
+                              & ~(S390_CPUMSF_PAGESZ - 1);
+                       /* Check existence of next page */
+                       if (pos >= len)
+                               break;
+                       aux_ts = get_trailer_time(buf + pos);
+                       if (!aux_ts) {
+                               aux_ts = ~0ULL;
+                               goto out;
+                       }
+                       if (aux_ts > *ts) {
+                               *ts = aux_ts;
+                               sfq->buffer->use_data += pos;
+                               sfq->buffer->use_size -= pos;
+                               return 0;
+                       }
+               }
+       }
+out:
+       *ts = aux_ts;
+       sfq->buffer->use_size = 0;
+       sfq->buffer->use_data = NULL;
+       return err;     /* Buffer completely scanned or error */
+}
+
+/* Run the s390 auxiliary trace decoder.
+ * Select the queue buffer to operate on, the caller already selected
+ * the proper queue, depending on second parameter 'ts'.
+ * This is the time stamp until which the auxiliary entries should
+ * be processed. This value is updated by called functions and
+ * returned to the caller.
+ *
+ * Resume processing in the current buffer. If there is no buffer
+ * get a new buffer from the queue and setup start position for
+ * processing.
+ * When a buffer is completely processed remove it from the queue
+ * before returning.
+ *
+ * This function returns
+ * 1: When the queue is empty. Second parameter will be set to
+ *    maximum time stamp.
+ * 0: Normal processing done.
+ * <0: Error during queue buffer setup. This causes the caller
+ *     to stop processing completely.
+ */
+static int s390_cpumsf_run_decoder(struct s390_cpumsf_queue *sfq,
+                                  u64 *ts)
+{
+
+       struct auxtrace_buffer *buffer;
+       struct auxtrace_queue *queue;
+       int err;
+
+       queue = &sfq->sf->queues.queue_array[sfq->queue_nr];
+
+       /* Get buffer and last position in buffer to resume
+        * decoding the auxiliary entries. One buffer might be large
+        * and decoding might stop in between. This depends on the time
+        * stamp of the trailer entry in each page of the auxiliary
+        * data and the time stamp of the event triggering the decoding.
+        */
+       if (sfq->buffer == NULL) {
+               sfq->buffer = buffer = auxtrace_buffer__next(queue,
+                                                            sfq->buffer);
+               if (!buffer) {
+                       *ts = ~0ULL;
+                       return 1;       /* Processing done on this queue */
+               }
+               /* Start with a new buffer on this queue */
+               if (buffer->data) {
+                       buffer->use_size = buffer->size;
+                       buffer->use_data = buffer->data;
+               }
+       } else
+               buffer = sfq->buffer;
+
+       if (!buffer->data) {
+               int fd = perf_data__fd(sfq->sf->session->data);
+
+               buffer->data = auxtrace_buffer__get_data(buffer, fd);
+               if (!buffer->data)
+                       return -ENOMEM;
+               buffer->use_size = buffer->size;
+               buffer->use_data = buffer->data;
+       }
+       pr_debug4("%s queue_nr:%d buffer:%" PRId64 " offset:%#" PRIx64 " size:%#zx rest:%#zx\n",
+                 __func__, sfq->queue_nr, buffer->buffer_nr, buffer->offset,
+                 buffer->size, buffer->use_size);
+       err = s390_cpumsf_samples(sfq, ts);
+
+       /* If non-zero, there is either an error (err < 0) or the buffer is
+        * completely done (err > 0). The error is unrecoverable, usually
+        * some descriptors could not be read successfully, so continue with
+        * the next buffer.
+        * In both cases the parameter 'ts' has been updated.
+        */
+       if (err) {
+               sfq->buffer = NULL;
+               list_del(&buffer->list);
+               auxtrace_buffer__free(buffer);
+               if (err > 0)            /* Buffer done, no error */
+                       err = 0;
+       }
+       return err;
+}
+
+static struct s390_cpumsf_queue *
+s390_cpumsf_alloc_queue(struct s390_cpumsf *sf, unsigned int queue_nr)
+{
+       struct s390_cpumsf_queue *sfq;
+
+       sfq = zalloc(sizeof(struct s390_cpumsf_queue));
+       if (sfq == NULL)
+               return NULL;
+
+       sfq->sf = sf;
+       sfq->queue_nr = queue_nr;
+       sfq->cpu = -1;
+       return sfq;
+}
+
+static int s390_cpumsf_setup_queue(struct s390_cpumsf *sf,
+                                  struct auxtrace_queue *queue,
+                                  unsigned int queue_nr, u64 ts)
+{
+       struct s390_cpumsf_queue *sfq = queue->priv;
+
+       if (list_empty(&queue->head))
+               return 0;
+
+       if (sfq == NULL) {
+               sfq = s390_cpumsf_alloc_queue(sf, queue_nr);
+               if (!sfq)
+                       return -ENOMEM;
+               queue->priv = sfq;
+
+               if (queue->cpu != -1)
+                       sfq->cpu = queue->cpu;
+       }
+       return auxtrace_heap__add(&sf->heap, queue_nr, ts);
+}
+
+static int s390_cpumsf_setup_queues(struct s390_cpumsf *sf, u64 ts)
+{
+       unsigned int i;
+       int ret = 0;
+
+       for (i = 0; i < sf->queues.nr_queues; i++) {
+               ret = s390_cpumsf_setup_queue(sf, &sf->queues.queue_array[i],
+                                             i, ts);
+               if (ret)
+                       break;
+       }
+       return ret;
+}
+
+static int s390_cpumsf_update_queues(struct s390_cpumsf *sf, u64 ts)
+{
+       if (!sf->queues.new_data)
+               return 0;
+
+       sf->queues.new_data = false;
+       return s390_cpumsf_setup_queues(sf, ts);
+}
+
+static int s390_cpumsf_process_queues(struct s390_cpumsf *sf, u64 timestamp)
+{
+       unsigned int queue_nr;
+       u64 ts;
+       int ret;
+
+       while (1) {
+               struct auxtrace_queue *queue;
+               struct s390_cpumsf_queue *sfq;
+
+               if (!sf->heap.heap_cnt)
+                       return 0;
+
+               if (sf->heap.heap_array[0].ordinal >= timestamp)
+                       return 0;
+
+               queue_nr = sf->heap.heap_array[0].queue_nr;
+               queue = &sf->queues.queue_array[queue_nr];
+               sfq = queue->priv;
+
+               auxtrace_heap__pop(&sf->heap);
+               if (sf->heap.heap_cnt) {
+                       ts = sf->heap.heap_array[0].ordinal + 1;
+                       if (ts > timestamp)
+                               ts = timestamp;
+               } else {
+                       ts = timestamp;
+               }
+
+               ret = s390_cpumsf_run_decoder(sfq, &ts);
+               if (ret < 0) {
+                       auxtrace_heap__add(&sf->heap, queue_nr, ts);
+                       return ret;
+               }
+               if (!ret) {
+                       ret = auxtrace_heap__add(&sf->heap, queue_nr, ts);
+                       if (ret < 0)
+                               return ret;
+               }
+       }
+       return 0;
+}
+
+static int s390_cpumsf_synth_error(struct s390_cpumsf *sf, int code, int cpu,
+                                  pid_t pid, pid_t tid, u64 ip)
+{
+       char msg[MAX_AUXTRACE_ERROR_MSG];
+       union perf_event event;
+       int err;
+
+       strncpy(msg, "Lost Auxiliary Trace Buffer", sizeof(msg) - 1);
+       auxtrace_synth_error(&event.auxtrace_error, PERF_AUXTRACE_ERROR_ITRACE,
+                            code, cpu, pid, tid, ip, msg);
+
+       err = perf_session__deliver_synth_event(sf->session, &event, NULL);
+       if (err)
+               pr_err("s390 Auxiliary Trace: failed to deliver error event,"
+                       "error %d\n", err);
+       return err;
+}
+
+static int s390_cpumsf_lost(struct s390_cpumsf *sf, struct perf_sample *sample)
+{
+       return s390_cpumsf_synth_error(sf, 1, sample->cpu,
+                                      sample->pid, sample->tid, 0);
+}
+
+static int
+s390_cpumsf_process_event(struct perf_session *session __maybe_unused,
+                         union perf_event *event,
+                         struct perf_sample *sample,
+                         struct perf_tool *tool)
+{
+       struct s390_cpumsf *sf = container_of(session->auxtrace,
+                                             struct s390_cpumsf,
+                                             auxtrace);
+       u64 timestamp = sample->time;
+       int err = 0;
+
+       if (dump_trace)
+               return 0;
+
+       if (!tool->ordered_events) {
+               pr_err("s390 Auxiliary Trace requires ordered events\n");
+               return -EINVAL;
+       }
+
+       if (event->header.type == PERF_RECORD_AUX &&
+           event->aux.flags & PERF_AUX_FLAG_TRUNCATED)
+               return s390_cpumsf_lost(sf, sample);
+
+       if (timestamp) {
+               err = s390_cpumsf_update_queues(sf, timestamp);
+               if (!err)
+                       err = s390_cpumsf_process_queues(sf, timestamp);
+       }
+       return err;
+}
+
+struct s390_cpumsf_synth {
+       struct perf_tool cpumsf_tool;
+       struct perf_session *session;
+};
+
+static int
+s390_cpumsf_process_auxtrace_event(struct perf_session *session,
+                                  union perf_event *event __maybe_unused,
+                                  struct perf_tool *tool __maybe_unused)
+{
+       struct s390_cpumsf *sf = container_of(session->auxtrace,
+                                             struct s390_cpumsf,
+                                             auxtrace);
+
+       int fd = perf_data__fd(session->data);
+       struct auxtrace_buffer *buffer;
+       off_t data_offset;
+       int err;
+
+       if (sf->data_queued)
+               return 0;
+
+       if (perf_data__is_pipe(session->data)) {
+               data_offset = 0;
+       } else {
+               data_offset = lseek(fd, 0, SEEK_CUR);
+               if (data_offset == -1)
+                       return -errno;
+       }
+
+       err = auxtrace_queues__add_event(&sf->queues, session, event,
+                                        data_offset, &buffer);
+       if (err)
+               return err;
+
+       /* Dump here after copying piped trace out of the pipe */
+       if (dump_trace) {
+               if (auxtrace_buffer__get_data(buffer, fd)) {
+                       s390_cpumsf_dump_event(sf, buffer->data,
+                                              buffer->size);
+                       auxtrace_buffer__put_data(buffer);
+               }
+       }
+       return 0;
+}
+
+static void s390_cpumsf_free_events(struct perf_session *session __maybe_unused)
+{
+}
+
+static int s390_cpumsf_flush(struct perf_session *session __maybe_unused,
+                            struct perf_tool *tool __maybe_unused)
+{
+       return 0;
+}
+
+static void s390_cpumsf_free_queues(struct perf_session *session)
+{
+       struct s390_cpumsf *sf = container_of(session->auxtrace,
+                                             struct s390_cpumsf,
+                                             auxtrace);
+       struct auxtrace_queues *queues = &sf->queues;
+       unsigned int i;
+
+       for (i = 0; i < queues->nr_queues; i++)
+               zfree(&queues->queue_array[i].priv);
+       auxtrace_queues__free(queues);
+}
+
+static void s390_cpumsf_free(struct perf_session *session)
+{
+       struct s390_cpumsf *sf = container_of(session->auxtrace,
+                                             struct s390_cpumsf,
+                                             auxtrace);
+
+       auxtrace_heap__free(&sf->heap);
+       s390_cpumsf_free_queues(session);
+       session->auxtrace = NULL;
+       free(sf);
+}
+
+static int s390_cpumsf_get_type(const char *cpuid)
+{
+       int ret, family = 0;
+
+       ret = sscanf(cpuid, "%*[^,],%u", &family);
+       return (ret == 1) ? family : 0;
+}
+
+/* Check itrace options set on perf report command.
+ * Return true, if none are set or all options specified can be
+ * handled on s390.
+ * Return false otherwise.
+ */
+static bool check_auxtrace_itrace(struct itrace_synth_opts *itops)
+{
+       if (!itops || !itops->set)
+               return true;
+       pr_err("No --itrace options supported\n");
+       return false;
+}
+
+int s390_cpumsf_process_auxtrace_info(union perf_event *event,
+                                     struct perf_session *session)
+{
+       struct auxtrace_info_event *auxtrace_info = &event->auxtrace_info;
+       struct s390_cpumsf *sf;
+       int err;
+
+       if (auxtrace_info->header.size < sizeof(struct auxtrace_info_event))
+               return -EINVAL;
+
+       sf = zalloc(sizeof(struct s390_cpumsf));
+       if (sf == NULL)
+               return -ENOMEM;
+
+       if (!check_auxtrace_itrace(session->itrace_synth_opts)) {
+               err = -EINVAL;
+               goto err_free;
+       }
+
+       err = auxtrace_queues__init(&sf->queues);
+       if (err)
+               goto err_free;
+
+       sf->session = session;
+       sf->machine = &session->machines.host; /* No kvm support */
+       sf->auxtrace_type = auxtrace_info->type;
+       sf->pmu_type = PERF_TYPE_RAW;
+       sf->machine_type = s390_cpumsf_get_type(session->evlist->env->cpuid);
+
+       sf->auxtrace.process_event = s390_cpumsf_process_event;
+       sf->auxtrace.process_auxtrace_event = s390_cpumsf_process_auxtrace_event;
+       sf->auxtrace.flush_events = s390_cpumsf_flush;
+       sf->auxtrace.free_events = s390_cpumsf_free_events;
+       sf->auxtrace.free = s390_cpumsf_free;
+       session->auxtrace = &sf->auxtrace;
+
+       if (dump_trace)
+               return 0;
+
+       err = auxtrace_queues__process_index(&sf->queues, session);
+       if (err)
+               goto err_free_queues;
+
+       if (sf->queues.populated)
+               sf->data_queued = true;
+
+       return 0;
+
+err_free_queues:
+       auxtrace_queues__free(&sf->queues);
+       session->auxtrace = NULL;
+err_free:
+       free(sf);
+       return err;
+}
diff --git a/tools/perf/util/s390-cpumsf.h b/tools/perf/util/s390-cpumsf.h
new file mode 100644 (file)
index 0000000..fb64d10
--- /dev/null
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright IBM Corp. 2018
+ * Auxtrace support for s390 CPU-Measurement Sampling Facility
+ *
+ * Author(s):  Thomas Richter <tmricht@linux.ibm.com>
+ */
+
+#ifndef INCLUDE__PERF_S390_CPUMSF_H
+#define INCLUDE__PERF_S390_CPUMSF_H
+
+union perf_event;
+struct perf_session;
+struct perf_pmu;
+
+struct auxtrace_record *
+s390_cpumsf_recording_init(int *err, struct perf_pmu *s390_cpumsf_pmu);
+
+int s390_cpumsf_process_auxtrace_info(union perf_event *event,
+                                     struct perf_session *session);
+#endif
index 7b79c41..45484f0 100644 (file)
@@ -535,7 +535,7 @@ static int perl_stop_script(void)
        return 0;
 }
 
-static int perl_generate_script(struct pevent *pevent, const char *outfile)
+static int perl_generate_script(struct tep_handle *pevent, const char *outfile)
 {
        struct event_format *event = NULL;
        struct format_field *f;
index bc32e57..dfc6093 100644 (file)
@@ -871,8 +871,8 @@ static void python_process_tracepoint(struct perf_sample *sample,
                        offset = field->offset;
                        len    = field->size;
                        if (field->flags & FIELD_IS_DYNAMIC) {
-                               val     = pevent_read_number(scripting_context->pevent,
-                                                            data + offset, len);
+                               val     = tep_read_number(scripting_context->pevent,
+                                                         data + offset, len);
                                offset  = val;
                                len     = offset >> 16;
                                offset &= 0xffff;
@@ -1588,7 +1588,7 @@ static int python_stop_script(void)
        return 0;
 }
 
-static int python_generate_script(struct pevent *pevent, const char *outfile)
+static int python_generate_script(struct tep_handle *pevent, const char *outfile)
 {
        struct event_format *event = NULL;
        struct format_field *f;
index 001be4f..97efbca 100644 (file)
@@ -1,12 +1,20 @@
 #!/usr/bin/python
 
 from os import getenv
+from subprocess import Popen, PIPE
+from re import sub
+
+def clang_has_option(option):
+    return [o for o in Popen(['clang', option], stderr=PIPE).stderr.readlines() if "unknown argument" in o] == [ ]
 
 cc = getenv("CC")
 if cc == "clang":
     from _sysconfigdata import build_time_vars
-    from re import sub
     build_time_vars["CFLAGS"] = sub("-specs=[^ ]+", "", build_time_vars["CFLAGS"])
+    if not clang_has_option("-mcet"):
+        build_time_vars["CFLAGS"] = sub("-mcet", "", build_time_vars["CFLAGS"])
+    if not clang_has_option("-fcf-protection"):
+        build_time_vars["CFLAGS"] = sub("-fcf-protection", "", build_time_vars["CFLAGS"])
 
 from distutils.core import setup, Extension
 
index fed2952..b284276 100644 (file)
@@ -601,7 +601,7 @@ static char *get_trace_output(struct hist_entry *he)
 {
        struct trace_seq seq;
        struct perf_evsel *evsel;
-       struct pevent_record rec = {
+       struct tep_record rec = {
                .data = he->raw_data,
                .size = he->raw_size,
        };
@@ -610,10 +610,10 @@ static char *get_trace_output(struct hist_entry *he)
 
        trace_seq_init(&seq);
        if (symbol_conf.raw_trace) {
-               pevent_print_fields(&seq, he->raw_data, he->raw_size,
-                                   evsel->tp_format);
+               tep_print_fields(&seq, he->raw_data, he->raw_size,
+                                evsel->tp_format);
        } else {
-               pevent_event_info(&seq, evsel->tp_format, &rec);
+               tep_event_info(&seq, evsel->tp_format, &rec);
        }
        /*
         * Trim the buffer, it starts at 4KB and we're not going to
@@ -2047,7 +2047,7 @@ static int __sort__hde_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
                struct trace_seq seq;
 raw_field:
                trace_seq_init(&seq);
-               pevent_print_field(&seq, he->raw_data, hde->field);
+               tep_print_field(&seq, he->raw_data, hde->field);
                str = seq.buffer;
        }
 
@@ -2074,7 +2074,7 @@ static int64_t __sort__hde_cmp(struct perf_hpp_fmt *fmt,
        if (field->flags & FIELD_IS_DYNAMIC) {
                unsigned long long dyn;
 
-               pevent_read_number_field(field, a->raw_data, &dyn);
+               tep_read_number_field(field, a->raw_data, &dyn);
                offset = dyn & 0xffff;
                size = (dyn >> 16) & 0xffff;
 
@@ -2311,7 +2311,7 @@ static int add_all_matching_fields(struct perf_evlist *evlist,
                if (evsel->attr.type != PERF_TYPE_TRACEPOINT)
                        continue;
 
-               field = pevent_find_any_field(evsel->tp_format, field_name);
+               field = tep_find_any_field(evsel->tp_format, field_name);
                if (field == NULL)
                        continue;
 
@@ -2378,7 +2378,7 @@ static int add_dynamic_entry(struct perf_evlist *evlist, const char *tok,
        if (!strcmp(field_name, "*")) {
                ret = add_evsel_fields(evsel, raw_trace, level);
        } else {
-               field = pevent_find_any_field(evsel->tp_format, field_name);
+               field = tep_find_any_field(evsel->tp_format, field_name);
                if (field == NULL) {
                        pr_debug("Cannot find event field for %s.%s\n",
                                 event_name, field_name);
index 8bf302c..a97cf8e 100644 (file)
@@ -276,7 +276,7 @@ extern struct sort_entry sort_thread;
 extern struct list_head hist_entry__sort_list;
 
 struct perf_evlist;
-struct pevent;
+struct tep_handle;
 int setup_sorting(struct perf_evlist *evlist);
 int setup_output_field(void);
 void reset_output_field(void);
index e0a6e9a..920b1d5 100644 (file)
@@ -32,7 +32,7 @@
 static int get_common_field(struct scripting_context *context,
                            int *offset, int *size, const char *type)
 {
-       struct pevent *pevent = context->pevent;
+       struct tep_handle *pevent = context->pevent;
        struct event_format *event;
        struct format_field *field;
 
@@ -41,14 +41,14 @@ static int get_common_field(struct scripting_context *context,
                        return 0;
 
                event = pevent->events[0];
-               field = pevent_find_common_field(event, type);
+               field = tep_find_common_field(event, type);
                if (!field)
                        return 0;
                *offset = field->offset;
                *size = field->size;
        }
 
-       return pevent_read_number(pevent, context->event_data + *offset, *size);
+       return tep_read_number(pevent, context->event_data + *offset, *size);
 }
 
 int common_lock_depth(struct scripting_context *context)
@@ -99,24 +99,24 @@ raw_field_value(struct event_format *event, const char *name, void *data)
        struct format_field *field;
        unsigned long long val;
 
-       field = pevent_find_any_field(event, name);
+       field = tep_find_any_field(event, name);
        if (!field)
                return 0ULL;
 
-       pevent_read_number_field(field, data, &val);
+       tep_read_number_field(field, data, &val);
 
        return val;
 }
 
 unsigned long long read_size(struct event_format *event, void *ptr, int size)
 {
-       return pevent_read_number(event->pevent, ptr, size);
+       return tep_read_number(event->pevent, ptr, size);
 }
 
 void event_format__fprintf(struct event_format *event,
                           int cpu, void *data, int size, FILE *fp)
 {
-       struct pevent_record record;
+       struct tep_record record;
        struct trace_seq s;
 
        memset(&record, 0, sizeof(record));
@@ -125,7 +125,7 @@ void event_format__fprintf(struct event_format *event,
        record.data = data;
 
        trace_seq_init(&s);
-       pevent_event_info(&s, event, &record);
+       tep_event_info(&s, event, &record);
        trace_seq_do_fprintf(&s, fp);
        trace_seq_destroy(&s);
 }
@@ -136,7 +136,7 @@ void event_format__print(struct event_format *event,
        return event_format__fprintf(event, cpu, data, size, stdout);
 }
 
-void parse_ftrace_printk(struct pevent *pevent,
+void parse_ftrace_printk(struct tep_handle *pevent,
                         char *file, unsigned int size __maybe_unused)
 {
        unsigned long long addr;
@@ -157,11 +157,11 @@ void parse_ftrace_printk(struct pevent *pevent,
                /* fmt still has a space, skip it */
                printk = strdup(fmt+1);
                line = strtok_r(NULL, "\n", &next);
-               pevent_register_print_string(pevent, printk, addr);
+               tep_register_print_string(pevent, printk, addr);
        }
 }
 
-void parse_saved_cmdline(struct pevent *pevent,
+void parse_saved_cmdline(struct tep_handle *pevent,
                         char *file, unsigned int size __maybe_unused)
 {
        char *comm;
@@ -172,24 +172,24 @@ void parse_saved_cmdline(struct pevent *pevent,
        line = strtok_r(file, "\n", &next);
        while (line) {
                sscanf(line, "%d %ms", &pid, &comm);
-               pevent_register_comm(pevent, comm, pid);
+               tep_register_comm(pevent, comm, pid);
                free(comm);
                line = strtok_r(NULL, "\n", &next);
        }
 }
 
-int parse_ftrace_file(struct pevent *pevent, char *buf, unsigned long size)
+int parse_ftrace_file(struct tep_handle *pevent, char *buf, unsigned long size)
 {
-       return pevent_parse_event(pevent, buf, size, "ftrace");
+       return tep_parse_event(pevent, buf, size, "ftrace");
 }
 
-int parse_event_file(struct pevent *pevent,
+int parse_event_file(struct tep_handle *pevent,
                     char *buf, unsigned long size, char *sys)
 {
-       return pevent_parse_event(pevent, buf, size, sys);
+       return tep_parse_event(pevent, buf, size, sys);
 }
 
-struct event_format *trace_find_next_event(struct pevent *pevent,
+struct event_format *trace_find_next_event(struct tep_handle *pevent,
                                           struct event_format *event)
 {
        static int idx;
index 40b4259..3dfc1db 100644 (file)
@@ -96,7 +96,7 @@ static void skip(int size)
        };
 }
 
-static unsigned int read4(struct pevent *pevent)
+static unsigned int read4(struct tep_handle *pevent)
 {
        unsigned int data;
 
@@ -105,7 +105,7 @@ static unsigned int read4(struct pevent *pevent)
        return __data2host4(pevent, data);
 }
 
-static unsigned long long read8(struct pevent *pevent)
+static unsigned long long read8(struct tep_handle *pevent)
 {
        unsigned long long data;
 
@@ -158,7 +158,7 @@ out:
        return str;
 }
 
-static int read_proc_kallsyms(struct pevent *pevent)
+static int read_proc_kallsyms(struct tep_handle *pevent)
 {
        unsigned int size;
 
@@ -181,7 +181,7 @@ static int read_proc_kallsyms(struct pevent *pevent)
        return 0;
 }
 
-static int read_ftrace_printk(struct pevent *pevent)
+static int read_ftrace_printk(struct tep_handle *pevent)
 {
        unsigned int size;
        char *buf;
@@ -208,7 +208,7 @@ static int read_ftrace_printk(struct pevent *pevent)
        return 0;
 }
 
-static int read_header_files(struct pevent *pevent)
+static int read_header_files(struct tep_handle *pevent)
 {
        unsigned long long size;
        char *header_page;
@@ -235,13 +235,13 @@ static int read_header_files(struct pevent *pevent)
                return -1;
        }
 
-       if (!pevent_parse_header_page(pevent, header_page, size,
-                                     pevent_get_long_size(pevent))) {
+       if (!tep_parse_header_page(pevent, header_page, size,
+                                  tep_get_long_size(pevent))) {
                /*
                 * The commit field in the page is of type long,
                 * use that instead, since it represents the kernel.
                 */
-               pevent_set_long_size(pevent, pevent->header_page_size_size);
+               tep_set_long_size(pevent, pevent->header_page_size_size);
        }
        free(header_page);
 
@@ -259,7 +259,7 @@ static int read_header_files(struct pevent *pevent)
        return ret;
 }
 
-static int read_ftrace_file(struct pevent *pevent, unsigned long long size)
+static int read_ftrace_file(struct tep_handle *pevent, unsigned long long size)
 {
        int ret;
        char *buf;
@@ -284,8 +284,8 @@ out:
        return ret;
 }
 
-static int read_event_file(struct pevent *pevent, char *sys,
-                           unsigned long long size)
+static int read_event_file(struct tep_handle *pevent, char *sys,
+                          unsigned long long size)
 {
        int ret;
        char *buf;
@@ -310,7 +310,7 @@ out:
        return ret;
 }
 
-static int read_ftrace_files(struct pevent *pevent)
+static int read_ftrace_files(struct tep_handle *pevent)
 {
        unsigned long long size;
        int count;
@@ -328,7 +328,7 @@ static int read_ftrace_files(struct pevent *pevent)
        return 0;
 }
 
-static int read_event_files(struct pevent *pevent)
+static int read_event_files(struct tep_handle *pevent)
 {
        unsigned long long size;
        char *sys;
@@ -356,7 +356,7 @@ static int read_event_files(struct pevent *pevent)
        return 0;
 }
 
-static int read_saved_cmdline(struct pevent *pevent)
+static int read_saved_cmdline(struct tep_handle *pevent)
 {
        unsigned long long size;
        char *buf;
@@ -399,7 +399,7 @@ ssize_t trace_report(int fd, struct trace_event *tevent, bool __repipe)
        int host_bigendian;
        int file_long_size;
        int file_page_size;
-       struct pevent *pevent = NULL;
+       struct tep_handle *pevent = NULL;
        int err;
 
        repipe = __repipe;
@@ -439,9 +439,9 @@ ssize_t trace_report(int fd, struct trace_event *tevent, bool __repipe)
 
        pevent = tevent->pevent;
 
-       pevent_set_flag(pevent, PEVENT_NSEC_OUTPUT);
-       pevent_set_file_bigendian(pevent, file_bigendian);
-       pevent_set_host_bigendian(pevent, host_bigendian);
+       tep_set_flag(pevent, TEP_NSEC_OUTPUT);
+       tep_set_file_bigendian(pevent, file_bigendian);
+       tep_set_host_bigendian(pevent, host_bigendian);
 
        if (do_read(buf, 1) < 0)
                goto out;
@@ -451,8 +451,8 @@ ssize_t trace_report(int fd, struct trace_event *tevent, bool __repipe)
        if (!file_page_size)
                goto out;
 
-       pevent_set_long_size(pevent, file_long_size);
-       pevent_set_page_size(pevent, file_page_size);
+       tep_set_long_size(pevent, file_long_size);
+       tep_set_page_size(pevent, file_page_size);
 
        err = read_header_files(pevent);
        if (err)
@@ -479,9 +479,9 @@ ssize_t trace_report(int fd, struct trace_event *tevent, bool __repipe)
        repipe = false;
 
        if (show_funcs) {
-               pevent_print_funcs(pevent);
+               tep_print_funcs(pevent);
        } else if (show_printk) {
-               pevent_print_printk(pevent);
+               tep_print_printk(pevent);
        }
 
        pevent = NULL;
index b1e5c3a..b749f81 100644 (file)
@@ -66,7 +66,7 @@ static int python_start_script_unsupported(const char *script __maybe_unused,
        return -1;
 }
 
-static int python_generate_script_unsupported(struct pevent *pevent
+static int python_generate_script_unsupported(struct tep_handle *pevent
                                              __maybe_unused,
                                              const char *outfile
                                              __maybe_unused)
@@ -130,7 +130,7 @@ static int perl_start_script_unsupported(const char *script __maybe_unused,
        return -1;
 }
 
-static int perl_generate_script_unsupported(struct pevent *pevent
+static int perl_generate_script_unsupported(struct tep_handle *pevent
                                            __maybe_unused,
                                            const char *outfile __maybe_unused)
 {
index 1aa3686..58bb72f 100644 (file)
@@ -28,10 +28,10 @@ static bool tevent_initialized;
 
 int trace_event__init(struct trace_event *t)
 {
-       struct pevent *pevent = pevent_alloc();
+       struct tep_handle *pevent = tep_alloc();
 
        if (pevent) {
-               t->plugin_list = traceevent_load_plugins(pevent);
+               t->plugin_list = tep_load_plugins(pevent);
                t->pevent  = pevent;
        }
 
@@ -40,33 +40,33 @@ int trace_event__init(struct trace_event *t)
 
 static int trace_event__init2(void)
 {
-       int be = traceevent_host_bigendian();
-       struct pevent *pevent;
+       int be = tep_host_bigendian();
+       struct tep_handle *pevent;
 
        if (trace_event__init(&tevent))
                return -1;
 
        pevent = tevent.pevent;
-       pevent_set_flag(pevent, PEVENT_NSEC_OUTPUT);
-       pevent_set_file_bigendian(pevent, be);
-       pevent_set_host_bigendian(pevent, be);
+       tep_set_flag(pevent, TEP_NSEC_OUTPUT);
+       tep_set_file_bigendian(pevent, be);
+       tep_set_host_bigendian(pevent, be);
        tevent_initialized = true;
        return 0;
 }
 
 int trace_event__register_resolver(struct machine *machine,
-                                  pevent_func_resolver_t *func)
+                                  tep_func_resolver_t *func)
 {
        if (!tevent_initialized && trace_event__init2())
                return -1;
 
-       return pevent_set_function_resolver(tevent.pevent, func, machine);
+       return tep_set_function_resolver(tevent.pevent, func, machine);
 }
 
 void trace_event__cleanup(struct trace_event *t)
 {
-       traceevent_unload_plugins(t->plugin_list, t->pevent);
-       pevent_free(t->pevent);
+       tep_unload_plugins(t->plugin_list, t->pevent);
+       tep_free(t->pevent);
 }
 
 /*
@@ -76,7 +76,7 @@ static struct event_format*
 tp_format(const char *sys, const char *name)
 {
        char *tp_dir = get_events_file(sys);
-       struct pevent *pevent = tevent.pevent;
+       struct tep_handle *pevent = tevent.pevent;
        struct event_format *event = NULL;
        char path[PATH_MAX];
        size_t size;
@@ -93,7 +93,7 @@ tp_format(const char *sys, const char *name)
        if (err)
                return ERR_PTR(err);
 
-       pevent_parse_format(pevent, &event, data, size, sys);
+       tep_parse_format(pevent, &event, data, size, sys);
 
        free(data);
        return event;
@@ -116,5 +116,5 @@ struct event_format *trace_event__tp_format_id(int id)
        if (!tevent_initialized && trace_event__init2())
                return ERR_PTR(-ENOMEM);
 
-       return pevent_find_event(tevent.pevent, id);
+       return tep_find_event(tevent.pevent, id);
 }
index dcbdb53..40204ec 100644 (file)
@@ -13,14 +13,14 @@ struct thread;
 struct plugin_list;
 
 struct trace_event {
-       struct pevent           *pevent;
+       struct tep_handle       *pevent;
        struct plugin_list      *plugin_list;
 };
 
 int trace_event__init(struct trace_event *t);
 void trace_event__cleanup(struct trace_event *t);
 int trace_event__register_resolver(struct machine *machine,
-                                  pevent_func_resolver_t *func);
+                                  tep_func_resolver_t *func);
 struct event_format*
 trace_event__tp_format(const char *sys, const char *name);
 
@@ -34,20 +34,20 @@ void event_format__fprintf(struct event_format *event,
 void event_format__print(struct event_format *event,
                         int cpu, void *data, int size);
 
-int parse_ftrace_file(struct pevent *pevent, char *buf, unsigned long size);
-int parse_event_file(struct pevent *pevent,
+int parse_ftrace_file(struct tep_handle *pevent, char *buf, unsigned long size);
+int parse_event_file(struct tep_handle *pevent,
                     char *buf, unsigned long size, char *sys);
 
 unsigned long long
 raw_field_value(struct event_format *event, const char *name, void *data);
 
-void parse_proc_kallsyms(struct pevent *pevent, char *file, unsigned int size);
-void parse_ftrace_printk(struct pevent *pevent, char *file, unsigned int size);
-void parse_saved_cmdline(struct pevent *pevent, char *file, unsigned int size);
+void parse_proc_kallsyms(struct tep_handle *pevent, char *file, unsigned int size);
+void parse_ftrace_printk(struct tep_handle *pevent, char *file, unsigned int size);
+void parse_saved_cmdline(struct tep_handle *pevent, char *file, unsigned int size);
 
 ssize_t trace_report(int fd, struct trace_event *tevent, bool repipe);
 
-struct event_format *trace_find_next_event(struct pevent *pevent,
+struct event_format *trace_find_next_event(struct tep_handle *pevent,
                                           struct event_format *event);
 unsigned long long read_size(struct event_format *event, void *ptr, int size);
 unsigned long long eval_flag(const char *flag);
@@ -83,7 +83,7 @@ struct scripting_ops {
        void (*process_stat)(struct perf_stat_config *config,
                             struct perf_evsel *evsel, u64 tstamp);
        void (*process_stat_interval)(u64 tstamp);
-       int (*generate_script) (struct pevent *pevent, const char *outfile);
+       int (*generate_script) (struct tep_handle *pevent, const char *outfile);
 };
 
 extern unsigned int scripting_max_stack;
@@ -94,7 +94,7 @@ void setup_perl_scripting(void);
 void setup_python_scripting(void);
 
 struct scripting_context {
-       struct pevent *pevent;
+       struct tep_handle *pevent;
        void *event_data;
 };
 
index a725b95..902ce63 100644 (file)
@@ -5,6 +5,8 @@
 #include <sys/stat.h>
 #include <sys/mman.h>
 #include <zlib.h>
+#include <linux/compiler.h>
+#include <unistd.h>
 
 #include "util/compress.h"
 #include "util/util.h"
@@ -79,3 +81,19 @@ out_close:
 
        return ret == Z_STREAM_END ? 0 : -1;
 }
+
+bool gzip_is_compressed(const char *input)
+{
+       int fd = open(input, O_RDONLY);
+       const uint8_t magic[2] = { 0x1f, 0x8b };
+       char buf[2] = { 0 };
+       ssize_t rc;
+
+       if (fd < 0)
+               return -1;
+
+       rc = read(fd, buf, sizeof(buf));
+       close(fd);
+       return rc == sizeof(buf) ?
+              memcmp(buf, magic, sizeof(buf)) == 0 : false;
+}
index 78c09e5..840c17c 100644 (file)
@@ -323,12 +323,12 @@ msgstr "  Hardwarebedingte Grenzen der Taktfrequenz: "
 #: utils/cpufreq-info.c:256
 #, c-format
 msgid "  available frequency steps: "
-msgstr "  mögliche Taktfrequenzen: "
+msgstr "  mögliche Taktfrequenzen: "
 
 #: utils/cpufreq-info.c:269
 #, c-format
 msgid "  available cpufreq governors: "
-msgstr "  mögliche Regler: "
+msgstr "  mögliche Regler: "
 
 #: utils/cpufreq-info.c:280
 #, c-format
@@ -381,7 +381,7 @@ msgstr "Optionen:\n"
 msgid "  -e, --debug          Prints out debug information [default]\n"
 msgstr ""
 "  -e, --debug          Erzeugt detaillierte Informationen, hilfreich\n"
-"                       zum Aufspüren von Fehlern\n"
+"                       zum Aufspüren von Fehlern\n"
 
 #: utils/cpufreq-info.c:475
 #, c-format
@@ -424,7 +424,7 @@ msgstr "  -p, --policy         Findet die momentane Taktik heraus *\n"
 #: utils/cpufreq-info.c:482
 #, c-format
 msgid "  -g, --governors      Determines available cpufreq governors *\n"
-msgstr "  -g, --governors      Erzeugt eine Liste mit verfügbaren Reglern *\n"
+msgstr "  -g, --governors      Erzeugt eine Liste mit verfügbaren Reglern *\n"
 
 #: utils/cpufreq-info.c:483
 #, c-format
@@ -450,7 +450,7 @@ msgstr ""
 #, c-format
 msgid "  -s, --stats          Shows cpufreq statistics if available\n"
 msgstr ""
-"  -s, --stats          Zeigt, sofern möglich, Statistiken über cpufreq an.\n"
+"  -s, --stats          Zeigt, sofern möglich, Statistiken über cpufreq an.\n"
 
 #: utils/cpufreq-info.c:487
 #, c-format
@@ -473,9 +473,9 @@ msgid ""
 "cpufreq\n"
 "                       interface in 2.4. and early 2.6. kernels\n"
 msgstr ""
-"  -o, --proc           Erzeugt Informationen in einem ähnlichem Format zu "
+"  -o, --proc           Erzeugt Informationen in einem ähnlichem Format zu "
 "dem\n"
-"                       der /proc/cpufreq-Datei in 2.4. und frühen 2.6.\n"
+"                       der /proc/cpufreq-Datei in 2.4. und frühen 2.6.\n"
 "                       Kernel-Versionen\n"
 
 #: utils/cpufreq-info.c:491
@@ -491,7 +491,7 @@ msgstr ""
 #: utils/cpufreq-info.c:492 utils/cpuidle-info.c:152
 #, c-format
 msgid "  -h, --help           Prints out this screen\n"
-msgstr "  -h, --help           Gibt diese Kurzübersicht aus\n"
+msgstr "  -h, --help           Gibt diese Kurzübersicht aus\n"
 
 #: utils/cpufreq-info.c:495
 #, c-format
@@ -501,7 +501,7 @@ msgid ""
 msgstr ""
 "Sofern kein anderer Parameter als '-c, --cpu' angegeben wird, liefert "
 "dieses\n"
-"Programm Informationen, die z.B. zum Berichten von Fehlern nützlich sind.\n"
+"Programm Informationen, die z.B. zum Berichten von Fehlern nützlich sind.\n"
 
 #: utils/cpufreq-info.c:497
 #, c-format
@@ -557,7 +557,7 @@ msgid ""
 "select\n"
 msgstr ""
 "  -d FREQ, --min FREQ      neue minimale Taktfrequenz, die der Regler\n"
-"                           auswählen darf\n"
+"                           auswählen darf\n"
 
 #: utils/cpufreq-set.c:28
 #, c-format
@@ -566,7 +566,7 @@ msgid ""
 "select\n"
 msgstr ""
 "  -u FREQ, --max FREQ      neue maximale Taktfrequenz, die der Regler\n"
-"                           auswählen darf\n"
+"                           auswählen darf\n"
 
 #: utils/cpufreq-set.c:29
 #, c-format
@@ -579,20 +579,20 @@ msgid ""
 "  -f FREQ, --freq FREQ     specific frequency to be set. Requires userspace\n"
 "                           governor to be available and loaded\n"
 msgstr ""
-"  -f FREQ, --freq FREQ     setze exakte Taktfrequenz. Benötigt den Regler\n"
+"  -f FREQ, --freq FREQ     setze exakte Taktfrequenz. Benötigt den Regler\n"
 "                           'userspace'.\n"
 
 #: utils/cpufreq-set.c:32
 #, c-format
 msgid "  -r, --related            Switches all hardware-related CPUs\n"
 msgstr ""
-"  -r, --related            Setze Werte für alle CPUs, deren Taktfrequenz\n"
+"  -r, --related            Setze Werte für alle CPUs, deren Taktfrequenz\n"
 "                           hardwarebedingt identisch ist.\n"
 
 #: utils/cpufreq-set.c:33 utils/cpupower-set.c:28 utils/cpupower-info.c:27
 #, c-format
 msgid "  -h, --help               Prints out this screen\n"
-msgstr "  -h, --help               Gibt diese Kurzübersicht aus\n"
+msgstr "  -h, --help               Gibt diese Kurzübersicht aus\n"
 
 #: utils/cpufreq-set.c:35
 #, fuzzy, c-format
@@ -618,8 +618,8 @@ msgstr ""
 "   angenommen\n"
 "2. Der Parameter -f bzw. --freq kann mit keinem anderen als dem Parameter\n"
 "   -c bzw. --cpu kombiniert werden\n"
-"3. FREQuenzen können in Hz, kHz (Standard), MHz, GHz oder THz eingegeben\n"
-"   werden, indem der Wert und unmittelbar anschließend (ohne Leerzeichen!)\n"
+"3. FREQuenzen können in Hz, kHz (Standard), MHz, GHz oder THz eingegeben\n"
+"   werden, indem der Wert und unmittelbar anschließend (ohne Leerzeichen!)\n"
 "   die Einheit angegeben werden. (Bsp: 1GHz )\n"
 "   (FREQuenz in kHz =^ MHz * 1000 =^ GHz * 1000000).\n"
 
@@ -638,7 +638,7 @@ msgid ""
 msgstr ""
 "Beim Einstellen ist ein Fehler aufgetreten. Typische Fehlerquellen sind:\n"
 "- nicht ausreichende Rechte (Administrator)\n"
-"- der Regler ist nicht verfügbar bzw. nicht geladen\n"
+"- der Regler ist nicht verfügbar bzw. nicht geladen\n"
 "- die angegebene Taktik ist inkorrekt\n"
 "- eine spezifische Frequenz wurde angegeben, aber der Regler 'userspace'\n"
 "  kann entweder hardwarebedingt nicht genutzt werden oder ist nicht geladen\n"
@@ -821,7 +821,7 @@ msgstr ""
 #: utils/cpuidle-info.c:48
 #, fuzzy, c-format
 msgid "Available idle states:"
-msgstr "  mögliche Taktfrequenzen: "
+msgstr "  mögliche Taktfrequenzen: "
 
 #: utils/cpuidle-info.c:71
 #, c-format
@@ -924,7 +924,7 @@ msgstr "Aufruf: cpufreq-info [Optionen]\n"
 msgid "  -s, --silent         Only show general C-state information\n"
 msgstr ""
 "  -e, --debug          Erzeugt detaillierte Informationen, hilfreich\n"
-"                       zum Aufspüren von Fehlern\n"
+"                       zum Aufspüren von Fehlern\n"
 
 #: utils/cpuidle-info.c:150
 #, fuzzy, c-format
@@ -933,9 +933,9 @@ msgid ""
 "acpi/processor/*/power\n"
 "                       interface in older kernels\n"
 msgstr ""
-"  -o, --proc           Erzeugt Informationen in einem ähnlichem Format zu "
+"  -o, --proc           Erzeugt Informationen in einem ähnlichem Format zu "
 "dem\n"
-"                       der /proc/cpufreq-Datei in 2.4. und frühen 2.6.\n"
+"                       der /proc/cpufreq-Datei in 2.4. und frühen 2.6.\n"
 "                       Kernel-Versionen\n"
 
 #: utils/cpuidle-info.c:209
@@ -949,7 +949,7 @@ msgstr ""
 #~ "  -c CPU, --cpu CPU    CPU number which information shall be determined "
 #~ "about\n"
 #~ msgstr ""
-#~ "  -c CPU, --cpu CPU    Nummer der CPU, über die Informationen "
+#~ "  -c CPU, --cpu CPU    Nummer der CPU, über die Informationen "
 #~ "herausgefunden werden sollen\n"
 
 #~ msgid ""
index 245ad20..b46ca25 100644 (file)
@@ -212,7 +212,7 @@ msgstr ""
 #: utils/cpupower.c:91
 #, c-format
 msgid "Report errors and bugs to %s, please.\n"
-msgstr "Veuillez rapportez les erreurs et les bogues à %s, s'il vous plait.\n"
+msgstr "Veuillez rapportez les erreurs et les bogues à %s, s'il vous plait.\n"
 
 #: utils/cpupower.c:114
 #, c-format
@@ -227,14 +227,14 @@ msgstr ""
 #: utils/cpufreq-info.c:31
 #, c-format
 msgid "Couldn't count the number of CPUs (%s: %s), assuming 1\n"
-msgstr "Détermination du nombre de CPUs (%s : %s) impossible.  Assume 1\n"
+msgstr "Détermination du nombre de CPUs (%s : %s) impossible.  Assume 1\n"
 
 #: utils/cpufreq-info.c:63
 #, c-format
 msgid ""
 "          minimum CPU frequency  -  maximum CPU frequency  -  governor\n"
 msgstr ""
-"         Fréquence CPU minimale - Fréquence CPU maximale  - régulateur\n"
+"         Fréquence CPU minimale - Fréquence CPU maximale  - régulateur\n"
 
 #: utils/cpufreq-info.c:151
 #, c-format
@@ -302,12 +302,12 @@ msgstr "  pilote : %s\n"
 #: utils/cpufreq-info.c:219
 #, fuzzy, c-format
 msgid "  CPUs which run at the same hardware frequency: "
-msgstr "  CPUs qui doivent changer de fréquences en même temps : "
+msgstr "  CPUs qui doivent changer de fréquences en même temps : "
 
 #: utils/cpufreq-info.c:230
 #, fuzzy, c-format
 msgid "  CPUs which need to have their frequency coordinated by software: "
-msgstr "  CPUs qui doivent changer de fréquences en même temps : "
+msgstr "  CPUs qui doivent changer de fréquences en même temps : "
 
 #: utils/cpufreq-info.c:241
 #, c-format
@@ -317,22 +317,22 @@ msgstr ""
 #: utils/cpufreq-info.c:247
 #, c-format
 msgid "  hardware limits: "
-msgstr "  limitation matérielle : "
+msgstr "  limitation matérielle : "
 
 #: utils/cpufreq-info.c:256
 #, c-format
 msgid "  available frequency steps: "
-msgstr "  plage de fréquence : "
+msgstr "  plage de fréquence : "
 
 #: utils/cpufreq-info.c:269
 #, c-format
 msgid "  available cpufreq governors: "
-msgstr "  régulateurs disponibles : "
+msgstr "  régulateurs disponibles : "
 
 #: utils/cpufreq-info.c:280
 #, c-format
 msgid "  current policy: frequency should be within "
-msgstr "  tactique actuelle : la fréquence doit être comprise entre "
+msgstr "  tactique actuelle : la fréquence doit être comprise entre "
 
 #: utils/cpufreq-info.c:282
 #, c-format
@@ -345,18 +345,18 @@ msgid ""
 "The governor \"%s\" may decide which speed to use\n"
 "                  within this range.\n"
 msgstr ""
-"Le régulateur \"%s\" est libre de choisir la vitesse\n"
-"                  dans cette plage de fréquences.\n"
+"Le régulateur \"%s\" est libre de choisir la vitesse\n"
+"                  dans cette plage de fréquences.\n"
 
 #: utils/cpufreq-info.c:293
 #, c-format
 msgid "  current CPU frequency is "
-msgstr "  la fréquence actuelle de ce CPU est "
+msgstr "  la fréquence actuelle de ce CPU est "
 
 #: utils/cpufreq-info.c:296
 #, c-format
 msgid " (asserted by call to hardware)"
-msgstr " (vérifié par un appel direct du matériel)"
+msgstr " (vérifié par un appel direct du matériel)"
 
 #: utils/cpufreq-info.c:304
 #, c-format
@@ -377,7 +377,7 @@ msgstr "Options :\n"
 #: utils/cpufreq-info.c:474
 #, fuzzy, c-format
 msgid "  -e, --debug          Prints out debug information [default]\n"
-msgstr "  -e, --debug          Afficher les informations de déboguage\n"
+msgstr "  -e, --debug          Afficher les informations de déboguage\n"
 
 #: utils/cpufreq-info.c:475
 #, c-format
@@ -385,8 +385,8 @@ msgid ""
 "  -f, --freq           Get frequency the CPU currently runs at, according\n"
 "                       to the cpufreq core *\n"
 msgstr ""
-"  -f, --freq           Obtenir la fréquence actuelle du CPU selon le point\n"
-"                       de vue du coeur du système de cpufreq *\n"
+"  -f, --freq           Obtenir la fréquence actuelle du CPU selon le point\n"
+"                       de vue du coeur du système de cpufreq *\n"
 
 #: utils/cpufreq-info.c:477
 #, c-format
@@ -394,8 +394,8 @@ msgid ""
 "  -w, --hwfreq         Get frequency the CPU currently runs at, by reading\n"
 "                       it from hardware (only available to root) *\n"
 msgstr ""
-"  -w, --hwfreq         Obtenir la fréquence actuelle du CPU directement par\n"
-"                       le matériel (doit être root) *\n"
+"  -w, --hwfreq         Obtenir la fréquence actuelle du CPU directement par\n"
+"                       le matériel (doit être root) *\n"
 
 #: utils/cpufreq-info.c:479
 #, c-format
@@ -403,13 +403,13 @@ msgid ""
 "  -l, --hwlimits       Determine the minimum and maximum CPU frequency "
 "allowed *\n"
 msgstr ""
-"  -l, --hwlimits       Affiche les fréquences minimales et maximales du CPU "
+"  -l, --hwlimits       Affiche les fréquences minimales et maximales du CPU "
 "*\n"
 
 #: utils/cpufreq-info.c:480
 #, c-format
 msgid "  -d, --driver         Determines the used cpufreq kernel driver *\n"
-msgstr "  -d, --driver         Affiche le pilote cpufreq utilisé *\n"
+msgstr "  -d, --driver         Affiche le pilote cpufreq utilisé *\n"
 
 #: utils/cpufreq-info.c:481
 #, c-format
@@ -420,7 +420,7 @@ msgstr "  -p, --policy         Affiche la tactique actuelle de cpufreq *\n"
 #, c-format
 msgid "  -g, --governors      Determines available cpufreq governors *\n"
 msgstr ""
-"  -g, --governors      Affiche les régulateurs disponibles de cpufreq *\n"
+"  -g, --governors      Affiche les régulateurs disponibles de cpufreq *\n"
 
 #: utils/cpufreq-info.c:483
 #, fuzzy, c-format
@@ -429,7 +429,7 @@ msgid ""
 "frequency *\n"
 msgstr ""
 "  -a, --affected-cpus   Affiche quels sont les CPUs qui doivent changer de\n"
-"                        fréquences en même temps *\n"
+"                        fréquences en même temps *\n"
 
 #: utils/cpufreq-info.c:484
 #, fuzzy, c-format
@@ -438,7 +438,7 @@ msgid ""
 "                       coordinated by software *\n"
 msgstr ""
 "  -a, --affected-cpus   Affiche quels sont les CPUs qui doivent changer de\n"
-"                        fréquences en même temps *\n"
+"                        fréquences en même temps *\n"
 
 #: utils/cpufreq-info.c:486
 #, c-format
@@ -453,7 +453,7 @@ msgid ""
 "  -y, --latency        Determines the maximum latency on CPU frequency "
 "changes *\n"
 msgstr ""
-"  -l, --hwlimits       Affiche les fréquences minimales et maximales du CPU "
+"  -l, --hwlimits       Affiche les fréquences minimales et maximales du CPU "
 "*\n"
 
 #: utils/cpufreq-info.c:488
@@ -469,7 +469,7 @@ msgid ""
 "                       interface in 2.4. and early 2.6. kernels\n"
 msgstr ""
 "  -o, --proc           Affiche les informations en utilisant l'interface\n"
-"                       fournie par /proc/cpufreq, présente dans les "
+"                       fournie par /proc/cpufreq, présente dans les "
 "versions\n"
 "                       2.4 et les anciennes versions 2.6 du noyau\n"
 
@@ -485,7 +485,7 @@ msgstr ""
 #: utils/cpufreq-info.c:492 utils/cpuidle-info.c:152
 #, c-format
 msgid "  -h, --help           Prints out this screen\n"
-msgstr "  -h, --help           affiche l'aide-mémoire\n"
+msgstr "  -h, --help           affiche l'aide-mémoire\n"
 
 #: utils/cpufreq-info.c:495
 #, c-format
@@ -493,8 +493,8 @@ msgid ""
 "If no argument or only the -c, --cpu parameter is given, debug output about\n"
 "cpufreq is printed which is useful e.g. for reporting bugs.\n"
 msgstr ""
-"Par défaut, les informations de déboguage seront affichées si aucun\n"
-"argument, ou bien si seulement l'argument -c (--cpu) est donné, afin de\n"
+"Par défaut, les informations de déboguage seront affichées si aucun\n"
+"argument, ou bien si seulement l'argument -c (--cpu) est donné, afin de\n"
 "faciliter les rapports de bogues par exemple\n"
 
 #: utils/cpufreq-info.c:497
@@ -517,8 +517,8 @@ msgid ""
 "You can't specify more than one --cpu parameter and/or\n"
 "more than one output-specific argument\n"
 msgstr ""
-"On ne peut indiquer plus d'un paramètre --cpu, tout comme l'on ne peut\n"
-"spécifier plus d'un argument de formatage\n"
+"On ne peut indiquer plus d'un paramètre --cpu, tout comme l'on ne peut\n"
+"spécifier plus d'un argument de formatage\n"
 
 #: utils/cpufreq-info.c:600 utils/cpufreq-set.c:82 utils/cpupower-set.c:42
 #: utils/cpupower-info.c:42 utils/cpuidle-info.c:213
@@ -529,7 +529,7 @@ msgstr "option invalide\n"
 #: utils/cpufreq-info.c:617
 #, c-format
 msgid "couldn't analyze CPU %d as it doesn't seem to be present\n"
-msgstr "analyse du CPU %d impossible puisqu'il ne semble pas être présent\n"
+msgstr "analyse du CPU %d impossible puisqu'il ne semble pas être présent\n"
 
 #: utils/cpufreq-info.c:620 utils/cpupower-info.c:142
 #, c-format
@@ -547,8 +547,8 @@ msgid ""
 "  -d FREQ, --min FREQ      new minimum CPU frequency the governor may "
 "select\n"
 msgstr ""
-"  -d FREQ, --min FREQ       nouvelle fréquence minimale du CPU à utiliser\n"
-"                            par le régulateur\n"
+"  -d FREQ, --min FREQ       nouvelle fréquence minimale du CPU à utiliser\n"
+"                            par le régulateur\n"
 
 #: utils/cpufreq-set.c:28
 #, c-format
@@ -556,13 +556,13 @@ msgid ""
 "  -u FREQ, --max FREQ      new maximum CPU frequency the governor may "
 "select\n"
 msgstr ""
-"  -u FREQ, --max FREQ       nouvelle fréquence maximale du CPU à utiliser\n"
-"                            par le régulateur\n"
+"  -u FREQ, --max FREQ       nouvelle fréquence maximale du CPU à utiliser\n"
+"                            par le régulateur\n"
 
 #: utils/cpufreq-set.c:29
 #, c-format
 msgid "  -g GOV, --governor GOV   new cpufreq governor\n"
-msgstr "  -g GOV, --governor GOV   active le régulateur GOV\n"
+msgstr "  -g GOV, --governor GOV   active le régulateur GOV\n"
 
 #: utils/cpufreq-set.c:30
 #, c-format
@@ -570,9 +570,9 @@ msgid ""
 "  -f FREQ, --freq FREQ     specific frequency to be set. Requires userspace\n"
 "                           governor to be available and loaded\n"
 msgstr ""
-"  -f FREQ, --freq FREQ     fixe la fréquence du processeur à FREQ. Il faut\n"
-"                           que le régulateur « userspace » soit disponible \n"
-"                           et activé.\n"
+"  -f FREQ, --freq FREQ     fixe la fréquence du processeur à FREQ. Il faut\n"
+"                           que le régulateur Â« userspace Â» soit disponible \n"
+"                           et activé.\n"
 
 #: utils/cpufreq-set.c:32
 #, c-format
@@ -582,7 +582,7 @@ msgstr ""
 #: utils/cpufreq-set.c:33 utils/cpupower-set.c:28 utils/cpupower-info.c:27
 #, fuzzy, c-format
 msgid "  -h, --help               Prints out this screen\n"
-msgstr "  -h, --help           affiche l'aide-mémoire\n"
+msgstr "  -h, --help           affiche l'aide-mémoire\n"
 
 #: utils/cpufreq-set.c:35
 #, fuzzy, c-format
@@ -602,11 +602,11 @@ msgid ""
 "   (FREQuency in kHz =^ Hz * 0.001 =^ MHz * 1000 =^ GHz * 1000000).\n"
 msgstr ""
 "Remarque :\n"
-"1. Le CPU numéro 0 sera utilisé par défaut si -c (ou --cpu) est omis ;\n"
-"2. l'argument -f FREQ (ou --freq FREQ) ne peut être utilisé qu'avec --cpu ;\n"
-"3. on pourra préciser l'unité des fréquences en postfixant sans aucune "
+"1. Le CPU numéro 0 sera utilisé par défaut si -c (ou --cpu) est omis ;\n"
+"2. l'argument -f FREQ (ou --freq FREQ) ne peut être utilisé qu'avec --cpu ;\n"
+"3. on pourra préciser l'unité des fréquences en postfixant sans aucune "
 "espace\n"
-"   les valeurs par hz, kHz (par défaut), MHz, GHz ou THz\n"
+"   les valeurs par hz, kHz (par défaut), MHz, GHz ou THz\n"
 "   (kHz =^ Hz * 0.001 =^ MHz * 1000 =^ GHz * 1000000).\n"
 
 #: utils/cpufreq-set.c:57
@@ -622,21 +622,21 @@ msgid ""
 "frequency\n"
 "   or because the userspace governor isn't loaded?\n"
 msgstr ""
-"En ajustant les nouveaux paramètres, une erreur est apparue. Les sources\n"
+"En ajustant les nouveaux paramètres, une erreur est apparue. Les sources\n"
 "d'erreur typique sont :\n"
-"- droit d'administration insuffisant (êtes-vous root ?) ;\n"
-"- le régulateur choisi n'est pas disponible, ou bien n'est pas disponible "
+"- droit d'administration insuffisant (êtes-vous root ?) ;\n"
+"- le régulateur choisi n'est pas disponible, ou bien n'est pas disponible "
 "en\n"
 "  tant que module noyau ;\n"
 "- la tactique n'est pas disponible ;\n"
-"- vous voulez utiliser l'option -f/--freq, mais le régulateur « userspace »\n"
-"  n'est pas disponible, par exemple parce que le matériel ne le supporte\n"
-"  pas, ou bien n'est tout simplement pas chargé.\n"
+"- vous voulez utiliser l'option -f/--freq, mais le régulateur Â« userspace Â»\n"
+"  n'est pas disponible, par exemple parce que le matériel ne le supporte\n"
+"  pas, ou bien n'est tout simplement pas chargé.\n"
 
 #: utils/cpufreq-set.c:170
 #, c-format
 msgid "wrong, unknown or unhandled CPU?\n"
-msgstr "CPU inconnu ou non supporté ?\n"
+msgstr "CPU inconnu ou non supporté ?\n"
 
 #: utils/cpufreq-set.c:302
 #, c-format
@@ -653,7 +653,7 @@ msgid ""
 "At least one parameter out of -f/--freq, -d/--min, -u/--max, and\n"
 "-g/--governor must be passed\n"
 msgstr ""
-"L'un de ces paramètres est obligatoire : -f/--freq, -d/--min, -u/--max et\n"
+"L'un de ces paramètres est obligatoire : -f/--freq, -d/--min, -u/--max et\n"
 "-g/--governor\n"
 
 #: utils/cpufreq-set.c:347
@@ -810,7 +810,7 @@ msgstr ""
 #: utils/cpuidle-info.c:48
 #, fuzzy, c-format
 msgid "Available idle states:"
-msgstr "  plage de fréquence : "
+msgstr "  plage de fréquence : "
 
 #: utils/cpuidle-info.c:71
 #, c-format
@@ -911,7 +911,7 @@ msgstr "Usage : cpufreq-info [options]\n"
 #: utils/cpuidle-info.c:149
 #, fuzzy, c-format
 msgid "  -s, --silent         Only show general C-state information\n"
-msgstr "  -e, --debug          Afficher les informations de déboguage\n"
+msgstr "  -e, --debug          Afficher les informations de déboguage\n"
 
 #: utils/cpuidle-info.c:150
 #, fuzzy, c-format
@@ -921,7 +921,7 @@ msgid ""
 "                       interface in older kernels\n"
 msgstr ""
 "  -o, --proc           Affiche les informations en utilisant l'interface\n"
-"                       fournie par /proc/cpufreq, présente dans les "
+"                       fournie par /proc/cpufreq, présente dans les "
 "versions\n"
 "                       2.4 et les anciennes versions 2.6 du noyau\n"
 
@@ -929,19 +929,19 @@ msgstr ""
 #, fuzzy, c-format
 msgid "You can't specify more than one output-specific argument\n"
 msgstr ""
-"On ne peut indiquer plus d'un paramètre --cpu, tout comme l'on ne peut\n"
-"spécifier plus d'un argument de formatage\n"
+"On ne peut indiquer plus d'un paramètre --cpu, tout comme l'on ne peut\n"
+"spécifier plus d'un argument de formatage\n"
 
 #~ msgid ""
 #~ "  -c CPU, --cpu CPU    CPU number which information shall be determined "
 #~ "about\n"
 #~ msgstr ""
-#~ "  -c CPU, --cpu CPU    Numéro du CPU pour lequel l'information sera "
-#~ "affichée\n"
+#~ "  -c CPU, --cpu CPU    Numéro du CPU pour lequel l'information sera "
+#~ "affichée\n"
 
 #~ msgid ""
 #~ "  -c CPU, --cpu CPU        number of CPU where cpufreq settings shall be "
 #~ "modified\n"
 #~ msgstr ""
-#~ "  -c CPU, --cpu CPU        numéro du CPU à prendre en compte pour les\n"
+#~ "  -c CPU, --cpu CPU        numéro du CPU à prendre en compte pour les\n"
 #~ "                           changements\n"
index b53596a..2e7fd82 100644 (file)
@@ -31,17 +31,21 @@ long __pmem_direct_access(struct pmem_device *pmem, pgoff_t pgoff,
        if (get_nfit_res(pmem->phys_addr + offset)) {
                struct page *page;
 
-               *kaddr = pmem->virt_addr + offset;
+               if (kaddr)
+                       *kaddr = pmem->virt_addr + offset;
                page = vmalloc_to_page(pmem->virt_addr + offset);
-               *pfn = page_to_pfn_t(page);
+               if (pfn)
+                       *pfn = page_to_pfn_t(page);
                pr_debug_ratelimited("%s: pmem: %p pgoff: %#lx pfn: %#lx\n",
                                __func__, pmem, pgoff, page_to_pfn(page));
 
                return 1;
        }
 
-       *kaddr = pmem->virt_addr + offset;
-       *pfn = phys_to_pfn_t(pmem->phys_addr + offset, pmem->pfn_flags);
+       if (kaddr)
+               *kaddr = pmem->virt_addr + offset;
+       if (pfn)
+               *pfn = phys_to_pfn_t(pmem->phys_addr + offset, pmem->pfn_flags);
 
        /*
         * If badblocks are present, limit known good range to the
index e2926f7..cffc2c5 100644 (file)
@@ -142,6 +142,28 @@ static u32 handle[] = {
 static unsigned long dimm_fail_cmd_flags[NUM_DCR];
 static int dimm_fail_cmd_code[NUM_DCR];
 
+static const struct nd_intel_smart smart_def = {
+       .flags = ND_INTEL_SMART_HEALTH_VALID
+               | ND_INTEL_SMART_SPARES_VALID
+               | ND_INTEL_SMART_ALARM_VALID
+               | ND_INTEL_SMART_USED_VALID
+               | ND_INTEL_SMART_SHUTDOWN_VALID
+               | ND_INTEL_SMART_MTEMP_VALID
+               | ND_INTEL_SMART_CTEMP_VALID,
+       .health = ND_INTEL_SMART_NON_CRITICAL_HEALTH,
+       .media_temperature = 23 * 16,
+       .ctrl_temperature = 25 * 16,
+       .pmic_temperature = 40 * 16,
+       .spares = 75,
+       .alarm_flags = ND_INTEL_SMART_SPARE_TRIP
+               | ND_INTEL_SMART_TEMP_TRIP,
+       .ait_status = 1,
+       .life_used = 5,
+       .shutdown_state = 0,
+       .vendor_size = 0,
+       .shutdown_count = 100,
+};
+
 struct nfit_test_fw {
        enum intel_fw_update_state state;
        u32 context;
@@ -752,15 +774,30 @@ static int nfit_test_cmd_smart_inject(
        if (buf_len != sizeof(*inj))
                return -EINVAL;
 
-       if (inj->mtemp_enable)
-               smart->media_temperature = inj->media_temperature;
-       if (inj->spare_enable)
-               smart->spares = inj->spares;
-       if (inj->fatal_enable)
-               smart->health = ND_INTEL_SMART_FATAL_HEALTH;
-       if (inj->unsafe_shutdown_enable) {
-               smart->shutdown_state = 1;
-               smart->shutdown_count++;
+       if (inj->flags & ND_INTEL_SMART_INJECT_MTEMP) {
+               if (inj->mtemp_enable)
+                       smart->media_temperature = inj->media_temperature;
+               else
+                       smart->media_temperature = smart_def.media_temperature;
+       }
+       if (inj->flags & ND_INTEL_SMART_INJECT_SPARE) {
+               if (inj->spare_enable)
+                       smart->spares = inj->spares;
+               else
+                       smart->spares = smart_def.spares;
+       }
+       if (inj->flags & ND_INTEL_SMART_INJECT_FATAL) {
+               if (inj->fatal_enable)
+                       smart->health = ND_INTEL_SMART_FATAL_HEALTH;
+               else
+                       smart->health = ND_INTEL_SMART_NON_CRITICAL_HEALTH;
+       }
+       if (inj->flags & ND_INTEL_SMART_INJECT_SHUTDOWN) {
+               if (inj->unsafe_shutdown_enable) {
+                       smart->shutdown_state = 1;
+                       smart->shutdown_count++;
+               } else
+                       smart->shutdown_state = 0;
        }
        inj->status = 0;
        smart_notify(bus_dev, dimm_dev, smart, thresh);
@@ -884,6 +921,16 @@ static int nd_intel_test_cmd_set_lss_status(struct nfit_test *t,
        return 0;
 }
 
+static int override_return_code(int dimm, unsigned int func, int rc)
+{
+       if ((1 << func) & dimm_fail_cmd_flags[dimm]) {
+               if (dimm_fail_cmd_code[dimm])
+                       return dimm_fail_cmd_code[dimm];
+               return -EIO;
+       }
+       return rc;
+}
+
 static int get_dimm(struct nfit_mem *nfit_mem, unsigned int func)
 {
        int i;
@@ -894,13 +941,6 @@ static int get_dimm(struct nfit_mem *nfit_mem, unsigned int func)
                        break;
        if (i >= ARRAY_SIZE(handle))
                return -ENXIO;
-
-       if ((1 << func) & dimm_fail_cmd_flags[i]) {
-               if (dimm_fail_cmd_code[i])
-                       return dimm_fail_cmd_code[i];
-               return -EIO;
-       }
-
        return i;
 }
 
@@ -939,48 +979,59 @@ static int nfit_test_ctl(struct nvdimm_bus_descriptor *nd_desc,
 
                        switch (func) {
                        case ND_INTEL_ENABLE_LSS_STATUS:
-                               return nd_intel_test_cmd_set_lss_status(t,
+                               rc = nd_intel_test_cmd_set_lss_status(t,
                                                buf, buf_len);
+                               break;
                        case ND_INTEL_FW_GET_INFO:
-                               return nd_intel_test_get_fw_info(t, buf,
+                               rc = nd_intel_test_get_fw_info(t, buf,
                                                buf_len, i - t->dcr_idx);
+                               break;
                        case ND_INTEL_FW_START_UPDATE:
-                               return nd_intel_test_start_update(t, buf,
+                               rc = nd_intel_test_start_update(t, buf,
                                                buf_len, i - t->dcr_idx);
+                               break;
                        case ND_INTEL_FW_SEND_DATA:
-                               return nd_intel_test_send_data(t, buf,
+                               rc = nd_intel_test_send_data(t, buf,
                                                buf_len, i - t->dcr_idx);
+                               break;
                        case ND_INTEL_FW_FINISH_UPDATE:
-                               return nd_intel_test_finish_fw(t, buf,
+                               rc = nd_intel_test_finish_fw(t, buf,
                                                buf_len, i - t->dcr_idx);
+                               break;
                        case ND_INTEL_FW_FINISH_QUERY:
-                               return nd_intel_test_finish_query(t, buf,
+                               rc = nd_intel_test_finish_query(t, buf,
                                                buf_len, i - t->dcr_idx);
+                               break;
                        case ND_INTEL_SMART:
-                               return nfit_test_cmd_smart(buf, buf_len,
+                               rc = nfit_test_cmd_smart(buf, buf_len,
                                                &t->smart[i - t->dcr_idx]);
+                               break;
                        case ND_INTEL_SMART_THRESHOLD:
-                               return nfit_test_cmd_smart_threshold(buf,
+                               rc = nfit_test_cmd_smart_threshold(buf,
                                                buf_len,
                                                &t->smart_threshold[i -
                                                        t->dcr_idx]);
+                               break;
                        case ND_INTEL_SMART_SET_THRESHOLD:
-                               return nfit_test_cmd_smart_set_threshold(buf,
+                               rc = nfit_test_cmd_smart_set_threshold(buf,
                                                buf_len,
                                                &t->smart_threshold[i -
                                                        t->dcr_idx],
                                                &t->smart[i - t->dcr_idx],
                                                &t->pdev.dev, t->dimm_dev[i]);
+                               break;
                        case ND_INTEL_SMART_INJECT:
-                               return nfit_test_cmd_smart_inject(buf,
+                               rc = nfit_test_cmd_smart_inject(buf,
                                                buf_len,
                                                &t->smart_threshold[i -
                                                        t->dcr_idx],
                                                &t->smart[i - t->dcr_idx],
                                                &t->pdev.dev, t->dimm_dev[i]);
+                               break;
                        default:
                                return -ENOTTY;
                        }
+                       return override_return_code(i, func, rc);
                }
 
                if (!test_bit(cmd, &cmd_mask)
@@ -1006,6 +1057,7 @@ static int nfit_test_ctl(struct nvdimm_bus_descriptor *nd_desc,
                default:
                        return -ENOTTY;
                }
+               return override_return_code(i, func, rc);
        } else {
                struct ars_state *ars_state = &t->ars_state;
                struct nd_cmd_pkg *call_pkg = buf;
@@ -1302,29 +1354,9 @@ static void smart_init(struct nfit_test *t)
                .ctrl_temperature = 30 * 16,
                .spares = 5,
        };
-       const struct nd_intel_smart smart_data = {
-               .flags = ND_INTEL_SMART_HEALTH_VALID
-                       | ND_INTEL_SMART_SPARES_VALID
-                       | ND_INTEL_SMART_ALARM_VALID
-                       | ND_INTEL_SMART_USED_VALID
-                       | ND_INTEL_SMART_SHUTDOWN_VALID
-                       | ND_INTEL_SMART_MTEMP_VALID,
-               .health = ND_INTEL_SMART_NON_CRITICAL_HEALTH,
-               .media_temperature = 23 * 16,
-               .ctrl_temperature = 25 * 16,
-               .pmic_temperature = 40 * 16,
-               .spares = 75,
-               .alarm_flags = ND_INTEL_SMART_SPARE_TRIP
-                       | ND_INTEL_SMART_TEMP_TRIP,
-               .ait_status = 1,
-               .life_used = 5,
-               .shutdown_state = 0,
-               .vendor_size = 0,
-               .shutdown_count = 100,
-       };
 
        for (i = 0; i < t->num_dcr; i++) {
-               memcpy(&t->smart[i], &smart_data, sizeof(smart_data));
+               memcpy(&t->smart[i], &smart_def, sizeof(smart_def));
                memcpy(&t->smart_threshold[i], &smart_t_data,
                                sizeof(smart_t_data));
        }
index db66f8a..37baecc 100644 (file)
@@ -1,7 +1,8 @@
 # SPDX-License-Identifier: GPL-2.0
 
-CFLAGS += -I. -I../../include -g -O2 -Wall -D_LGPL_SOURCE -fsanitize=address
-LDFLAGS += -fsanitize=address
+CFLAGS += -I. -I../../include -g -Og -Wall -D_LGPL_SOURCE -fsanitize=address \
+         -fsanitize=undefined
+LDFLAGS += -fsanitize=address -fsanitize=undefined
 LDLIBS+= -lpthread -lurcu
 TARGETS = main idr-test multiorder
 CORE_OFILES := radix-tree.o idr.o linux.o test.o find_bit.o
@@ -21,6 +22,7 @@ targets: generated/map-shift.h $(TARGETS)
 
 main:  $(OFILES)
 
+idr-test.o: ../../../lib/test_ida.c
 idr-test: idr-test.o $(CORE_OFILES)
 
 multiorder: multiorder.o $(CORE_OFILES)
index ee820fc..321ba92 100644 (file)
@@ -309,141 +309,61 @@ void idr_checks(void)
        idr_u32_test(0);
 }
 
+#define module_init(x)
+#define module_exit(x)
+#define MODULE_AUTHOR(x)
+#define MODULE_LICENSE(x)
+#define dump_stack()    assert(0)
+void ida_dump(struct ida *);
+
+#include "../../../lib/test_ida.c"
+
 /*
  * Check that we get the correct error when we run out of memory doing
- * allocations.  To ensure we run out of memory, just "forget" to preload.
+ * allocations.  In userspace, GFP_NOWAIT will always fail an allocation.
  * The first test is for not having a bitmap available, and the second test
  * is for not being able to allocate a level of the radix tree.
  */
 void ida_check_nomem(void)
 {
        DEFINE_IDA(ida);
-       int id, err;
-
-       err = ida_get_new_above(&ida, 256, &id);
-       assert(err == -EAGAIN);
-       err = ida_get_new_above(&ida, 1UL << 30, &id);
-       assert(err == -EAGAIN);
-}
-
-/*
- * Check what happens when we fill a leaf and then delete it.  This may
- * discover mishandling of IDR_FREE.
- */
-void ida_check_leaf(void)
-{
-       DEFINE_IDA(ida);
        int id;
-       unsigned long i;
 
-       for (i = 0; i < IDA_BITMAP_BITS; i++) {
-               assert(ida_pre_get(&ida, GFP_KERNEL));
-               assert(!ida_get_new(&ida, &id));
-               assert(id == i);
-       }
-
-       ida_destroy(&ida);
-       assert(ida_is_empty(&ida));
-
-       assert(ida_pre_get(&ida, GFP_KERNEL));
-       assert(!ida_get_new(&ida, &id));
-       assert(id == 0);
-       ida_destroy(&ida);
-       assert(ida_is_empty(&ida));
+       id = ida_alloc_min(&ida, 256, GFP_NOWAIT);
+       IDA_BUG_ON(&ida, id != -ENOMEM);
+       id = ida_alloc_min(&ida, 1UL << 30, GFP_NOWAIT);
+       IDA_BUG_ON(&ida, id != -ENOMEM);
+       IDA_BUG_ON(&ida, !ida_is_empty(&ida));
 }
 
 /*
  * Check handling of conversions between exceptional entries and full bitmaps.
  */
-void ida_check_conv(void)
+void ida_check_conv_user(void)
 {
        DEFINE_IDA(ida);
-       int id;
        unsigned long i;
 
-       for (i = 0; i < IDA_BITMAP_BITS * 2; i += IDA_BITMAP_BITS) {
-               assert(ida_pre_get(&ida, GFP_KERNEL));
-               assert(!ida_get_new_above(&ida, i + 1, &id));
-               assert(id == i + 1);
-               assert(!ida_get_new_above(&ida, i + BITS_PER_LONG, &id));
-               assert(id == i + BITS_PER_LONG);
-               ida_remove(&ida, i + 1);
-               ida_remove(&ida, i + BITS_PER_LONG);
-               assert(ida_is_empty(&ida));
-       }
-
-       assert(ida_pre_get(&ida, GFP_KERNEL));
-
-       for (i = 0; i < IDA_BITMAP_BITS * 2; i++) {
-               assert(ida_pre_get(&ida, GFP_KERNEL));
-               assert(!ida_get_new(&ida, &id));
-               assert(id == i);
-       }
-
-       for (i = IDA_BITMAP_BITS * 2; i > 0; i--) {
-               ida_remove(&ida, i - 1);
-       }
-       assert(ida_is_empty(&ida));
-
-       for (i = 0; i < IDA_BITMAP_BITS + BITS_PER_LONG - 4; i++) {
-               assert(ida_pre_get(&ida, GFP_KERNEL));
-               assert(!ida_get_new(&ida, &id));
-               assert(id == i);
-       }
-
-       for (i = IDA_BITMAP_BITS + BITS_PER_LONG - 4; i > 0; i--) {
-               ida_remove(&ida, i - 1);
-       }
-       assert(ida_is_empty(&ida));
-
        radix_tree_cpu_dead(1);
        for (i = 0; i < 1000000; i++) {
-               int err = ida_get_new(&ida, &id);
-               if (err == -EAGAIN) {
-                       assert((i % IDA_BITMAP_BITS) == (BITS_PER_LONG - 2));
-                       assert(ida_pre_get(&ida, GFP_KERNEL));
-                       err = ida_get_new(&ida, &id);
+               int id = ida_alloc(&ida, GFP_NOWAIT);
+               if (id == -ENOMEM) {
+                       IDA_BUG_ON(&ida, (i % IDA_BITMAP_BITS) !=
+                                       BITS_PER_LONG - 2);
+                       id = ida_alloc(&ida, GFP_KERNEL);
                } else {
-                       assert((i % IDA_BITMAP_BITS) != (BITS_PER_LONG - 2));
+                       IDA_BUG_ON(&ida, (i % IDA_BITMAP_BITS) ==
+                                       BITS_PER_LONG - 2);
                }
-               assert(!err);
-               assert(id == i);
+               IDA_BUG_ON(&ida, id != i);
        }
        ida_destroy(&ida);
 }
 
-/*
- * Check allocations up to and slightly above the maximum allowed (2^31-1) ID.
- * Allocating up to 2^31-1 should succeed, and then allocating the next one
- * should fail.
- */
-void ida_check_max(void)
-{
-       DEFINE_IDA(ida);
-       int id, err;
-       unsigned long i, j;
-
-       for (j = 1; j < 65537; j *= 2) {
-               unsigned long base = (1UL << 31) - j;
-               for (i = 0; i < j; i++) {
-                       assert(ida_pre_get(&ida, GFP_KERNEL));
-                       assert(!ida_get_new_above(&ida, base, &id));
-                       assert(id == base + i);
-               }
-               assert(ida_pre_get(&ida, GFP_KERNEL));
-               err = ida_get_new_above(&ida, base, &id);
-               assert(err == -ENOSPC);
-               ida_destroy(&ida);
-               assert(ida_is_empty(&ida));
-               rcu_barrier();
-       }
-}
-
 void ida_check_random(void)
 {
        DEFINE_IDA(ida);
        DECLARE_BITMAP(bitmap, 2048);
-       int id, err;
        unsigned int i;
        time_t s = time(NULL);
 
@@ -454,15 +374,11 @@ void ida_check_random(void)
                int bit = i & 2047;
                if (test_bit(bit, bitmap)) {
                        __clear_bit(bit, bitmap);
-                       ida_remove(&ida, bit);
+                       ida_free(&ida, bit);
                } else {
                        __set_bit(bit, bitmap);
-                       do {
-                               ida_pre_get(&ida, GFP_KERNEL);
-                               err = ida_get_new_above(&ida, bit, &id);
-                       } while (err == -EAGAIN);
-                       assert(!err);
-                       assert(id == bit);
+                       IDA_BUG_ON(&ida, ida_alloc_min(&ida, bit, GFP_KERNEL)
+                                       != bit);
                }
        }
        ida_destroy(&ida);
@@ -488,71 +404,12 @@ void ida_simple_get_remove_test(void)
        ida_destroy(&ida);
 }
 
-void ida_checks(void)
+void user_ida_checks(void)
 {
-       DEFINE_IDA(ida);
-       int id;
-       unsigned long i;
-
        radix_tree_cpu_dead(1);
-       ida_check_nomem();
-
-       for (i = 0; i < 10000; i++) {
-               assert(ida_pre_get(&ida, GFP_KERNEL));
-               assert(!ida_get_new(&ida, &id));
-               assert(id == i);
-       }
-
-       ida_remove(&ida, 20);
-       ida_remove(&ida, 21);
-       for (i = 0; i < 3; i++) {
-               assert(ida_pre_get(&ida, GFP_KERNEL));
-               assert(!ida_get_new(&ida, &id));
-               if (i == 2)
-                       assert(id == 10000);
-       }
-
-       for (i = 0; i < 5000; i++)
-               ida_remove(&ida, i);
-
-       assert(ida_pre_get(&ida, GFP_KERNEL));
-       assert(!ida_get_new_above(&ida, 5000, &id));
-       assert(id == 10001);
-
-       ida_destroy(&ida);
-
-       assert(ida_is_empty(&ida));
 
-       assert(ida_pre_get(&ida, GFP_KERNEL));
-       assert(!ida_get_new_above(&ida, 1, &id));
-       assert(id == 1);
-
-       ida_remove(&ida, id);
-       assert(ida_is_empty(&ida));
-       ida_destroy(&ida);
-       assert(ida_is_empty(&ida));
-
-       assert(ida_pre_get(&ida, GFP_KERNEL));
-       assert(!ida_get_new_above(&ida, 1, &id));
-       ida_destroy(&ida);
-       assert(ida_is_empty(&ida));
-
-       assert(ida_pre_get(&ida, GFP_KERNEL));
-       assert(!ida_get_new_above(&ida, 1, &id));
-       assert(id == 1);
-       assert(ida_pre_get(&ida, GFP_KERNEL));
-       assert(!ida_get_new_above(&ida, 1025, &id));
-       assert(id == 1025);
-       assert(ida_pre_get(&ida, GFP_KERNEL));
-       assert(!ida_get_new_above(&ida, 10000, &id));
-       assert(id == 10000);
-       ida_remove(&ida, 1025);
-       ida_destroy(&ida);
-       assert(ida_is_empty(&ida));
-
-       ida_check_leaf();
-       ida_check_max();
-       ida_check_conv();
+       ida_check_nomem();
+       ida_check_conv_user();
        ida_check_random();
        ida_simple_get_remove_test();
 
@@ -582,12 +439,19 @@ void ida_thread_tests(void)
                pthread_join(threads[i], NULL);
 }
 
+void ida_tests(void)
+{
+       user_ida_checks();
+       ida_checks();
+       ida_exit();
+       ida_thread_tests();
+}
+
 int __weak main(void)
 {
        radix_tree_init();
        idr_checks();
-       ida_checks();
-       ida_thread_tests();
+       ida_tests();
        radix_tree_cpu_dead(1);
        rcu_barrier();
        if (nr_allocated)
diff --git a/tools/testing/radix-tree/linux/xarray.h b/tools/testing/radix-tree/linux/xarray.h
new file mode 100644 (file)
index 0000000..df3812c
--- /dev/null
@@ -0,0 +1,2 @@
+#include "generated/map-shift.h"
+#include "../../../../include/linux/xarray.h"
index 257f3f8..b741686 100644 (file)
@@ -27,20 +27,22 @@ void __gang_check(unsigned long middle, long down, long up, int chunk, int hop)
                item_check_present(&tree, middle + idx);
        item_check_absent(&tree, middle + up);
 
-       item_gang_check_present(&tree, middle - down,
-                       up + down, chunk, hop);
-       item_full_scan(&tree, middle - down, down + up, chunk);
+       if (chunk > 0) {
+               item_gang_check_present(&tree, middle - down, up + down,
+                               chunk, hop);
+               item_full_scan(&tree, middle - down, down + up, chunk);
+       }
        item_kill_tree(&tree);
 }
 
 void gang_check(void)
 {
-       __gang_check(1 << 30, 128, 128, 35, 2);
-       __gang_check(1 << 31, 128, 128, 32, 32);
-       __gang_check(1 << 31, 128, 128, 32, 100);
-       __gang_check(1 << 31, 128, 128, 17, 7);
-       __gang_check(0xffff0000, 0, 65536, 17, 7);
-       __gang_check(0xfffffffe, 1, 1, 17, 7);
+       __gang_check(1UL << 30, 128, 128, 35, 2);
+       __gang_check(1UL << 31, 128, 128, 32, 32);
+       __gang_check(1UL << 31, 128, 128, 32, 100);
+       __gang_check(1UL << 31, 128, 128, 17, 7);
+       __gang_check(0xffff0000UL, 0, 65536, 17, 7);
+       __gang_check(0xfffffffeUL, 1, 1, 17, 7);
 }
 
 void __big_gang_check(void)
@@ -322,7 +324,7 @@ static void single_thread_tests(bool long_run)
        printv(2, "after dynamic_height_check: %d allocated, preempt %d\n",
                nr_allocated, preempt_count);
        idr_checks();
-       ida_checks();
+       ida_tests();
        rcu_barrier();
        printv(2, "after idr_checks: %d allocated, preempt %d\n",
                nr_allocated, preempt_count);
@@ -369,7 +371,6 @@ int main(int argc, char **argv)
        iteration_test(0, 10 + 90 * long_run);
        iteration_test(7, 10 + 90 * long_run);
        single_thread_tests(long_run);
-       ida_thread_tests();
 
        /* Free any remaining preallocated nodes */
        radix_tree_cpu_dead(0);
index 31f1d9b..92d901e 100644 (file)
@@ -39,8 +39,7 @@ void multiorder_checks(void);
 void iteration_test(unsigned order, unsigned duration);
 void benchmark(void);
 void idr_checks(void);
-void ida_checks(void);
-void ida_thread_tests(void);
+void ida_tests(void);
 
 struct item *
 item_tag_set(struct radix_tree_root *root, unsigned long index, int tag);
index a944e72..b5fa0a2 100644 (file)
@@ -51,6 +51,7 @@ int main(int argc, char *argv[])
 
        heap_size = 0;
        flags = 0;
+       heap_type = ION_HEAP_TYPE_SYSTEM;
 
        while ((opt = getopt(argc, argv, "hi:s:")) != -1) {
                switch (opt) {
diff --git a/tools/testing/selftests/cgroup/.gitignore b/tools/testing/selftests/cgroup/.gitignore
new file mode 100644 (file)
index 0000000..95eb3a5
--- /dev/null
@@ -0,0 +1 @@
+test_memcontrol
index f7a3139..23fbaa4 100644 (file)
@@ -4,7 +4,9 @@ CFLAGS += -Wall
 all:
 
 TEST_GEN_PROGS = test_memcontrol
+TEST_GEN_PROGS += test_core
 
 include ../lib.mk
 
 $(OUTPUT)/test_memcontrol: cgroup_util.c
+$(OUTPUT)/test_core: cgroup_util.c
index 1e9e3c4..1c5d2b2 100644 (file)
@@ -229,6 +229,14 @@ retry:
        return ret;
 }
 
+int cg_enter_current(const char *cgroup)
+{
+       char pidbuf[64];
+
+       snprintf(pidbuf, sizeof(pidbuf), "%d", getpid());
+       return cg_write(cgroup, "cgroup.procs", pidbuf);
+}
+
 int cg_run(const char *cgroup,
           int (*fn)(const char *cgroup, void *arg),
           void *arg)
index fe82a29..1ff6f9f 100644 (file)
@@ -32,6 +32,7 @@ extern int cg_write(const char *cgroup, const char *control, char *buf);
 extern int cg_run(const char *cgroup,
                  int (*fn)(const char *cgroup, void *arg),
                  void *arg);
+extern int cg_enter_current(const char *cgroup);
 extern int cg_run_nowait(const char *cgroup,
                         int (*fn)(const char *cgroup, void *arg),
                         void *arg);
diff --git a/tools/testing/selftests/cgroup/test_core.c b/tools/testing/selftests/cgroup/test_core.c
new file mode 100644 (file)
index 0000000..be59f9c
--- /dev/null
@@ -0,0 +1,395 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#include <linux/limits.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <errno.h>
+
+#include "../kselftest.h"
+#include "cgroup_util.h"
+
+/*
+ * A(0) - B(0) - C(1)
+ *        \ D(0)
+ *
+ * A, B and C's "populated" fields would be 1 while D's 0.
+ * test that after the one process in C is moved to root,
+ * A,B and C's "populated" fields would flip to "0" and file
+ * modified events will be generated on the
+ * "cgroup.events" files of both cgroups.
+ */
+static int test_cgcore_populated(const char *root)
+{
+       int ret = KSFT_FAIL;
+       char *cg_test_a = NULL, *cg_test_b = NULL;
+       char *cg_test_c = NULL, *cg_test_d = NULL;
+
+       cg_test_a = cg_name(root, "cg_test_a");
+       cg_test_b = cg_name(root, "cg_test_a/cg_test_b");
+       cg_test_c = cg_name(root, "cg_test_a/cg_test_b/cg_test_c");
+       cg_test_d = cg_name(root, "cg_test_a/cg_test_b/cg_test_d");
+
+       if (!cg_test_a || !cg_test_b || !cg_test_c || !cg_test_d)
+               goto cleanup;
+
+       if (cg_create(cg_test_a))
+               goto cleanup;
+
+       if (cg_create(cg_test_b))
+               goto cleanup;
+
+       if (cg_create(cg_test_c))
+               goto cleanup;
+
+       if (cg_create(cg_test_d))
+               goto cleanup;
+
+       if (cg_enter_current(cg_test_c))
+               goto cleanup;
+
+       if (cg_read_strcmp(cg_test_a, "cgroup.events", "populated 1\n"))
+               goto cleanup;
+
+       if (cg_read_strcmp(cg_test_b, "cgroup.events", "populated 1\n"))
+               goto cleanup;
+
+       if (cg_read_strcmp(cg_test_c, "cgroup.events", "populated 1\n"))
+               goto cleanup;
+
+       if (cg_read_strcmp(cg_test_d, "cgroup.events", "populated 0\n"))
+               goto cleanup;
+
+       if (cg_enter_current(root))
+               goto cleanup;
+
+       if (cg_read_strcmp(cg_test_a, "cgroup.events", "populated 0\n"))
+               goto cleanup;
+
+       if (cg_read_strcmp(cg_test_b, "cgroup.events", "populated 0\n"))
+               goto cleanup;
+
+       if (cg_read_strcmp(cg_test_c, "cgroup.events", "populated 0\n"))
+               goto cleanup;
+
+       if (cg_read_strcmp(cg_test_d, "cgroup.events", "populated 0\n"))
+               goto cleanup;
+
+       ret = KSFT_PASS;
+
+cleanup:
+       if (cg_test_d)
+               cg_destroy(cg_test_d);
+       if (cg_test_c)
+               cg_destroy(cg_test_c);
+       if (cg_test_b)
+               cg_destroy(cg_test_b);
+       if (cg_test_a)
+               cg_destroy(cg_test_a);
+       free(cg_test_d);
+       free(cg_test_c);
+       free(cg_test_b);
+       free(cg_test_a);
+       return ret;
+}
+
+/*
+ * A (domain threaded) - B (threaded) - C (domain)
+ *
+ * test that C can't be used until it is turned into a
+ * threaded cgroup.  "cgroup.type" file will report "domain (invalid)" in
+ * these cases. Operations which fail due to invalid topology use
+ * EOPNOTSUPP as the errno.
+ */
+static int test_cgcore_invalid_domain(const char *root)
+{
+       int ret = KSFT_FAIL;
+       char *grandparent = NULL, *parent = NULL, *child = NULL;
+
+       grandparent = cg_name(root, "cg_test_grandparent");
+       parent = cg_name(root, "cg_test_grandparent/cg_test_parent");
+       child = cg_name(root, "cg_test_grandparent/cg_test_parent/cg_test_child");
+       if (!parent || !child || !grandparent)
+               goto cleanup;
+
+       if (cg_create(grandparent))
+               goto cleanup;
+
+       if (cg_create(parent))
+               goto cleanup;
+
+       if (cg_create(child))
+               goto cleanup;
+
+       if (cg_write(parent, "cgroup.type", "threaded"))
+               goto cleanup;
+
+       if (cg_read_strcmp(child, "cgroup.type", "domain invalid\n"))
+               goto cleanup;
+
+       if (!cg_enter_current(child))
+               goto cleanup;
+
+       if (errno != EOPNOTSUPP)
+               goto cleanup;
+
+       ret = KSFT_PASS;
+
+cleanup:
+       cg_enter_current(root);
+       if (child)
+               cg_destroy(child);
+       if (parent)
+               cg_destroy(parent);
+       if (grandparent)
+               cg_destroy(grandparent);
+       free(child);
+       free(parent);
+       free(grandparent);
+       return ret;
+}
+
+/*
+ * Test that when a child becomes threaded
+ * the parent type becomes domain threaded.
+ */
+static int test_cgcore_parent_becomes_threaded(const char *root)
+{
+       int ret = KSFT_FAIL;
+       char *parent = NULL, *child = NULL;
+
+       parent = cg_name(root, "cg_test_parent");
+       child = cg_name(root, "cg_test_parent/cg_test_child");
+       if (!parent || !child)
+               goto cleanup;
+
+       if (cg_create(parent))
+               goto cleanup;
+
+       if (cg_create(child))
+               goto cleanup;
+
+       if (cg_write(child, "cgroup.type", "threaded"))
+               goto cleanup;
+
+       if (cg_read_strcmp(parent, "cgroup.type", "domain threaded\n"))
+               goto cleanup;
+
+       ret = KSFT_PASS;
+
+cleanup:
+       if (child)
+               cg_destroy(child);
+       if (parent)
+               cg_destroy(parent);
+       free(child);
+       free(parent);
+       return ret;
+
+}
+
+/*
+ * Test that there's no internal process constrain on threaded cgroups.
+ * You can add threads/processes on a parent with a controller enabled.
+ */
+static int test_cgcore_no_internal_process_constraint_on_threads(const char *root)
+{
+       int ret = KSFT_FAIL;
+       char *parent = NULL, *child = NULL;
+
+       if (cg_read_strstr(root, "cgroup.controllers", "cpu") ||
+           cg_read_strstr(root, "cgroup.subtree_control", "cpu")) {
+               ret = KSFT_SKIP;
+               goto cleanup;
+       }
+
+       parent = cg_name(root, "cg_test_parent");
+       child = cg_name(root, "cg_test_parent/cg_test_child");
+       if (!parent || !child)
+               goto cleanup;
+
+       if (cg_create(parent))
+               goto cleanup;
+
+       if (cg_create(child))
+               goto cleanup;
+
+       if (cg_write(parent, "cgroup.type", "threaded"))
+               goto cleanup;
+
+       if (cg_write(child, "cgroup.type", "threaded"))
+               goto cleanup;
+
+       if (cg_write(parent, "cgroup.subtree_control", "+cpu"))
+               goto cleanup;
+
+       if (cg_enter_current(parent))
+               goto cleanup;
+
+       ret = KSFT_PASS;
+
+cleanup:
+       cg_enter_current(root);
+       cg_enter_current(root);
+       if (child)
+               cg_destroy(child);
+       if (parent)
+               cg_destroy(parent);
+       free(child);
+       free(parent);
+       return ret;
+}
+
+/*
+ * Test that you can't enable a controller on a child if it's not enabled
+ * on the parent.
+ */
+static int test_cgcore_top_down_constraint_enable(const char *root)
+{
+       int ret = KSFT_FAIL;
+       char *parent = NULL, *child = NULL;
+
+       parent = cg_name(root, "cg_test_parent");
+       child = cg_name(root, "cg_test_parent/cg_test_child");
+       if (!parent || !child)
+               goto cleanup;
+
+       if (cg_create(parent))
+               goto cleanup;
+
+       if (cg_create(child))
+               goto cleanup;
+
+       if (!cg_write(child, "cgroup.subtree_control", "+memory"))
+               goto cleanup;
+
+       ret = KSFT_PASS;
+
+cleanup:
+       if (child)
+               cg_destroy(child);
+       if (parent)
+               cg_destroy(parent);
+       free(child);
+       free(parent);
+       return ret;
+}
+
+/*
+ * Test that you can't disable a controller on a parent
+ * if it's enabled in a child.
+ */
+static int test_cgcore_top_down_constraint_disable(const char *root)
+{
+       int ret = KSFT_FAIL;
+       char *parent = NULL, *child = NULL;
+
+       parent = cg_name(root, "cg_test_parent");
+       child = cg_name(root, "cg_test_parent/cg_test_child");
+       if (!parent || !child)
+               goto cleanup;
+
+       if (cg_create(parent))
+               goto cleanup;
+
+       if (cg_create(child))
+               goto cleanup;
+
+       if (cg_write(parent, "cgroup.subtree_control", "+memory"))
+               goto cleanup;
+
+       if (cg_write(child, "cgroup.subtree_control", "+memory"))
+               goto cleanup;
+
+       if (!cg_write(parent, "cgroup.subtree_control", "-memory"))
+               goto cleanup;
+
+       ret = KSFT_PASS;
+
+cleanup:
+       if (child)
+               cg_destroy(child);
+       if (parent)
+               cg_destroy(parent);
+       free(child);
+       free(parent);
+       return ret;
+}
+
+/*
+ * Test internal process constraint.
+ * You can't add a pid to a domain parent if a controller is enabled.
+ */
+static int test_cgcore_internal_process_constraint(const char *root)
+{
+       int ret = KSFT_FAIL;
+       char *parent = NULL, *child = NULL;
+
+       parent = cg_name(root, "cg_test_parent");
+       child = cg_name(root, "cg_test_parent/cg_test_child");
+       if (!parent || !child)
+               goto cleanup;
+
+       if (cg_create(parent))
+               goto cleanup;
+
+       if (cg_create(child))
+               goto cleanup;
+
+       if (cg_write(parent, "cgroup.subtree_control", "+memory"))
+               goto cleanup;
+
+       if (!cg_enter_current(parent))
+               goto cleanup;
+
+       ret = KSFT_PASS;
+
+cleanup:
+       if (child)
+               cg_destroy(child);
+       if (parent)
+               cg_destroy(parent);
+       free(child);
+       free(parent);
+       return ret;
+}
+
+#define T(x) { x, #x }
+struct corecg_test {
+       int (*fn)(const char *root);
+       const char *name;
+} tests[] = {
+       T(test_cgcore_internal_process_constraint),
+       T(test_cgcore_top_down_constraint_enable),
+       T(test_cgcore_top_down_constraint_disable),
+       T(test_cgcore_no_internal_process_constraint_on_threads),
+       T(test_cgcore_parent_becomes_threaded),
+       T(test_cgcore_invalid_domain),
+       T(test_cgcore_populated),
+};
+#undef T
+
+int main(int argc, char *argv[])
+{
+       char root[PATH_MAX];
+       int i, ret = EXIT_SUCCESS;
+
+       if (cg_find_unified_root(root, sizeof(root)))
+               ksft_exit_skip("cgroup v2 isn't mounted\n");
+       for (i = 0; i < ARRAY_SIZE(tests); i++) {
+               switch (tests[i].fn(root)) {
+               case KSFT_PASS:
+                       ksft_test_result_pass("%s\n", tests[i].name);
+                       break;
+               case KSFT_SKIP:
+                       ksft_test_result_skip("%s\n", tests[i].name);
+                       break;
+               default:
+                       ret = EXIT_FAILURE;
+                       ksft_test_result_fail("%s\n", tests[i].name);
+                       break;
+               }
+       }
+
+       return ret;
+}
index b01924c..07db5ab 100644 (file)
@@ -4,3 +4,6 @@ CONFIG_FUNCTION_PROFILER=y
 CONFIG_TRACER_SNAPSHOT=y
 CONFIG_STACK_TRACER=y
 CONFIG_HIST_TRIGGERS=y
+CONFIG_PREEMPT_TRACER=y
+CONFIG_IRQSOFF_TRACER=y
+CONFIG_PREEMPTIRQ_DELAY_TEST=m
index a000256..1ad70cd 100644 (file)
@@ -9,28 +9,22 @@ echo > kprobe_events
 
 case `uname -m` in
 x86_64)
-  ARG2=%si
-  OFFS=8
+  ARG1=%di
 ;;
 i[3456]86)
-  ARG2=%cx
-  OFFS=4
+  ARG1=%ax
 ;;
 aarch64)
-  ARG2=%x1
-  OFFS=8
+  ARG1=%x0
 ;;
 arm*)
-  ARG2=%r1
-  OFFS=4
+  ARG1=%r0
 ;;
 ppc64*)
-  ARG2=%r4
-  OFFS=8
+  ARG1=%r3
 ;;
 ppc*)
-  ARG2=%r4
-  OFFS=4
+  ARG1=%r3
 ;;
 *)
   echo "Please implement other architecture here"
@@ -38,17 +32,17 @@ ppc*)
 esac
 
 : "Test get argument (1)"
-echo "p:testprobe create_trace_kprobe arg1=+0(+0(${ARG2})):string" > kprobe_events
+echo "p:testprobe tracefs_create_dir arg1=+0(${ARG1}):string" > kprobe_events
 echo 1 > events/kprobes/testprobe/enable
-! echo test >> kprobe_events
-tail -n 1 trace | grep -qe "testprobe.* arg1=\"test\""
+echo "p:test _do_fork" >> kprobe_events
+grep -qe "testprobe.* arg1=\"test\"" trace
 
 echo 0 > events/kprobes/testprobe/enable
 : "Test get argument (2)"
-echo "p:testprobe create_trace_kprobe arg1=+0(+0(${ARG2})):string arg2=+0(+${OFFS}(${ARG2})):string" > kprobe_events
+echo "p:testprobe tracefs_create_dir arg1=+0(${ARG1}):string arg2=+0(${ARG1}):string" > kprobe_events
 echo 1 > events/kprobes/testprobe/enable
-! echo test1 test2 >> kprobe_events
-tail -n 1 trace | grep -qe "testprobe.* arg1=\"test1\" arg2=\"test2\""
+echo "p:test _do_fork" >> kprobe_events
+grep -qe "testprobe.* arg1=\"test\" arg2=\"test\"" trace
 
 echo 0 > events/enable
 echo > kprobe_events
index 4fda01a..519d276 100644 (file)
@@ -4,7 +4,7 @@
 
 [ -f kprobe_events ] || exit_unsupported # this is configurable
 
-TARGET_FUNC=create_trace_kprobe
+TARGET_FUNC=tracefs_create_dir
 
 dec_addr() { # hexaddr
   printf "%d" "0x"`echo $1 | tail -c 8`
diff --git a/tools/testing/selftests/ftrace/test.d/preemptirq/irqsoff_tracer.tc b/tools/testing/selftests/ftrace/test.d/preemptirq/irqsoff_tracer.tc
new file mode 100644 (file)
index 0000000..cbd1743
--- /dev/null
@@ -0,0 +1,73 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0
+# description: test for the preemptirqsoff tracer
+
+MOD=preemptirq_delay_test
+
+fail() {
+    reset_tracer
+    rmmod $MOD || true
+    exit_fail
+}
+
+unsup() { #msg
+    reset_tracer
+    rmmod $MOD || true
+    echo $1
+    exit_unsupported
+}
+
+modprobe $MOD || unsup "$MOD module not available"
+rmmod $MOD
+
+grep -q "preemptoff" available_tracers || unsup "preemptoff tracer not enabled"
+grep -q "irqsoff" available_tracers || unsup "irqsoff tracer not enabled"
+
+reset_tracer
+
+# Simulate preemptoff section for half a second couple of times
+echo preemptoff > current_tracer
+sleep 1
+modprobe $MOD test_mode=preempt delay=500000 || fail
+rmmod $MOD || fail
+modprobe $MOD test_mode=preempt delay=500000 || fail
+rmmod $MOD || fail
+modprobe $MOD test_mode=preempt delay=500000 || fail
+rmmod $MOD || fail
+
+cat trace
+
+# Confirm which tracer
+grep -q "tracer: preemptoff" trace || fail
+
+# Check the end of the section
+egrep -q "5.....us : <stack trace>" trace || fail
+
+# Check for 500ms of latency
+egrep -q "latency: 5..... us" trace || fail
+
+reset_tracer
+
+# Simulate irqsoff section for half a second couple of times
+echo irqsoff > current_tracer
+sleep 1
+modprobe $MOD test_mode=irq delay=500000 || fail
+rmmod $MOD || fail
+modprobe $MOD test_mode=irq delay=500000 || fail
+rmmod $MOD || fail
+modprobe $MOD test_mode=irq delay=500000 || fail
+rmmod $MOD || fail
+
+cat trace
+
+# Confirm which tracer
+grep -q "tracer: irqsoff" trace || fail
+
+# Check the end of the section
+egrep -q "5.....us : <stack trace>" trace || fail
+
+# Check for 500ms of latency
+egrep -q "latency: 5..... us" trace || fail
+
+reset_tracer
+exit 0
index dd0e516..03b0f55 100644 (file)
@@ -11,13 +11,16 @@ TEST_GEN_PROGS_x86_64 += sync_regs_test
 TEST_GEN_PROGS_x86_64 += vmx_tsc_adjust_test
 TEST_GEN_PROGS_x86_64 += cr4_cpuid_sync_test
 TEST_GEN_PROGS_x86_64 += state_test
+TEST_GEN_PROGS_x86_64 += dirty_log_test
 
 TEST_GEN_PROGS += $(TEST_GEN_PROGS_$(UNAME_M))
 LIBKVM += $(LIBKVM_$(UNAME_M))
 
 INSTALL_HDR_PATH = $(top_srcdir)/usr
 LINUX_HDR_PATH = $(INSTALL_HDR_PATH)/include/
-CFLAGS += -O2 -g -std=gnu99 -I$(LINUX_HDR_PATH) -Iinclude -I$(<D) -I..
+LINUX_TOOL_INCLUDE = $(top_srcdir)tools/include
+CFLAGS += -O2 -g -std=gnu99 -I$(LINUX_TOOL_INCLUDE) -I$(LINUX_HDR_PATH) -Iinclude -I$(<D) -I..
+LDFLAGS += -lpthread
 
 # After inclusion, $(OUTPUT) is defined and
 # $(TEST_GEN_PROGS) starts with $(OUTPUT)/
index 8346b33..11ec358 100644 (file)
 #define X86_FEATURE_OSXSAVE    (1<<27)
 #define VCPU_ID                        1
 
-enum {
-       GUEST_UPDATE_CR4 = 0x1000,
-       GUEST_FAILED,
-       GUEST_DONE,
-};
-
-static void exit_to_hv(uint16_t port)
-{
-       __asm__ __volatile__("in %[port], %%al"
-                            :
-                            : [port]"d"(port)
-                            : "rax");
-}
-
 static inline bool cr4_cpuid_is_sync(void)
 {
        int func, subfunc;
@@ -64,17 +50,15 @@ static void guest_code(void)
        set_cr4(cr4);
 
        /* verify CR4.OSXSAVE == CPUID.OSXSAVE */
-       if (!cr4_cpuid_is_sync())
-               exit_to_hv(GUEST_FAILED);
+       GUEST_ASSERT(cr4_cpuid_is_sync());
 
        /* notify hypervisor to change CR4 */
-       exit_to_hv(GUEST_UPDATE_CR4);
+       GUEST_SYNC(0);
 
        /* check again */
-       if (!cr4_cpuid_is_sync())
-               exit_to_hv(GUEST_FAILED);
+       GUEST_ASSERT(cr4_cpuid_is_sync());
 
-       exit_to_hv(GUEST_DONE);
+       GUEST_DONE();
 }
 
 int main(int argc, char *argv[])
@@ -95,7 +79,7 @@ int main(int argc, char *argv[])
        setbuf(stdout, NULL);
 
        /* Create VM */
-       vm = vm_create_default(VCPU_ID, guest_code);
+       vm = vm_create_default(VCPU_ID, 0, guest_code);
        vcpu_set_cpuid(vm, VCPU_ID, kvm_get_supported_cpuid());
        run = vcpu_state(vm, VCPU_ID);
 
@@ -104,16 +88,16 @@ int main(int argc, char *argv[])
 
                if (run->exit_reason == KVM_EXIT_IO) {
                        switch (run->io.port) {
-                       case GUEST_UPDATE_CR4:
+                       case GUEST_PORT_SYNC:
                                /* emulate hypervisor clearing CR4.OSXSAVE */
                                vcpu_sregs_get(vm, VCPU_ID, &sregs);
                                sregs.cr4 &= ~X86_CR4_OSXSAVE;
                                vcpu_sregs_set(vm, VCPU_ID, &sregs);
                                break;
-                       case GUEST_FAILED:
+                       case GUEST_PORT_ABORT:
                                TEST_ASSERT(false, "Guest CR4 bit (OSXSAVE) unsynchronized with CPUID bit.");
                                break;
-                       case GUEST_DONE:
+                       case GUEST_PORT_DONE:
                                goto done;
                        default:
                                TEST_ASSERT(false, "Unknown port 0x%x.",
diff --git a/tools/testing/selftests/kvm/dirty_log_test.c b/tools/testing/selftests/kvm/dirty_log_test.c
new file mode 100644 (file)
index 0000000..0c2cdc1
--- /dev/null
@@ -0,0 +1,308 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * KVM dirty page logging test
+ *
+ * Copyright (C) 2018, Red Hat, Inc.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <time.h>
+#include <pthread.h>
+#include <linux/bitmap.h>
+#include <linux/bitops.h>
+
+#include "test_util.h"
+#include "kvm_util.h"
+
+#define  DEBUG                 printf
+
+#define  VCPU_ID                        1
+/* The memory slot index to track dirty pages */
+#define  TEST_MEM_SLOT_INDEX            1
+/*
+ * GPA offset of the testing memory slot. Must be bigger than the
+ * default vm mem slot, which is DEFAULT_GUEST_PHY_PAGES.
+ */
+#define  TEST_MEM_OFFSET                (1ULL << 30) /* 1G */
+/* Size of the testing memory slot */
+#define  TEST_MEM_PAGES                 (1ULL << 18) /* 1G for 4K pages */
+/* How many pages to dirty for each guest loop */
+#define  TEST_PAGES_PER_LOOP            1024
+/* How many host loops to run (one KVM_GET_DIRTY_LOG for each loop) */
+#define  TEST_HOST_LOOP_N               32
+/* Interval for each host loop (ms) */
+#define  TEST_HOST_LOOP_INTERVAL        10
+
+/*
+ * Guest variables.  We use these variables to share data between host
+ * and guest.  There are two copies of the variables, one in host memory
+ * (which is unused) and one in guest memory.  When the host wants to
+ * access these variables, it needs to call addr_gva2hva() to access the
+ * guest copy.
+ */
+uint64_t guest_random_array[TEST_PAGES_PER_LOOP];
+uint64_t guest_iteration;
+uint64_t guest_page_size;
+
+/*
+ * Writes to the first byte of a random page within the testing memory
+ * region continuously.
+ */
+void guest_code(void)
+{
+       int i = 0;
+       uint64_t volatile *array = guest_random_array;
+       uint64_t volatile *guest_addr;
+
+       while (true) {
+               for (i = 0; i < TEST_PAGES_PER_LOOP; i++) {
+                       /*
+                        * Write to the first 8 bytes of a random page
+                        * on the testing memory region.
+                        */
+                       guest_addr = (uint64_t *)
+                           (TEST_MEM_OFFSET +
+                            (array[i] % TEST_MEM_PAGES) * guest_page_size);
+                       *guest_addr = guest_iteration;
+               }
+               /* Tell the host that we need more random numbers */
+               GUEST_SYNC(1);
+       }
+}
+
+/*
+ * Host variables.  These variables should only be used by the host
+ * rather than the guest.
+ */
+bool host_quit;
+
+/* Points to the test VM memory region on which we track dirty logs */
+void *host_test_mem;
+
+/* For statistics only */
+uint64_t host_dirty_count;
+uint64_t host_clear_count;
+uint64_t host_track_next_count;
+
+/*
+ * We use this bitmap to track some pages that should have its dirty
+ * bit set in the _next_ iteration.  For example, if we detected the
+ * page value changed to current iteration but at the same time the
+ * page bit is cleared in the latest bitmap, then the system must
+ * report that write in the next get dirty log call.
+ */
+unsigned long *host_bmap_track;
+
+void generate_random_array(uint64_t *guest_array, uint64_t size)
+{
+       uint64_t i;
+
+       for (i = 0; i < size; i++) {
+               guest_array[i] = random();
+       }
+}
+
+void *vcpu_worker(void *data)
+{
+       int ret;
+       uint64_t loops, *guest_array, pages_count = 0;
+       struct kvm_vm *vm = data;
+       struct kvm_run *run;
+       struct guest_args args;
+
+       run = vcpu_state(vm, VCPU_ID);
+
+       /* Retrieve the guest random array pointer and cache it */
+       guest_array = addr_gva2hva(vm, (vm_vaddr_t)guest_random_array);
+
+       DEBUG("VCPU starts\n");
+
+       generate_random_array(guest_array, TEST_PAGES_PER_LOOP);
+
+       while (!READ_ONCE(host_quit)) {
+               /* Let the guest to dirty these random pages */
+               ret = _vcpu_run(vm, VCPU_ID);
+               guest_args_read(vm, VCPU_ID, &args);
+               if (run->exit_reason == KVM_EXIT_IO &&
+                   args.port == GUEST_PORT_SYNC) {
+                       pages_count += TEST_PAGES_PER_LOOP;
+                       generate_random_array(guest_array, TEST_PAGES_PER_LOOP);
+               } else {
+                       TEST_ASSERT(false,
+                                   "Invalid guest sync status: "
+                                   "exit_reason=%s\n",
+                                   exit_reason_str(run->exit_reason));
+               }
+       }
+
+       DEBUG("VCPU exits, dirtied %"PRIu64" pages\n", pages_count);
+
+       return NULL;
+}
+
+void vm_dirty_log_verify(unsigned long *bmap, uint64_t iteration)
+{
+       uint64_t page;
+       uint64_t volatile *value_ptr;
+
+       for (page = 0; page < TEST_MEM_PAGES; page++) {
+               value_ptr = host_test_mem + page * getpagesize();
+
+               /* If this is a special page that we were tracking... */
+               if (test_and_clear_bit(page, host_bmap_track)) {
+                       host_track_next_count++;
+                       TEST_ASSERT(test_bit(page, bmap),
+                                   "Page %"PRIu64" should have its dirty bit "
+                                   "set in this iteration but it is missing",
+                                   page);
+               }
+
+               if (test_bit(page, bmap)) {
+                       host_dirty_count++;
+                       /*
+                        * If the bit is set, the value written onto
+                        * the corresponding page should be either the
+                        * previous iteration number or the current one.
+                        */
+                       TEST_ASSERT(*value_ptr == iteration ||
+                                   *value_ptr == iteration - 1,
+                                   "Set page %"PRIu64" value %"PRIu64
+                                   " incorrect (iteration=%"PRIu64")",
+                                   page, *value_ptr, iteration);
+               } else {
+                       host_clear_count++;
+                       /*
+                        * If cleared, the value written can be any
+                        * value smaller or equals to the iteration
+                        * number.  Note that the value can be exactly
+                        * (iteration-1) if that write can happen
+                        * like this:
+                        *
+                        * (1) increase loop count to "iteration-1"
+                        * (2) write to page P happens (with value
+                        *     "iteration-1")
+                        * (3) get dirty log for "iteration-1"; we'll
+                        *     see that page P bit is set (dirtied),
+                        *     and not set the bit in host_bmap_track
+                        * (4) increase loop count to "iteration"
+                        *     (which is current iteration)
+                        * (5) get dirty log for current iteration,
+                        *     we'll see that page P is cleared, with
+                        *     value "iteration-1".
+                        */
+                       TEST_ASSERT(*value_ptr <= iteration,
+                                   "Clear page %"PRIu64" value %"PRIu64
+                                   " incorrect (iteration=%"PRIu64")",
+                                   page, *value_ptr, iteration);
+                       if (*value_ptr == iteration) {
+                               /*
+                                * This page is _just_ modified; it
+                                * should report its dirtyness in the
+                                * next run
+                                */
+                               set_bit(page, host_bmap_track);
+                       }
+               }
+       }
+}
+
+void help(char *name)
+{
+       puts("");
+       printf("usage: %s [-i iterations] [-I interval] [-h]\n", name);
+       puts("");
+       printf(" -i: specify iteration counts (default: %"PRIu64")\n",
+              TEST_HOST_LOOP_N);
+       printf(" -I: specify interval in ms (default: %"PRIu64" ms)\n",
+              TEST_HOST_LOOP_INTERVAL);
+       puts("");
+       exit(0);
+}
+
+int main(int argc, char *argv[])
+{
+       pthread_t vcpu_thread;
+       struct kvm_vm *vm;
+       uint64_t volatile *psize, *iteration;
+       unsigned long *bmap, iterations = TEST_HOST_LOOP_N,
+           interval = TEST_HOST_LOOP_INTERVAL;
+       int opt;
+
+       while ((opt = getopt(argc, argv, "hi:I:")) != -1) {
+               switch (opt) {
+               case 'i':
+                       iterations = strtol(optarg, NULL, 10);
+                       break;
+               case 'I':
+                       interval = strtol(optarg, NULL, 10);
+                       break;
+               case 'h':
+               default:
+                       help(argv[0]);
+                       break;
+               }
+       }
+
+       TEST_ASSERT(iterations > 2, "Iteration must be bigger than zero\n");
+       TEST_ASSERT(interval > 0, "Interval must be bigger than zero");
+
+       DEBUG("Test iterations: %"PRIu64", interval: %"PRIu64" (ms)\n",
+             iterations, interval);
+
+       srandom(time(0));
+
+       bmap = bitmap_alloc(TEST_MEM_PAGES);
+       host_bmap_track = bitmap_alloc(TEST_MEM_PAGES);
+
+       vm = vm_create_default(VCPU_ID, TEST_MEM_PAGES, guest_code);
+
+       /* Add an extra memory slot for testing dirty logging */
+       vm_userspace_mem_region_add(vm, VM_MEM_SRC_ANONYMOUS,
+                                   TEST_MEM_OFFSET,
+                                   TEST_MEM_SLOT_INDEX,
+                                   TEST_MEM_PAGES,
+                                   KVM_MEM_LOG_DIRTY_PAGES);
+       /* Cache the HVA pointer of the region */
+       host_test_mem = addr_gpa2hva(vm, (vm_paddr_t)TEST_MEM_OFFSET);
+
+       /* Do 1:1 mapping for the dirty track memory slot */
+       virt_map(vm, TEST_MEM_OFFSET, TEST_MEM_OFFSET,
+                TEST_MEM_PAGES * getpagesize(), 0);
+
+       vcpu_set_cpuid(vm, VCPU_ID, kvm_get_supported_cpuid());
+
+       /* Tell the guest about the page size on the system */
+       psize = addr_gva2hva(vm, (vm_vaddr_t)&guest_page_size);
+       *psize = getpagesize();
+
+       /* Start the iterations */
+       iteration = addr_gva2hva(vm, (vm_vaddr_t)&guest_iteration);
+       *iteration = 1;
+
+       /* Start dirtying pages */
+       pthread_create(&vcpu_thread, NULL, vcpu_worker, vm);
+
+       while (*iteration < iterations) {
+               /* Give the vcpu thread some time to dirty some pages */
+               usleep(interval * 1000);
+               kvm_vm_get_dirty_log(vm, TEST_MEM_SLOT_INDEX, bmap);
+               vm_dirty_log_verify(bmap, *iteration);
+               (*iteration)++;
+       }
+
+       /* Tell the vcpu thread to quit */
+       host_quit = true;
+       pthread_join(vcpu_thread, NULL);
+
+       DEBUG("Total bits checked: dirty (%"PRIu64"), clear (%"PRIu64"), "
+             "track_next (%"PRIu64")\n", host_dirty_count, host_clear_count,
+             host_track_next_count);
+
+       free(bmap);
+       free(host_bmap_track);
+       kvm_vm_free(vm);
+
+       return 0;
+}
index d32632f..bb5a25f 100644 (file)
@@ -55,6 +55,7 @@ struct kvm_vm *vm_create(enum vm_guest_mode mode, uint64_t phy_pages, int perm);
 void kvm_vm_free(struct kvm_vm *vmp);
 void kvm_vm_restart(struct kvm_vm *vmp, int perm);
 void kvm_vm_release(struct kvm_vm *vmp);
+void kvm_vm_get_dirty_log(struct kvm_vm *vm, int slot, void *log);
 
 int kvm_memcmp_hva_gva(void *hva,
        struct kvm_vm *vm, const vm_vaddr_t gva, size_t len);
@@ -80,6 +81,8 @@ void vm_mem_region_set_flags(struct kvm_vm *vm, uint32_t slot, uint32_t flags);
 void vm_vcpu_add(struct kvm_vm *vm, uint32_t vcpuid, int pgd_memslot, int gdt_memslot);
 vm_vaddr_t vm_vaddr_alloc(struct kvm_vm *vm, size_t sz, vm_vaddr_t vaddr_min,
        uint32_t data_memslot, uint32_t pgd_memslot);
+void virt_map(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr,
+             size_t size, uint32_t pgd_memslot);
 void *addr_gpa2hva(struct kvm_vm *vm, vm_paddr_t gpa);
 void *addr_gva2hva(struct kvm_vm *vm, vm_vaddr_t gva);
 vm_paddr_t addr_hva2gpa(struct kvm_vm *vm, void *hva);
@@ -127,7 +130,8 @@ kvm_get_supported_cpuid_entry(uint32_t function)
        return kvm_get_supported_cpuid_index(function, 0);
 }
 
-struct kvm_vm *vm_create_default(uint32_t vcpuid, void *guest_code);
+struct kvm_vm *vm_create_default(uint32_t vcpuid, uint64_t extra_mem_size,
+                                void *guest_code);
 void vm_vcpu_add_default(struct kvm_vm *vm, uint32_t vcpuid, void *guest_code);
 
 typedef void (*vmx_guest_code_t)(vm_vaddr_t vmxon_vaddr,
@@ -144,4 +148,43 @@ allocate_kvm_dirty_log(struct kvm_userspace_memory_region *region);
 
 int vm_create_device(struct kvm_vm *vm, struct kvm_create_device *cd);
 
+#define GUEST_PORT_SYNC         0x1000
+#define GUEST_PORT_ABORT        0x1001
+#define GUEST_PORT_DONE         0x1002
+
+static inline void __exit_to_l0(uint16_t port, uint64_t arg0, uint64_t arg1)
+{
+       __asm__ __volatile__("in %[port], %%al"
+                            :
+                            : [port]"d"(port), "D"(arg0), "S"(arg1)
+                            : "rax");
+}
+
+/*
+ * Allows to pass three arguments to the host: port is 16bit wide,
+ * arg0 & arg1 are 64bit wide
+ */
+#define GUEST_SYNC_ARGS(_port, _arg0, _arg1) \
+       __exit_to_l0(_port, (uint64_t) (_arg0), (uint64_t) (_arg1))
+
+#define GUEST_ASSERT(_condition) do {                          \
+               if (!(_condition))                              \
+                       GUEST_SYNC_ARGS(GUEST_PORT_ABORT,       \
+                                       "Failed guest assert: " \
+                                       #_condition, __LINE__); \
+       } while (0)
+
+#define GUEST_SYNC(stage)  GUEST_SYNC_ARGS(GUEST_PORT_SYNC, "hello", stage)
+
+#define GUEST_DONE()  GUEST_SYNC_ARGS(GUEST_PORT_DONE, 0, 0)
+
+struct guest_args {
+       uint64_t arg0;
+       uint64_t arg1;
+       uint16_t port;
+} __attribute__ ((packed));
+
+void guest_args_read(struct kvm_vm *vm, uint32_t vcpu_id,
+                    struct guest_args *args);
+
 #endif /* SELFTEST_KVM_UTIL_H */
index ac53730..73c3933 100644 (file)
@@ -28,8 +28,6 @@ int test_seq_read(const char *path, char **bufp, size_t *sizep);
 void test_assert(bool exp, const char *exp_str,
                 const char *file, unsigned int line, const char *fmt, ...);
 
-#define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0]))
-
 #define TEST_ASSERT(e, fmt, ...) \
        test_assert((e), #e, __FILE__, __LINE__, fmt, ##__VA_ARGS__)
 
index 643309d..e9ba389 100644 (file)
@@ -14,6 +14,7 @@
 #include <sys/mman.h>
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <linux/kernel.h>
 
 #define KVM_DEV_PATH "/dev/kvm"
 
@@ -168,6 +169,16 @@ void kvm_vm_restart(struct kvm_vm *vmp, int perm)
        }
 }
 
+void kvm_vm_get_dirty_log(struct kvm_vm *vm, int slot, void *log)
+{
+       struct kvm_dirty_log args = { .dirty_bitmap = log, .slot = slot };
+       int ret;
+
+       ret = ioctl(vm->fd, KVM_GET_DIRTY_LOG, &args);
+       TEST_ASSERT(ret == 0, "%s: KVM_GET_DIRTY_LOG failed: %s",
+                   strerror(-ret));
+}
+
 /* Userspace Memory Region Find
  *
  * Input Args:
@@ -923,6 +934,39 @@ vm_vaddr_t vm_vaddr_alloc(struct kvm_vm *vm, size_t sz, vm_vaddr_t vaddr_min,
        return vaddr_start;
 }
 
+/*
+ * Map a range of VM virtual address to the VM's physical address
+ *
+ * Input Args:
+ *   vm - Virtual Machine
+ *   vaddr - Virtuall address to map
+ *   paddr - VM Physical Address
+ *   size - The size of the range to map
+ *   pgd_memslot - Memory region slot for new virtual translation tables
+ *
+ * Output Args: None
+ *
+ * Return: None
+ *
+ * Within the VM given by vm, creates a virtual translation for the
+ * page range starting at vaddr to the page range starting at paddr.
+ */
+void virt_map(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr,
+             size_t size, uint32_t pgd_memslot)
+{
+       size_t page_size = vm->page_size;
+       size_t npages = size / page_size;
+
+       TEST_ASSERT(vaddr + size > vaddr, "Vaddr overflow");
+       TEST_ASSERT(paddr + size > paddr, "Paddr overflow");
+
+       while (npages--) {
+               virt_pg_map(vm, vaddr, paddr, pgd_memslot);
+               vaddr += page_size;
+               paddr += page_size;
+       }
+}
+
 /* Address VM Physical to Host Virtual
  *
  * Input Args:
@@ -1536,3 +1580,17 @@ void *addr_gva2hva(struct kvm_vm *vm, vm_vaddr_t gva)
 {
        return addr_gpa2hva(vm, addr_gva2gpa(vm, gva));
 }
+
+void guest_args_read(struct kvm_vm *vm, uint32_t vcpu_id,
+                    struct guest_args *args)
+{
+       struct kvm_run *run = vcpu_state(vm, vcpu_id);
+       struct kvm_regs regs;
+
+       memset(&regs, 0, sizeof(regs));
+       vcpu_regs_get(vm, vcpu_id, &regs);
+
+       args->port = run->io.port;
+       args->arg0 = regs.rdi;
+       args->arg1 = regs.rsi;
+}
index e383452..a3122f1 100644 (file)
@@ -702,6 +702,9 @@ void vcpu_set_cpuid(struct kvm_vm *vm,
  *
  * Input Args:
  *   vcpuid - The id of the single VCPU to add to the VM.
+ *   extra_mem_pages - The size of extra memories to add (this will
+ *                     decide how much extra space we will need to
+ *                     setup the page tables using mem slot 0)
  *   guest_code - The vCPU's entry point
  *
  * Output Args: None
@@ -709,12 +712,23 @@ void vcpu_set_cpuid(struct kvm_vm *vm,
  * Return:
  *   Pointer to opaque structure that describes the created VM.
  */
-struct kvm_vm *vm_create_default(uint32_t vcpuid, void *guest_code)
+struct kvm_vm *vm_create_default(uint32_t vcpuid, uint64_t extra_mem_pages,
+                                void *guest_code)
 {
        struct kvm_vm *vm;
+       /*
+        * For x86 the maximum page table size for a memory region
+        * will be when only 4K pages are used.  In that case the
+        * total extra size for page tables (for extra N pages) will
+        * be: N/512+N/512^2+N/512^3+... which is definitely smaller
+        * than N/512*2.
+        */
+       uint64_t extra_pg_pages = extra_mem_pages / 512 * 2;
 
        /* Create VM */
-       vm = vm_create(VM_MODE_FLAT48PG, DEFAULT_GUEST_PHY_PAGES, O_RDWR);
+       vm = vm_create(VM_MODE_FLAT48PG,
+                      DEFAULT_GUEST_PHY_PAGES + extra_pg_pages,
+                      O_RDWR);
 
        /* Setup guest code */
        kvm_vm_elf_load(vm, program_invocation_name, 0, 0);
index 090fd3f..881419d 100644 (file)
@@ -36,7 +36,7 @@ int main(int argc, char *argv[])
        setbuf(stdout, NULL);
 
        /* Create VM */
-       vm = vm_create_default(VCPU_ID, NULL);
+       vm = vm_create_default(VCPU_ID, 0, NULL);
 
        vcpu_sregs_get(vm, VCPU_ID, &sregs);
        sregs.apic_base = 1 << 10;
index ecabf25..900e3e9 100644 (file)
 #include "vmx.h"
 
 #define VCPU_ID                5
-#define PORT_SYNC      0x1000
-#define PORT_ABORT     0x1001
-#define PORT_DONE      0x1002
-
-static inline void __exit_to_l0(uint16_t port, uint64_t arg0, uint64_t arg1)
-{
-       __asm__ __volatile__("in %[port], %%al"
-                            :
-                            : [port]"d"(port), "D"(arg0), "S"(arg1)
-                            : "rax");
-}
-
-#define exit_to_l0(_port, _arg0, _arg1) \
-       __exit_to_l0(_port, (uint64_t) (_arg0), (uint64_t) (_arg1))
-
-#define GUEST_ASSERT(_condition) do { \
-       if (!(_condition)) \
-               exit_to_l0(PORT_ABORT, "Failed guest assert: " #_condition, __LINE__);\
-} while (0)
-
-#define GUEST_SYNC(stage) \
-       exit_to_l0(PORT_SYNC, "hello", stage);
 
 static bool have_nested_state;
 
@@ -137,7 +115,7 @@ void guest_code(struct vmx_pages *vmx_pages)
        if (vmx_pages)
                l1_guest_code(vmx_pages);
 
-       exit_to_l0(PORT_DONE, 0, 0);
+       GUEST_DONE();
 }
 
 int main(int argc, char *argv[])
@@ -154,7 +132,7 @@ int main(int argc, char *argv[])
        struct kvm_cpuid_entry2 *entry = kvm_get_supported_cpuid_entry(1);
 
        /* Create VM */
-       vm = vm_create_default(VCPU_ID, guest_code);
+       vm = vm_create_default(VCPU_ID, 0, guest_code);
        vcpu_set_cpuid(vm, VCPU_ID, kvm_get_supported_cpuid());
        run = vcpu_state(vm, VCPU_ID);
 
@@ -178,13 +156,13 @@ int main(int argc, char *argv[])
                memset(&regs1, 0, sizeof(regs1));
                vcpu_regs_get(vm, VCPU_ID, &regs1);
                switch (run->io.port) {
-               case PORT_ABORT:
+               case GUEST_PORT_ABORT:
                        TEST_ASSERT(false, "%s at %s:%d", (const char *) regs1.rdi,
                                    __FILE__, regs1.rsi);
                        /* NOT REACHED */
-               case PORT_SYNC:
+               case GUEST_PORT_SYNC:
                        break;
-               case PORT_DONE:
+               case GUEST_PORT_DONE:
                        goto done;
                default:
                        TEST_ASSERT(false, "Unknown port 0x%x.", run->io.port);
index eae1ece..213343e 100644 (file)
 #include "x86.h"
 
 #define VCPU_ID 5
-#define PORT_HOST_SYNC 0x1000
-
-static void __exit_to_l0(uint16_t port, uint64_t arg0, uint64_t arg1)
-{
-               __asm__ __volatile__("in %[port], %%al"
-                                    :
-                                    : [port]"d"(port), "D"(arg0), "S"(arg1)
-                                    : "rax");
-}
-
-#define exit_to_l0(_port, _arg0, _arg1) \
-        __exit_to_l0(_port, (uint64_t) (_arg0), (uint64_t) (_arg1))
-
-#define GUEST_ASSERT(_condition) do { \
-       if (!(_condition)) \
-               exit_to_l0(PORT_ABORT, "Failed guest assert: " #_condition, 0);\
-} while (0)
 
 void guest_code(void)
 {
        for (;;) {
-               exit_to_l0(PORT_HOST_SYNC, "hello", 0);
+               GUEST_SYNC(0);
                asm volatile ("inc %r11");
        }
 }
@@ -111,7 +94,7 @@ int main(int argc, char *argv[])
        }
 
        /* Create VM */
-       vm = vm_create_default(VCPU_ID, guest_code);
+       vm = vm_create_default(VCPU_ID, 0, guest_code);
 
        run = vcpu_state(vm, VCPU_ID);
 
index fc414c2..49bcc68 100644 (file)
@@ -62,27 +62,12 @@ struct kvm_single_msr {
 /* The virtual machine object. */
 static struct kvm_vm *vm;
 
-#define exit_to_l0(_port, _arg) do_exit_to_l0(_port, (unsigned long) (_arg))
-static void do_exit_to_l0(uint16_t port, unsigned long arg)
-{
-       __asm__ __volatile__("in %[port], %%al"
-               :
-               : [port]"d"(port), "D"(arg)
-               : "rax");
-}
-
-
-#define GUEST_ASSERT(_condition) do {                                       \
-       if (!(_condition))                                                   \
-               exit_to_l0(PORT_ABORT, "Failed guest assert: " #_condition); \
-} while (0)
-
 static void check_ia32_tsc_adjust(int64_t max)
 {
        int64_t adjust;
 
        adjust = rdmsr(MSR_IA32_TSC_ADJUST);
-       exit_to_l0(PORT_REPORT, adjust);
+       GUEST_SYNC(adjust);
        GUEST_ASSERT(adjust <= max);
 }
 
@@ -132,7 +117,7 @@ static void l1_guest_code(struct vmx_pages *vmx_pages)
 
        check_ia32_tsc_adjust(-2 * TSC_ADJUST_VALUE);
 
-       exit_to_l0(PORT_DONE, 0);
+       GUEST_DONE();
 }
 
 void report(int64_t val)
@@ -152,7 +137,7 @@ int main(int argc, char *argv[])
                exit(KSFT_SKIP);
        }
 
-       vm = vm_create_default(VCPU_ID, (void *) l1_guest_code);
+       vm = vm_create_default(VCPU_ID, 0, (void *) l1_guest_code);
        vcpu_set_cpuid(vm, VCPU_ID, kvm_get_supported_cpuid());
 
        /* Allocate VMX pages and shared descriptors (vmx_pages). */
@@ -161,26 +146,26 @@ int main(int argc, char *argv[])
 
        for (;;) {
                volatile struct kvm_run *run = vcpu_state(vm, VCPU_ID);
-               struct kvm_regs regs;
+               struct guest_args args;
 
                vcpu_run(vm, VCPU_ID);
-               vcpu_regs_get(vm, VCPU_ID, &regs);
+               guest_args_read(vm, VCPU_ID, &args);
                TEST_ASSERT(run->exit_reason == KVM_EXIT_IO,
-                           "Got exit_reason other than KVM_EXIT_IO: %u (%s), rip=%lx\n",
+                           "Got exit_reason other than KVM_EXIT_IO: %u (%s)\n",
                            run->exit_reason,
-                           exit_reason_str(run->exit_reason), regs.rip);
+                           exit_reason_str(run->exit_reason));
 
-               switch (run->io.port) {
-               case PORT_ABORT:
-                       TEST_ASSERT(false, "%s", (const char *) regs.rdi);
+               switch (args.port) {
+               case GUEST_PORT_ABORT:
+                       TEST_ASSERT(false, "%s", (const char *) args.arg0);
                        /* NOT REACHED */
-               case PORT_REPORT:
-                       report(regs.rdi);
+               case GUEST_PORT_SYNC:
+                       report(args.arg1);
                        break;
-               case PORT_DONE:
+               case GUEST_PORT_DONE:
                        goto done;
                default:
-                       TEST_ASSERT(false, "Unknown port 0x%x.", run->io.port);
+                       TEST_ASSERT(false, "Unknown port 0x%x.", args.port);
                }
        }
 
index b5d881e..416bd53 100644 (file)
@@ -1,2 +1 @@
 CONFIG_USER_NS=y
-CONFIG_DEVPTS_MULTIPLE_INSTANCES=y
index 74e5912..82121a8 100644 (file)
@@ -9,3 +9,5 @@
 /proc-uptime-001
 /proc-uptime-002
 /read
+/self
+/thread-self
index db310ee..1c12c34 100644 (file)
@@ -1,4 +1,5 @@
 CFLAGS += -Wall -O2 -Wno-unused-function
+CFLAGS += -D_GNU_SOURCE
 
 TEST_GEN_PROGS :=
 TEST_GEN_PROGS += fd-001-lookup
@@ -12,5 +13,7 @@ TEST_GEN_PROGS += proc-self-wchan
 TEST_GEN_PROGS += proc-uptime-001
 TEST_GEN_PROGS += proc-uptime-002
 TEST_GEN_PROGS += read
+TEST_GEN_PROGS += self
+TEST_GEN_PROGS += thread-self
 
 include ../lib.mk
index 4e17816..b7d57ea 100644 (file)
@@ -6,6 +6,18 @@
 #include <stdbool.h>
 #include <stdlib.h>
 #include <string.h>
+#include <unistd.h>
+#include <sys/syscall.h>
+
+static inline pid_t sys_getpid(void)
+{
+       return syscall(SYS_getpid);
+}
+
+static inline pid_t sys_gettid(void)
+{
+       return syscall(SYS_gettid);
+}
 
 static inline bool streq(const char *s1, const char *s2)
 {
diff --git a/tools/testing/selftests/proc/self.c b/tools/testing/selftests/proc/self.c
new file mode 100644 (file)
index 0000000..21c15a1
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright © 2018 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 /proc/self gives correct TGID.
+#undef NDEBUG
+#include <assert.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include "proc.h"
+
+int main(void)
+{
+       char buf1[64], buf2[64];
+       pid_t pid;
+       ssize_t rv;
+
+       pid = sys_getpid();
+       snprintf(buf1, sizeof(buf1), "%u", pid);
+
+       rv = readlink("/proc/self", buf2, sizeof(buf2));
+       assert(rv == strlen(buf1));
+       buf2[rv] = '\0';
+       assert(streq(buf1, buf2));
+
+       return 0;
+}
diff --git a/tools/testing/selftests/proc/thread-self.c b/tools/testing/selftests/proc/thread-self.c
new file mode 100644 (file)
index 0000000..4b23b39
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright © 2018 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 /proc/thread-self gives correct TGID/PID.
+#undef NDEBUG
+#include <assert.h>
+#include <sched.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/wait.h>
+
+#include "proc.h"
+
+int f(void *arg)
+{
+       char buf1[64], buf2[64];
+       pid_t pid, tid;
+       ssize_t rv;
+
+       pid = sys_getpid();
+       tid = sys_gettid();
+       snprintf(buf1, sizeof(buf1), "%u/task/%u", pid, tid);
+
+       rv = readlink("/proc/thread-self", buf2, sizeof(buf2));
+       assert(rv == strlen(buf1));
+       buf2[rv] = '\0';
+       assert(streq(buf1, buf2));
+
+       if (arg)
+               exit(0);
+       return 0;
+}
+
+int main(void)
+{
+       const int PAGE_SIZE = sysconf(_SC_PAGESIZE);
+       pid_t pid;
+       void *stack;
+
+       /* main thread */
+       f((void *)0);
+
+       stack = mmap(NULL, 2 * PAGE_SIZE, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
+       assert(stack != MAP_FAILED);
+       /* side thread */
+       pid = clone(f, stack + PAGE_SIZE, CLONE_THREAD|CLONE_SIGHAND|CLONE_VM, (void *)1);
+       assert(pid > 0);
+       pause();
+
+       return 0;
+}
index f5d7a78..9e03d61 100644 (file)
@@ -1,6 +1,14 @@
 # SPDX-License-Identifier: GPL-2.0
 include ../lib.mk
 
+uname_M := $(shell uname -m 2>/dev/null || echo not)
+ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/x86/ -e s/x86_64/x86/)
+
+TEST_GEN_PROGS := $(OUTPUT)/vdso_test
+ifeq ($(ARCH),x86)
+TEST_GEN_PROGS += $(OUTPUT)/vdso_standalone_test_x86
+endif
+
 ifndef CROSS_COMPILE
 CFLAGS := -std=gnu99
 CFLAGS_vdso_standalone_test_x86 := -nostdlib -fno-asynchronous-unwind-tables -fno-stack-protector
@@ -8,14 +16,11 @@ ifeq ($(CONFIG_X86_32),y)
 LDLIBS += -lgcc_s
 endif
 
-TEST_PROGS := $(OUTPUT)/vdso_test $(OUTPUT)/vdso_standalone_test_x86
-
-all: $(TEST_PROGS)
+all: $(TEST_GEN_PROGS)
 $(OUTPUT)/vdso_test: parse_vdso.c vdso_test.c
 $(OUTPUT)/vdso_standalone_test_x86: vdso_standalone_test_x86.c parse_vdso.c
        $(CC) $(CFLAGS) $(CFLAGS_vdso_standalone_test_x86) \
                vdso_standalone_test_x86.c parse_vdso.c \
                -o $@
 
-EXTRA_CLEAN := $(TEST_PROGS)
 endif
index 2df26bd..eda53f8 100644 (file)
@@ -15,6 +15,8 @@
 #include <sys/auxv.h>
 #include <sys/time.h>
 
+#include "../kselftest.h"
+
 extern void *vdso_sym(const char *version, const char *name);
 extern void vdso_init_from_sysinfo_ehdr(uintptr_t base);
 extern void vdso_init_from_auxv(void *auxv);
@@ -37,7 +39,7 @@ int main(int argc, char **argv)
        unsigned long sysinfo_ehdr = getauxval(AT_SYSINFO_EHDR);
        if (!sysinfo_ehdr) {
                printf("AT_SYSINFO_EHDR is not present!\n");
-               return 0;
+               return KSFT_SKIP;
        }
 
        vdso_init_from_sysinfo_ehdr(getauxval(AT_SYSINFO_EHDR));
@@ -48,7 +50,7 @@ int main(int argc, char **argv)
 
        if (!gtod) {
                printf("Could not find %s\n", name);
-               return 1;
+               return KSFT_SKIP;
        }
 
        struct timeval tv;
@@ -59,6 +61,7 @@ int main(int argc, char **argv)
                       (long long)tv.tv_sec, (long long)tv.tv_usec);
        } else {
                printf("%s failed\n", name);
+               return KSFT_FAIL;
        }
 
        return 0;
index 342c7bc..af5ff83 100644 (file)
@@ -1,6 +1,7 @@
 hugepage-mmap
 hugepage-shm
 map_hugetlb
+map_populate
 thuge-gen
 compaction_test
 mlock2-tests
index fdefa22..9881876 100644 (file)
@@ -12,6 +12,7 @@ TEST_GEN_FILES += gup_benchmark
 TEST_GEN_FILES += hugepage-mmap
 TEST_GEN_FILES += hugepage-shm
 TEST_GEN_FILES += map_hugetlb
+TEST_GEN_FILES += map_populate
 TEST_GEN_FILES += mlock-random-test
 TEST_GEN_FILES += mlock2-tests
 TEST_GEN_FILES += on-fault-limit
diff --git a/tools/testing/selftests/vm/map_populate.c b/tools/testing/selftests/vm/map_populate.c
new file mode 100644 (file)
index 0000000..6b8aeaa
--- /dev/null
@@ -0,0 +1,113 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2018 Dmitry Safonov, Arista Networks
+ *
+ * MAP_POPULATE | MAP_PRIVATE should COW VMA pages.
+ */
+
+#define _GNU_SOURCE
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#ifndef MMAP_SZ
+#define MMAP_SZ                4096
+#endif
+
+#define BUG_ON(condition, description)                                 \
+       do {                                                            \
+               if (condition) {                                        \
+                       fprintf(stderr, "[FAIL]\t%s:%d\t%s:%s\n", __func__, \
+                               __LINE__, (description), strerror(errno)); \
+                       exit(1);                                        \
+               }                                                       \
+       } while (0)
+
+static int parent_f(int sock, unsigned long *smap, int child)
+{
+       int status, ret;
+
+       ret = read(sock, &status, sizeof(int));
+       BUG_ON(ret <= 0, "read(sock)");
+
+       *smap = 0x22222BAD;
+       ret = msync(smap, MMAP_SZ, MS_SYNC);
+       BUG_ON(ret, "msync()");
+
+       ret = write(sock, &status, sizeof(int));
+       BUG_ON(ret <= 0, "write(sock)");
+
+       waitpid(child, &status, 0);
+       BUG_ON(!WIFEXITED(status), "child in unexpected state");
+
+       return WEXITSTATUS(status);
+}
+
+static int child_f(int sock, unsigned long *smap, int fd)
+{
+       int ret, buf = 0;
+
+       smap = mmap(0, MMAP_SZ, PROT_READ | PROT_WRITE,
+                       MAP_PRIVATE | MAP_POPULATE, fd, 0);
+       BUG_ON(smap == MAP_FAILED, "mmap()");
+
+       BUG_ON(*smap != 0xdeadbabe, "MAP_PRIVATE | MAP_POPULATE changed file");
+
+       ret = write(sock, &buf, sizeof(int));
+       BUG_ON(ret <= 0, "write(sock)");
+
+       ret = read(sock, &buf, sizeof(int));
+       BUG_ON(ret <= 0, "read(sock)");
+
+       BUG_ON(*smap == 0x22222BAD, "MAP_POPULATE didn't COW private page");
+       BUG_ON(*smap != 0xdeadbabe, "mapping was corrupted");
+
+       return 0;
+}
+
+int main(int argc, char **argv)
+{
+       int sock[2], child, ret;
+       FILE *ftmp;
+       unsigned long *smap;
+
+       ftmp = tmpfile();
+       BUG_ON(ftmp == 0, "tmpfile()");
+
+       ret = ftruncate(fileno(ftmp), MMAP_SZ);
+       BUG_ON(ret, "ftruncate()");
+
+       smap = mmap(0, MMAP_SZ, PROT_READ | PROT_WRITE,
+                       MAP_SHARED, fileno(ftmp), 0);
+       BUG_ON(smap == MAP_FAILED, "mmap()");
+
+       *smap = 0xdeadbabe;
+       /* Probably unnecessary, but let it be. */
+       ret = msync(smap, MMAP_SZ, MS_SYNC);
+       BUG_ON(ret, "msync()");
+
+       ret = socketpair(PF_LOCAL, SOCK_SEQPACKET, 0, sock);
+       BUG_ON(ret, "socketpair()");
+
+       child = fork();
+       BUG_ON(child == -1, "fork()");
+
+       if (child) {
+               ret = close(sock[0]);
+               BUG_ON(ret, "close()");
+
+               return parent_f(sock[1], smap, child);
+       }
+
+       ret = close(sock[1]);
+       BUG_ON(ret, "close()");
+
+       return child_f(sock[0], smap, fileno(ftmp));
+}
index 88cbe55..584a91a 100755 (executable)
@@ -168,6 +168,17 @@ else
 fi
 
 echo "--------------------"
+echo "running map_populate"
+echo "--------------------"
+./map_populate
+if [ $? -ne 0 ]; then
+       echo "[FAIL]"
+       exitcode=1
+else
+       echo "[PASS]"
+fi
+
+echo "--------------------"
 echo "running mlock2-tests"
 echo "--------------------"
 ./mlock2-tests
index 237a028..748f6a6 100644 (file)
@@ -24,7 +24,7 @@ $(obj)/initramfs_data.o: $(obj)/$(datafile_y) FORCE
 # Generate the initramfs cpio archive
 
 hostprogs-y := gen_init_cpio
-initramfs   := $(CONFIG_SHELL) $(srctree)/scripts/gen_initramfs_list.sh
+initramfs   := $(CONFIG_SHELL) $(srctree)/$(src)/gen_initramfs_list.sh
 ramfs-input := $(if $(filter-out "",$(CONFIG_INITRAMFS_SOURCE)), \
                        $(shell echo $(CONFIG_INITRAMFS_SOURCE)),-d)
 ramfs-args  := \
similarity index 99%
rename from scripts/gen_initramfs_list.sh
rename to usr/gen_initramfs_list.sh
index 10e528b..0aad760 100755 (executable)
@@ -174,7 +174,7 @@ dir_filelist() {
        ${dep_list}header "$1"
 
        srcdir=$(echo "$1" | sed -e 's://*:/:g')
-       dirlist=$(find "${srcdir}" -printf "%p %m %U %G\n" | sort)
+       dirlist=$(find "${srcdir}" -printf "%p %m %U %G\n" | LANG=C sort)
 
        # If $dirlist is only one line, then the directory is empty
        if [  "$(echo "${dirlist}" | wc -l)" -gt 1 ]; then
index b28da79..d07648f 100644 (file)
@@ -30,8 +30,8 @@ __irf_start:
 .incbin __stringify(INITRAMFS_IMAGE)
 __irf_end:
 .section .init.ramfs.info,"a"
-.globl VMLINUX_SYMBOL(__initramfs_size)
-VMLINUX_SYMBOL(__initramfs_size):
+.globl __initramfs_size
+__initramfs_size:
 #ifdef CONFIG_64BIT
        .quad __irf_end - __irf_start
 #else
index bd3d57f..17cecc9 100644 (file)
@@ -295,9 +295,9 @@ static void phys_timer_emulate(struct kvm_vcpu *vcpu)
        struct arch_timer_context *ptimer = vcpu_ptimer(vcpu);
 
        /*
-        * If the timer can fire now we have just raised the IRQ line and we
-        * don't need to have a soft timer scheduled for the future.  If the
-        * timer cannot fire at all, then we also don't need a soft timer.
+        * If the timer can fire now, we don't need to have a soft timer
+        * scheduled for the future.  If the timer cannot fire at all,
+        * then we also don't need a soft timer.
         */
        if (kvm_timer_should_fire(ptimer) || !kvm_timer_irq_can_fire(ptimer)) {
                soft_timer_cancel(&timer->phys_timer, NULL);
@@ -332,10 +332,10 @@ static void kvm_timer_update_state(struct kvm_vcpu *vcpu)
        level = kvm_timer_should_fire(vtimer);
        kvm_timer_update_irq(vcpu, level, vtimer);
 
+       phys_timer_emulate(vcpu);
+
        if (kvm_timer_should_fire(ptimer) != ptimer->irq.level)
                kvm_timer_update_irq(vcpu, !ptimer->irq.level, ptimer);
-
-       phys_timer_emulate(vcpu);
 }
 
 static void vtimer_save_state(struct kvm_vcpu *vcpu)
@@ -487,6 +487,7 @@ void kvm_timer_vcpu_load(struct kvm_vcpu *vcpu)
 {
        struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
        struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
+       struct arch_timer_context *ptimer = vcpu_ptimer(vcpu);
 
        if (unlikely(!timer->enabled))
                return;
@@ -502,6 +503,10 @@ void kvm_timer_vcpu_load(struct kvm_vcpu *vcpu)
 
        /* Set the background timer for the physical timer emulation. */
        phys_timer_emulate(vcpu);
+
+       /* If the timer fired while we weren't running, inject it now */
+       if (kvm_timer_should_fire(ptimer) != ptimer->irq.level)
+               kvm_timer_update_irq(vcpu, !ptimer->irq.level, ptimer);
 }
 
 bool kvm_timer_should_notify_user(struct kvm_vcpu *vcpu)
index 108250e..c92053b 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/kvm.h>
 #include <linux/kvm_irqfd.h>
 #include <linux/irqbypass.h>
+#include <linux/sched/stat.h>
 #include <trace/events/kvm.h>
 #include <kvm/arm_pmu.h>
 #include <kvm/arm_psci.h>
@@ -380,6 +381,11 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
        kvm_timer_vcpu_load(vcpu);
        kvm_vcpu_load_sysregs(vcpu);
        kvm_arch_vcpu_load_fp(vcpu);
+
+       if (single_task_running())
+               vcpu_clear_wfe_traps(vcpu);
+       else
+               vcpu_set_wfe_traps(vcpu);
 }
 
 void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
@@ -1044,6 +1050,32 @@ static int kvm_arm_vcpu_has_attr(struct kvm_vcpu *vcpu,
        return ret;
 }
 
+static int kvm_arm_vcpu_get_events(struct kvm_vcpu *vcpu,
+                                  struct kvm_vcpu_events *events)
+{
+       memset(events, 0, sizeof(*events));
+
+       return __kvm_arm_vcpu_get_events(vcpu, events);
+}
+
+static int kvm_arm_vcpu_set_events(struct kvm_vcpu *vcpu,
+                                  struct kvm_vcpu_events *events)
+{
+       int i;
+
+       /* check whether the reserved field is zero */
+       for (i = 0; i < ARRAY_SIZE(events->reserved); i++)
+               if (events->reserved[i])
+                       return -EINVAL;
+
+       /* check whether the pad field is zero */
+       for (i = 0; i < ARRAY_SIZE(events->exception.pad); i++)
+               if (events->exception.pad[i])
+                       return -EINVAL;
+
+       return __kvm_arm_vcpu_set_events(vcpu, events);
+}
+
 long kvm_arch_vcpu_ioctl(struct file *filp,
                         unsigned int ioctl, unsigned long arg)
 {
@@ -1124,6 +1156,25 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
                r = kvm_arm_vcpu_has_attr(vcpu, &attr);
                break;
        }
+       case KVM_GET_VCPU_EVENTS: {
+               struct kvm_vcpu_events events;
+
+               if (kvm_arm_vcpu_get_events(vcpu, &events))
+                       return -EINVAL;
+
+               if (copy_to_user(argp, &events, sizeof(events)))
+                       return -EFAULT;
+
+               return 0;
+       }
+       case KVM_SET_VCPU_EVENTS: {
+               struct kvm_vcpu_events events;
+
+               if (copy_from_user(&events, argp, sizeof(events)))
+                       return -EFAULT;
+
+               return kvm_arm_vcpu_set_events(vcpu, &events);
+       }
        default:
                r = -EINVAL;
        }
index 1d90d79..91aaf73 100644 (file)
@@ -177,6 +177,35 @@ static void clear_stage2_pmd_entry(struct kvm *kvm, pmd_t *pmd, phys_addr_t addr
        put_page(virt_to_page(pmd));
 }
 
+static inline void kvm_set_pte(pte_t *ptep, pte_t new_pte)
+{
+       WRITE_ONCE(*ptep, new_pte);
+       dsb(ishst);
+}
+
+static inline void kvm_set_pmd(pmd_t *pmdp, pmd_t new_pmd)
+{
+       WRITE_ONCE(*pmdp, new_pmd);
+       dsb(ishst);
+}
+
+static inline void kvm_pmd_populate(pmd_t *pmdp, pte_t *ptep)
+{
+       kvm_set_pmd(pmdp, kvm_mk_pmd(ptep));
+}
+
+static inline void kvm_pud_populate(pud_t *pudp, pmd_t *pmdp)
+{
+       WRITE_ONCE(*pudp, kvm_mk_pud(pmdp));
+       dsb(ishst);
+}
+
+static inline void kvm_pgd_populate(pgd_t *pgdp, pud_t *pudp)
+{
+       WRITE_ONCE(*pgdp, kvm_mk_pgd(pudp));
+       dsb(ishst);
+}
+
 /*
  * Unmapping vs dcache management:
  *
@@ -196,6 +225,10 @@ static void clear_stage2_pmd_entry(struct kvm *kvm, pmd_t *pmd, phys_addr_t addr
  * This is why right after unmapping a page/section and invalidating
  * the corresponding TLBs, we call kvm_flush_dcache_p*() to make sure
  * the IO subsystem will never hit in the cache.
+ *
+ * This is all avoided on systems that have ARM64_HAS_STAGE2_FWB, as
+ * we then fully enforce cacheability of RAM, no matter what the guest
+ * does.
  */
 static void unmap_stage2_ptes(struct kvm *kvm, pmd_t *pmd,
                       phys_addr_t addr, phys_addr_t end)
@@ -576,7 +609,6 @@ static void create_hyp_pte_mappings(pmd_t *pmd, unsigned long start,
                pte = pte_offset_kernel(pmd, addr);
                kvm_set_pte(pte, pfn_pte(pfn, prot));
                get_page(virt_to_page(pte));
-               kvm_flush_dcache_to_poc(pte, sizeof(*pte));
                pfn++;
        } while (addr += PAGE_SIZE, addr != end);
 }
@@ -601,9 +633,8 @@ static int create_hyp_pmd_mappings(pud_t *pud, unsigned long start,
                                kvm_err("Cannot allocate Hyp pte\n");
                                return -ENOMEM;
                        }
-                       pmd_populate_kernel(NULL, pmd, pte);
+                       kvm_pmd_populate(pmd, pte);
                        get_page(virt_to_page(pmd));
-                       kvm_flush_dcache_to_poc(pmd, sizeof(*pmd));
                }
 
                next = pmd_addr_end(addr, end);
@@ -634,9 +665,8 @@ static int create_hyp_pud_mappings(pgd_t *pgd, unsigned long start,
                                kvm_err("Cannot allocate Hyp pmd\n");
                                return -ENOMEM;
                        }
-                       pud_populate(NULL, pud, pmd);
+                       kvm_pud_populate(pud, pmd);
                        get_page(virt_to_page(pud));
-                       kvm_flush_dcache_to_poc(pud, sizeof(*pud));
                }
 
                next = pud_addr_end(addr, end);
@@ -671,9 +701,8 @@ static int __create_hyp_mappings(pgd_t *pgdp, unsigned long ptrs_per_pgd,
                                err = -ENOMEM;
                                goto out;
                        }
-                       pgd_populate(NULL, pgd, pud);
+                       kvm_pgd_populate(pgd, pud);
                        get_page(virt_to_page(pgd));
-                       kvm_flush_dcache_to_poc(pgd, sizeof(*pgd));
                }
 
                next = pgd_addr_end(addr, end);
@@ -1015,19 +1044,35 @@ static int stage2_set_pmd_huge(struct kvm *kvm, struct kvm_mmu_memory_cache
        pmd = stage2_get_pmd(kvm, cache, addr);
        VM_BUG_ON(!pmd);
 
-       /*
-        * Mapping in huge pages should only happen through a fault.  If a
-        * page is merged into a transparent huge page, the individual
-        * subpages of that huge page should be unmapped through MMU
-        * notifiers before we get here.
-        *
-        * Merging of CompoundPages is not supported; they should become
-        * splitting first, unmapped, merged, and mapped back in on-demand.
-        */
-       VM_BUG_ON(pmd_present(*pmd) && pmd_pfn(*pmd) != pmd_pfn(*new_pmd));
-
        old_pmd = *pmd;
        if (pmd_present(old_pmd)) {
+               /*
+                * Multiple vcpus faulting on the same PMD entry, can
+                * lead to them sequentially updating the PMD with the
+                * same value. Following the break-before-make
+                * (pmd_clear() followed by tlb_flush()) process can
+                * hinder forward progress due to refaults generated
+                * on missing translations.
+                *
+                * Skip updating the page table if the entry is
+                * unchanged.
+                */
+               if (pmd_val(old_pmd) == pmd_val(*new_pmd))
+                       return 0;
+
+               /*
+                * Mapping in huge pages should only happen through a
+                * fault.  If a page is merged into a transparent huge
+                * page, the individual subpages of that huge page
+                * should be unmapped through MMU notifiers before we
+                * get here.
+                *
+                * Merging of CompoundPages is not supported; they
+                * should become splitting first, unmapped, merged,
+                * and mapped back in on-demand.
+                */
+               VM_BUG_ON(pmd_pfn(old_pmd) != pmd_pfn(*new_pmd));
+
                pmd_clear(pmd);
                kvm_tlb_flush_vmid_ipa(kvm, addr);
        } else {
@@ -1090,7 +1135,7 @@ static int stage2_set_pte(struct kvm *kvm, struct kvm_mmu_memory_cache *cache,
                if (!cache)
                        return 0; /* ignore calls from kvm_set_spte_hva */
                pte = mmu_memory_cache_alloc(cache);
-               pmd_populate_kernel(NULL, pmd, pte);
+               kvm_pmd_populate(pmd, pte);
                get_page(virt_to_page(pmd));
        }
 
@@ -1102,6 +1147,10 @@ static int stage2_set_pte(struct kvm *kvm, struct kvm_mmu_memory_cache *cache,
        /* Create 2nd stage page table mapping - Level 3 */
        old_pte = *pte;
        if (pte_present(old_pte)) {
+               /* Skip page table update if there is no change */
+               if (pte_val(old_pte) == pte_val(*new_pte))
+                       return 0;
+
                kvm_set_pte(pte, __pte(0));
                kvm_tlb_flush_vmid_ipa(kvm, addr);
        } else {
index c589d4c..07aa900 100644 (file)
 struct vgic_state_iter {
        int nr_cpus;
        int nr_spis;
+       int nr_lpis;
        int dist_id;
        int vcpu_id;
        int intid;
+       int lpi_idx;
+       u32 *lpi_array;
 };
 
 static void iter_next(struct vgic_state_iter *iter)
@@ -52,6 +55,12 @@ static void iter_next(struct vgic_state_iter *iter)
        if (iter->intid == VGIC_NR_PRIVATE_IRQS &&
            ++iter->vcpu_id < iter->nr_cpus)
                iter->intid = 0;
+
+       if (iter->intid >= (iter->nr_spis + VGIC_NR_PRIVATE_IRQS)) {
+               if (iter->lpi_idx < iter->nr_lpis)
+                       iter->intid = iter->lpi_array[iter->lpi_idx];
+               iter->lpi_idx++;
+       }
 }
 
 static void iter_init(struct kvm *kvm, struct vgic_state_iter *iter,
@@ -63,6 +72,11 @@ static void iter_init(struct kvm *kvm, struct vgic_state_iter *iter,
 
        iter->nr_cpus = nr_cpus;
        iter->nr_spis = kvm->arch.vgic.nr_spis;
+       if (kvm->arch.vgic.vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3) {
+               iter->nr_lpis = vgic_copy_lpi_list(kvm, NULL, &iter->lpi_array);
+               if (iter->nr_lpis < 0)
+                       iter->nr_lpis = 0;
+       }
 
        /* Fast forward to the right position if needed */
        while (pos--)
@@ -73,7 +87,8 @@ static bool end_of_vgic(struct vgic_state_iter *iter)
 {
        return iter->dist_id > 0 &&
                iter->vcpu_id == iter->nr_cpus &&
-               (iter->intid - VGIC_NR_PRIVATE_IRQS) == iter->nr_spis;
+               iter->intid >= (iter->nr_spis + VGIC_NR_PRIVATE_IRQS) &&
+               iter->lpi_idx > iter->nr_lpis;
 }
 
 static void *vgic_debug_start(struct seq_file *s, loff_t *pos)
@@ -130,6 +145,7 @@ static void vgic_debug_stop(struct seq_file *s, void *v)
 
        mutex_lock(&kvm->lock);
        iter = kvm->arch.vgic.iter;
+       kfree(iter->lpi_array);
        kfree(iter);
        kvm->arch.vgic.iter = NULL;
        mutex_unlock(&kvm->lock);
@@ -137,17 +153,20 @@ static void vgic_debug_stop(struct seq_file *s, void *v)
 
 static void print_dist_state(struct seq_file *s, struct vgic_dist *dist)
 {
+       bool v3 = dist->vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3;
+
        seq_printf(s, "Distributor\n");
        seq_printf(s, "===========\n");
-       seq_printf(s, "vgic_model:\t%s\n",
-                  (dist->vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3) ?
-                  "GICv3" : "GICv2");
+       seq_printf(s, "vgic_model:\t%s\n", v3 ? "GICv3" : "GICv2");
        seq_printf(s, "nr_spis:\t%d\n", dist->nr_spis);
+       if (v3)
+               seq_printf(s, "nr_lpis:\t%d\n", dist->lpi_list_count);
        seq_printf(s, "enabled:\t%d\n", dist->enabled);
        seq_printf(s, "\n");
 
        seq_printf(s, "P=pending_latch, L=line_level, A=active\n");
        seq_printf(s, "E=enabled, H=hw, C=config (level=1, edge=0)\n");
+       seq_printf(s, "G=group\n");
 }
 
 static void print_header(struct seq_file *s, struct vgic_irq *irq,
@@ -162,8 +181,8 @@ static void print_header(struct seq_file *s, struct vgic_irq *irq,
        }
 
        seq_printf(s, "\n");
-       seq_printf(s, "%s%2d TYP   ID TGT_ID PLAEHC     HWID   TARGET SRC PRI VCPU_ID\n", hdr, id);
-       seq_printf(s, "---------------------------------------------------------------\n");
+       seq_printf(s, "%s%2d TYP   ID TGT_ID PLAEHCG     HWID   TARGET SRC PRI VCPU_ID\n", hdr, id);
+       seq_printf(s, "----------------------------------------------------------------\n");
 }
 
 static void print_irq_state(struct seq_file *s, struct vgic_irq *irq,
@@ -174,15 +193,17 @@ static void print_irq_state(struct seq_file *s, struct vgic_irq *irq,
                type = "SGI";
        else if (irq->intid < VGIC_NR_PRIVATE_IRQS)
                type = "PPI";
-       else
+       else if (irq->intid < VGIC_MAX_SPI)
                type = "SPI";
+       else
+               type = "LPI";
 
        if (irq->intid ==0 || irq->intid == VGIC_NR_PRIVATE_IRQS)
                print_header(s, irq, vcpu);
 
        seq_printf(s, "       %s %4d "
                      "    %2d "
-                     "%d%d%d%d%d%d "
+                     "%d%d%d%d%d%d%d "
                      "%8d "
                      "%8x "
                      " %2x "
@@ -197,12 +218,12 @@ static void print_irq_state(struct seq_file *s, struct vgic_irq *irq,
                        irq->enabled,
                        irq->hw,
                        irq->config == VGIC_CONFIG_LEVEL,
+                       irq->group,
                        irq->hwintid,
                        irq->mpidr,
                        irq->source,
                        irq->priority,
                        (irq->vcpu) ? irq->vcpu->vcpu_id : -1);
-
 }
 
 static int vgic_debug_show(struct seq_file *s, void *v)
@@ -221,17 +242,20 @@ static int vgic_debug_show(struct seq_file *s, void *v)
        if (!kvm->arch.vgic.initialized)
                return 0;
 
-       if (iter->vcpu_id < iter->nr_cpus) {
+       if (iter->vcpu_id < iter->nr_cpus)
                vcpu = kvm_get_vcpu(kvm, iter->vcpu_id);
-               irq = &vcpu->arch.vgic_cpu.private_irqs[iter->intid];
-       } else {
-               irq = &kvm->arch.vgic.spis[iter->intid - VGIC_NR_PRIVATE_IRQS];
+
+       irq = vgic_get_irq(kvm, vcpu, iter->intid);
+       if (!irq) {
+               seq_printf(s, "       LPI %4d freed\n", iter->intid);
+               return 0;
        }
 
        spin_lock_irqsave(&irq->irq_lock, flags);
        print_irq_state(s, irq, vcpu);
        spin_unlock_irqrestore(&irq->irq_lock, flags);
 
+       vgic_put_irq(kvm, irq);
        return 0;
 }
 
index 2673efc..c0c0b88 100644 (file)
@@ -175,10 +175,13 @@ static int kvm_vgic_dist_init(struct kvm *kvm, unsigned int nr_spis)
                irq->vcpu = NULL;
                irq->target_vcpu = vcpu0;
                kref_init(&irq->refcount);
-               if (dist->vgic_model == KVM_DEV_TYPE_ARM_VGIC_V2)
+               if (dist->vgic_model == KVM_DEV_TYPE_ARM_VGIC_V2) {
                        irq->targets = 0;
-               else
+                       irq->group = 0;
+               } else {
                        irq->mpidr = 0;
+                       irq->group = 1;
+               }
        }
        return 0;
 }
@@ -227,6 +230,18 @@ int kvm_vgic_vcpu_init(struct kvm_vcpu *vcpu)
                        /* PPIs */
                        irq->config = VGIC_CONFIG_LEVEL;
                }
+
+               /*
+                * GICv3 can only be created via the KVM_DEVICE_CREATE API and
+                * so we always know the emulation type at this point as it's
+                * either explicitly configured as GICv3, or explicitly
+                * configured as GICv2, or not configured yet which also
+                * implies GICv2.
+                */
+               if (dist->vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3)
+                       irq->group = 1;
+               else
+                       irq->group = 0;
        }
 
        if (!irqchip_in_kernel(vcpu->kvm))
@@ -271,6 +286,10 @@ int vgic_init(struct kvm *kvm)
        if (vgic_initialized(kvm))
                return 0;
 
+       /* Are we also in the middle of creating a VCPU? */
+       if (kvm->created_vcpus != atomic_read(&kvm->online_vcpus))
+               return -EBUSY;
+
        /* freeze the number of spis */
        if (!dist->nr_spis)
                dist->nr_spis = VGIC_NR_IRQS_LEGACY - VGIC_NR_PRIVATE_IRQS;
@@ -294,6 +313,7 @@ int vgic_init(struct kvm *kvm)
 
        vgic_debug_init(kvm);
 
+       dist->implementation_rev = 2;
        dist->initialized = true;
 
 out:
index 4ed79c9..1250225 100644 (file)
@@ -71,6 +71,7 @@ static struct vgic_irq *vgic_add_lpi(struct kvm *kvm, u32 intid,
        kref_init(&irq->refcount);
        irq->intid = intid;
        irq->target_vcpu = vcpu;
+       irq->group = 1;
 
        spin_lock_irqsave(&dist->lpi_list_lock, flags);
 
@@ -168,8 +169,14 @@ struct vgic_its_abi {
        int (*commit)(struct vgic_its *its);
 };
 
+#define ABI_0_ESZ      8
+#define ESZ_MAX                ABI_0_ESZ
+
 static const struct vgic_its_abi its_table_abi_versions[] = {
-       [0] = {.cte_esz = 8, .dte_esz = 8, .ite_esz = 8,
+       [0] = {
+        .cte_esz = ABI_0_ESZ,
+        .dte_esz = ABI_0_ESZ,
+        .ite_esz = ABI_0_ESZ,
         .save_tables = vgic_its_save_tables_v0,
         .restore_tables = vgic_its_restore_tables_v0,
         .commit = vgic_its_commit_v0,
@@ -183,7 +190,7 @@ inline const struct vgic_its_abi *vgic_its_get_abi(struct vgic_its *its)
        return &its_table_abi_versions[its->abi_rev];
 }
 
-int vgic_its_set_abi(struct vgic_its *its, int rev)
+static int vgic_its_set_abi(struct vgic_its *its, u32 rev)
 {
        const struct vgic_its_abi *abi;
 
@@ -312,9 +319,9 @@ static int update_lpi_config(struct kvm *kvm, struct vgic_irq *irq,
  * enumerate those LPIs without holding any lock.
  * Returns their number and puts the kmalloc'ed array into intid_ptr.
  */
-static int vgic_copy_lpi_list(struct kvm_vcpu *vcpu, u32 **intid_ptr)
+int vgic_copy_lpi_list(struct kvm *kvm, struct kvm_vcpu *vcpu, u32 **intid_ptr)
 {
-       struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
+       struct vgic_dist *dist = &kvm->arch.vgic;
        struct vgic_irq *irq;
        unsigned long flags;
        u32 *intids;
@@ -337,7 +344,7 @@ static int vgic_copy_lpi_list(struct kvm_vcpu *vcpu, u32 **intid_ptr)
                if (i == irq_count)
                        break;
                /* We don't need to "get" the IRQ, as we hold the list lock. */
-               if (irq->target_vcpu != vcpu)
+               if (vcpu && irq->target_vcpu != vcpu)
                        continue;
                intids[i++] = irq->intid;
        }
@@ -429,7 +436,7 @@ static int its_sync_lpi_pending_table(struct kvm_vcpu *vcpu)
        unsigned long flags;
        u8 pendmask;
 
-       nr_irqs = vgic_copy_lpi_list(vcpu, &intids);
+       nr_irqs = vgic_copy_lpi_list(vcpu->kvm, vcpu, &intids);
        if (nr_irqs < 0)
                return nr_irqs;
 
@@ -1154,7 +1161,7 @@ static int vgic_its_cmd_handle_invall(struct kvm *kvm, struct vgic_its *its,
 
        vcpu = kvm_get_vcpu(kvm, collection->target_addr);
 
-       irq_count = vgic_copy_lpi_list(vcpu, &intids);
+       irq_count = vgic_copy_lpi_list(kvm, vcpu, &intids);
        if (irq_count < 0)
                return irq_count;
 
@@ -1202,7 +1209,7 @@ static int vgic_its_cmd_handle_movall(struct kvm *kvm, struct vgic_its *its,
        vcpu1 = kvm_get_vcpu(kvm, target1_addr);
        vcpu2 = kvm_get_vcpu(kvm, target2_addr);
 
-       irq_count = vgic_copy_lpi_list(vcpu1, &intids);
+       irq_count = vgic_copy_lpi_list(kvm, vcpu1, &intids);
        if (irq_count < 0)
                return irq_count;
 
@@ -1881,14 +1888,14 @@ typedef int (*entry_fn_t)(struct vgic_its *its, u32 id, void *entry,
  * Return: < 0 on error, 0 if last element was identified, 1 otherwise
  * (the last element may not be found on second level tables)
  */
-static int scan_its_table(struct vgic_its *its, gpa_t base, int size, int esz,
+static int scan_its_table(struct vgic_its *its, gpa_t base, int size, u32 esz,
                          int start_id, entry_fn_t fn, void *opaque)
 {
        struct kvm *kvm = its->dev->kvm;
        unsigned long len = size;
        int id = start_id;
        gpa_t gpa = base;
-       char entry[esz];
+       char entry[ESZ_MAX];
        int ret;
 
        memset(entry, 0, esz);
index ffc587b..738b65d 100644 (file)
 #include "vgic.h"
 #include "vgic-mmio.h"
 
+/*
+ * The Revision field in the IIDR have the following meanings:
+ *
+ * Revision 1: Report GICv2 interrupts as group 0 instead of group 1
+ * Revision 2: Interrupt groups are guest-configurable and signaled using
+ *            their configured groups.
+ */
+
 static unsigned long vgic_mmio_read_v2_misc(struct kvm_vcpu *vcpu,
                                            gpa_t addr, unsigned int len)
 {
+       struct vgic_dist *vgic = &vcpu->kvm->arch.vgic;
        u32 value;
 
        switch (addr & 0x0c) {
        case GIC_DIST_CTRL:
-               value = vcpu->kvm->arch.vgic.enabled ? GICD_ENABLE : 0;
+               value = vgic->enabled ? GICD_ENABLE : 0;
                break;
        case GIC_DIST_CTR:
-               value = vcpu->kvm->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS;
+               value = vgic->nr_spis + VGIC_NR_PRIVATE_IRQS;
                value = (value >> 5) - 1;
                value |= (atomic_read(&vcpu->kvm->online_vcpus) - 1) << 5;
                break;
        case GIC_DIST_IIDR:
-               value = (PRODUCT_ID_KVM << 24) | (IMPLEMENTER_ARM << 0);
+               value = (PRODUCT_ID_KVM << GICD_IIDR_PRODUCT_ID_SHIFT) |
+                       (vgic->implementation_rev << GICD_IIDR_REVISION_SHIFT) |
+                       (IMPLEMENTER_ARM << GICD_IIDR_IMPLEMENTER_SHIFT);
                break;
        default:
                return 0;
@@ -66,6 +77,42 @@ static void vgic_mmio_write_v2_misc(struct kvm_vcpu *vcpu,
        }
 }
 
+static int vgic_mmio_uaccess_write_v2_misc(struct kvm_vcpu *vcpu,
+                                          gpa_t addr, unsigned int len,
+                                          unsigned long val)
+{
+       switch (addr & 0x0c) {
+       case GIC_DIST_IIDR:
+               if (val != vgic_mmio_read_v2_misc(vcpu, addr, len))
+                       return -EINVAL;
+
+               /*
+                * If we observe a write to GICD_IIDR we know that userspace
+                * has been updated and has had a chance to cope with older
+                * kernels (VGICv2 IIDR.Revision == 0) incorrectly reporting
+                * interrupts as group 1, and therefore we now allow groups to
+                * be user writable.  Doing this by default would break
+                * migration from old kernels to new kernels with legacy
+                * userspace.
+                */
+               vcpu->kvm->arch.vgic.v2_groups_user_writable = true;
+               return 0;
+       }
+
+       vgic_mmio_write_v2_misc(vcpu, addr, len, val);
+       return 0;
+}
+
+static int vgic_mmio_uaccess_write_v2_group(struct kvm_vcpu *vcpu,
+                                           gpa_t addr, unsigned int len,
+                                           unsigned long val)
+{
+       if (vcpu->kvm->arch.vgic.v2_groups_user_writable)
+               vgic_mmio_write_group(vcpu, addr, len, val);
+
+       return 0;
+}
+
 static void vgic_mmio_write_sgir(struct kvm_vcpu *source_vcpu,
                                 gpa_t addr, unsigned int len,
                                 unsigned long val)
@@ -352,17 +399,22 @@ static void vgic_mmio_write_apr(struct kvm_vcpu *vcpu,
 
                if (n > vgic_v3_max_apr_idx(vcpu))
                        return;
+
+               n = array_index_nospec(n, 4);
+
                /* GICv3 only uses ICH_AP1Rn for memory mapped (GICv2) guests */
                vgicv3->vgic_ap1r[n] = val;
        }
 }
 
 static const struct vgic_register_region vgic_v2_dist_registers[] = {
-       REGISTER_DESC_WITH_LENGTH(GIC_DIST_CTRL,
-               vgic_mmio_read_v2_misc, vgic_mmio_write_v2_misc, 12,
-               VGIC_ACCESS_32bit),
+       REGISTER_DESC_WITH_LENGTH_UACCESS(GIC_DIST_CTRL,
+               vgic_mmio_read_v2_misc, vgic_mmio_write_v2_misc,
+               NULL, vgic_mmio_uaccess_write_v2_misc,
+               12, VGIC_ACCESS_32bit),
        REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_IGROUP,
-               vgic_mmio_read_rao, vgic_mmio_write_wi, NULL, NULL, 1,
+               vgic_mmio_read_group, vgic_mmio_write_group,
+               NULL, vgic_mmio_uaccess_write_v2_group, 1,
                VGIC_ACCESS_32bit),
        REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ENABLE_SET,
                vgic_mmio_read_enable, vgic_mmio_write_senable, NULL, NULL, 1,
index 2877840..a2a175b 100644 (file)
@@ -59,19 +59,27 @@ bool vgic_supports_direct_msis(struct kvm *kvm)
        return kvm_vgic_global_state.has_gicv4 && vgic_has_its(kvm);
 }
 
+/*
+ * The Revision field in the IIDR have the following meanings:
+ *
+ * Revision 2: Interrupt groups are guest-configurable and signaled using
+ *            their configured groups.
+ */
+
 static unsigned long vgic_mmio_read_v3_misc(struct kvm_vcpu *vcpu,
                                            gpa_t addr, unsigned int len)
 {
+       struct vgic_dist *vgic = &vcpu->kvm->arch.vgic;
        u32 value = 0;
 
        switch (addr & 0x0c) {
        case GICD_CTLR:
-               if (vcpu->kvm->arch.vgic.enabled)
+               if (vgic->enabled)
                        value |= GICD_CTLR_ENABLE_SS_G1;
                value |= GICD_CTLR_ARE_NS | GICD_CTLR_DS;
                break;
        case GICD_TYPER:
-               value = vcpu->kvm->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS;
+               value = vgic->nr_spis + VGIC_NR_PRIVATE_IRQS;
                value = (value >> 5) - 1;
                if (vgic_has_its(vcpu->kvm)) {
                        value |= (INTERRUPT_ID_BITS_ITS - 1) << 19;
@@ -81,7 +89,9 @@ static unsigned long vgic_mmio_read_v3_misc(struct kvm_vcpu *vcpu,
                }
                break;
        case GICD_IIDR:
-               value = (PRODUCT_ID_KVM << 24) | (IMPLEMENTER_ARM << 0);
+               value = (PRODUCT_ID_KVM << GICD_IIDR_PRODUCT_ID_SHIFT) |
+                       (vgic->implementation_rev << GICD_IIDR_REVISION_SHIFT) |
+                       (IMPLEMENTER_ARM << GICD_IIDR_IMPLEMENTER_SHIFT);
                break;
        default:
                return 0;
@@ -110,6 +120,20 @@ static void vgic_mmio_write_v3_misc(struct kvm_vcpu *vcpu,
        }
 }
 
+static int vgic_mmio_uaccess_write_v3_misc(struct kvm_vcpu *vcpu,
+                                          gpa_t addr, unsigned int len,
+                                          unsigned long val)
+{
+       switch (addr & 0x0c) {
+       case GICD_IIDR:
+               if (val != vgic_mmio_read_v3_misc(vcpu, addr, len))
+                       return -EINVAL;
+       }
+
+       vgic_mmio_write_v3_misc(vcpu, addr, len, val);
+       return 0;
+}
+
 static unsigned long vgic_mmio_read_irouter(struct kvm_vcpu *vcpu,
                                            gpa_t addr, unsigned int len)
 {
@@ -246,9 +270,9 @@ static unsigned long vgic_v3_uaccess_read_pending(struct kvm_vcpu *vcpu,
        return value;
 }
 
-static void vgic_v3_uaccess_write_pending(struct kvm_vcpu *vcpu,
-                                         gpa_t addr, unsigned int len,
-                                         unsigned long val)
+static int vgic_v3_uaccess_write_pending(struct kvm_vcpu *vcpu,
+                                        gpa_t addr, unsigned int len,
+                                        unsigned long val)
 {
        u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
        int i;
@@ -273,6 +297,8 @@ static void vgic_v3_uaccess_write_pending(struct kvm_vcpu *vcpu,
 
                vgic_put_irq(vcpu->kvm, irq);
        }
+
+       return 0;
 }
 
 /* We want to avoid outer shareable. */
@@ -444,14 +470,15 @@ static void vgic_mmio_write_pendbase(struct kvm_vcpu *vcpu,
        }
 
 static const struct vgic_register_region vgic_v3_dist_registers[] = {
-       REGISTER_DESC_WITH_LENGTH(GICD_CTLR,
-               vgic_mmio_read_v3_misc, vgic_mmio_write_v3_misc, 16,
-               VGIC_ACCESS_32bit),
+       REGISTER_DESC_WITH_LENGTH_UACCESS(GICD_CTLR,
+               vgic_mmio_read_v3_misc, vgic_mmio_write_v3_misc,
+               NULL, vgic_mmio_uaccess_write_v3_misc,
+               16, VGIC_ACCESS_32bit),
        REGISTER_DESC_WITH_LENGTH(GICD_STATUSR,
                vgic_mmio_read_rao, vgic_mmio_write_wi, 4,
                VGIC_ACCESS_32bit),
        REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IGROUPR,
-               vgic_mmio_read_rao, vgic_mmio_write_wi, NULL, NULL, 1,
+               vgic_mmio_read_group, vgic_mmio_write_group, NULL, NULL, 1,
                VGIC_ACCESS_32bit),
        REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ISENABLER,
                vgic_mmio_read_enable, vgic_mmio_write_senable, NULL, NULL, 1,
@@ -465,7 +492,7 @@ static const struct vgic_register_region vgic_v3_dist_registers[] = {
                VGIC_ACCESS_32bit),
        REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ICPENDR,
                vgic_mmio_read_pending, vgic_mmio_write_cpending,
-               vgic_mmio_read_raz, vgic_mmio_write_wi, 1,
+               vgic_mmio_read_raz, vgic_mmio_uaccess_write_wi, 1,
                VGIC_ACCESS_32bit),
        REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ISACTIVER,
                vgic_mmio_read_active, vgic_mmio_write_sactive,
@@ -524,7 +551,7 @@ static const struct vgic_register_region vgic_v3_rdbase_registers[] = {
 
 static const struct vgic_register_region vgic_v3_sgibase_registers[] = {
        REGISTER_DESC_WITH_LENGTH(GICR_IGROUPR0,
-               vgic_mmio_read_rao, vgic_mmio_write_wi, 4,
+               vgic_mmio_read_group, vgic_mmio_write_group, 4,
                VGIC_ACCESS_32bit),
        REGISTER_DESC_WITH_LENGTH(GICR_ISENABLER0,
                vgic_mmio_read_enable, vgic_mmio_write_senable, 4,
@@ -538,7 +565,7 @@ static const struct vgic_register_region vgic_v3_sgibase_registers[] = {
                VGIC_ACCESS_32bit),
        REGISTER_DESC_WITH_LENGTH_UACCESS(GICR_ICPENDR0,
                vgic_mmio_read_pending, vgic_mmio_write_cpending,
-               vgic_mmio_read_raz, vgic_mmio_write_wi, 4,
+               vgic_mmio_read_raz, vgic_mmio_uaccess_write_wi, 4,
                VGIC_ACCESS_32bit),
        REGISTER_DESC_WITH_LENGTH_UACCESS(GICR_ISACTIVER0,
                vgic_mmio_read_active, vgic_mmio_write_sactive,
@@ -873,7 +900,8 @@ static int match_mpidr(u64 sgi_aff, u16 sgi_cpu_mask, struct kvm_vcpu *vcpu)
 /**
  * vgic_v3_dispatch_sgi - handle SGI requests from VCPUs
  * @vcpu: The VCPU requesting a SGI
- * @reg: The value written into the ICC_SGI1R_EL1 register by that VCPU
+ * @reg: The value written into ICC_{ASGI1,SGI0,SGI1}R by that VCPU
+ * @allow_group1: Does the sysreg access allow generation of G1 SGIs
  *
  * With GICv3 (and ARE=1) CPUs trigger SGIs by writing to a system register.
  * This will trap in sys_regs.c and call this function.
@@ -883,7 +911,7 @@ static int match_mpidr(u64 sgi_aff, u16 sgi_cpu_mask, struct kvm_vcpu *vcpu)
  * check for matching ones. If this bit is set, we signal all, but not the
  * calling VCPU.
  */
-void vgic_v3_dispatch_sgi(struct kvm_vcpu *vcpu, u64 reg)
+void vgic_v3_dispatch_sgi(struct kvm_vcpu *vcpu, u64 reg, bool allow_group1)
 {
        struct kvm *kvm = vcpu->kvm;
        struct kvm_vcpu *c_vcpu;
@@ -932,9 +960,19 @@ void vgic_v3_dispatch_sgi(struct kvm_vcpu *vcpu, u64 reg)
                irq = vgic_get_irq(vcpu->kvm, c_vcpu, sgi);
 
                spin_lock_irqsave(&irq->irq_lock, flags);
-               irq->pending_latch = true;
 
-               vgic_queue_irq_unlock(vcpu->kvm, irq, flags);
+               /*
+                * An access targetting Group0 SGIs can only generate
+                * those, while an access targetting Group1 SGIs can
+                * generate interrupts of either group.
+                */
+               if (!irq->group || allow_group1) {
+                       irq->pending_latch = true;
+                       vgic_queue_irq_unlock(vcpu->kvm, irq, flags);
+               } else {
+                       spin_unlock_irqrestore(&irq->irq_lock, flags);
+               }
+
                vgic_put_irq(vcpu->kvm, irq);
        }
 }
index ff9655c..f56ff1c 100644 (file)
@@ -40,6 +40,51 @@ void vgic_mmio_write_wi(struct kvm_vcpu *vcpu, gpa_t addr,
        /* Ignore */
 }
 
+int vgic_mmio_uaccess_write_wi(struct kvm_vcpu *vcpu, gpa_t addr,
+                              unsigned int len, unsigned long val)
+{
+       /* Ignore */
+       return 0;
+}
+
+unsigned long vgic_mmio_read_group(struct kvm_vcpu *vcpu,
+                                  gpa_t addr, unsigned int len)
+{
+       u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
+       u32 value = 0;
+       int i;
+
+       /* Loop over all IRQs affected by this read */
+       for (i = 0; i < len * 8; i++) {
+               struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+               if (irq->group)
+                       value |= BIT(i);
+
+               vgic_put_irq(vcpu->kvm, irq);
+       }
+
+       return value;
+}
+
+void vgic_mmio_write_group(struct kvm_vcpu *vcpu, gpa_t addr,
+                          unsigned int len, unsigned long val)
+{
+       u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
+       int i;
+       unsigned long flags;
+
+       for (i = 0; i < len * 8; i++) {
+               struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+               spin_lock_irqsave(&irq->irq_lock, flags);
+               irq->group = !!(val & BIT(i));
+               vgic_queue_irq_unlock(vcpu->kvm, irq, flags);
+
+               vgic_put_irq(vcpu->kvm, irq);
+       }
+}
+
 /*
  * Read accesses to both GICD_ICENABLER and GICD_ISENABLER return the value
  * of the enabled bit, so there is only one function for both here.
@@ -363,11 +408,12 @@ void vgic_mmio_write_cactive(struct kvm_vcpu *vcpu,
        mutex_unlock(&vcpu->kvm->lock);
 }
 
-void vgic_mmio_uaccess_write_cactive(struct kvm_vcpu *vcpu,
+int vgic_mmio_uaccess_write_cactive(struct kvm_vcpu *vcpu,
                                     gpa_t addr, unsigned int len,
                                     unsigned long val)
 {
        __vgic_mmio_write_cactive(vcpu, addr, len, val);
+       return 0;
 }
 
 static void __vgic_mmio_write_sactive(struct kvm_vcpu *vcpu,
@@ -399,11 +445,12 @@ void vgic_mmio_write_sactive(struct kvm_vcpu *vcpu,
        mutex_unlock(&vcpu->kvm->lock);
 }
 
-void vgic_mmio_uaccess_write_sactive(struct kvm_vcpu *vcpu,
+int vgic_mmio_uaccess_write_sactive(struct kvm_vcpu *vcpu,
                                     gpa_t addr, unsigned int len,
                                     unsigned long val)
 {
        __vgic_mmio_write_sactive(vcpu, addr, len, val);
+       return 0;
 }
 
 unsigned long vgic_mmio_read_priority(struct kvm_vcpu *vcpu,
@@ -735,10 +782,9 @@ static int vgic_uaccess_write(struct kvm_vcpu *vcpu, struct kvm_io_device *dev,
 
        r_vcpu = iodev->redist_vcpu ? iodev->redist_vcpu : vcpu;
        if (region->uaccess_write)
-               region->uaccess_write(r_vcpu, addr, sizeof(u32), *val);
-       else
-               region->write(r_vcpu, addr, sizeof(u32), *val);
+               return region->uaccess_write(r_vcpu, addr, sizeof(u32), *val);
 
+       region->write(r_vcpu, addr, sizeof(u32), *val);
        return 0;
 }
 
index 5693f6d..a07f90a 100644 (file)
@@ -37,8 +37,8 @@ struct vgic_register_region {
        unsigned long (*uaccess_read)(struct kvm_vcpu *vcpu, gpa_t addr,
                                      unsigned int len);
        union {
-               void (*uaccess_write)(struct kvm_vcpu *vcpu, gpa_t addr,
-                                     unsigned int len, unsigned long val);
+               int (*uaccess_write)(struct kvm_vcpu *vcpu, gpa_t addr,
+                                    unsigned int len, unsigned long val);
                int (*uaccess_its_write)(struct kvm *kvm, struct vgic_its *its,
                                         gpa_t addr, unsigned int len,
                                         unsigned long val);
@@ -134,6 +134,15 @@ unsigned long vgic_mmio_read_rao(struct kvm_vcpu *vcpu,
 void vgic_mmio_write_wi(struct kvm_vcpu *vcpu, gpa_t addr,
                        unsigned int len, unsigned long val);
 
+int vgic_mmio_uaccess_write_wi(struct kvm_vcpu *vcpu, gpa_t addr,
+                              unsigned int len, unsigned long val);
+
+unsigned long vgic_mmio_read_group(struct kvm_vcpu *vcpu, gpa_t addr,
+                                  unsigned int len);
+
+void vgic_mmio_write_group(struct kvm_vcpu *vcpu, gpa_t addr,
+                          unsigned int len, unsigned long val);
+
 unsigned long vgic_mmio_read_enable(struct kvm_vcpu *vcpu,
                                    gpa_t addr, unsigned int len);
 
@@ -167,13 +176,13 @@ void vgic_mmio_write_sactive(struct kvm_vcpu *vcpu,
                             gpa_t addr, unsigned int len,
                             unsigned long val);
 
-void vgic_mmio_uaccess_write_cactive(struct kvm_vcpu *vcpu,
-                                    gpa_t addr, unsigned int len,
-                                    unsigned long val);
+int vgic_mmio_uaccess_write_cactive(struct kvm_vcpu *vcpu,
+                                   gpa_t addr, unsigned int len,
+                                   unsigned long val);
 
-void vgic_mmio_uaccess_write_sactive(struct kvm_vcpu *vcpu,
-                                    gpa_t addr, unsigned int len,
-                                    unsigned long val);
+int vgic_mmio_uaccess_write_sactive(struct kvm_vcpu *vcpu,
+                                   gpa_t addr, unsigned int len,
+                                   unsigned long val);
 
 unsigned long vgic_mmio_read_priority(struct kvm_vcpu *vcpu,
                                      gpa_t addr, unsigned int len);
index a5f2e44..69b892a 100644 (file)
@@ -62,7 +62,8 @@ void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu)
        struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
        struct vgic_v2_cpu_if *cpuif = &vgic_cpu->vgic_v2;
        int lr;
-       unsigned long flags;
+
+       DEBUG_SPINLOCK_BUG_ON(!irqs_disabled());
 
        cpuif->vgic_hcr &= ~GICH_HCR_UIE;
 
@@ -83,7 +84,7 @@ void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu)
 
                irq = vgic_get_irq(vcpu->kvm, vcpu, intid);
 
-               spin_lock_irqsave(&irq->irq_lock, flags);
+               spin_lock(&irq->irq_lock);
 
                /* Always preserve the active bit */
                irq->active = !!(val & GICH_LR_ACTIVE_BIT);
@@ -126,7 +127,7 @@ void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu)
                                vgic_irq_set_phys_active(irq, false);
                }
 
-               spin_unlock_irqrestore(&irq->irq_lock, flags);
+               spin_unlock(&irq->irq_lock);
                vgic_put_irq(vcpu->kvm, irq);
        }
 
@@ -159,6 +160,9 @@ void vgic_v2_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr)
                }
        }
 
+       if (irq->group)
+               val |= GICH_LR_GROUP1;
+
        if (irq->hw) {
                val |= GICH_LR_HW;
                val |= irq->hwintid << GICH_LR_PHYSID_CPUID_SHIFT;
index cdce653..9c0dd23 100644 (file)
@@ -46,7 +46,8 @@ void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu)
        struct vgic_v3_cpu_if *cpuif = &vgic_cpu->vgic_v3;
        u32 model = vcpu->kvm->arch.vgic.vgic_model;
        int lr;
-       unsigned long flags;
+
+       DEBUG_SPINLOCK_BUG_ON(!irqs_disabled());
 
        cpuif->vgic_hcr &= ~ICH_HCR_UIE;
 
@@ -75,7 +76,7 @@ void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu)
                if (!irq)       /* An LPI could have been unmapped. */
                        continue;
 
-               spin_lock_irqsave(&irq->irq_lock, flags);
+               spin_lock(&irq->irq_lock);
 
                /* Always preserve the active bit */
                irq->active = !!(val & ICH_LR_ACTIVE_BIT);
@@ -118,7 +119,7 @@ void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu)
                                vgic_irq_set_phys_active(irq, false);
                }
 
-               spin_unlock_irqrestore(&irq->irq_lock, flags);
+               spin_unlock(&irq->irq_lock);
                vgic_put_irq(vcpu->kvm, irq);
        }
 
@@ -197,11 +198,7 @@ void vgic_v3_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr)
        if (vgic_irq_is_mapped_level(irq) && (val & ICH_LR_PENDING_BIT))
                irq->line_level = false;
 
-       /*
-        * We currently only support Group1 interrupts, which is a
-        * known defect. This needs to be addressed at some point.
-        */
-       if (model == KVM_DEV_TYPE_ARM_VGIC_V3)
+       if (irq->group)
                val |= ICH_LR_GROUP;
 
        val |= (u64)irq->priority << ICH_LR_PRIORITY_SHIFT;
index 33c8325..7cfdfbc 100644 (file)
 #define CREATE_TRACE_POINTS
 #include "trace.h"
 
-#ifdef CONFIG_DEBUG_SPINLOCK
-#define DEBUG_SPINLOCK_BUG_ON(p) BUG_ON(p)
-#else
-#define DEBUG_SPINLOCK_BUG_ON(p)
-#endif
-
 struct vgic_global kvm_vgic_global_state __ro_after_init = {
        .gicv3_cpuif = STATIC_KEY_FALSE_INIT,
 };
@@ -599,10 +593,11 @@ static void vgic_prune_ap_list(struct kvm_vcpu *vcpu)
 {
        struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
        struct vgic_irq *irq, *tmp;
-       unsigned long flags;
+
+       DEBUG_SPINLOCK_BUG_ON(!irqs_disabled());
 
 retry:
-       spin_lock_irqsave(&vgic_cpu->ap_list_lock, flags);
+       spin_lock(&vgic_cpu->ap_list_lock);
 
        list_for_each_entry_safe(irq, tmp, &vgic_cpu->ap_list_head, ap_list) {
                struct kvm_vcpu *target_vcpu, *vcpuA, *vcpuB;
@@ -643,7 +638,7 @@ retry:
                /* This interrupt looks like it has to be migrated. */
 
                spin_unlock(&irq->irq_lock);
-               spin_unlock_irqrestore(&vgic_cpu->ap_list_lock, flags);
+               spin_unlock(&vgic_cpu->ap_list_lock);
 
                /*
                 * Ensure locking order by always locking the smallest
@@ -657,7 +652,7 @@ retry:
                        vcpuB = vcpu;
                }
 
-               spin_lock_irqsave(&vcpuA->arch.vgic_cpu.ap_list_lock, flags);
+               spin_lock(&vcpuA->arch.vgic_cpu.ap_list_lock);
                spin_lock_nested(&vcpuB->arch.vgic_cpu.ap_list_lock,
                                 SINGLE_DEPTH_NESTING);
                spin_lock(&irq->irq_lock);
@@ -682,7 +677,7 @@ retry:
 
                spin_unlock(&irq->irq_lock);
                spin_unlock(&vcpuB->arch.vgic_cpu.ap_list_lock);
-               spin_unlock_irqrestore(&vcpuA->arch.vgic_cpu.ap_list_lock, flags);
+               spin_unlock(&vcpuA->arch.vgic_cpu.ap_list_lock);
 
                if (target_vcpu_needs_kick) {
                        kvm_make_request(KVM_REQ_IRQ_PENDING, target_vcpu);
@@ -692,7 +687,7 @@ retry:
                goto retry;
        }
 
-       spin_unlock_irqrestore(&vgic_cpu->ap_list_lock, flags);
+       spin_unlock(&vgic_cpu->ap_list_lock);
 }
 
 static inline void vgic_fold_lr_state(struct kvm_vcpu *vcpu)
index ead00b2..a900247 100644 (file)
 #define KVM_VGIC_V3_RDIST_COUNT_MASK   GENMASK_ULL(63, 52)
 #define KVM_VGIC_V3_RDIST_COUNT_SHIFT  52
 
+#ifdef CONFIG_DEBUG_SPINLOCK
+#define DEBUG_SPINLOCK_BUG_ON(p) BUG_ON(p)
+#else
+#define DEBUG_SPINLOCK_BUG_ON(p)
+#endif
+
 /* Requires the irq_lock to be held by the caller. */
 static inline bool irq_is_pending(struct vgic_irq *irq)
 {
@@ -305,6 +311,7 @@ static inline bool vgic_dist_overlap(struct kvm *kvm, gpa_t base, size_t size)
                (base < d->vgic_dist_base + KVM_VGIC_V3_DIST_SIZE);
 }
 
+int vgic_copy_lpi_list(struct kvm *kvm, struct kvm_vcpu *vcpu, u32 **intid_ptr);
 int vgic_its_resolve_lpi(struct kvm *kvm, struct vgic_its *its,
                         u32 devid, u32 eventid, struct vgic_irq **irq);
 struct vgic_its *vgic_msi_to_its(struct kvm *kvm, struct kvm_msi *msi);
index 9263ead..f986e31 100644 (file)
@@ -140,9 +140,10 @@ static void kvm_uevent_notify_change(unsigned int type, struct kvm *kvm);
 static unsigned long long kvm_createvm_count;
 static unsigned long long kvm_active_vms;
 
-__weak void kvm_arch_mmu_notifier_invalidate_range(struct kvm *kvm,
-               unsigned long start, unsigned long end)
+__weak int kvm_arch_mmu_notifier_invalidate_range(struct kvm *kvm,
+               unsigned long start, unsigned long end, bool blockable)
 {
+       return 0;
 }
 
 bool kvm_is_reserved_pfn(kvm_pfn_t pfn)
@@ -360,13 +361,15 @@ static void kvm_mmu_notifier_change_pte(struct mmu_notifier *mn,
        srcu_read_unlock(&kvm->srcu, idx);
 }
 
-static void kvm_mmu_notifier_invalidate_range_start(struct mmu_notifier *mn,
+static int kvm_mmu_notifier_invalidate_range_start(struct mmu_notifier *mn,
                                                    struct mm_struct *mm,
                                                    unsigned long start,
-                                                   unsigned long end)
+                                                   unsigned long end,
+                                                   bool blockable)
 {
        struct kvm *kvm = mmu_notifier_to_kvm(mn);
        int need_tlb_flush = 0, idx;
+       int ret;
 
        idx = srcu_read_lock(&kvm->srcu);
        spin_lock(&kvm->mmu_lock);
@@ -384,9 +387,11 @@ static void kvm_mmu_notifier_invalidate_range_start(struct mmu_notifier *mn,
 
        spin_unlock(&kvm->mmu_lock);
 
-       kvm_arch_mmu_notifier_invalidate_range(kvm, start, end);
+       ret = kvm_arch_mmu_notifier_invalidate_range(kvm, start, end, blockable);
 
        srcu_read_unlock(&kvm->srcu, idx);
+
+       return ret;
 }
 
 static void kvm_mmu_notifier_invalidate_range_end(struct mmu_notifier *mn,
@@ -2568,7 +2573,7 @@ static long kvm_vcpu_ioctl(struct file *filp,
                if (arg)
                        goto out;
                oldpid = rcu_access_pointer(vcpu->pid);
-               if (unlikely(oldpid != current->pids[PIDTYPE_PID].pid)) {
+               if (unlikely(oldpid != task_pid(current))) {
                        /* The thread running this VCPU changed. */
                        struct pid *newpid;